summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-10 05:27:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-10 05:27:25 +0000
commitc9c06167e7933d93a6e396174c68abf242294abb (patch)
treed9a8bb30663e9a3405a1ef37ffb62bc14b9f019f
parentf79e8cc3c34e4192a3e5ef4cc9c6542fdef703c0 (diff)
Merge with Linux 2.4.0-test12.
-rw-r--r--CREDITS14
-rw-r--r--Documentation/Changes13
-rw-r--r--Documentation/Configure.help97
-rw-r--r--Documentation/DMA-mapping.txt2
-rw-r--r--Documentation/DocBook/kernel-hacking.tmpl14
-rw-r--r--Documentation/DocBook/videobook.tmpl2
-rw-r--r--Documentation/README.DAC96010
-rw-r--r--Documentation/SubmittingDrivers18
-rw-r--r--Documentation/SubmittingPatches286
-rw-r--r--Documentation/arm/README3
-rw-r--r--Documentation/arm/SA1100/GraphicsClient (renamed from Documentation/arm/SA1100/ThinClient)21
-rw-r--r--Documentation/arm/SA1100/Pangolin25
-rw-r--r--Documentation/arm/SA1100/serial_UART65
-rw-r--r--Documentation/cachetlb.txt2
-rw-r--r--Documentation/filesystems/devfs/README4
-rw-r--r--Documentation/filesystems/proc.txt137
-rw-r--r--Documentation/initrd.txt350
-rw-r--r--Documentation/ioctl-number.txt4
-rw-r--r--Documentation/isdn/INTERFACE.fax2
-rw-r--r--Documentation/isdn/README.HiSax4
-rw-r--r--Documentation/kbuild/makefiles.txt68
-rw-r--r--Documentation/networking/irda.txt6
-rw-r--r--Documentation/parisc/00-INDEX10
-rw-r--r--Documentation/parisc/IODC.txt68
-rw-r--r--Documentation/parisc/debugging39
-rw-r--r--Documentation/parisc/mm31
-rw-r--r--Documentation/parisc/registers126
-rw-r--r--Documentation/sound/CMI83302
-rw-r--r--Documentation/usb/URB.txt61
-rw-r--r--Documentation/usb/error-codes.txt44
-rw-r--r--Documentation/usb/usb-help.txt1
-rw-r--r--Documentation/usb/usb-serial.txt30
-rw-r--r--MAINTAINERS26
-rw-r--r--Makefile3
-rw-r--r--arch/alpha/Makefile12
-rw-r--r--arch/alpha/config.in15
-rw-r--r--arch/alpha/kernel/core_cia.c13
-rw-r--r--arch/alpha/kernel/pci.c214
-rw-r--r--arch/alpha/kernel/pci_iommu.c4
-rw-r--r--arch/alpha/kernel/sys_ruffian.c4
-rw-r--r--arch/alpha/lib/Makefile65
-rw-r--r--arch/alpha/lib/checksum.c32
-rw-r--r--arch/alpha/lib/csum_partial_copy.c35
-rw-r--r--arch/alpha/lib/ev6-clear_user.S228
-rw-r--r--arch/alpha/lib/ev6-copy_user.S262
-rw-r--r--arch/alpha/lib/ev6-csum_ipv6_magic.S126
-rw-r--r--arch/alpha/lib/ev6-divide.S259
-rw-r--r--arch/alpha/lib/ev6-memchr.S191
-rw-r--r--arch/alpha/lib/ev6-memcpy.S248
-rw-r--r--arch/alpha/lib/ev6-memset.S596
-rw-r--r--arch/alpha/lib/ev6-strncpy_from_user.S425
-rw-r--r--arch/alpha/lib/ev6-stxcpy.S321
-rw-r--r--arch/alpha/lib/ev6-stxncpy.S399
-rw-r--r--arch/alpha/lib/ev67-strcat.S54
-rw-r--r--arch/alpha/lib/ev67-strchr.S88
-rw-r--r--arch/alpha/lib/ev67-strlen.S49
-rw-r--r--arch/alpha/lib/ev67-strlen_user.S109
-rw-r--r--arch/alpha/lib/ev67-strncat.S94
-rw-r--r--arch/alpha/lib/memcpy.c21
-rw-r--r--arch/alpha/lib/memmove.S103
-rw-r--r--arch/alpha/lib/strcpy.S1
-rw-r--r--arch/alpha/lib/strncpy.S4
-rw-r--r--arch/alpha/lib/stxcpy.S3
-rw-r--r--arch/alpha/lib/stxncpy.S3
-rw-r--r--arch/alpha/mm/init.c2
-rw-r--r--arch/arm/boot/Makefile22
-rw-r--r--arch/arm/boot/compressed/Makefile6
-rw-r--r--arch/arm/def-configs/a5k435
-rw-r--r--arch/arm/def-configs/assabet94
-rw-r--r--arch/arm/def-configs/brutus36
-rw-r--r--arch/arm/def-configs/cerf85
-rw-r--r--arch/arm/def-configs/ebsa110135
-rw-r--r--arch/arm/def-configs/footbridge767
-rw-r--r--arch/arm/def-configs/graphicsclient486
-rw-r--r--arch/arm/def-configs/integrator511
-rw-r--r--arch/arm/def-configs/neponset576
-rw-r--r--arch/arm/def-configs/pangolin (renamed from arch/arm/def-configs/thinclient)389
-rw-r--r--arch/arm/def-configs/rpc493
-rw-r--r--arch/arm/def-configs/sherman210
-rw-r--r--arch/arm/kernel/bios32.c22
-rw-r--r--arch/arm/kernel/dec21285.c10
-rw-r--r--arch/arm/kernel/dma-arc.c4
-rw-r--r--arch/arm/kernel/entry-armv.S152
-rw-r--r--arch/arm/kernel/fiq.c18
-rw-r--r--arch/arm/kernel/head-armo.S1
-rw-r--r--arch/arm/kernel/head-armv.S31
-rw-r--r--arch/arm/kernel/oldlatches.c10
-rw-r--r--arch/arm/kernel/traps.c181
-rw-r--r--arch/arm/kernel/via82c505.c2
-rw-r--r--arch/arm/lib/Makefile32
-rw-r--r--arch/arm/lib/ecard.S47
-rw-r--r--arch/arm/lib/io-acorn.S549
-rw-r--r--arch/arm/lib/io-ebsa110.S169
-rw-r--r--arch/arm/lib/io-footbridge.S202
-rw-r--r--arch/arm/lib/io-pcio.S38
-rw-r--r--arch/arm/lib/io-readsb.S111
-rw-r--r--arch/arm/lib/io-readsl.S65
-rw-r--r--arch/arm/lib/io-readsw-armv3.S102
-rw-r--r--arch/arm/lib/io-readsw-armv4.S87
-rw-r--r--arch/arm/lib/io-writesb.S115
-rw-r--r--arch/arm/lib/io-writesl.S55
-rw-r--r--arch/arm/lib/io-writesw-armv3.S125
-rw-r--r--arch/arm/lib/io-writesw-armv4.S79
-rw-r--r--arch/arm/mach-footbridge/netwinder-hw.c6
-rw-r--r--arch/arm/mm/fault-common.c50
-rw-r--r--arch/arm/mm/init.c45
-rw-r--r--arch/arm/mm/mm-armv.c2
-rw-r--r--arch/arm/mm/proc-arm720.S35
-rw-r--r--arch/arm/nwfpe/double_cpdo.c4
-rw-r--r--arch/arm/nwfpe/extended_cpdo.c2
-rw-r--r--arch/arm/nwfpe/fpa11_cpdo.c2
-rw-r--r--arch/arm/nwfpe/fpa11_cpdt.c6
-rw-r--r--arch/arm/nwfpe/fpa11_cprt.c20
-rw-r--r--arch/arm/nwfpe/fpmodule.c15
-rw-r--r--arch/arm/nwfpe/softfloat.c7
-rw-r--r--arch/arm/tools/mach-types23
-rw-r--r--arch/arm/vmlinux-armo.lds.in1
-rw-r--r--arch/arm/vmlinux-armv.lds.in1
-rw-r--r--arch/i386/boot/setup.S12
-rw-r--r--arch/i386/config.in2
-rw-r--r--arch/i386/defconfig53
-rw-r--r--arch/i386/kernel/apic.c118
-rw-r--r--arch/i386/kernel/apm.c188
-rw-r--r--arch/i386/kernel/dmi_scan.c182
-rw-r--r--arch/i386/kernel/head.S2
-rw-r--r--arch/i386/kernel/i386_ksyms.c2
-rw-r--r--arch/i386/kernel/irq.c2
-rw-r--r--arch/i386/kernel/microcode.c122
-rw-r--r--arch/i386/kernel/mtrr.c378
-rw-r--r--arch/i386/kernel/pci-irq.c128
-rw-r--r--arch/i386/kernel/process.c4
-rw-r--r--arch/i386/kernel/setup.c59
-rw-r--r--arch/i386/kernel/smpboot.c8
-rw-r--r--arch/i386/kernel/traps.c12
-rw-r--r--arch/i386/mm/init.c8
-rw-r--r--arch/ia64/kernel/irq.c2
-rw-r--r--arch/ia64/mm/init.c6
-rw-r--r--arch/m68k/amiga/amiga_ksyms.c1
-rw-r--r--arch/m68k/amiga/amiints.c66
-rw-r--r--arch/m68k/amiga/amisound.c10
-rw-r--r--arch/m68k/amiga/chipram.c216
-rw-r--r--arch/m68k/amiga/cia.c7
-rw-r--r--arch/m68k/amiga/config.c56
-rw-r--r--arch/m68k/atari/atakeyb.c17
-rw-r--r--arch/m68k/atari/config.c4
-rw-r--r--arch/m68k/atari/stram.c485
-rw-r--r--arch/m68k/fpsp040/bindec.S2
-rw-r--r--arch/m68k/fpsp040/decbin.S6
-rw-r--r--arch/m68k/fpsp040/do_func.S2
-rw-r--r--arch/m68k/fpsp040/get_op.S2
-rw-r--r--arch/m68k/fpsp040/util.S8
-rw-r--r--arch/m68k/fpsp040/x_store.S2
-rw-r--r--arch/m68k/ifpsp060/os.S68
-rw-r--r--arch/m68k/kernel/entry.S21
-rw-r--r--arch/m68k/kernel/ints.c8
-rw-r--r--arch/m68k/kernel/m68k_defs.c1
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c2
-rw-r--r--arch/m68k/kernel/ptrace.c22
-rw-r--r--arch/m68k/kernel/setup.c2
-rw-r--r--arch/m68k/kernel/signal.c2
-rw-r--r--arch/m68k/kernel/sys_m68k.c6
-rw-r--r--arch/m68k/kernel/traps.c241
-rw-r--r--arch/m68k/lib/Makefile2
-rw-r--r--arch/m68k/lib/muldi3.c63
-rw-r--r--arch/m68k/mac/baboon.c2
-rw-r--r--arch/m68k/mac/config.c156
-rw-r--r--arch/m68k/mac/macints.c2
-rw-r--r--arch/m68k/mac/oss.c1
-rw-r--r--arch/m68k/mac/psc.c2
-rw-r--r--arch/m68k/mac/via.c1
-rw-r--r--arch/m68k/mm/fault.c164
-rw-r--r--arch/m68k/mvme147/config.c37
-rw-r--r--arch/m68k/q40/README20
-rw-r--r--arch/m68k/q40/config.c87
-rw-r--r--arch/m68k/q40/q40ints.c308
-rw-r--r--arch/mips/Makefile4
-rw-r--r--arch/mips/arc/Makefile12
-rw-r--r--arch/mips/defconfig2
-rw-r--r--arch/mips/defconfig-atlas4
-rw-r--r--arch/mips/defconfig-cp70002
-rw-r--r--arch/mips/defconfig-ddb54762
-rw-r--r--arch/mips/defconfig-decstation2
-rw-r--r--arch/mips/defconfig-ev641202
-rw-r--r--arch/mips/defconfig-ev961002
-rw-r--r--arch/mips/defconfig-ip222
-rw-r--r--arch/mips/defconfig-malta5
-rw-r--r--arch/mips/defconfig-rm2002
-rw-r--r--arch/mips/kernel/Makefile93
-rw-r--r--arch/mips/kernel/irixsig.c2
-rw-r--r--arch/mips/kernel/traps.c13
-rw-r--r--arch/mips/lib/Makefile25
-rw-r--r--arch/mips/mm/Makefile50
-rw-r--r--arch/mips/sgi/kernel/Makefile13
-rw-r--r--arch/mips64/arc/Makefile12
-rw-r--r--arch/mips64/defconfig2
-rw-r--r--arch/mips64/defconfig-ip222
-rw-r--r--arch/mips64/defconfig-ip272
-rw-r--r--arch/mips64/kernel/traps.c13
-rw-r--r--arch/mips64/lib/Makefile5
-rw-r--r--arch/mips64/mm/Makefile31
-rw-r--r--arch/mips64/sgi-ip22/Makefile8
-rw-r--r--arch/mips64/sgi-ip27/Makefile9
-rw-r--r--arch/mips64/tools/Makefile1
-rw-r--r--arch/parisc/Makefile91
-rw-r--r--arch/parisc/config.in208
-rw-r--r--arch/parisc/defconfig363
-rw-r--r--arch/parisc/hpux/Makefile16
-rw-r--r--arch/parisc/hpux/entry_hpux.S537
-rw-r--r--arch/parisc/hpux/fs.c250
-rw-r--r--arch/parisc/hpux/gate.S72
-rw-r--r--arch/parisc/hpux/ioctl.c63
-rw-r--r--arch/parisc/hpux/sys_hpux.c334
-rw-r--r--arch/parisc/hpux/wrappers.S244
-rw-r--r--arch/parisc/kernel/Makefile52
-rw-r--r--arch/parisc/kernel/cache.c253
-rw-r--r--arch/parisc/kernel/ccio-dma.c1209
-rw-r--r--arch/parisc/kernel/ccio-rm-dma.c212
-rw-r--r--arch/parisc/kernel/drivers.c134
-rw-r--r--arch/parisc/kernel/entry.S1867
-rw-r--r--arch/parisc/kernel/hardware.c1446
-rw-r--r--arch/parisc/kernel/head.S156
-rw-r--r--arch/parisc/kernel/hpmc.S319
-rw-r--r--arch/parisc/kernel/init_task.c29
-rw-r--r--arch/parisc/kernel/inventory.c397
-rw-r--r--arch/parisc/kernel/iosapic.c1100
-rw-r--r--arch/parisc/kernel/iosapic_private.h165
-rw-r--r--arch/parisc/kernel/irq.c538
-rw-r--r--arch/parisc/kernel/keyboard.c82
-rw-r--r--arch/parisc/kernel/lasimap.map322
-rw-r--r--arch/parisc/kernel/lba_pci.c1346
-rw-r--r--arch/parisc/kernel/led.c451
-rw-r--r--arch/parisc/kernel/pa7300lc.c54
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c138
-rw-r--r--arch/parisc/kernel/pci-dma.c547
-rw-r--r--arch/parisc/kernel/pci.c535
-rw-r--r--arch/parisc/kernel/pdc.c217
-rw-r--r--arch/parisc/kernel/pdc_cons.c179
-rw-r--r--arch/parisc/kernel/process.c250
-rw-r--r--arch/parisc/kernel/ptrace.c305
-rw-r--r--arch/parisc/kernel/real1.c154
-rw-r--r--arch/parisc/kernel/real2.S274
-rw-r--r--arch/parisc/kernel/sba_iommu.c1752
-rw-r--r--arch/parisc/kernel/semaphore.c239
-rw-r--r--arch/parisc/kernel/setup.c614
-rw-r--r--arch/parisc/kernel/signal.c653
-rw-r--r--arch/parisc/kernel/sys_parisc.c88
-rw-r--r--arch/parisc/kernel/syscall.S563
-rw-r--r--arch/parisc/kernel/time.c98
-rw-r--r--arch/parisc/kernel/traps.c895
-rw-r--r--arch/parisc/lib/Makefile13
-rw-r--r--arch/parisc/lib/bitops.c60
-rw-r--r--arch/parisc/lib/checksum.c130
-rw-r--r--arch/parisc/lib/lusercopy.S242
-rw-r--r--arch/parisc/mm/Makefile13
-rw-r--r--arch/parisc/mm/extable.c69
-rw-r--r--arch/parisc/mm/fault.c283
-rw-r--r--arch/parisc/mm/init.c479
-rw-r--r--arch/parisc/mm/kmap.c143
-rw-r--r--arch/parisc/mm/pa11.c170
-rw-r--r--arch/parisc/mm/pa20.c170
-rw-r--r--arch/parisc/tools/Makefile28
-rw-r--r--arch/parisc/tools/offset.c326
-rw-r--r--arch/parisc/vmlinux.lds79
-rw-r--r--arch/ppc/8260_io/uart.c12
-rw-r--r--arch/ppc/8xx_io/fec.c4
-rw-r--r--arch/ppc/8xx_io/uart.c12
-rw-r--r--arch/ppc/amiga/config.c93
-rw-r--r--arch/ppc/mm/init.c2
-rw-r--r--arch/s390/kernel/traps.c6
-rw-r--r--arch/s390/mm/init.c6
-rw-r--r--arch/sh/kernel/traps.c6
-rw-r--r--arch/sh/mm/init.c6
-rw-r--r--arch/sparc/boot/piggyback.c49
-rw-r--r--arch/sparc/config.in2
-rw-r--r--arch/sparc/kernel/ioport.c7
-rw-r--r--arch/sparc/kernel/pcic.c14
-rw-r--r--arch/sparc/kernel/smp.c1
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c7
-rw-r--r--arch/sparc/kernel/sun4d_smp.c1
-rw-r--r--arch/sparc/kernel/sun4m_smp.c1
-rw-r--r--arch/sparc/kernel/sys_sparc.c25
-rw-r--r--arch/sparc/mm/init.c9
-rw-r--r--arch/sparc/mm/srmmu.c76
-rw-r--r--arch/sparc/mm/sun4c.c79
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c3
-rw-r--r--arch/sparc64/kernel/sys_sparc.c24
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c10
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c2
-rw-r--r--arch/sparc64/kernel/traps.c14
-rw-r--r--arch/sparc64/mm/init.c13
-rw-r--r--arch/sparc64/solaris/ioctl.c2
-rw-r--r--arch/sparc64/solaris/socket.c2
-rw-r--r--drivers/acpi/driver.c4
-rw-r--r--drivers/atm/ambassador.c2
-rw-r--r--drivers/block/DAC960.c22
-rw-r--r--drivers/block/acsi.c2
-rw-r--r--drivers/block/ataflop.c4
-rw-r--r--drivers/block/ll_rw_blk.c206
-rw-r--r--drivers/block/paride/pseudo.h6
-rw-r--r--drivers/block/z2ram.c3
-rw-r--r--drivers/char/Makefile3
-rw-r--r--drivers/char/README.epca2
-rw-r--r--drivers/char/adbmouse.c1
-rw-r--r--drivers/char/amigamouse.c4
-rw-r--r--drivers/char/amikeyb.c19
-rw-r--r--drivers/char/applicom.c2
-rw-r--r--drivers/char/drm/gamma_dma.c2
-rw-r--r--drivers/char/drm/i810_dma.c2
-rw-r--r--drivers/char/drm/mga_dma.c8
-rw-r--r--drivers/char/drm/mga_drv.c2
-rw-r--r--drivers/char/drm/mga_drv.h4
-rw-r--r--drivers/char/epca.c8
-rw-r--r--drivers/char/esp.c11
-rw-r--r--drivers/char/isicom.c15
-rw-r--r--drivers/char/istallion.c23
-rw-r--r--drivers/char/mixcomwd.c2
-rw-r--r--drivers/char/moxa.c19
-rw-r--r--drivers/char/mxser.c29
-rw-r--r--drivers/char/n_r3964.c24
-rw-r--r--drivers/char/q40_keyb.c19
-rw-r--r--drivers/char/rio/host.h2
-rw-r--r--drivers/char/riscom8.c86
-rw-r--r--drivers/char/riscom8.h2
-rw-r--r--drivers/char/scan_keyb.c2
-rw-r--r--drivers/char/serial.c6
-rw-r--r--drivers/char/serial167.c223
-rw-r--r--drivers/char/specialix.c12
-rw-r--r--drivers/char/stallion.c24
-rw-r--r--drivers/char/sx.h2
-rw-r--r--drivers/char/sysrq.c1
-rw-r--r--drivers/char/tpqic02.c2
-rw-r--r--drivers/char/tty_io.c12
-rw-r--r--drivers/char/vme_scc.c16
-rw-r--r--drivers/char/vt.c4
-rw-r--r--drivers/i2o/i2o_lan.c21
-rw-r--r--drivers/ide/buddha.c6
-rw-r--r--drivers/ide/gayle.c10
-rw-r--r--drivers/ide/ide-cd.c6
-rw-r--r--drivers/ide/ide.c8
-rw-r--r--drivers/ide/q40ide.c53
-rw-r--r--drivers/ieee1394/guid.c2
-rw-r--r--drivers/ieee1394/ieee1394_types.h180
-rw-r--r--drivers/ieee1394/ohci1394.c2
-rw-r--r--drivers/ieee1394/pcilynx.c2
-rw-r--r--drivers/ieee1394/raw1394.c4
-rw-r--r--drivers/isdn/avmb1/Makefile72
-rw-r--r--drivers/isdn/avmb1/avm_cs.c14
-rw-r--r--drivers/isdn/avmb1/b1.c34
-rw-r--r--drivers/isdn/avmb1/b1capi.c9
-rw-r--r--drivers/isdn/avmb1/b1dma.c23
-rw-r--r--drivers/isdn/avmb1/b1isa.c28
-rw-r--r--drivers/isdn/avmb1/b1pci.c52
-rw-r--r--drivers/isdn/avmb1/b1pcmcia.c28
-rw-r--r--drivers/isdn/avmb1/c4.c62
-rw-r--r--drivers/isdn/avmb1/capi.c42
-rw-r--r--drivers/isdn/avmb1/capidev.h5
-rw-r--r--drivers/isdn/avmb1/capidrv.c21
-rw-r--r--drivers/isdn/avmb1/capifs.c44
-rw-r--r--drivers/isdn/avmb1/capiutil.c26
-rw-r--r--drivers/isdn/avmb1/kcapi.c77
-rw-r--r--drivers/isdn/avmb1/t1isa.c22
-rw-r--r--drivers/isdn/avmb1/t1pci.c54
-rw-r--r--drivers/isdn/divert/divert_procfs.c2
-rw-r--r--drivers/isdn/hisax/amd7930.c8
-rw-r--r--drivers/isdn/hisax/arcofi.c2
-rw-r--r--drivers/isdn/hisax/asuscom.c9
-rw-r--r--drivers/isdn/hisax/avm_a1.c9
-rw-r--r--drivers/isdn/hisax/avm_a1p.c9
-rw-r--r--drivers/isdn/hisax/avm_pci.c28
-rw-r--r--drivers/isdn/hisax/bkm_a4t.c11
-rw-r--r--drivers/isdn/hisax/bkm_a8.c21
-rw-r--r--drivers/isdn/hisax/bkm_ax.h23
-rw-r--r--drivers/isdn/hisax/callc.c23
-rw-r--r--drivers/isdn/hisax/config.c232
-rw-r--r--drivers/isdn/hisax/diva.c29
-rw-r--r--drivers/isdn/hisax/elsa.c22
-rw-r--r--drivers/isdn/hisax/elsa_ser.c2
-rw-r--r--drivers/isdn/hisax/fsm.c8
-rw-r--r--drivers/isdn/hisax/gazel.c23
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c11
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.c11
-rw-r--r--drivers/isdn/hisax/hfc_pci.c48
-rw-r--r--drivers/isdn/hisax/hfc_sx.c16
-rw-r--r--drivers/isdn/hisax/hfcscard.c9
-rw-r--r--drivers/isdn/hisax/hisax.h36
-rw-r--r--drivers/isdn/hisax/hscx.c21
-rw-r--r--drivers/isdn/hisax/hscx_irq.c2
-rw-r--r--drivers/isdn/hisax/icc.c13
-rw-r--r--drivers/isdn/hisax/isac.c13
-rw-r--r--drivers/isdn/hisax/isar.c7
-rw-r--r--drivers/isdn/hisax/isdnl1.c25
-rw-r--r--drivers/isdn/hisax/isdnl2.c15
-rw-r--r--drivers/isdn/hisax/isdnl3.c35
-rw-r--r--drivers/isdn/hisax/isurf.c9
-rw-r--r--drivers/isdn/hisax/ix1_micro.c9
-rw-r--r--drivers/isdn/hisax/jade.c15
-rw-r--r--drivers/isdn/hisax/jade_irq.c2
-rw-r--r--drivers/isdn/hisax/l3_1tr6.c4
-rw-r--r--drivers/isdn/hisax/l3dss1.c4
-rw-r--r--drivers/isdn/hisax/l3ni1.c50
-rw-r--r--drivers/isdn/hisax/l3ni1.h5
-rw-r--r--drivers/isdn/hisax/mic.c9
-rw-r--r--drivers/isdn/hisax/netjet.c160
-rw-r--r--drivers/isdn/hisax/netjet.h11
-rw-r--r--drivers/isdn/hisax/niccy.c17
-rw-r--r--drivers/isdn/hisax/nj_s.c55
-rw-r--r--drivers/isdn/hisax/nj_u.c56
-rw-r--r--drivers/isdn/hisax/s0box.c9
-rw-r--r--drivers/isdn/hisax/saphir.c9
-rw-r--r--drivers/isdn/hisax/sedlbauer.c17
-rw-r--r--drivers/isdn/hisax/sportster.c13
-rw-r--r--drivers/isdn/hisax/tei.c15
-rw-r--r--drivers/isdn/hisax/teleint.c9
-rw-r--r--drivers/isdn/hisax/teles0.c9
-rw-r--r--drivers/isdn/hisax/teles3.c9
-rw-r--r--drivers/isdn/hisax/telespci.c17
-rw-r--r--drivers/isdn/hisax/w6692.c30
-rw-r--r--drivers/isdn/hysdn/boardergo.c4
-rw-r--r--drivers/isdn/hysdn/hycapi.c4
-rw-r--r--drivers/isdn/hysdn/hysdn_defs.h17
-rw-r--r--drivers/isdn/hysdn/hysdn_init.c24
-rw-r--r--drivers/isdn/hysdn/hysdn_proclog.c2
-rw-r--r--drivers/isdn/hysdn/hysdn_sched.c2
-rw-r--r--drivers/isdn/isdn_cards.c12
-rw-r--r--drivers/isdn/isdn_common.c4
-rw-r--r--drivers/isdn/isdn_common.h2
-rw-r--r--drivers/isdn/isdn_ppp.c4
-rw-r--r--drivers/isdn/isdn_tty.c4
-rw-r--r--drivers/isdn/pcbit/drv.c2
-rw-r--r--drivers/macintosh/mac_keyb.c2
-rw-r--r--drivers/macintosh/via-macii.c1
-rw-r--r--drivers/md/Makefile18
-rw-r--r--drivers/md/linear.c36
-rw-r--r--drivers/md/lvm.c7
-rw-r--r--drivers/md/md.c106
-rw-r--r--drivers/md/raid0.c29
-rw-r--r--drivers/md/raid1.c173
-rw-r--r--drivers/md/raid5.c19
-rw-r--r--drivers/md/xor.c1
-rw-r--r--drivers/media/radio/radio-aimslab.c7
-rw-r--r--drivers/media/radio/radio-aztech.c6
-rw-r--r--drivers/media/radio/radio-cadet.c42
-rw-r--r--drivers/media/radio/radio-gemtek.c7
-rw-r--r--drivers/media/radio/radio-rtrack2.c6
-rw-r--r--drivers/media/radio/radio-sf16fmi.c6
-rw-r--r--drivers/media/radio/radio-terratec.c6
-rw-r--r--drivers/media/radio/radio-trust.c7
-rw-r--r--drivers/media/radio/radio-typhoon.c7
-rw-r--r--drivers/media/radio/radio-zoltrix.c14
-rw-r--r--drivers/media/video/bttv-cards.c18
-rw-r--r--drivers/media/video/bttv-driver.c18
-rw-r--r--drivers/media/video/bw-qcam.c5
-rw-r--r--drivers/media/video/c-qcam.c5
-rw-r--r--drivers/media/video/msp3400.c2
-rw-r--r--drivers/media/video/tvaudio.c3
-rw-r--r--drivers/media/video/zr36120.h2
-rw-r--r--drivers/mtd/Config.in45
-rw-r--r--drivers/mtd/Makefile8
-rw-r--r--drivers/mtd/cfi_cmdset_0002.c2
-rw-r--r--drivers/mtd/doc1000.c71
-rw-r--r--drivers/mtd/doc2000.c1101
-rw-r--r--drivers/mtd/doc2001.c356
-rw-r--r--drivers/mtd/docecc.c522
-rw-r--r--drivers/mtd/docprobe.c97
-rw-r--r--drivers/mtd/ftl.c24
-rw-r--r--drivers/mtd/map_ram.c13
-rw-r--r--drivers/mtd/map_rom.c46
-rw-r--r--drivers/mtd/mtdblock.c677
-rw-r--r--drivers/mtd/mtdchar.c195
-rw-r--r--drivers/mtd/mtdcore.c158
-rw-r--r--drivers/mtd/mtdpart.c228
-rw-r--r--drivers/mtd/nftl.c1263
-rw-r--r--drivers/mtd/nftlmount.c678
-rw-r--r--drivers/mtd/nora.c50
-rw-r--r--drivers/mtd/octagon-5066.c57
-rw-r--r--drivers/mtd/physmap.c38
-rw-r--r--drivers/mtd/pmc551.c344
-rw-r--r--drivers/mtd/pnc2000.c140
-rw-r--r--drivers/mtd/rpxlite.c105
-rw-r--r--drivers/mtd/vmax301.c61
-rw-r--r--drivers/net/3c503.c14
-rw-r--r--drivers/net/3c505.h2
-rw-r--r--drivers/net/8139too.c230
-rw-r--r--drivers/net/8390.c123
-rw-r--r--drivers/net/acenic.c2
-rw-r--r--drivers/net/aironet4500.h2
-rw-r--r--drivers/net/aironet4500_core.c2
-rw-r--r--drivers/net/apne.c15
-rw-r--r--drivers/net/appletalk/cops.c68
-rw-r--r--drivers/net/appletalk/ipddp.c19
-rw-r--r--drivers/net/appletalk/ltpc.c34
-rw-r--r--drivers/net/arlan.c2
-rw-r--r--drivers/net/arlan.h6
-rw-r--r--drivers/net/daynaport.c2
-rw-r--r--drivers/net/dgrs.c16
-rw-r--r--drivers/net/dmfe.c14
-rw-r--r--drivers/net/dummy.c23
-rw-r--r--drivers/net/e2100.c19
-rw-r--r--drivers/net/eepro.c9
-rw-r--r--drivers/net/eepro100.c238
-rw-r--r--drivers/net/eexpress.c24
-rw-r--r--drivers/net/eql.c14
-rw-r--r--drivers/net/es3210.c22
-rw-r--r--drivers/net/eth16i.c8
-rw-r--r--drivers/net/ethertap.c9
-rw-r--r--drivers/net/ewrk3.c17
-rw-r--r--drivers/net/fmv18x.c6
-rw-r--r--drivers/net/hamachi.c12
-rw-r--r--drivers/net/hamradio/6pack.h3
-rw-r--r--drivers/net/hamradio/baycom_epp.c3
-rw-r--r--drivers/net/hamradio/hdlcdrv.c21
-rw-r--r--drivers/net/hamradio/mkiss.h3
-rw-r--r--drivers/net/hp-plus.c20
-rw-r--r--drivers/net/hp.c26
-rw-r--r--drivers/net/hp100.c15
-rw-r--r--drivers/net/hplance.c3
-rw-r--r--drivers/net/ibmlana.c28
-rw-r--r--drivers/net/irda/irtty.c2
-rw-r--r--drivers/net/irda/nsc-ircc.c14
-rw-r--r--drivers/net/isa-skeleton.c18
-rw-r--r--drivers/net/lance.c1
-rw-r--r--drivers/net/lasi_82596.c1549
-rw-r--r--drivers/net/lne390.c26
-rw-r--r--drivers/net/mvme147.c6
-rw-r--r--drivers/net/natsemi.c11
-rw-r--r--drivers/net/ne.c6
-rw-r--r--drivers/net/ne2.c4
-rw-r--r--drivers/net/ne2k-pci.c11
-rw-r--r--drivers/net/ne3210.c4
-rw-r--r--drivers/net/pcnet32.c44
-rw-r--r--drivers/net/plip.c9
-rw-r--r--drivers/net/ppp_generic.c2
-rw-r--r--drivers/net/pppoe.c9
-rw-r--r--drivers/net/rclanmtl.c2
-rw-r--r--drivers/net/sb1000.c17
-rw-r--r--drivers/net/setup.c9
-rw-r--r--drivers/net/shaper.c136
-rw-r--r--drivers/net/sis900.c13
-rw-r--r--drivers/net/sk_mca.c7
-rw-r--r--drivers/net/slip.c4
-rw-r--r--drivers/net/slip.h2
-rw-r--r--drivers/net/smc-mca.c26
-rw-r--r--drivers/net/smc-ultra.c7
-rw-r--r--drivers/net/smc-ultra32.c84
-rw-r--r--drivers/net/smc9194.c167
-rw-r--r--drivers/net/sundance.c12
-rw-r--r--drivers/net/sunhme.c8
-rw-r--r--drivers/net/tlan.c6
-rw-r--r--drivers/net/tokenring/abyss.c316
-rw-r--r--drivers/net/tokenring/olympic.c7
-rw-r--r--drivers/net/tokenring/tms380tr_microcode.h2
-rw-r--r--drivers/net/tokenring/tmspci.c326
-rw-r--r--drivers/net/tulip/eeprom.c1
-rw-r--r--drivers/net/tulip/tulip_core.c8
-rw-r--r--drivers/net/tun.c4
-rw-r--r--drivers/net/via-rhine.c13
-rw-r--r--drivers/net/wan/comx-hw-mixcom.c2
-rw-r--r--drivers/net/wan/comx.h4
-rw-r--r--drivers/net/wan/sdlamain.c24
-rw-r--r--drivers/net/wan/x25_asy.h2
-rw-r--r--drivers/net/wd.c16
-rw-r--r--drivers/net/winbond-840.c12
-rw-r--r--drivers/net/yellowfin.c54
-rw-r--r--drivers/nubus/nubus.c9
-rw-r--r--drivers/parport/ChangeLog6
-rw-r--r--drivers/parport/Makefile1
-rw-r--r--drivers/parport/parport_amiga.c108
-rw-r--r--drivers/parport/parport_atari.c68
-rw-r--r--drivers/parport/parport_gsc.c573
-rw-r--r--drivers/parport/parport_mfc3.c106
-rw-r--r--drivers/parport/parport_pc.c8
-rw-r--r--drivers/pci/pci.c84
-rw-r--r--drivers/pci/setup-bus.c317
-rw-r--r--drivers/pci/setup-res.c91
-rw-r--r--drivers/pnp/isapnp.c46
-rw-r--r--drivers/s390/net/ctc.c2
-rw-r--r--drivers/sbus/audio/dmy.c2
-rw-r--r--drivers/sbus/char/aurora.c20
-rw-r--r--drivers/sbus/char/sab82532.c16
-rw-r--r--drivers/scsi/Makefile4
-rw-r--r--drivers/scsi/a2091.c2
-rw-r--r--drivers/scsi/a2091.h1
-rw-r--r--drivers/scsi/a3000.c21
-rw-r--r--drivers/scsi/a3000.h3
-rw-r--r--drivers/scsi/aha1542.c11
-rw-r--r--drivers/scsi/atari_scsi.c2
-rw-r--r--drivers/scsi/eata.c287
-rw-r--r--drivers/scsi/eata.h11
-rw-r--r--drivers/scsi/gvp11.c2
-rw-r--r--drivers/scsi/ide-scsi.c2
-rw-r--r--drivers/scsi/imm.c21
-rw-r--r--drivers/scsi/imm.h5
-rw-r--r--drivers/scsi/ips.h2
-rw-r--r--drivers/scsi/megaraid.c3
-rw-r--r--drivers/scsi/mvme147.c116
-rw-r--r--drivers/scsi/mvme147.h50
-rw-r--r--drivers/scsi/ppa.c18
-rw-r--r--drivers/scsi/ppa.h5
-rw-r--r--drivers/scsi/qla1280.c9
-rw-r--r--drivers/scsi/u14-34f.c284
-rw-r--r--drivers/scsi/u14-34f.h13
-rw-r--r--drivers/scsi/wd33c93.c75
-rw-r--r--drivers/scsi/wd33c93.h3
-rw-r--r--drivers/sound/Config.in5
-rw-r--r--drivers/sound/Makefile1
-rw-r--r--drivers/sound/ac97_codec.c42
-rw-r--r--drivers/sound/cs4281.c2
-rw-r--r--drivers/sound/cs461x_image.h3775
-rw-r--r--drivers/sound/cs46xx.c2928
-rw-r--r--drivers/sound/dmasound/dmasound_atari.c2
-rw-r--r--drivers/sound/dmasound/dmasound_paula.c2
-rw-r--r--drivers/sound/es1370.c15
-rw-r--r--drivers/sound/es1371.c15
-rw-r--r--drivers/sound/esssolo1.c13
-rw-r--r--drivers/sound/maestro.c42
-rw-r--r--drivers/sound/sonicvibes.c13
-rw-r--r--drivers/sound/sound_core.c7
-rw-r--r--drivers/sound/vwsnd.c2
-rw-r--r--drivers/sound/ymfpci.c2385
-rw-r--r--drivers/sound/ymfpci.h343
-rw-r--r--drivers/sound/ymfpci_image.h1565
-rw-r--r--drivers/usb/Config.in74
-rw-r--r--drivers/usb/acm.c183
-rw-r--r--drivers/usb/audio.c53
-rw-r--r--drivers/usb/bluetooth.c30
-rw-r--r--drivers/usb/hid.c5
-rw-r--r--drivers/usb/hub.h4
-rw-r--r--drivers/usb/plusb.c25
-rw-r--r--drivers/usb/printer.c76
-rw-r--r--drivers/usb/scanner.c3
-rw-r--r--drivers/usb/serial/Config.in30
-rw-r--r--drivers/usb/serial/Makefile2
-rw-r--r--drivers/usb/serial/digi_acceleport.c8
-rw-r--r--drivers/usb/serial/empeg.c648
-rw-r--r--drivers/usb/serial/ftdi_sio.c358
-rw-r--r--drivers/usb/serial/ftdi_sio.h42
-rw-r--r--drivers/usb/serial/keyspan.c1696
-rw-r--r--drivers/usb/serial/keyspan.h290
-rw-r--r--drivers/usb/serial/keyspan_pda.c21
-rw-r--r--drivers/usb/serial/keyspan_usa26msg.h28
-rw-r--r--drivers/usb/serial/keyspan_usa28msg.h28
-rw-r--r--drivers/usb/serial/keyspan_usa49msg.h255
-rw-r--r--drivers/usb/serial/keyspan_usa49w_fw.h457
-rw-r--r--drivers/usb/serial/mct_u232.c774
-rw-r--r--drivers/usb/serial/mct_u232.h362
-rw-r--r--drivers/usb/serial/usbserial.c5
-rw-r--r--drivers/usb/serial/visor.c14
-rw-r--r--drivers/usb/storage/freecom.c18
-rw-r--r--drivers/usb/storage/protocol.c6
-rw-r--r--drivers/usb/storage/scsiglue.c8
-rw-r--r--drivers/usb/storage/sddr09.c28
-rw-r--r--drivers/usb/storage/shuttle_usbat.c24
-rw-r--r--drivers/usb/storage/transport.c381
-rw-r--r--drivers/usb/storage/usb.c62
-rw-r--r--drivers/usb/storage/usb.h5
-rw-r--r--drivers/usb/uhci.c174
-rw-r--r--drivers/usb/usb-uhci.c480
-rw-r--r--drivers/usb/usb.c26
-rw-r--r--drivers/usb/wacom.c49
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/amifb.c90
-rw-r--r--drivers/video/atafb.c17
-rw-r--r--drivers/video/aty128fb.c21
-rw-r--r--drivers/video/atyfb.c19
-rw-r--r--drivers/video/dummycon.c3
-rw-r--r--drivers/video/fbcon-sti.c330
-rw-r--r--drivers/video/fbmem.c5
-rw-r--r--drivers/video/macmodes.c2
-rw-r--r--drivers/video/mdacon.c18
-rw-r--r--drivers/video/platinumfb.c24
-rw-r--r--drivers/video/sti-bmode.h287
-rw-r--r--drivers/video/sti.h289
-rw-r--r--drivers/video/sticon-bmode.c906
-rw-r--r--drivers/video/sticon.c229
-rw-r--r--drivers/video/sticore.c598
-rw-r--r--drivers/video/stifb.c230
-rw-r--r--drivers/video/tdfxfb.c42
-rw-r--r--drivers/video/vgacon.c2
-rw-r--r--fs/adfs/inode.c2
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/bfs/inode.c1
-rw-r--r--fs/binfmt_elf.c6
-rw-r--r--fs/buffer.c445
-rw-r--r--fs/dquot.c4
-rw-r--r--fs/exec.c2
-rw-r--r--fs/ext2/fsync.c130
-rw-r--r--fs/ext2/ialloc.c60
-rw-r--r--fs/ext2/inode.c12
-rw-r--r--fs/ext2/namei.c34
-rw-r--r--fs/fat/inode.c2
-rw-r--r--fs/file.c4
-rw-r--r--fs/file_table.c2
-rw-r--r--fs/hfs/inode.c2
-rw-r--r--fs/hpfs/buffer.c4
-rw-r--r--fs/hpfs/file.c2
-rw-r--r--fs/inode.c81
-rw-r--r--fs/isofs/dir.c10
-rw-r--r--fs/isofs/inode.c257
-rw-r--r--fs/isofs/namei.c20
-rw-r--r--fs/isofs/rock.c47
-rw-r--r--fs/isofs/util.c2
-rw-r--r--fs/lockd/clntproc.c2
-rw-r--r--fs/locks.c13
-rw-r--r--fs/minix/inode.c2
-rw-r--r--fs/namei.c22
-rw-r--r--fs/ncpfs/Config.in2
-rw-r--r--fs/ncpfs/ioctl.c4
-rw-r--r--fs/ncpfs/ncplib_kernel.h6
-rw-r--r--fs/nfs/dir.c189
-rw-r--r--fs/nfs/file.c19
-rw-r--r--fs/nfs/inode.c242
-rw-r--r--fs/nfs/nfs3proc.c127
-rw-r--r--fs/nfs/proc.c87
-rw-r--r--fs/nfs/read.c65
-rw-r--r--fs/nfs/symlink.c16
-rw-r--r--fs/nfs/write.c152
-rw-r--r--fs/ntfs/fs.c26
-rw-r--r--fs/proc/generic.c3
-rw-r--r--fs/proc/root.c1
-rw-r--r--fs/qnx4/inode.c2
-rw-r--r--fs/ramfs/inode.c2
-rw-r--r--fs/readdir.c1
-rw-r--r--fs/smbfs/dir.c6
-rw-r--r--fs/smbfs/file.c54
-rw-r--r--fs/smbfs/inode.c18
-rw-r--r--fs/smbfs/proc.c21
-rw-r--r--fs/smbfs/sock.c4
-rw-r--r--fs/stat.c8
-rw-r--r--fs/super.c10
-rw-r--r--fs/sysv/inode.c2
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/udf/inode.c4
-rw-r--r--fs/ufs/inode.c2
-rw-r--r--include/asm-alpha/bitops.h153
-rw-r--r--include/asm-alpha/byteorder.h38
-rw-r--r--include/asm-alpha/fpu.h33
-rw-r--r--include/asm-alpha/pgtable.h19
-rw-r--r--include/asm-arm/arch-arc/memory.h6
-rw-r--r--include/asm-arm/arch-arc/processor.h31
-rw-r--r--include/asm-arm/arch-cl7500/memory.h6
-rw-r--r--include/asm-arm/arch-cl7500/processor.h27
-rw-r--r--include/asm-arm/arch-ebsa285/hardware.h7
-rw-r--r--include/asm-arm/arch-ebsa285/memory.h6
-rw-r--r--include/asm-arm/arch-ebsa285/processor.h30
-rw-r--r--include/asm-arm/arch-l7200/hardware.h3
-rw-r--r--include/asm-arm/arch-l7200/memory.h6
-rw-r--r--include/asm-arm/arch-l7200/processor.h27
-rw-r--r--include/asm-arm/arch-nexuspci/memory.h6
-rw-r--r--include/asm-arm/arch-nexuspci/processor.h27
-rw-r--r--include/asm-arm/arch-rpc/memory.h6
-rw-r--r--include/asm-arm/arch-rpc/processor.h31
-rw-r--r--include/asm-arm/arch-rpc/uncompress.h20
-rw-r--r--include/asm-arm/arch-shark/memory.h6
-rw-r--r--include/asm-arm/arch-shark/processor.h28
-rw-r--r--include/asm-arm/arch-tbox/memory.h6
-rw-r--r--include/asm-arm/arch-tbox/processor.h24
-rw-r--r--include/asm-arm/bitops.h3
-rw-r--r--include/asm-arm/hardware.h6
-rw-r--r--include/asm-arm/pci.h5
-rw-r--r--include/asm-arm/proc-armo/processor.h2
-rw-r--r--include/asm-arm/proc-armv/processor.h6
-rw-r--r--include/asm-arm/proc-armv/ptrace.h6
-rw-r--r--include/asm-arm/proc-armv/system.h71
-rw-r--r--include/asm-arm/processor.h27
-rw-r--r--include/asm-arm/system.h11
-rw-r--r--include/asm-generic/bitops.h8
-rw-r--r--include/asm-generic/pgtable.h2
-rw-r--r--include/asm-i386/apic.h2
-rw-r--r--include/asm-i386/hardirq.h2
-rw-r--r--include/asm-i386/msr.h4
-rw-r--r--include/asm-i386/mtrr.h18
-rw-r--r--include/asm-i386/page.h2
-rw-r--r--include/asm-i386/pgtable.h2
-rw-r--r--include/asm-i386/processor.h3
-rw-r--r--include/asm-i386/spinlock.h2
-rw-r--r--include/asm-ia64/hardirq.h2
-rw-r--r--include/asm-m68k/amigahw.h24
-rw-r--r--include/asm-m68k/amigaints.h6
-rw-r--r--include/asm-m68k/amipcmcia.h6
-rw-r--r--include/asm-m68k/atari_stram.h10
-rw-r--r--include/asm-m68k/atarihw.h2
-rw-r--r--include/asm-m68k/bitops.h6
-rw-r--r--include/asm-m68k/entry.h14
-rw-r--r--include/asm-m68k/fcntl.h12
-rw-r--r--include/asm-m68k/keyboard.h30
-rw-r--r--include/asm-m68k/machdep.h1
-rw-r--r--include/asm-m68k/mman.h6
-rw-r--r--include/asm-m68k/motorola_pgalloc.h260
-rw-r--r--include/asm-m68k/motorola_pgtable.h266
-rw-r--r--include/asm-m68k/page.h2
-rw-r--r--include/asm-m68k/param.h4
-rw-r--r--include/asm-m68k/parport.h23
-rw-r--r--include/asm-m68k/pgalloc.h263
-rw-r--r--include/asm-m68k/pgtable.h318
-rw-r--r--include/asm-m68k/processor.h3
-rw-r--r--include/asm-m68k/q40_keyboard.h2
-rw-r--r--include/asm-m68k/q40_master.h41
-rw-r--r--include/asm-m68k/q40ints.h2
-rw-r--r--include/asm-m68k/siginfo.h22
-rw-r--r--include/asm-m68k/softirq.h12
-rw-r--r--include/asm-m68k/spinlock.h2
-rw-r--r--include/asm-m68k/stat.h12
-rw-r--r--include/asm-m68k/sun3_pgalloc.h274
-rw-r--r--include/asm-m68k/sun3_pgtable.h219
-rw-r--r--include/asm-m68k/system.h15
-rw-r--r--include/asm-m68k/types.h4
-rw-r--r--include/asm-m68k/unistd.h5
-rw-r--r--include/asm-parisc/a.out.h29
-rw-r--r--include/asm-parisc/asmregs.h183
-rw-r--r--include/asm-parisc/assembly.h374
-rw-r--r--include/asm-parisc/atomic.h103
-rw-r--r--include/asm-parisc/bitops.h247
-rw-r--r--include/asm-parisc/bootdata.h16
-rw-r--r--include/asm-parisc/bugs.h19
-rw-r--r--include/asm-parisc/byteorder.h75
-rw-r--r--include/asm-parisc/cache.h58
-rw-r--r--include/asm-parisc/checksum.h174
-rw-r--r--include/asm-parisc/current.h19
-rw-r--r--include/asm-parisc/delay.h45
-rw-r--r--include/asm-parisc/div64.h54
-rw-r--r--include/asm-parisc/elf.h97
-rw-r--r--include/asm-parisc/errno.h147
-rw-r--r--include/asm-parisc/fcntl.h90
-rw-r--r--include/asm-parisc/fixmap.h8
-rw-r--r--include/asm-parisc/gsc.h79
-rw-r--r--include/asm-parisc/hardirq.h87
-rw-r--r--include/asm-parisc/hardware.h103
-rw-r--r--include/asm-parisc/hdreg.h6
-rw-r--r--include/asm-parisc/hil.h26
-rw-r--r--include/asm-parisc/hw_irq.h17
-rw-r--r--include/asm-parisc/ide.h111
-rw-r--r--include/asm-parisc/io.h61
-rw-r--r--include/asm-parisc/ioctl.h67
-rw-r--r--include/asm-parisc/ioctls.h82
-rw-r--r--include/asm-parisc/iosapic.h53
-rw-r--r--include/asm-parisc/ipcbuf.h11
-rw-r--r--include/asm-parisc/irq.h89
-rw-r--r--include/asm-parisc/keyboard.h67
-rw-r--r--include/asm-parisc/led.h33
-rw-r--r--include/asm-parisc/linux_logo.h48
-rw-r--r--include/asm-parisc/machdep.h16
-rw-r--r--include/asm-parisc/mc146818rtc.h9
-rw-r--r--include/asm-parisc/md.h13
-rw-r--r--include/asm-parisc/mman.h52
-rw-r--r--include/asm-parisc/mmu.h64
-rw-r--r--include/asm-parisc/mmu_context.h67
-rw-r--r--include/asm-parisc/msgbuf.h31
-rw-r--r--include/asm-parisc/namei.h17
-rw-r--r--include/asm-parisc/page.h86
-rw-r--r--include/asm-parisc/param.h24
-rw-r--r--include/asm-parisc/parport.h18
-rw-r--r--include/asm-parisc/parport_gsc.h193
-rw-r--r--include/asm-parisc/pci.h215
-rw-r--r--include/asm-parisc/pdc.h629
-rw-r--r--include/asm-parisc/pdcpat.h247
-rw-r--r--include/asm-parisc/pgalloc.h404
-rw-r--r--include/asm-parisc/pgtable.h337
-rw-r--r--include/asm-parisc/poll.h25
-rw-r--r--include/asm-parisc/posix_types.h140
-rw-r--r--include/asm-parisc/processor.h341
-rw-r--r--include/asm-parisc/psw.h54
-rw-r--r--include/asm-parisc/ptrace.h56
-rw-r--r--include/asm-parisc/real.h5
-rw-r--r--include/asm-parisc/resource.h47
-rw-r--r--include/asm-parisc/runway.h9
-rw-r--r--include/asm-parisc/scatterlist.h20
-rw-r--r--include/asm-parisc/segment.h6
-rw-r--r--include/asm-parisc/semaphore-helper.h89
-rw-r--r--include/asm-parisc/semaphore.h301
-rw-r--r--include/asm-parisc/sembuf.h25
-rw-r--r--include/asm-parisc/serial.h47
-rw-r--r--include/asm-parisc/setup.h10
-rw-r--r--include/asm-parisc/shmbuf.h50
-rw-r--r--include/asm-parisc/shmparam.h6
-rw-r--r--include/asm-parisc/sigcontext.h20
-rw-r--r--include/asm-parisc/siginfo.h234
-rw-r--r--include/asm-parisc/signal.h163
-rw-r--r--include/asm-parisc/smp.h10
-rw-r--r--include/asm-parisc/smplock.h49
-rw-r--r--include/asm-parisc/socket.h59
-rw-r--r--include/asm-parisc/sockios.h12
-rw-r--r--include/asm-parisc/softirq.h15
-rw-r--r--include/asm-parisc/som.h8
-rw-r--r--include/asm-parisc/spinlock.h95
-rw-r--r--include/asm-parisc/stat.h71
-rw-r--r--include/asm-parisc/statfs.h25
-rw-r--r--include/asm-parisc/string.h2
-rw-r--r--include/asm-parisc/system.h148
-rw-r--r--include/asm-parisc/termbits.h174
-rw-r--r--include/asm-parisc/termios.h103
-rw-r--r--include/asm-parisc/timex.h21
-rw-r--r--include/asm-parisc/traps.h4
-rw-r--r--include/asm-parisc/types.h54
-rw-r--r--include/asm-parisc/uaccess.h189
-rw-r--r--include/asm-parisc/ucontext.h12
-rw-r--r--include/asm-parisc/unaligned.h20
-rw-r--r--include/asm-parisc/unistd.h901
-rw-r--r--include/asm-parisc/user.h5
-rw-r--r--include/asm-sh/page.h2
-rw-r--r--include/asm-sparc/atops.h24
-rw-r--r--include/asm-sparc/hdreg.h4
-rw-r--r--include/asm-sparc/processor.h3
-rw-r--r--include/asm-sparc64/pgalloc.h11
-rw-r--r--include/asm-sparc64/processor.h3
-rw-r--r--include/linux/agpgart.h2
-rw-r--r--include/linux/apm_bios.h20
-rw-r--r--include/linux/atmdev.h2
-rw-r--r--include/linux/bfs_fs.h2
-rw-r--r--include/linux/bfs_fs_i.h2
-rw-r--r--include/linux/bfs_fs_sb.h2
-rw-r--r--include/linux/compatmac.h1
-rw-r--r--include/linux/ext2_fs.h3
-rw-r--r--include/linux/fs.h45
-rw-r--r--include/linux/hdlcdrv.h2
-rw-r--r--include/linux/highmem.h4
-rw-r--r--include/linux/highuid.h28
-rw-r--r--include/linux/icmp.h5
-rw-r--r--include/linux/ioport.h7
-rw-r--r--include/linux/isdn.h4
-rw-r--r--include/linux/isdnif.h4
-rw-r--r--include/linux/iso_fs.h2
-rw-r--r--include/linux/kernel.h17
-rw-r--r--include/linux/kernelcapi.h2
-rw-r--r--include/linux/mm.h10
-rw-r--r--include/linux/module.h4
-rw-r--r--include/linux/mtd/cfi.h3
-rw-r--r--include/linux/mtd/doc2000.h34
-rw-r--r--include/linux/mtd/map.h19
-rw-r--r--include/linux/mtd/mtd.h50
-rw-r--r--include/linux/mtd/nand.h169
-rw-r--r--include/linux/mtd/nand_ids.h52
-rw-r--r--include/linux/mtd/nftl.h44
-rw-r--r--include/linux/mtd/partitions.h50
-rw-r--r--include/linux/mtd/pmc551.h52
-rw-r--r--include/linux/netdevice.h26
-rw-r--r--include/linux/nfs_fs.h18
-rw-r--r--include/linux/nfs_fs_i.h7
-rw-r--r--include/linux/nfs_page.h3
-rw-r--r--include/linux/nfs_xdr.h40
-rw-r--r--include/linux/pci.h7
-rw-r--r--include/linux/pci_ids.h201
-rw-r--r--include/linux/raid/md_k.h5
-rw-r--r--include/linux/raid/raid0.h2
-rw-r--r--include/linux/raid/raid1.h1
-rw-r--r--include/linux/sched.h64
-rw-r--r--include/linux/signal.h4
-rw-r--r--include/linux/skbuff.h6
-rw-r--r--include/linux/smb_fs.h4
-rw-r--r--include/linux/smb_fs_sb.h5
-rw-r--r--include/linux/spinlock.h4
-rw-r--r--include/linux/stallion.h2
-rw-r--r--include/linux/sunrpc/sched.h2
-rw-r--r--include/linux/sunrpc/xprt.h15
-rw-r--r--include/linux/swap.h2
-rw-r--r--include/linux/tqueue.h65
-rw-r--r--include/linux/tty.h1
-rw-r--r--include/linux/usb.h6
-rw-r--r--include/linux/wanrouter.h2
-rw-r--r--include/net/checksum.h23
-rw-r--r--include/net/icmp.h5
-rw-r--r--include/net/ipx.h2
-rw-r--r--include/net/sock.h6
-rw-r--r--include/net/tcp.h49
-rw-r--r--include/video/fbcon.h28
-rw-r--r--init/main.c21
-rw-r--r--ipc/shm.c301
-rw-r--r--kernel/Makefile7
-rw-r--r--kernel/context.c143
-rw-r--r--kernel/dma.c1
-rw-r--r--kernel/exit.c12
-rw-r--r--kernel/fork.c9
-rw-r--r--kernel/kmod.c121
-rw-r--r--kernel/ksyms.c4
-rw-r--r--kernel/module.c13
-rw-r--r--kernel/sched.c24
-rw-r--r--kernel/sysctl.c2
-rw-r--r--kernel/timer.c3
-rw-r--r--kernel/user.c26
-rw-r--r--lib/vsprintf.c32
-rw-r--r--mm/filemap.c86
-rw-r--r--mm/highmem.c71
-rw-r--r--mm/memory.c62
-rw-r--r--mm/mmap.c17
-rw-r--r--mm/mprotect.c1
-rw-r--r--mm/mremap.c2
-rw-r--r--mm/page_alloc.c4
-rw-r--r--mm/swap.c30
-rw-r--r--mm/swap_state.c10
-rw-r--r--mm/vmalloc.c2
-rw-r--r--mm/vmscan.c82
-rw-r--r--net/802/fddi.c7
-rw-r--r--net/atm/proc.c2
-rw-r--r--net/core/dev.c111
-rw-r--r--net/core/dst.c3
-rw-r--r--net/core/dv.c2
-rw-r--r--net/core/neighbour.c39
-rw-r--r--net/core/skbuff.c14
-rw-r--r--net/decnet/dn_nsp_in.c6
-rw-r--r--net/decnet/dn_route.c5
-rw-r--r--net/ipv4/devinet.c5
-rw-r--r--net/ipv4/ip_fragment.c34
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_input.c8
-rw-r--r--net/ipv4/ip_sockglue.c6
-rw-r--r--net/ipv4/ipip.c4
-rw-r--r--net/ipv4/ipmr.c4
-rw-r--r--net/ipv4/netfilter/ip_queue.c7
-rw-r--r--net/ipv4/netfilter/ip_tables.c13
-rw-r--r--net/ipv4/netfilter/ipt_MIRROR.c2
-rw-r--r--net/ipv4/raw.c8
-rw-r--r--net/ipv4/tcp.c59
-rw-r--r--net/ipv4/tcp_input.c155
-rw-r--r--net/ipv4/tcp_ipv4.c17
-rw-r--r--net/ipv4/tcp_minisocks.c6
-rw-r--r--net/ipv4/tcp_output.c87
-rw-r--r--net/ipv4/udp.c8
-rw-r--r--net/ipv6/addrconf.c8
-rw-r--r--net/ipv6/datagram.c6
-rw-r--r--net/ipv6/ip6_input.c7
-rw-r--r--net/ipv6/ipv6_sockglue.c61
-rw-r--r--net/ipv6/ndisc.c29
-rw-r--r--net/ipv6/raw.c8
-rw-r--r--net/ipv6/reassembly.c19
-rw-r--r--net/ipv6/sit.c30
-rw-r--r--net/ipv6/tcp_ipv6.c11
-rw-r--r--net/ipv6/udp.c8
-rw-r--r--net/ipx/af_ipx.c459
-rw-r--r--net/irda/ircomm/ircomm_core.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c4
-rw-r--r--net/irda/irda_device.c2
-rw-r--r--net/irda/irlan/irlan_client_event.c3
-rw-r--r--net/irda/irlap_event.c14
-rw-r--r--net/packet/af_packet.c13
-rw-r--r--net/sunrpc/clnt.c4
-rw-r--r--net/sunrpc/sched.c2
-rw-r--r--net/sunrpc/xprt.c75
-rw-r--r--net/x25/af_x25.c3
-rw-r--r--scripts/kernel-doc45
1039 files changed, 72954 insertions, 20294 deletions
diff --git a/CREDITS b/CREDITS
index 7f8a8c70c..b2e00bf57 100644
--- a/CREDITS
+++ b/CREDITS
@@ -41,7 +41,7 @@ N: Tigran A. Aivazian
E: tigran@veritas.com
W: http://www.ocston.org/~tigran
D: BFS filesystem
-D: Intel P6 CPU microcode update support
+D: Intel IA32 CPU microcode update support
D: Various kernel patches
S: United Kingdom
@@ -152,10 +152,12 @@ E: balasub@cis.ohio-state.edu
D: Wrote SYS V IPC (part of standard kernel since 0.99.10)
N: Dario Ballabio
-E: dario@milano.europe.dg.com
+E: ballabio_dario@emc.com
+E: dario.ballabio@tiscalinet.it
+E: dario.ballabio@inwind.it
D: Author and maintainer of the Ultrastor 14F/34F SCSI driver
D: Author and maintainer of the EATA ISA/EISA/PCI SCSI driver
-S: Data General Corporation
+S: EMC Corporation
S: Milano
S: Italy
@@ -339,6 +341,7 @@ D: Texas Instruments PCILynx IEEE 1394 driver
N: Al Borchers
E: alborchers@steinerpoint.com
D: Author/maintainer of Digi AccelePort USB driver
+D: work on usbserial and keyspan_pda drivers
S: 4912 Zenith Ave. S.
S: Minneapolis, MN 55410
S: USA
@@ -408,6 +411,10 @@ N: Zach Brown
E: zab@zabbo.net
D: maestro pci sound
+N: Gary Brubaker
+E: xavyer@ix.netcom.com
+D: USB Serial Empeg Empeg-car Mark I/II Driver
+
N: Ray Burr
E: ryb@nightmare.com
D: Original author of Amiga FFS filesystem
@@ -760,6 +767,7 @@ N: Nils Faerber
E: nils@kernelconcepts.de
D: i810 TCO watchdog driver author
D: Mitsumi LU005 tests and fixes
+D: port and fixes of cs46xx sounddriver
S: Dreisbachstrasse 24
S: D-57250 Netphen
S: Germany
diff --git a/Documentation/Changes b/Documentation/Changes
index abcb21c64..ed3bfb602 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -185,10 +185,10 @@ PCMCIA (PC Card) support is now partially implemented in the main
kernel source. Pay attention when you recompile your kernel ;-).
Also, be sure to upgrade to the latest pcmcia-cs release.
-Intel P6 microcode
-------------------
+Intel IA32 microcode
+--------------------
-A driver has been added to allow updating of Intel P6 microcode,
+A driver has been added to allow updating of Intel IA32 microcode,
accessible as both a devfs regular file and as a normal (misc)
character device. If you are not using devfs you may need to:
@@ -199,6 +199,13 @@ chmod 0644 /dev/cpu/microcode
as root before you can use this. You'll probably also want to
get the user-space microcode_ctl utility to use with this.
+If you have compiled the driver as a module you may need to add
+the following line:
+
+alias char-major-10-184 microcode
+
+to your /etc/modules.conf file.
+
Networking
==========
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index 76c55c43c..fefc32bb4 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -10303,6 +10303,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 Documentation/modules.txt.
+USB Belkin and Paracom Single Port Serial Driver
+CONFIG_USB_SERIAL_BELKIN
+ Say Y here if you want to use a Belkin USB Serial single port
+ adaptor (F5U103 is one of the model numbers) or the Peracom single
+ port USB to serial adapter.
+
+ 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 belkin_sa.o. If you want to compile it as
+ a module, say M here and read Documentation/modules.txt.
+
USB FTDI Single Port Serial Driver
CONFIG_USB_SERIAL_FTDI_SIO
Say Y here if you want to use a FTDI SIO single port USB to serial
@@ -10378,11 +10389,36 @@ CONFIG_USB_SERIAL_DIGI_ACCELEPORT
parallel port on the USB 2 appears as a third serial port on Linux.
The Digi Acceleport USB 8 is not yet supported by this driver.
+ This driver works under SMP with the usb-uhci driver. It does not
+ work under SMP with the uhci driver.
+
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 digi_acceleport.o. If you want to compile
it as a module, say M here and read Documentation/modules.txt.
+USB Empeg empeg-car Mark I/II Driver
+CONFIG_USB_SERIAL_EMPEG
+ Say Y here if you want to connect to your Empeg empeg-car Mark I/II
+ mp3 player via USB. The driver uses a single ttyUSB{0,1,2,...}
+ device node. See Documentation/usb/usb-serial.txt for more
+ tidbits of 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 empeg.o. If you want to compile it as a
+ module, say M here and read Documentation/modules.txt.
+
+USB MCT Single Port Serial Driver
+CONFIG_USB_SERIAL_MCT_U232
+ Say Y here if you want to use a USB Serial single port adapter from
+ Magic Control Technology Corp. (U232 is one of the model numbers).
+
+ 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 mct_u232.o. If you want to compile it as
+ a module, say M here and read 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
@@ -13412,13 +13448,24 @@ CONFIG_MIXCOMWD
module, say M here and read Documentation/modules.txt. Most people
will say N.
-/dev/cpu/microcode - Intel P6 CPU microcode support
+Toshiba Laptop support
+CONFIG_TOSHIBA
+ If you intend to run this the kernel on a Toshiba portable say yes
+ here. This adds a driver to safely access the System Management
+ Mode of the CPU on Toshiba portables. The System Management Mode
+ is used to set the BIOS and power saving options on Toshiba portables.
+
+ For information on utilities to make use of this driver see the
+ Toshiba Linux utilities website at:
+ http://www.buzzard.org.uk/toshiba/
+
+/dev/cpu/microcode - Intel IA32 CPU microcode support
CONFIG_MICROCODE
If you say Y here and also to "/dev file system support" in the
'File systems' section, you will be able to update the microcode on
- Intel processors in the P6 family, e.g. Pentium Pro, Pentium II,
- Pentium III, Xeon etc. You will obviously need the actual microcode
- binary data itself which is not shipped with the Linux kernel.
+ Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II,
+ Pentium III, Pentium 4, Xeon etc. You will obviously need the actual
+ microcode binary data itself which is not shipped with the Linux kernel.
For latest news and information on obtaining all the required
ingredients for this driver, check:
@@ -13427,7 +13474,9 @@ CONFIG_MICROCODE
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called microcode.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt.
+ a module, say M here and read Documentation/modules.txt. If you use
+ modprobe or kmod you may also want to add the line
+ 'alias char-major-10-184 microcode' to your /etc/modules.conf file.
/dev/cpu/*/msr - Model-specific register support
CONFIG_X86_MSR
@@ -16288,12 +16337,6 @@ CONFIG_SA1100_LART
(also known as the LART). See http://www.lart.tudelft.nl/ for
information on the LART.
-Include support for ThinClient
-CONFIG_SA1100_THINCLIENT
- Say Y here if you are using an Applied Data Systems Intel(R)
- StrongARM(R) SA-1100 based Thin Client SBC. See
- http://www.flatpanels.com/ for information on this system.
-
Include support for GraphicsClient
CONFIG_SA1100_GRAPHICSCLIENT
Say Y here if you are using an Applied Data Systems Intel(R)
@@ -16328,6 +16371,27 @@ Support ARM920
CONFIG_CPU_ARM920
Say Y here if you wish to include support for the ARM920 processor.
+Support ARM610 processor
+CONFIG_CPU_ARM6
+ Say Y here if you wish to include support for the ARM610 processor.
+
+Support ARM710 processor
+CONFIG_CPU_ARM7
+ Say Y here if you wish to include support for the ARM710 processor.
+
+Support StrongARM(R) SA-110 processor
+CONFIG_CPU_SA110
+ Say Y here if you wish to include support for the Intel(R)
+ StrongARM(R) SA-110 processor.
+
+Support ARM720 processor
+CONFIG_CPU_ARM720
+ Say Y here if you wish to include support for the ARM720 processor.
+
+Support ARM920
+CONFIG_CPU_ARM920
+ Say Y here if you wish to include support for the ARM920 processor.
+
Math emulation
CONFIG_NWFPE
Say Y to include the NWFPE floating point emulator in the kernel.
@@ -16451,6 +16515,17 @@ CONFIG_SERIAL_21285_CONSOLE
If you have enabled the serial port on the 21285 footbridge you can
make it the console by answering Y to this option.
+SA1100 serial port support
+CONFIG_SERIAL_SA1100
+ If you have a machine based on a SA1100/SA1110 StrongARM CPU you can
+ enable its onboard serial port by enabling this option.
+ Please read Documentation/arm/SA1100/serial_UART for further info.
+
+Console on SA1100 serial port
+CONFIG_SERIAL_SA1100_CONSOLE
+ If you have enabled the serial port on the SA1100/SA1110 StrongARM
+ CPU you can make it the console by answering Y to this option.
+
L7200 serial port support
CONFIG_SERIAL_L7200
If you have a LinkUp Systems L7200 board you can enable its two
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index 0ffccdee2..b59a97dd1 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -341,7 +341,7 @@ to use the pci_dma_sync_*() interfaces.
struct my_card_header *hp;
/* Examine the header to see if we wish
- * to except the data. But synchronize
+ * to accept the data. But synchronize
* the DMA transfer with the CPU first
* so that we see updated contents.
*/
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 8d87787ad..47fbe077e 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -846,7 +846,7 @@ foo_open (...)
first class of operations work on <type>atomic_t</type>
<filename class=headerfile>include/asm/atomic.h</filename>; this
- contains a signed integer (at least 32 bits long), and you must use
+ contains a signed integer (at least 24 bits long), and you must use
these functions to manipulate or read atomic_t variables.
<function>atomic_read()</function> and
<function>atomic_set()</function> get and set the counter,
@@ -870,8 +870,8 @@ foo_open (...)
</para>
<para>
- The second class of atomic operations is atomic bit operations,
- defined in
+ The second class of atomic operations is atomic bit operations on a
+ <type>long</type>, defined in
<filename class=headerfile>include/asm/bitops.h</filename>. These
operations generally take a pointer to the bit pattern, and a bit
@@ -887,9 +887,15 @@ foo_open (...)
<para>
It is possible to call these operations with bit indices greater
- than 31. The resulting behavior is strange on big-endian
+ than BITS_PER_LONG. The resulting behavior is strange on big-endian
platforms though so it is a good idea not to do this.
</para>
+
+ <para>
+ Note that the order of bits depends on the architecture, and in
+ particular, the bitfield passed to these operations must be at
+ least as large as a <type>long</type>.
+ </para>
</chapter>
<chapter id="symbols">
diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl
index 2174af671..3798fc310 100644
--- a/Documentation/DocBook/videobook.tmpl
+++ b/Documentation/DocBook/videobook.tmpl
@@ -66,7 +66,7 @@
vertical blanking data interfaces are also provided.
</para>
</chapter>
- <chapter>
+ <chapter id="radio">
<title>Radio Devices</title>
<para>
There are a wide variety of radio interfaces available for PC's, and these
diff --git a/Documentation/README.DAC960 b/Documentation/README.DAC960
index 88f52364b..4c0832e79 100644
--- a/Documentation/README.DAC960
+++ b/Documentation/README.DAC960
@@ -1,11 +1,11 @@
Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
- Version 2.2.8 for Linux 2.2.16
- Version 2.4.8 for Linux 2.4.0
+ Version 2.2.9 for Linux 2.2.17
+ Version 2.4.9 for Linux 2.4.0
PRODUCTION RELEASE
- 19 August 2000
+ 7 September 2000
Leonard N. Zubkoff
Dandelion Digital
@@ -203,13 +203,13 @@ ftp://ftp.mylex.com/pub/dac960/diskcomp.html.
DRIVER INSTALLATION
-This distribution was prepared for Linux kernel version 2.2.16 or 2.4.0.
+This distribution was prepared for Linux kernel version 2.2.17 or 2.4.0.
To install the DAC960 RAID driver, you may use the following commands,
replacing "/usr/src" with wherever you keep your Linux kernel source tree:
cd /usr/src
- tar -xvzf DAC960-2.2.8.tar.gz (or DAC960-2.4.8.tar.gz)
+ tar -xvzf DAC960-2.2.9.tar.gz (or DAC960-2.4.9.tar.gz)
mv README.DAC960 linux/Documentation
mv DAC960.[ch] linux/drivers/block
patch -p0 < DAC960.patch (if DAC960.patch is included)
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index 29c597385..92a169ac2 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -6,13 +6,17 @@ Linux 2.2 and 2.4test kernel trees. Note that if you are interested in video
card drivers you should probably talk to XFree86 (http://wwww.xfree86.org)
instead.
+Also read the Documentation/SubmittingPatches document.
+
+
Allocating Device Numbers
-------------------------
-Major and minor numbers for devices are allocated by the Linux assigned name
-and number authority (currently better known as H Peter Anvin). The
-site is http://www.lanana.org/. This also deals with allocating numbers for
-devices that are not going to be submitted to the mainstream kernel.
+Major and minor numbers for block and character devices are allocated
+by the Linux assigned name and number authority (currently better
+known as H Peter Anvin). The site is http://www.lanana.org/. This
+also deals with allocating numbers for devices that are not going to
+be submitted to the mainstream kernel.
If you don't use assigned numbers then when you device is submitted it will
get given an assigned number even if that is different from values you may
@@ -76,7 +80,8 @@ Control: In general if there is active maintainance of a driver by
the author then patches will be redirected to them unless
they are totally obvious and without need of checking.
If you want to be the contact and update point for the
- driver it is a good idea to state this in the comments.
+ driver it is a good idea to state this in the comments,
+ and include an entry in MAINTAINERS for your driver.
What Criteria Do Not Determine Acceptance
-----------------------------------------
@@ -97,7 +102,8 @@ Resources
---------
Linux kernel master tree:
- ftp.kernel.org:/pub/linux/kernel/...
+ ftp.??.kernel.org:/pub/linux/kernel/...
+ ?? == your country code, such as "us", "uk", "fr", etc.
Linux kernel mailing list:
linux-kernel@vger.kernel.org
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
new file mode 100644
index 000000000..4f48032c7
--- /dev/null
+++ b/Documentation/SubmittingPatches
@@ -0,0 +1,286 @@
+
+ How to Get Your Change Into the Linux Kernel
+ or
+ Care And Operation Of Your Linus Torvalds
+
+
+
+For a person or company who wishes to submit a change to the Linux
+kernel, the process can sometimes be daunting if you're not familiar
+with "the system." This text is a collection of suggestions which
+can greatly increase the chances of your change being accepted.
+
+If you are submitting a driver, also read Documentation/SubmittingDrivers.
+
+
+
+--------------------------------------------
+SECTION 1 - CREATING AND SENDING YOUR CHANGE
+--------------------------------------------
+
+
+
+1) "diff -u"
+------------
+
+Use "diff -u" or "diff -urN" to create patches.
+
+All changes to the Linux kernel occur in the form of patches, as
+generated by diff(1). When creating your patch, make sure to create it
+in "unified diff" format, as supplied by the '-u' argument to diff(1).
+Patches should be based in the root kernel source directory, not in
+any lower subdirectory.
+
+To create a patch for a single file, it is often sufficient to do:
+
+ SRCTREE= /devel/linux-2.4
+ MYFILE= drivers/net/mydriver.c
+
+ cd $SRCTREE
+ cp $MYFILE $MYFILE.orig
+ vi $MYFILE # make your change
+ diff -u $MYFILE.orig $MYFILE > /tmp/patch
+
+To create a patch for multiple files, you should unpack a "vanilla",
+or unmodified kernel source tree, and generate a diff against your
+own source tree. For example:
+
+ MYSRC= /devel/linux-2.4
+
+ tar xvfz linux-2.4.0-test11.tar.gz
+ mv linux linux-vanilla
+ wget http://www.moses.uklinux.net/patches/dontdiff
+ diff -urN -X dontdiff linux-vanilla $MYSRC > /tmp/patch
+ rm -f dontdiff
+
+"dontdiff" is a list of files which are generated by the kernel during
+the build process, and should be ignored in any diff(1)-generated
+patch. dontdiff is maintained by Tigran Aivazian <tigran@veritas.com>
+
+Make sure your patch does not include any extra files which do not
+belong in a patch submission. Make sure to review your patch -after-
+generated it with diff(1), to ensure accuracy.
+
+
+2) Describe your changes.
+
+Describe the technical detail of the change(s) your patch includes.
+
+Be as specific as possible. The WORST descriptions possible include
+things like "update driver X", "bug fix for driver X", or "this patch
+includes updates for subsystem X. Please apply."
+
+If your description starts to get long, that's a sign that you probably
+need to split up your patch. See #3, next.
+
+
+
+3) Separate your changes.
+
+Separate each logical change into its own patch.
+
+For example, if your changes include both bug fixes and performance
+enhancements for a single driver, separate those changes into two
+or more patches. If your changes include an API update, and a new
+driver which uses that new API, separate those into two patches.
+
+On the other hand, if you make a single change to numerous files,
+group those changes into a single patch. Thus a single logical change
+is contained within a single patch.
+
+If one patch depends on another patch in order for a change to be
+complete, that is OK. Simply note "this patch depends on patch X"
+in your patch description.
+
+
+4) Select e-mail destination.
+
+Look through the MAINTAINERS file and the source code, and determine
+if your change applies to a specific subsystem of the kernel, with
+an assigned maintainer. If so, e-mail that person.
+
+If no maintainer is listed, or the maintainer does not respond, send
+your patch to the primary Linux kernel developer's mailing list,
+linux-kernel@vger.kernel.org. Most kernel developers monitor this
+e-mail list, and can comment on your changes.
+
+Linus Torvalds is the final arbiter of all changes accepted into the
+Linux kernel. His e-mail address is torvalds@transmeta.com. He gets
+a lot of e-mail, so typically you should do your best to -avoid- sending
+him e-mail.
+
+Patches which are bug fixes, are "obvious" changes, or similarly
+require little discussion should be sent or CC'd to Linus. Patches
+which require discussion or do not have a clear advantage should
+usually be sent first to linux-kernel. Only after the patch is
+discussed should the patch then be submitted to Linus.
+
+
+
+5) Select your CC (e-mail carbon copy) list.
+
+Unless you have a reason NOT to do so, CC linux-kernel@vger.kernel.org.
+
+Other kernel developers besides Linus need to be aware of your change,
+so that they may comment on it and offer code review and suggestions.
+linux-kernel is the primary Linux kernel developer mailing list.
+Other mailing lists are available for specific subsystems, such as
+USB, framebuffer devices, the VFS, the SCSI subsystem, etc. See the
+MAINTAINERS file for a mailing list that relates specifically to
+your change.
+
+Even if the maintainer did not respond in step #4, make sure to ALWAYS
+copy the maintainer when you change their code.
+
+
+
+6) No MIME, no links, no compression, no attachments. Just plain text.
+
+Linus and other kernel developers need to be able to read and comment
+on the changes you are submitting. It is important for a kernel
+developer to be able to "quote" your changes, using standard e-mail
+tools, so that they may comment on specific portions of your code.
+
+For this reason, all patches should be submitting e-mail "inline".
+WARNING: Be wary of your editor's word-wrap corrupting your patch,
+if you choose to cut-n-paste your patch.
+
+Do not attach the patch as a MIME attachment, compressed or not.
+Many popular e-mail applications will not always transmit a MIME
+attachment as plain text, making it impossible to comment on your
+code. A MIME attachment also takes Linus a bit more time to process,
+decreasing the likelihood of your MIME-attached change being accepted.
+
+Exception: If your mailer is mangling patches then someone may ask
+you to re-send them using MIME.
+
+
+
+7) E-mail size.
+
+When sending patches to Linus, always follow step #6.
+
+Large changes are not appropriate for mailing lists, and some
+maintainers. If your patch, uncompressed, exceeds 40Kb in size,
+it is preferred that you store your patch on an Internet-accessible
+server, and provide instead a URL (link) pointing to your patch.
+
+
+
+8) Name your kernel version.
+
+It is important to note, either in the subject line or in the patch
+description, the kernel version to which this patch applies.
+
+If the patch does not apply cleanly to the latest kernel version,
+Linus will not apply it.
+
+
+
+9) Don't get discouraged. Re-submit.
+
+After you have submitted your change, be patient and wait. If Linus
+likes your change and applies it, it will appear in the next version
+of the kernel that he releases.
+
+However, if your change doesn't appear in the next version of the
+kernel, there could be any number of reasons. It's YOUR job to
+narrow down those reasons, correct what was wrong, and submit your
+updated change.
+
+It is quite common for Linus to "drop" your patch without comment.
+That's the nature of the system. If he drops your patch, it could be
+due to
+* Your patch did not apply cleanly to the latest kernel version
+* Your patch was not sufficiently discussed on linux-kernel.
+* A style issue (see section 2),
+* An e-mail formatting issue (re-read this section)
+* A technical problem with your change
+* He gets tons of e-mail, and yours got lost in the shuffle
+* You are being annoying (See Figure 1)
+
+When in doubt, solicit comments on linux-kernel mailing list.
+
+
+
+10) Include PATCH in the subject
+
+Due to high e-mail traffic to Linus, and to linux-kernel, it is common
+convention to prefix your subject line with [PATCH]. This lets Linus
+and other kernel developers more easily distinguish patches from other
+e-mail discussions.
+
+
+
+-----------------------------------
+SECTION 2 - HINTS, TIPS, AND TRICKS
+-----------------------------------
+
+This section lists many of the common "rules" associated with code
+submitted to the kernel. There are always exceptions... but you must
+have a really good reason for doing so. You could probably call this
+section Linus Computer Science 101.
+
+
+
+1) Read Documentation/CodingStyle
+
+Nuff said. If your code deviates too much from this, it is likely
+to be rejected without further review, and without comment.
+
+
+
+2) #ifdefs are ugly
+
+Code cluttered with ifdefs is difficult to read and maintain. Don't do
+it. Instead, put your ifdefs in a header, and conditionally define
+'static inline' functions, or macros, which are used in the code.
+Let the compiler optimize away the "no-op" case.
+
+Simple example, of poor code:
+
+ dev = init_etherdev (NULL, 0);
+ if (!dev)
+ return -ENODEV;
+ #ifdef CONFIG_NET_FUNKINESS
+ init_funky_net(dev);
+ #endif
+
+Cleaned-up example:
+
+(in header)
+ #ifndef CONFIG_NET_FUNKINESS
+ static inline void init_funky_net (struct net_device *d) {}
+ #endif
+
+(in the code itself)
+ dev = init_etherdev (NULL, 0);
+ if (!dev)
+ return -ENODEV;
+ init_funky_net(dev);
+
+
+
+3) 'static inline' is better than a macro
+
+Static inline functions are greatly preferred over macros.
+They provide type safety, have no length limitations, no formatting
+limitations, and under gcc they are as cheap as macros.
+
+Macros should only be used for cases where a static inline is clearly
+suboptimal [there a few, isolated cases of this in fast paths],
+or where it is impossible to use a static inline function [such as
+string-izing].
+
+'static inline' is preferred over 'static __inline__', 'extern inline',
+and 'extern __inline__'.
+
+
+
+4) Don't over-design.
+
+Don't try to anticipate nebulous future cases which may or may not
+be useful: "Make it as simple as you can, and no simpler"
+
+
+
diff --git a/Documentation/arm/README b/Documentation/arm/README
index 96bdfe3e2..8514dac03 100644
--- a/Documentation/arm/README
+++ b/Documentation/arm/README
@@ -157,7 +157,8 @@ Kernel entry (head-armv.S)
the mail a subject of 'Register new architecture':
Name: <name of your architecture>
- ARCHDIR: <name of include/asm-arm/arch-* directory>
+ ArchDir: <name of include/asm-arm/arch-* directory>
+ Type: <MACH_TYPE_* macro name>
Description:
<description of your architecture>
diff --git a/Documentation/arm/SA1100/ThinClient b/Documentation/arm/SA1100/GraphicsClient
index d5d7625fd..01f3f050a 100644
--- a/Documentation/arm/SA1100/ThinClient
+++ b/Documentation/arm/SA1100/GraphicsClient
@@ -1,24 +1,21 @@
-Thin Client / Single Board Computer
-
-The Thin Client, a low cost high power single board computer, has been
-designed to provide intuitive graphical displays in embedded systems.
+ADS GraphicsClient/ThinClient Single Board Computer
For more details, contact Applied Data Systems or see
http://www.flatpanels.com/products.html
-Current Linux support for this product has been provided by Nicolas Pitre
-<nico@cam.org>.
+The original Linux support for this product has been provided by
+Nicolas Pitre <nico@cam.org>.
It's currently possible to mount a root filesystem via NFS providing a
complete Linux environment. Otherwise a ramdisk image may be used. Use
-'make thinclient_config' before any 'make config'. This will set up
-defaults for ThinClient support.
+'make graphicsclient_config' before any 'make config'. This will set up
+defaults for GraphicsClient/ThinClient support.
The kernel zImage is linked to be loaded and executed at 0xc0200000.
Also the following registers should have the specified values upon entry:
r0 = 0
- r1 = 24 (this is the ThinClient architecture number)
+ r1 = 29 (this is the GraphicsClient architecture number)
Here is a tipical angel.opt option file if the kernel is loaded through
the Angel Debug Monitor:
@@ -27,7 +24,7 @@ the Angel Debug Monitor:
base 0xc0200000
entry 0xc0200000
r0 0x00000000
-r1 0x00000018
+r1 0x0000001d
device /dev/ttyS1
options "9600 8N1"
baud 115200
@@ -41,7 +38,7 @@ uncommented) would be loaded with:
angelboot -f angelboot.opt zImage
-Here it is assumed that the ThinClient is connected to ttyS1 on your PC
+Here it is assumed that the board is connected to ttyS1 on your PC
and that minicom is preconfigured with /dev/ttyS1, 9600 baud, 8N1, no flow
control by default.
@@ -54,13 +51,13 @@ Supported peripherals:
- on-board SMC 92C94 ethernet NIC
- SA1100 serial port
- flash memory access
+- pcmcia
- possibly UCB1200 audio (not tested yet)
To do:
- touchscreen driver
- 16bpp frame buffer support
- extra (external) serial port driver
-- pcmcia
- some console keyboard support (maybe IR?)
- everything else! :-)
diff --git a/Documentation/arm/SA1100/Pangolin b/Documentation/arm/SA1100/Pangolin
new file mode 100644
index 000000000..88cff5bf1
--- /dev/null
+++ b/Documentation/arm/SA1100/Pangolin
@@ -0,0 +1,25 @@
+Pangolin is a StrongARM 1110-based evaluation platform produced
+by Dialogue Technoloy (http://www.dialogue.com.tw/).
+It has EISA slots for ease of configuration with SDRAM/Flash
+memory card, USB/Serial/Audio card, Compact Flash card,
+and TFT-LCD card.
+This platform is currently under development.
+
+To compile for Pangolin, you must issue the following commands:
+
+ make pangolin_config
+ make config
+ [accept all defaults]
+ make dep
+ make zImage
+
+Supported peripherals:
+- SA1110 serial port
+- flash memory access
+
+Testing:
+- pcmcia driver
+- sound driver
+
+To do:
+- MQ-200 driver
diff --git a/Documentation/arm/SA1100/serial_UART b/Documentation/arm/SA1100/serial_UART
new file mode 100644
index 000000000..3807dea19
--- /dev/null
+++ b/Documentation/arm/SA1100/serial_UART
@@ -0,0 +1,65 @@
+The SA1100 serial port finally had its major/minor numbers officially
+assigned:
+
+> Date: Sun, 24 Sep 2000 21:40:27 -0700
+> From: H. Peter Anvin <hpa@transmeta.com>
+> To: Nicolas Pitre <nico@CAM.ORG>
+> Cc: Device List Maintainer <device@lanana.org>
+> Subject: Re: device
+>
+> Okay. Note that device numbers 204 and 205 are used for "low density
+> serial devices", so you will have a range of minors on those majors (the
+> tty device layer handles this just fine, so you don't have to worry about
+> doing anything special.)
+>
+> So your assignments are:
+>
+> 204 char Low-density serial ports
+> 5 = /dev/ttySA0 SA1100 builtin serial port 0
+> 6 = /dev/ttySA1 SA1100 builtin serial port 1
+> 7 = /dev/ttySA2 SA1100 builtin serial port 2
+>
+> 205 char Low-density serial ports (alternate device)
+> 5 = /dev/cusa0 Callout device for ttySA0
+> 6 = /dev/cusa1 Callout device for ttySA1
+> 7 = /dev/cusa2 Callout device for ttySA2
+>
+
+So, if you're not using devfs, you must create those inodes in /dev
+on the root filesystem used by your SA1100-based device:
+
+ mknod ttySA0 c 204 5
+ mknod ttySA1 c 204 6
+ mknod ttySA2 c 204 7
+ mknod cusa0 c 205 5
+ mknod cusa1 c 205 6
+ mknod cusa2 c 205 7
+
+Note that the old incorrect use of /dev/ttyS0 in order to use the serial port
+won't work anymore. This device node is reserved to the conventionnal 16x50
+UART which may appear on devices like PCMCIA modem, etc.
+
+In addition to the creation of the appropriate device nodes above, you must
+ensure your user space applications make use of the correct device name.
+The classic example is the content of the /etc/inittab where you might have
+a getty process started on ttyS0. In this case you have two choices:
+
+1- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc.
+
+2- in the occurence of 'ttyS0', you may consider replacing it with 'console'.
+ as in "T0:12345:respawn:/sbin/getty -L console 9600 vt100"
+
+(don't forget to add 'ttySA0', 'console', or the appropriate tty name
+ in /etc/securetty for root to be allowed to login as well.)
+
+The use of /dev/console has the advantage of being independent of the real
+serial device used. The kernel automatically forward all operations on
+/dev/console to the apropriate serial device. The nature of the console may
+also be modified with a kernel command line parameter (see
+Documentation/serial-console.txt for the details). Of course,
+/dev/console must have been created as a char device with major 5 minor 1.
+
+Using /dev/console is also compatible with older kernels that used /dev/ttyS0.
+Therefore it is handy for ramdisk images which are targetted for different
+StrongARM platforms and older kernels.
+
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 5201a2f54..f3ae78497 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -257,7 +257,7 @@ the proper points in time.
Here is the new interface:
- void copy_user_page(void *from, void *to, unsigned long address)
+ void copy_user_page(void *to, void *from, unsigned long address)
void clear_user_page(void *to, unsigned long address)
These two routines store data in user anonymous or COW
diff --git a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README
index 6febda525..0c6fde510 100644
--- a/Documentation/filesystems/devfs/README
+++ b/Documentation/filesystems/devfs/README
@@ -529,7 +529,7 @@ yielded code size reductions and simplifications.
If you want to construct a minimal chroot() gaol, the following
command should suffice:
-mount -t bind /dev/null /gaol/dev/null
+mount --bind /dev/null /gaol/dev/null
Repeat for other device nodes you want to expose. Simple!
@@ -739,7 +739,7 @@ create the /dev-state directory
add the following lines near the very beginning of your boot
scripts:
-mount -t bind /dev /dev-state
+mount --bind /dev /dev-state
mount -t devfs none /dev
devfsd /dev
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 5dcf02cfe..ea8d32afb 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -3,8 +3,11 @@
------------------------------------------------------------------------------
/proc/sys Terrehon Bowden <terrehon@pacbell.net> October 7 1999
Bodo Bauer <bb@ricochet.net>
+
+2.4.x update Jorge Nerin <comandante@zaralinux.com> November 14 2000
------------------------------------------------------------------------------
-Version 1.2 Kernel version 2.2.12
+Version 1.3 Kernel version 2.2.12
+ Kernel version 2.4.0-test11-pre4
------------------------------------------------------------------------------
Table of Contents
@@ -42,17 +45,18 @@ Preface
0.1 Introduction/Credits
------------------------
-This documentation is part of a soon (or so we hope) to be released book on
-the SuSE Linux distribution. As there is no complete documentation for the
-/proc file system and we've used many freely available sources to write these
-chapters, it seems only fair to give the work back to the Linux community.
-This work is based on the 2.2.* kernel version. I'm afraid it's still far from
-complete, but we hope it will be useful. As far as we know, it is the first
-'all-in-one' document about the /proc file system. It is focused on the Intel
-x86 hardware, so if you are looking for PPC, ARM, SPARC, APX, etc., features,
-you probably won't find what you are looking for. It also only covers IPv4
-networking, not IPv6 nor other protocols - sorry. But additions and patches
-are welcome and will be added to this document if you mail them to Bodo.
+This documentation is part of a soon (or so we hope) to be released book on
+the SuSE Linux distribution. As there is no complete documentation for the
+/proc file system and we've used many freely available sources to write these
+chapters, it seems only fair to give the work back to the Linux community.
+This work is based on the 2.2.* kernel version and the upcomming 2.4.*. I'm
+afraid it's still far from complete, but we hope it will be useful. As far as
+we know, it is the first 'all-in-one' document about the /proc file system. It
+is focused on the Intel x86 hardware, so if you are looking for PPC, ARM,
+SPARC, APX, etc., features, you probably won't find what you are looking for.
+It also only covers IPv4 networking, not IPv6 nor other protocols - sorry. But
+additions and patches are welcome and will be added to this document if you
+mail them to Bodo.
We'd like to thank Alan Cox, Rik van Riel, and Alexey Kuznetsov and a lot of
other people for help compiling this documentation. We'd also like to extend a
@@ -65,9 +69,13 @@ If you have any comments, corrections or additions, please don't hesitate to
contact Bodo Bauer at bb@ricochet.net. We'll be happy to add them to this
document.
-The latest version of this document is available online at
+The latest version of this document is available online at
http://skaro.nightcrawler.com/~bb/Docs/Proc as HTML version.
+If the above direction does not works for you, ypu could try the kernel
+mailing list at linux-kernel@vger.kernel.org and/or try to reach me at
+comandante@zaralinux.com.
+
0.2 Legal Stuff
---------------
@@ -92,7 +100,7 @@ In This Chapter
The proc file system acts as an interface to internal data structures in the
kernel. It can be used to obtain information about the system and to change
-certain kernel parameters at runtime.
+certain kernel parameters at runtime (sysctl).
First, we'll take a look at the read-only parts of /proc. In Chapter 2, we
show you how you can use /proc/sys to change settings.
@@ -111,16 +119,17 @@ Table 1-1: Process specific entries in /proc
..............................................................................
File Content
cmdline Command line arguments
- environ Values of environment variables
+ cpu Current and last cpu in wich it was executed (2.4)(smp)
+ cwd Link to the current working directory
+ environ Values of environment variables
+ exe Link to the executable of this process
fd Directory, which contains all file descriptors
+ maps Memory maps to executables and library files (2.4)
mem Memory held by this process
+ root Link to the root directory of this process
stat Process status
- status Process status in human readable form
- cwd Link to the current working directory
- exe Link to the executable of this process
- maps Memory maps
- root Link to the root directory of this process
statm Process memory status information
+ status Process status in human readable form
..............................................................................
For example, to get the status information of a process, all you have to do is
@@ -131,6 +140,7 @@ read the file /proc/PID/status:
State: R (running)
Pid: 5452
PPid: 743
+ TracerPid: 0 (2.4)
Uid: 501 501 501 501
Gid: 100 100 100 100
Groups: 100 14 16
@@ -187,13 +197,20 @@ Table 1-3: Kernel info in /proc
devices Available devices (block and character)
dma Used DMS channels
filesystems Supported filesystems
+ driver Various drivers grouped here, currently rtc (2.4)
+ execdomains Execdomains, related to security (2.4)
+ fb Frame Buffer devices (2.4)
+ fs File system parameters, currently nfs/exports (2.4)
ide Directory containing info about the IDE subsystem
interrupts Interrupt usage
+ iomem Memory map (2.4)
ioports I/O port usage
- kcore Kernel core image (can be ELF or A.OUT)
+ irq Masks for irq to cpu affinity (2.4)(smp?)
+ isapnp ISA PnP (Plug&Play) Info (2.4)
+ kcore Kernel core image (can be ELF or A.OUT(deprecated in 2.4))
kmsg Kernel messages
ksyms Kernel symbol table
- loadavg Load average
+ loadavg Load average of last 1, 5 & 15 minutes
locks Kernel locks
meminfo Memory info
misc Miscellaneous
@@ -201,14 +218,19 @@ Table 1-3: Kernel info in /proc
mounts Mounted filesystems
net Networking info (see text)
partitions Table of partitions known to the system
+ pci Depreciated info of PCI bus (new way -> /proc/bus/pci/,
+ decoupled by lspci (2.4)
rtc Real time clock
scsi SCSI info (see text)
slabinfo Slab pool info
stat Overall statistics
swaps Swap space utilization
sys See chapter 2
+ sysvipc Info of SysVIPC Resources (msg, sem, shm) (2.4)
+ tty Info of tty drivers
uptime System uptime
version Kernel version
+ video bttv info of video resources (2.4)
..............................................................................
You can, for example, check which interrupts are currently in use and what
@@ -230,6 +252,68 @@ they are used for by looking in the file /proc/interrupts:
15: 7 XT-PIC ide1
NMI: 0
+In 2.4.* a couple of lines where added to this file LOC & ERR (this time is the
+output of a SMP machine):
+
+ > cat /proc/interrupts
+
+ CPU0 CPU1
+ 0: 1243498 1214548 IO-APIC-edge timer
+ 1: 8949 8958 IO-APIC-edge keyboard
+ 2: 0 0 XT-PIC cascade
+ 5: 11286 10161 IO-APIC-edge soundblaster
+ 8: 1 0 IO-APIC-edge rtc
+ 9: 27422 27407 IO-APIC-edge 3c503
+ 12: 113645 113873 IO-APIC-edge PS/2 Mouse
+ 13: 0 0 XT-PIC fpu
+ 14: 22491 24012 IO-APIC-edge ide0
+ 15: 2183 2415 IO-APIC-edge ide1
+ 17: 30564 30414 IO-APIC-level eth0
+ 18: 177 164 IO-APIC-level bttv
+ NMI: 2457961 2457959
+ LOC: 2457882 2457881
+ ERR: 2155
+
+NMI is incremented in this case because every timer interrupt generates a NMI
+(Non Maskable Interrupt) which is used by the NMI Watchdog to detect lookups.
+
+LOC is the local interrupt counter of the internal APIC of every CPU.
+
+ERR is incremented in the case of errors in the IO-APIC bus (the bus that
+connects the CPUs in a SMP system. This means that an error has been detected,
+the IO-APIC automatically retry the transmision, so it should not be a big
+problem, but you should read the SMP-FAQ.
+
+In this context it could be interesting to note the new irq directory in 2.4.
+It could be used to set IRQ to CPU affinity, this means that you can "hook" an
+IRQ to only one CPU, or to exclude a CPU of handling IRQs. The contents of the
+irq subdir is one subdir for each IRQ, and one file; prof_cpu_mask
+
+For example
+ > ls /proc/irq/
+ 0 10 12 14 16 18 2 4 6 8 prof_cpu_mask
+ 1 11 13 15 17 19 3 5 7 9
+ > ls /proc/irq/0/
+ smp_affinity
+
+The contents of the prof_cpu_mask file and each smp_affinity file for each IRQ
+is the same by default:
+
+ > cat /proc/irq/0/smp_affinity
+ ffffffff
+
+It's a bitmask, in wich you can specify wich CPUs can handle the IRQ, you can
+set it by doing:
+
+ > echo 1 > /proc/irq/prof_cpu_mask
+
+This means that only the first CPU will handle the IRQ, but you can also echo 5
+wich means that only the first and fourth CPU can handle the IRQ.
+
+The way IRQs are routed is handled by the IO-APIC, and it's Round Robin
+between all the CPUs which are allowed to handle it. As usual the kernel has
+more info than you and does a better job than you, so the defaults are the
+best choice for almost everyone.
There are three more important subdirectories in /proc: net, scsi, and sys.
The general rule is that the contents, or even the existence of these
@@ -1307,6 +1391,15 @@ Time in seconds to keep an IP fragment in memory.
TCP settings
------------
+tcp_ecn
+-------
+
+This file controls the use of the ECN bit in the IPv4 headers, this is a new
+feature about Explicit Congestion Notification, but some routers and firewalls
+block trafic that has this bit set, so it could be necessary to echo 0 to
+/proc/sys/net/ipv4/tcp_ecn, if you want to talk to this sites. For more info
+you could read RFC2481.
+
tcp_retrans_collapse
--------------------
diff --git a/Documentation/initrd.txt b/Documentation/initrd.txt
index acc2315a4..941f9ddd0 100644
--- a/Documentation/initrd.txt
+++ b/Documentation/initrd.txt
@@ -1,25 +1,28 @@
Using the initial RAM disk (initrd)
===================================
-Written 1996 by Werner Almesberger <almesber@lrc.epfl.ch> and
- Hans Lermen <lermen@elserv.ffm.fgan.de>
+Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch> and
+ Hans Lermen <lermen@fgan.de>
-initrd adds the capability to load a RAM disk by the boot loader. This
-RAM disk can then be mounted as the root file system and programs can be
-run from it. Afterwards, a new root file system can be mounted from a
-different device. The previous root (from initrd) is then either moved
-to the directory /initrd or it is unmounted.
+initrd provides the capability to load a RAM disk by the boot loader.
+This RAM disk can then be mounted as the root file system and programs
+can be run from it. Afterwards, a new root file system can be mounted
+from a different device. The previous root (from initrd) is then moved
+to a directory and can be subsequently unmounted.
initrd is mainly designed to allow system startup to occur in two phases,
where the kernel comes up with a minimum set of compiled-in drivers, and
where additional modules are loaded from initrd.
+This document gives a brief overview of the use of initrd. A more detailed
+discussion of the boot process can be found in [1].
+
Operation
---------
-When using initrd, the system boots as follows:
+When using initrd, the system typically boots as follows:
1) the boot loader loads the kernel and the initial RAM disk
2) the kernel converts initrd into a "normal" RAM disk and
@@ -28,28 +31,17 @@ When using initrd, the system boots as follows:
4) /linuxrc is executed (this can be any valid executable, including
shell scripts; it is run with uid 0 and can do basically everything
init can do)
- 5) when linuxrc terminates, the "real" root file system is mounted
- 6) if a directory /initrd exists, the initrd is moved there
- otherwise, initrd is unmounted
+ 5) linuxrc mounts the "real" root file system
+ 6) linuxrc places the root file system at the root directory using the
+ pivot_root system call
7) the usual boot sequence (e.g. invocation of /sbin/init) is performed
on the root file system
+ 8) the initrd file system is removed
-Note that moving initrd from / to /initrd does not involve unmounting it.
-It is therefore possible to leave processes running on initrd (or leave
-file systems mounted, but see below) during that procedure. However, if
-/initrd doesn't exist, initrd can only be unmounted if it is not used by
-anything. If it can't be unmounted, it will stay in memory.
-
-Also note that file systems mounted under initrd continue to be accessible,
-but their /proc/mounts entries are not updated. Also, if /initrd doesn't
-exist, initrd can't be unmounted and will "disappear" and take those file
-systems with it, thereby preventing them from being re-mounted. It is
-therefore strongly suggested to generally unmount all file systems (except
-of course for the root file system, but including /proc) before switching
-from initrd to the "normal" root file system.
-
-In order to deallocate the memory used for the initial RAM disk, you have
-to execute freeramdisk (see 'Resources' below) after unmounting /initrd.
+Note that changing the root directory does not involve unmounting it.
+It is therefore possible to leave processes running on initrd during that
+procedure. Also note that file systems mounted under initrd continue to
+be accessible.
Boot command-line options
@@ -57,7 +49,7 @@ Boot command-line options
initrd adds the following new options:
- initrd=<path> (LOADLIN only)
+ initrd=<path> (e.g. LOADLIN)
Loads the specified file as the initial RAM disk. When using LILO, you
have to specify the RAM disk image file in /etc/lilo.conf, using the
@@ -71,40 +63,38 @@ initrd adds the following new options:
in this case and doesn't necessarily have to be a file system image.
This option is used mainly for debugging.
- Note that /dev/initrd is read-only and that it can only be used once.
- As soon as the last process has closed it, all data is freed and
- /dev/initrd can't be opened any longer.
+ Note: /dev/initrd is read-only and it can only be used once. As soon
+ as the last process has closed it, all data is freed and /dev/initrd
+ can't be opened anymore.
- root=/dev/ram
+ root=/dev/ram0 (without devfs)
+ root=/dev/rd/0 (with devfs)
- initrd is mounted as root, and /linuxrc is started. If no /linuxrc
- exists, the normal boot procedure is followed, with the RAM disk
- still mounted as root. This option is mainly useful when booting from
- a floppy disk. Compared to directly mounting an on-disk file system,
- the intermediate step of going via initrd adds a little speed
- advantage and it allows the use of a compressed file system.
- Also, together with LOADLIN you may load the RAM disk directly from
- CDROM or disk, hence having a floppyless boot from CD,
- e.g.: E:\loadlin E:\bzImage root=/dev/ram initrd=E:\rdimage
+ initrd is mounted as root, and the normal boot procedure is followed,
+ with the RAM disk still mounted as root.
Installation
------------
-First, the "normal" root file system has to be prepared as follows:
+First, a directory for the initrd file system has to be created on the
+"normal" root file system, e.g.
-# mknod /dev/initrd b 1 250
-# chmod 400 /dev/initrd
# mkdir /initrd
+The name is not relevant. More details can be found on the pivot_root(2)
+man page.
+
If the root file system is created during the boot procedure (i.e. if
-you're creating an install floppy), the root file system creation
-procedure should perform these operations.
+you're building an install floppy), the root file system creation
+procedure should create the /initrd directory.
+
+If initrd will not be mounted in some cases, its content is still
+accessible if the following device has been created (note that this
+does not work if using devfs):
-Note that neither /dev/initrd nor /initrd are strictly required for
-correct operation of initrd, but it is a lot easier to experiment with
-initrd if you have them, and you may also want to use /initrd to pass
-data to the "real" system.
+# mknod /dev/initrd b 1 250
+# chmod 400 /dev/initrd
Second, the kernel has to be compiled with RAM disk support and with
support for the initial RAM disk enabled. Also, at least all components
@@ -112,100 +102,148 @@ needed to execute programs from initrd (e.g. executable format and file
system) must be compiled into the kernel.
Third, you have to create the RAM disk image. This is done by creating a
-file system on a block device and then by copying files to it as needed.
-With recent kernels, at least three types of devices are suitable for
-that:
+file system on a block device, copying files to it as needed, and then
+copying the content of the block device to the initrd file. With recent
+kernels, at least three types of devices are suitable for that:
- a floppy disk (works everywhere but it's painfully slow)
- a RAM disk (fast, but allocates physical memory)
- - a loopback device (the most elegant solution, but currently requires a
- modified mount)
+ - a loopback device (the most elegant solution)
-We'll describe the RAM disk method:
+We'll describe the loopback device method:
- 1) make sure you have a RAM disk device /dev/ram (block, major 1, minor 0)
+ 1) make sure loopback block devices are configured into the kernel
2) create an empty file system of the appropriate size, e.g.
- # mke2fs -m0 /dev/ram 300
+ # dd if=/dev/zero of=initrd bs=300k count=1
+ # mke2fs -F -m0 initrd
(if space is critical, you may want to use the Minix FS instead of Ext2)
- 3) mount the file system on an appropriate directory, e.g.
- # mount -t ext2 /dev/ram /mnt
- 4) create the console device:
+ 3) mount the file system, e.g.
+ # mount -t ext2 -o loop initrd /mnt
+ 4) create the console device (not necessary if using devfs, but it can't
+ hurt to do it anyway):
# mkdir /mnt/dev
- # mknod /mnt/dev/tty1 c 4 1
+ # mknod /mnt/dev/console c 5 1
5) copy all the files that are needed to properly use the initrd
environment. Don't forget the most important file, /linuxrc
Note that /linuxrc's permissions must include "x" (execute).
- 6) unmount the RAM disk
- # umount /dev/ram
- 7) copy the image to a file
- # dd if=/dev/ram bs=1k count=300 of=/boot/initrd
- 8) deallocate the RAM disk
- # freeramdisk /dev/ram
-
-For experimenting with initrd, you may want to take a rescue floppy (e.g.
-rescue.gz from Slackware) and only add a symbolic link from /linuxrc to
-/bin/sh, e.g.
-
- # gunzip <rescue.gz >/dev/ram
- # mount -t minix /dev/ram /mnt
- # ln -s /bin/sh /mnt/linuxrc
- # umount /dev/ram
- # dd if=/dev/ram bs=1k count=1440 of=/boot/initrd
- # freeramdisk /dev/ram
-
-Finally, you have to boot the kernel and load initrd. Currently,
-preliminary versions of LOADLIN 1.6 and LILO 18 support initrd (see
-below for where to get them). With LOADLIN, you simply execute
+ 6) correct operation the initrd environment can frequently be tested
+ even without rebooting with the command
+ # chroot /mnt /linuxrc
+ This is of course limited to initrds that do not interfere with the
+ general system state (e.g. by reconfiguring network interfaces,
+ overwriting mounted devices, trying to start already running demons,
+ etc. Note however that it is usually possible to use pivot_root in
+ such a chroot'ed initrd environment.)
+ 7) unmount the file system
+ # umount /mnt
+ 8) the initrd is now in the file "initrd". Optionally, it can now be
+ compressed
+ # gzip -9 initrd
+
+For experimenting with initrd, you may want to take a rescue floppy and
+only add a symbolic link from /linuxrc to /bin/sh. Alternatively, you
+can try the experimental newlib environment [2] to create a small
+initrd.
+
+Finally, you have to boot the kernel and load initrd. Almost all Linux
+boot loaders support initrd. Since the boot process is still compatible
+with an older mechanism, the following boot command line parameters
+have to be given:
+
+ root=/dev/ram0 init=/linuxrc rw
+
+if not using devfs, or
+
+ root=/dev/rd/0 init=/linuxrc rw
+
+if using devfs. (rw is only necessary if writing to the initrd file
+system.)
+
+With LOADLIN, you simply execute
LOADLIN <kernel> initrd=<disk_image>
-e.g. LOADLIN C:\LINUX\VMLINUZ initrd=C:\LINUX\INITRD
+e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0
+ init=/linuxrc rw
With LILO, you add the option INITRD=<path> to either the global section
-or to the section of the respective kernel in /etc/lilo.conf, e.g.
+or to the section of the respective kernel in /etc/lilo.conf, and pass
+the options using APPEND, e.g.
- image = /vmlinuz
- initrd = /boot/initrd
+ image = /bzImage
+ initrd = /boot/initrd.gz
+ append = "root=/dev/ram0 init=/linuxrc rw"
and run /sbin/lilo
+For other boot loaders, please refer to the respective documentation.
+
Now you can boot and enjoy using initrd.
-Setting the root device
------------------------
+Changing the root device
+------------------------
-By default, the standard settings in the kernel are used for the root
-device, i.e. the default compiled in or set with rdev, or what was passed
-with root=xxx on the command line, or, with LILO, what was specified in
-/etc/lilo.conf It is also possible to use initrd with an NFS-mounted
-root; you have to use the nfs_root_name and nfs_root_addrs boot options
-for this.
+When finished with its duties, linuxrc typically changes the root device
+and proceeds with starting the Linux system on the "real" root device.
-It is also possible to change the root device from within the initrd
-environment. In order to do so, /proc has to be mounted. Then, the
-following files are available:
+The procedure involves the following steps:
+ - mounting the new root file system
+ - turning it into the root file system
+ - removing all accesses to the old (initrd) root file system
+ - unmounting the initrd file system and de-allocating the RAM disk
- /proc/sys/kernel/real-root-dev
- /proc/sys/kernel/nfs-root-name
- /proc/sys/kernel/nfs-root-addrs
+Mounting the new root file system is easy: it just needs to be mounted on
+a directory under the current root. Example:
-real-root-dev can be changed by writing the number of the new root FS
-device to it, e.g.
+# mkdir /new-root
+# mount -o ro /dev/hda1 /new-root
- # echo 0x301 >/proc/sys/kernel/real-root-dev
+The root change is accomplished with the pivot_root system call, which
+is also available via the pivot_root utility (see pivot_root(8) man
+page; pivot_root is distributed with util-linux version 2.10h or higher
+[3]). pivot_root moves the current root to a directory under the new
+root, and puts the new root at its place. The directory for the old root
+must exist before calling pivot_root. Example:
+
+# cd /new-root
+# mkdir initrd
+# pivot_root . initrd
+
+Now, the linuxrc process may still access the old root via its
+executable, shared libraries, standard input/output/error, and its
+current root directory. All these references are dropped by the
+following command:
+
+# exec chroot . what-follows <dev/console >dev/console 2>&1
+
+Where what-follows is a program under the new root, e.g. /sbin/init
+If the new root file system will be used with devfs and has no valid
+/dev directory, devfs must be mounted before invoking chroot in order to
+provide /dev/console.
-for /dev/hda1. When using an NFS-mounted root, nfs-root-name and
-nfs-root-addrs have to be set accordingly and then real-root-dev has to
-be set to 0xff, e.g.
+Note: implementation details of pivot_root may change with time. In order
+to ensure compatibility, the following points should be observed:
- # echo /var/nfsroot >/proc/sys/kernel/nfs-root-name
- # echo 193.8.232.2:193.8.232.7::255.255.255.0:idefix \
- >/proc/sys/kernel/nfs-root-addrs
- # echo 255 >/proc/sys/kernel/real-root-dev
+ - before calling pivot_root, the current directory of the invoking
+ process should point to the new root directory
+ - use . as the first argument, and the _relative_ path of the directory
+ for the old root as the second argument
+ - a chroot program must be available under the old and the new root
+ - chroot to the new root afterwards
+ - use relative paths for dev/console in the exec command
-If the root device is set to the RAM disk, the root file system is not
-moved to /initrd, but the boot procedure is simply continued by starting
-init on the initial RAM disk.
+Now, the initrd can be unmounted and the memory allocated by the RAM
+disk can be freed:
+
+# umount /initrd
+# blockdev --flushbufs /dev/ram0 # /dev/rd/0 if using devfs
+
+It is also possible to use initrd with an NFS-mounted root, see the
+pivot_root(8) man page for details.
+
+Note: if linuxrc or any program exec'ed from it terminates for some
+reason, the old change_root mechanism is invoked (see section "Obsolete
+root change mechanism").
Usage scenarios
@@ -215,32 +253,30 @@ The main motivation for implementing initrd was to allow for modular
kernel configuration at system installation. The procedure would work
as follows:
- 1) systems boots from floppy or other media with a minimal kernel
- (e.g. support for RAM disks, initrd, a.out, and the ext2 FS) and
+ 1) system boots from floppy or other media with a minimal kernel
+ (e.g. support for RAM disks, initrd, a.out, and the Ext2 FS) and
loads initrd
2) /linuxrc determines what is needed to (1) mount the "real" root FS
(i.e. device type, device drivers, file system) and (2) the
distribution media (e.g. CD-ROM, network, tape, ...). This can be
done by asking the user, by auto-probing, or by using a hybrid
approach.
- 3) /linuxrc loads the necessary modules
+ 3) /linuxrc loads the necessary kernel modules
4) /linuxrc creates and populates the root file system (this doesn't
have to be a very usable system yet)
- 5) /linuxrc unmounts the root file system and possibly any other file
- systems it has mounted, sets /proc/sys/kernel/..., and terminates
- 6) the root file system is mounted
- 7) now that we're sure that the file system is accessible and intact,
- the boot loader can be installed
- 8) the boot loader is configured to load an initrd with the set of
+ 5) /linuxrc invokes pivot_root to change the root file system and
+ execs - via chroot - a program that continues the installation
+ 6) the boot loader is installed
+ 7) the boot loader is configured to load an initrd with the set of
modules that was used to bring up the system (e.g. /initrd can be
modified, then unmounted, and finally, the image is written from
- /dev/ram to a file)
- 9) now the system is bootable and additional installation tasks can be
+ /dev/ram0 or /dev/rd/0 to a file)
+ 8) now the system is bootable and additional installation tasks can be
performed
The key role of initrd here is to re-use the configuration data during
normal system operation without requiring the use of a bloated "generic"
-kernel or re-compilation or re-linking of the kernel.
+kernel or re-compiling or re-linking the kernel.
A second scenario is for installations where Linux runs on systems with
different hardware configurations in a single administrative domain. In
@@ -252,35 +288,53 @@ read by it would have to be different.
A third scenario are more convenient recovery disks, because information
like the location of the root FS partition doesn't have to be provided at
-boot time, but the system loaded from initrd can use a user-friendly
+boot time, but the system loaded from initrd can invoke a user-friendly
dialog and it can also perform some sanity checks (or even some form of
auto-detection).
-Last not least, CDROM distributors may use it for better installation from CD,
-either using a LILO boot floppy and bootstrapping a bigger RAM disk via
-initrd from CD, or using LOADLIN to directly load the RAM disk from CD
-without need of floppies.
+Last not least, CD-ROM distributors may use it for better installation
+from CD, e.g. by using a boot floppy and bootstrapping a bigger RAM disk
+via initrd from CD; or by booting via a loader like LOADLIN or directly
+from the CD-ROM, and loading the RAM disk from CD without need of
+floppies.
-Since initrd is a fairly generic mechanism, it is likely that additional
-uses will be found.
+Obsolete root change mechanism
+------------------------------
-Resources
----------
+The following mechanism was used before the introduction of pivot_root.
+Current kernels still support it, but you should _not_ rely on its
+continued availability.
+
+It works by mounting the "real" root device (i.e. the one set with rdev
+in the kernel image or with root=... at the boot command line) as the
+root file system when linuxrc exits. The initrd file system is then
+unmounted, or, if it is still busy, moved to a directory /initrd, if
+such a directory exists on the new root file system.
+
+In order to use this mechanism, you do not have to specify the boot
+command options root, init, or rw. (If specified, they will affect
+the real root file system, not the initrd environment.)
+
+If /proc is mounted, the "real" root device can be changed from within
+linuxrc by writing the number of the new root FS device to the special
+file /proc/sys/kernel/real-root-dev, e.g.
+
+ # echo 0x301 >/proc/sys/kernel/real-root-dev
+
+Note that the mechanism is incompatible with NFS and similar file
+systems.
-The bzImage+initrd patch (bzImage is an extension to load kernels directly
-above 1 MB, which allows kernels sizes of up to approximately 2 MB) can be
-found at
-ftp://lrcftp.epfl.ch/pub/people/almesber/lilo/bzImage+initrd-1.3.71.patch.gz
-and
-ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/bzImage+initrd-1.3.71.patch.gz
+This old, deprecated mechanism is commonly called "change_root", while
+the new, supported mechanism is called "pivot_root".
-A preliminary version of LOADLIN 1.6 is available on
-ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/loadlin-1.6-pre8-bin.tgz
-A preliminary version of LILO 18 is available on
-ftp://lrcftp.epfl.ch/pub/people/almesber/lilo/lilo.18dev3.tar.gz
+Resources
+---------
-A very simple example for building an image for initrd, also including
-the program 'freeramdisk', can be found on
-ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/initrd-example.tgz
+[1] Almesberger, Werner; "Booting Linux: The History and the Future"
+ ftp://icaftp.epfl.ch/pub/people/almesber/booting/bootinglinux-current.ps.gz
+[2] newlib package (experimental), with initrd example
+ ftp://icaftp.epfl.ch/pub/people/almesber/misc/newlib-linux/
+[3] Brouwer, Andries; "util-linux: Miscellaneous utilities for Linux"
+ ftp://ftp.win.tue.nl/pub/linux-local/utils/util-linux/
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index 0edc635ff..4fd9a4b5a 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -74,8 +74,8 @@ Code Seq# Include File Comments
0x22 all scsi/sg.h
'1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl
<ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
-'6' 00-10 <asm-i386/processor.h> Intel P6 microcode update driver
- <tigran@veritas.com>
+'6' 00-10 <asm-i386/processor.h> Intel IA32 microcode update driver
+ <mailto:tigran@veritas.com>
'8' all SNP8023 advanced NIC card
<mailto:mcr@solidum.com>
'A' 00-1F linux/apm_bios.h
diff --git a/Documentation/isdn/INTERFACE.fax b/Documentation/isdn/INTERFACE.fax
index 4c164b805..7e5731319 100644
--- a/Documentation/isdn/INTERFACE.fax
+++ b/Documentation/isdn/INTERFACE.fax
@@ -1,4 +1,4 @@
-$Id: INTERFACE.fax,v 1.1 1999/08/11 20:30:28 armin Exp $
+$Id: INTERFACE.fax,v 1.2 2000/08/06 09:22:50 armin Exp $
Description of the fax-subinterface between linklevel and hardwarelevel of
diff --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax
index 2dddf96ec..63308c20a 100644
--- a/Documentation/isdn/README.HiSax
+++ b/Documentation/isdn/README.HiSax
@@ -54,6 +54,7 @@ Sedlbauer ISDN-Controller PC/104
USR Sportster internal TA (compatible Stollmann tina-pp V3)
ith Kommunikationstechnik GmbH MIC 16 ISA card
Traverse Technologie NETjet PCI S0 card and NETspider U card
+Ovislink ISDN sc100-p card (NETjet driver)
Dr. Neuhaus Niccy PnP/PCI
Siemens I-Surf 1.0
Siemens I-Surf 2.0 (with IPAC, try type 12 asuscom)
@@ -191,8 +192,9 @@ Card types:
34 Gazel ISDN cards (PCI) none
35 HFC 2BDS0 PCI none
36 W6692 based PCI cards none
- 37 HFC 2BDS0 S+, SP/PCMCIA irq,io (pcmcia must be set with cardmgr)
+ 37 HFC 2BDS0 S+, SP irq,io
38 NETspider U PCI card none
+ 39 HFC 2BDS0 SP/PCMCIA irq,io (set with cardmgr)
At the moment IRQ sharing is only possible with PCI cards. Please make sure
that your IRQ is free and enabled for ISA use.
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 1b63892c6..ef789acf2 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -32,6 +32,8 @@ This document describes the Linux kernel Makefiles.
7.6 Compilation flags
7.7 Miscellaneous variables
8 New-style variables
+ 8.1 New variables
+ 8.2 Converting to old-style
9 Compatibility with Linux Kernel 2.2
10 Credits
@@ -521,6 +523,8 @@ contains boilerplate code which converts from new-style variables to
old-style variables. This is because Rules.make processes only the
old-style variables.
+See section 8.2 ("Converting to old-style") for examples.
+
--- 6.4 Rules.make section
@@ -679,6 +683,25 @@ The public interface of Rules.make consists of the following variables:
options still control whether or not its $(O_TARGET) goes into
vmlinux. See the $(M_OBJS) example below.
+ Sometimes the ordering of all $(OX_OBJS) files before all
+ $(O_OBJS) files can be a problem, particularly if both
+ $(O_OBJS) files and $(OX_OBJS) files contain __initcall
+ declarations where order is important. To avoid this imposed
+ ordering, the use of $(OX_OBJS) can be dropped altogether and
+ $(MIX_OBJS) used instead.
+
+ If this approach is used, then:
+ - All objects to be linked into vmlinux should be listed in
+ $(O_OBJS) in the desired order.
+ - All objects to be created as modules should be listed in
+ $(M_OBJS)
+ - All objects that export symbols should also be listed in
+ $(MIX_OBJS).
+
+ This has the same effect as maintaining the
+ exported/non-exported split, except that there is more control
+ over the ordering of object files in vmlinux.
+
--- 7.3 Library file goals
@@ -865,6 +888,14 @@ The public interface of Rules.make consists of the following variables:
$(LD) -r -o $@ $(sb-objs)
+ As is mentioned in section 7.2 ("Object file goals"),
+ $(MIX_OBJS) can also be used simply to list all objects that
+ export any symbols. If this approach is taken, then
+ $(O_OBJS), $(L_OBJS), $(M_OBJS) and $(MI_OBJS) should simply
+ lists all of the vmlinux object files, library object files,
+ module object files and intermediate module files
+ respectively. Duplication between $(MI_OBJS) and $(MIX_OBJS)
+ is not a problem.
--- 7.6 Compilation flags
@@ -993,6 +1024,8 @@ variables into old-style variables. There is also some mixing, where
people define most variables using "new style" but then fall back to
"old style" for a few lines.
+--- 8.1 New variables
+
obj-y obj-m obj-n obj-
These variables replace $(O_OBJS), $(OX_OBJS), $(M_OBJS),
@@ -1184,6 +1217,41 @@ people define most variables using "new style" but then fall back to
This means nls should be added to (subdir-y) and $(subdir-m) if
CONFIG_NFS = y.
+--- 8.2 Converting to old-style
+
+ The following example is taken from drivers/usb/Makefile.
+ Note that this uses MIX_OBJS to avoid the need for OX_OBJS and
+ MX_OBJS and thus to maintain the ordering of objects in $(obj-y)
+
+ # Translate to Rules.make lists.
+ multi-used := $(filter $(list-multi), $(obj-y) $(obj-m))
+ multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs))
+ active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m))
+
+ O_OBJS := $(obj-y)
+ M_OBJS := $(obj-m)
+ MIX_OBJS := $(filter $(export-objs), $(active-objs))
+
+ An example for libraries from drivers/acorn/scsi/Makefile:
+
+ # Translate to Rules.make lists.
+
+ L_OBJS := $(filter-out $(export-objs), $(obj-y))
+ LX_OBJS := $(filter $(export-objs), $(obj-y))
+ M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
+ MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
+
+ As ordering is not so important in libraries, this still uses
+ LX_OBJS and MX_OBJS, though (presumably) it could be changed to
+ use MIX_OBJS as follows:
+
+ active-objs := $(sort $(obj-y) $(obj-m))
+ L_OBJS := $(obj-y)
+ M_OBJS := $(obj-m)
+ MIX_OBJS := $(filter $(export-objs), $(active-objs))
+
+
+ which is clearly shorted and arguably clearer.
=== 9 Compatibility with Linux Kernel 2.2
diff --git a/Documentation/networking/irda.txt b/Documentation/networking/irda.txt
index fa455100e..a4b5a110d 100644
--- a/Documentation/networking/irda.txt
+++ b/Documentation/networking/irda.txt
@@ -1,10 +1,10 @@
To use the IrDA protocols within Linux you will need to get a suitable copy
of the IrDA Utilities. More detailed information about these and associated
-programs can be found on http://www.cs.uit.no/linux-irda/
+programs can be found on http://irda.sourceforge.net/
For more information about how to use the IrDA protocol stack, see the
-IR-HOWTO (http://www.snafu.de/~wehe/IR-HOWTO.html) written by Werner Heuser
-<wehe@snafu.de>
+IR-HOWTO (http://www.mobilix.org/Infrared-HOWTO/Infrared-HOWTO.html) written by Werner Heuser
+<wehe@mobilix.org>
There is an active mailing list for discussing Linux-IrDA matters called
linux-irda. To subscribe to it, visit:
diff --git a/Documentation/parisc/00-INDEX b/Documentation/parisc/00-INDEX
new file mode 100644
index 000000000..7c8494ea2
--- /dev/null
+++ b/Documentation/parisc/00-INDEX
@@ -0,0 +1,10 @@
+00-INDEX
+ - this file.
+IODC.txt
+ - Documentation IODC
+debugging
+ - some debugging hints for real-mode code
+mm
+ - Documentation on parisc mm status
+registers
+ - current/planned usage of registers
diff --git a/Documentation/parisc/IODC.txt b/Documentation/parisc/IODC.txt
new file mode 100644
index 000000000..d686536f1
--- /dev/null
+++ b/Documentation/parisc/IODC.txt
@@ -0,0 +1,68 @@
+Some notes on IODC, its general brokenness, and how to work around it.
+
+Short Version
+
+IODC is HP's pre-PCI standard for device identification (a la PCI vendor,
+device IDs), detection, configuration, initialization and so on.
+
+It also can provide firmware function to do the actual IO, which are slow,
+not really defined for runtime usage and generally not desirable. (There
+are other firmware standards, such as STI, to do real IO).
+
+Usually, there are two parts to IODC. The actual ROMs, which are laid out,
+detected aso in a bus-specific manner (IO_DC_ADDRESS / IO_DC_DATA on
+GSC/Runway, PCI spec - compliant ROMs for PCI, God-only-knows how on EISA),
+and the slightly cooked data read by PDC_IODC.
+
+The ROM layout is generally icky (only one byte out of every 4-byte-word
+might be valid, and many devices don't implement required options), so
+using PDC_IODC is highly recommended. (In fact, you should use the device
+lists set up by the kernel proper instead of calling PDC_IODC yourself).
+
+Now, let's have a look at what the cooked ROM looks like (see iodc.pdf for
+the details, this is the simplified version).
+
+Basically, the first 8 bytes of IODC contain two 32-bit ids called HVERSION
+and SVERSION. Those are further split up into bit fields, and
+unfortunately just ignoring this split up isn't an option.
+
+SVERSION consists of a 4-bit revision field, a 20-bit model field and a
+8-bit opt field. Now, forget the revision and opt fields exist. Basically,
+the model field is equivalent to a PCI device id (there is no vendor id.
+this is proprietary hardware we're talking about). That is, all your
+driver cares for, in 90 % of the cases, is to find all devices that match
+the model field.
+
+The rev field is - you guessed it - roughly equivalent to the revision
+byte for PCI, with the exception that higher revisions should be strict
+supersets of lower revisions.
+
+The last byte of HVERSION, "type", and the last byte of SVERSION, "opt",
+belong together; type gives a very rough indication of what the device
+is supposed to do, and opt contains some type-specific information. (For
+example, the "bus converter" (ie bus bridge) type encodes the kind of
+bus behind the bridge in the opt field.
+
+The rest of HVERSION contains, in most cases, a number identifying the
+machine the chip was used in, or a revision indicator that just fixed
+bugs and didn't add any features (or was done in a shrinked process or
+whatever).
+
+So, here's the interface you actually should use to find your devices:
+
+
+/* Find a device, matching the model field of sversion only (from=NULL
+ * for the first call */
+struct iodc_dev *iodc_find_device(u32 sversion, struct iodc_dev *from);
+
+
+Here's a function you should use if you have special requirements, such
+as finding devices by type rather than by model. Generally, if you're
+using this, you should be me).
+
+/* Find a device, masking out bits as specified */
+struct iodc_dev *iodc_find_device_mask(u32 hversion, u32 sversion,
+ u32 hversion_mask, u32 sversion_mask, struct iodc_dev *from);
+
+
+ Philipp Rumpf <prumpf@tux.org>
diff --git a/Documentation/parisc/debugging b/Documentation/parisc/debugging
new file mode 100644
index 000000000..5e060917a
--- /dev/null
+++ b/Documentation/parisc/debugging
@@ -0,0 +1,39 @@
+okay, here are some hints for debugging the lower-level parts of
+linux/parisc.
+
+
+1. Absolute addresses
+
+A lot of the assembly code currently runs in real mode, which means
+absolute addresses are used instead of virtual addresses as in the
+rest of the kernel. To translate an absolute address to a virtual
+address you can lookup in System.map, add __PAGE_OFFSET (0xc0000000
+currently).
+
+
+2. HPMCs
+
+When real-mode code tries to access non-existent memory, you'll get
+an HPMC instead of a kernel oops. To debug an HPMC, try to find
+the System Responder/Requestor addresses. The System Requestor
+address should match (one of the) processor HPAs (high addresses in
+the I/O range); the System Responder address is the address real-mode
+code tried to access.
+
+Typical values for the System Responder address are addresses larger
+than __PAGE_OFFSET (0xc0000000) which mean a virtual address didn't
+get translated to a physical address before real-mode code tried to
+access it.
+
+
+3. Q bit fun
+
+Certain, very critical code has to clear the Q bit in the PSW. What
+happens when the Q bit is cleared is the CPU does not update the
+registers interruption handlers read to find out where the machine
+was interrupted - so if you get an interruption between the instruction
+that clears the Q bit and the RFI that sets it again you don't know
+where exactly it happened. If you're lucky the IAOQ will point to the
+instrucion that cleared the Q bit, if you're not it points anywhere
+at all. Usually Q bit problems will show themselves in unexplainable
+system hangs or running off the end of physical memory.
diff --git a/Documentation/parisc/mm b/Documentation/parisc/mm
new file mode 100644
index 000000000..d53b29508
--- /dev/null
+++ b/Documentation/parisc/mm
@@ -0,0 +1,31 @@
+
+The current state of Linux/PA-RISC mm is BROKEN.
+
+Someone needs to sit down and thoroughly rewrite all the cache flushing
+macro definitions. Here are some of the problems, followed by what I
+think needs to be done about them.
+
+(1) We're using fdce / fice everywhere. This has to stop (except in
+the routines which flush the entire cache). The right instructions to
+be using are fdc/fic.
+
+(2) fdc/fic will throw exceptions if the address they reference isn't
+mapped. Therefore we need to check the page is mapped before flushing
+(we're guaranteed not to have the page dirty if we don't have a software
+mapping for it any longer, right?)
+
+(3) the flush macros are right now tunnelled down to one routine to flush
+the data cache and one routine to flush the insn cache. this is wrong.
+we should take hints from how we're called and optimise our routines
+accordingly.
+
+(4) fdc/fic actually take space register arguments. fic takes an 3-bit sr
+argument and fdc takes a 2-bit sr argument. right now, there's a lot of
+pissing about with %sr1 and all the macros use %sr1. This is crazy. We
+normally _know_ what's being referred to, and it's the current task. So
+if we want to flush that, just use %sr3. If it happens to be kernel,
+use %sr0 for fdc and %sr4 for fic.
+
+(5) we need to write flush_kernel_dcache_range and use it on kernel
+addresses. all the macros are defined to work on the _current task's_
+virtual address space.
diff --git a/Documentation/parisc/registers b/Documentation/parisc/registers
new file mode 100644
index 000000000..28097fe49
--- /dev/null
+++ b/Documentation/parisc/registers
@@ -0,0 +1,126 @@
+Register Usage for Linux/PA-RISC
+
+[ an asterisk is used for planned usage which is currently unimplemented ]
+
+ General Registers as specified by ABI
+
+ FPU Registers must not be used in kernel mode
+
+ Control Registers
+
+CR 0 (Recovery Counter) used for ptrace
+CR 1-CR 7(undefined) unused
+CR 8 (Protection ID) per-process value*
+CR 9, 12, 13 (PIDS) unused
+CR10 (CCR) lazy FPU saving*
+CR11 as specified by ABI
+CR14 (interruption vector) initialized to fault_vector
+CR15 (EIEM) initialized to all ones*
+CR16 (Interval Timer) timer interrupt
+CR17-CR22 interruption parameters
+CR23 (EIRR) read for pending interrupts
+CR24 (TR 0) Kernel Space Page Directory Pointer
+CR25 (TR 1) User Space Page Directory Pointer
+CR26 (TR 2)
+CR27 (TR 3)
+CR28 (TR 4) used by interruption handlers
+CR29 (TR 5) used by interruption handlers
+CR30 (TR 6) current / 0
+CR31 (TR 7) used by interruption handlers
+
+ Space Registers (kernel mode)
+
+SR0 temporary space register
+SR4-SR7 set to 0
+SR1 temporary space register
+SR2 unused
+SR3 used for userspace accesses (current process)*
+
+ Space Registers (user mode)
+
+SR0 temporary space register
+SR1 temporary space register
+SR2 holds space of linux gateway page
+SR3 holds user address space value while in kernel
+SR4-SR7 Defines short address space for user/kernel
+
+
+ Processor Status Word
+
+W (64-bit addresses) 0
+E (Little-endian) 0
+S (Secure Interval Timer) 0
+T (Taken Branch Trap) 0
+H (Higher-privilege trap) 0
+L (Lower-privilege trap) 0
+N (Nullify next instruction) used by C code
+X (Data memory break disable) 0
+B (Taken Branch) used by C code
+C (code address translation) 1, 0 while executing real-mode code
+V (divide step correction) used by C code
+M (HPMC mask) 0, 1 while executing HPMC handler*
+C/B (carry/borrow bits) used by C code
+O (ordered references) 1*
+F (performance monitor) 0
+R (Recovery Counter trap) 0
+Q (collect interruption state) 1 (0 in code directly preceding an rfi)
+P (Protection Identifiers) 1*
+D (Data address translation) 1, 0 while executing real-mode code
+I (external interrupt mask) used by cli()/sti() macros
+
+ "Invisible" Registers
+
+PSW default W value 0
+PSW default E value 0
+Shadow Registers used by interruption handler code
+TOC enable bit 1
+
+=========================================================================
+Info from John Marvin:
+
+From: "John Marvin" <jsm@udlkern.fc.hp.com>
+To: randolf@tausq.org
+Subject: Re: parisc asm questions
+
+[...]
+
+For the general registers:
+
+r1,r2,r19-r26,r28,r29 & r31 can be used without saving them first. And of
+course, you need to save them if you care about them, before calling
+another procedure. Some of the above registers do have special meanings
+that you should be aware of:
+
+ r1: The addil instruction is hardwired to place its result in r1,
+ so if you use that instruction be aware of that.
+
+ r2: This is the return pointer. In general you don't want to
+ use this, since you need the pointer to get back to your
+ caller. However, it is grouped with this set of registers
+ since the caller can't rely on the value being the same
+ when you return, i.e. you can copy r2 to another register
+ and return through that register after trashing r2, and
+ that should not cause a problem for the calling routine.
+
+ r19-r22: these are generally regarded as temporary registers.
+ Note that in 64 bit they are arg7-arg4.
+
+ r23-r26: these are arg3-arg0, i.e. you can use them if you
+ don't care about the values that were passed in anymore.
+
+ r28,r29: are ret0 and ret1. They are what you pass return values
+ in. r28 is the primary return. I'm not sure I remember
+ under what circumstances stuff is returned in r29 (millicode
+ perhaps).
+
+ r31: the ble instruction puts the return pointer in here.
+
+
+r3-r18,r27,r30 need to be saved and restored. r3-r18 are just
+ general purpose registers. r27 is the data pointer, and is
+ used to make references to global variables easier. r30 is
+ the stack pointer.
+
+John
+
+
diff --git a/Documentation/sound/CMI8330 b/Documentation/sound/CMI8330
index 8885d3307..287799884 100644
--- a/Documentation/sound/CMI8330
+++ b/Documentation/sound/CMI8330
@@ -57,7 +57,7 @@ How to enable CMI 8330 (SOUNDPRO) soundchip on Linux
------------------------------------------
Stefan Laudat <Stefan.Laudat@asit.ro>
-[Note: The CMI 8338 is unrelated and right now unsupported]
+[Note: The CMI 8338 is unrelated and is supported by cmpci.o]
In order to use CMI8330 under Linux you just have to use a proper isapnp.conf, a good isapnp and a little bit of patience. I use isapnp 1.17, but
diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt
index 7d99567ad..234c75cf3 100644
--- a/Documentation/usb/URB.txt
+++ b/Documentation/usb/URB.txt
@@ -1,3 +1,5 @@
+Revised: 2000-Dec-05.
+
1. Specification of the API
1.1. Basic concept or 'What is an URB?'
@@ -8,16 +10,16 @@ called USB Request Block, or URB for short.
- An URB consists of all relevant information to execute any USB transaction
and deliver the data and status back.
-- Execution of an URB is an inherently asynchronous operation, i.e. the
-submit_urb(urb) call returns immediately after it has successfully queued
+- Execution of an URB is inherently an asynchronous operation, i.e. the
+usb_submit_urb(urb) call returns immediately after it has successfully queued
the requested action.
- Ongoing transfers for one URB (e.g. ISO) can simply be canceled with
-unlink_urb(urb) at any time.
+usb_unlink_urb(urb) at any time.
- Each URB has a completion handler, which is called after the action
has been successfully completed or canceled (INT transfers behave a bit
-different, see below). The URB also contains a context-pointer for free
+differently, see below). The URB also contains a context-pointer for free
usage and information passing to the completion handler.
- URBs can be linked. After completing one URB, the next one can be
@@ -31,6 +33,8 @@ URB-machinery.
typedef struct urb
{
+ spinlock_t lock; // lock for the URB
+
// ignore, for host controller/URB machine internal use
void *hcpriv; // private data for host controller
struct list_head urb_list; // list pointer to all active urbs
@@ -39,12 +43,12 @@ typedef struct urb
struct urb* next; // pointer to next URB
struct usb_device *dev; // pointer to associated USB device
-// pipe is assembled by the various well known pipe-macros in usb.h
+// pipe is assembled by the various well-known pipe macros in usb.h
unsigned int pipe; // pipe information
// status after each completion
int status; // returned status
- unsigned int transfer_flags; // ASAP, SP_OK, etc.
+ unsigned int transfer_flags; // ASAP, DISABLE_SPD, etc.
// for data stage (CTRL), BULK, INT and ISO
void *transfer_buffer; // associated data buffer
@@ -55,7 +59,7 @@ typedef struct urb
// setup stage for CTRL (always 8 bytes!)
unsigned char* setup_packet; // setup packet (control only)
-
+
// with ASAP, start_frame is set to the determined frame
int start_frame; // start frame (iso/irq)
int number_of_packets; // # of packets (iso/int)
@@ -66,7 +70,7 @@ typedef struct urb
usb_complete_t complete; // pointer to completion routine
//
// specification of the requested data offsets and length for ISO
- iso_packet_descriptor_t iso_frame_desc[0];
+ iso_packet_descriptor_t iso_frame_desc[0];
} urb_t, *purb_t;
@@ -74,7 +78,7 @@ typedef struct urb
URBs are allocated with the following call
- purb_t alloc_urb(int isoframes)
+ purb_t usb_alloc_urb(int isoframes)
Return value is a pointer to the allocated URB, 0 if allocation failed.
The parameter isoframes specifies the number of isochronous transfer frames
@@ -82,7 +86,7 @@ you want to schedule. For CTRL/BULK/INT, use 0.
To free an URB, use
- void free_urb(purb_t purb)
+ void usb_free_urb(purb_t purb)
This call also may free internal (host controller specific) memory in the
future.
@@ -91,12 +95,13 @@ future.
1.4. What has to be filled in?
Depending on the type of transaction, there are some macros
-(FILL_CONTROL_URB, FILL_BULK_URB, and FILL_INT_URB, defined in uhci.h)
+(FILL_CONTROL_URB, FILL_CONTROL_URB_TO, FILL_BULK_URB,
+FILL_BULK_URB_TO, and FILL_INT_URB, defined in usb.h)
that simplify the URB creation. In general, all macros need the usb
-device pointer, the pipe (usual format), the transfer buffer, the
-desired transfer length, the completion handler, and its context.
-Take a look at the uhci_control_msg-function that convert the old API
-into an URB.
+device pointer, the pipe (usual format from usb.h), the transfer buffer,
+the desired transfer length, the completion handler, and its context.
+Take a look at the usb_control_msg function that converts the old API
+into the URB API.
Flags:
For ISO there are two startup behaviors: Specified start_frame or ASAP.
@@ -114,7 +119,7 @@ re-submission for INT transfers that are being continued.
Just call
- int submit_urb(purb_t purb)
+ int usb_submit_urb(purb_t purb)
It immediately returns, either with status 0 (request queued) or some
error code, usually caused by the following:
@@ -128,7 +133,7 @@ error code, usually caused by the following:
- Invalid INT interval (-EINVAL)
- More than one packet for INT (-EINVAL)
-After submission, urb->status is USB_ST_URB_PENDING.
+After submission, urb->status is USB_ST_URB_PENDING (-EINPROGRESS).
For isochronous endpoints, subsequent submitting of URBs to the same endpoint
with the ASAP flag result in a seamless ISO streaming. Exception: The
@@ -142,18 +147,18 @@ independent of the transfer flags (implicitly ASAP).
For an URB which you've submitted, but which hasn't been returned to
your driver by the host controller, call
- int unlink_urb(purb_t purb)
+ int usb_unlink_urb(purb_t purb)
It removes the urb from the internal list and frees all allocated
HW descriptors. The status is changed to USB_ST_URB_KILLED. After
-unlink_urb() returns, you can safely free the URB with free_urb(urb)
+usb_unlink_urb() returns, you can safely free the URB with usb_free_urb(urb)
and all other possibly associated data (urb->context etc.)
There is also an asynchronous unlink mode. To use this, set the
the USB_ASYNC_UNLINK flag in urb->transfer flags before calling
usb_unlink_urb(). When using async unlinking, the URB will not
-normally be unlinked when unlink_urb() returns. Instead, wait for
-the completion handler to be called.
+normally be unlinked when usb_unlink_urb() returns. Instead, wait
+for the completion handler to be called.
1.7. What about the completion handler?
@@ -187,13 +192,13 @@ in completion handlers.
1.8. How to do isochronous (ISO) transfers?
For ISO transfers you have to append the iso_packet_descriptor_t structure
-to the URB for each frame you want to schedule. When using alloc_urb(n)
-(recommended), the isoframe-parameter n can be used to allocate the
-structures for n frames.
+to the URB for each frame you want to schedule. When using usb_alloc_urb(n)
+(recommended), the iso_packets parameter can be used to allocate the
+structures for iso_packets frames.
For each entry you have to specify the data offset for this frame (base is
transfer_buffer), and the length you want to write/expect to read.
-After completion, actual_length contains the actual transfered length and
+After completion, actual_length contains the actual transferred length and
status contains the resulting USB-status for the ISO transfer for this frame.
It is allowed to specify a varying length from frame to frame (e.g. for
audio synchronisation/adaptive transfer rates). You can also use the length
@@ -217,7 +222,7 @@ for 1, 2, 4,... 128ms. Only one URB is allocated for each interrupt. After
calling the completion handler, that URB is recycled by the host controller
driver (HCD).
With the submission of one URB, the interrupt is scheduled until it is
-canceled by unlink_urb.
-
-The submit_urb()-call modifies urb->interval to the rounded value.
+canceled by usb_unlink_urb.
+The usb_submit_urb() call modifies urb->interval to the implemented interval
+value that is less than or equal to the requested interval value.
diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
index d1dccece5..964af3033 100644
--- a/Documentation/usb/error-codes.txt
+++ b/Documentation/usb/error-codes.txt
@@ -1,12 +1,12 @@
-$Id: README.error-codes,v 1.1 1999/12/14 14:03:02 fliegl Exp $
+Revised: 2000-Dec-05.
This is the documentation of (hopefully) all possible error codes (and
-their interpretation) that can be returned from the hostcontroller driver
+their interpretation) that can be returned from the host controller drivers
and from usbcore.
NOTE:
-The USB_ST_* codes are deferred and are only listed for compatibility, new
-software should use only -E* instead!
+The USB_ST_* codes are deprecated and are only listed for compatibility;
+new software should use only -E* instead!
@@ -25,12 +25,16 @@ USB-specific:
-ENODEV specified USB-device or bus doesn't exist
--ENXIO specified endpoint doesn't exist on the device
+USB_ST_REQUEST_ERROR
+-ENXIO a control or interrupt URB is already queued to this endpoint; or
+ a bulk URB is already queued to this endpoint and
+ USB_QUEUE_BULK wasn't used (UHCI HCDs only)
USB_ST_URB_INVALID_ERROR
-EINVAL a) Invalid transfer type specified (or not supported)
b) Invalid interrupt interval (0<=n<256)
c) more than one interrupt packet requested
+ d) ISO: number_of_packets is < 0
-EAGAIN a) specified ISO start frame too early
b) (using ISO-ASAP) too much scheduled for the future
@@ -38,6 +42,7 @@ USB_ST_URB_INVALID_ERROR
-EFBIG too much ISO frames requested (currently uhci>900)
+USB_ST_STALL
-EPIPE specified pipe-handle is already stalled
-EMSGSIZE endpoint message size is zero, do interface/alternate setting
@@ -59,7 +64,7 @@ USB_ST_NOERROR
0 Transfer completed successfully
USB_ST_URB_KILLED
--ENOENT URB was canceled by unlink_urb
+-ENOENT URB was canceled by usb_unlink_urb
USB_ST_URB_PENDING
-EINPROGRESS URB still pending, no results yet
@@ -73,12 +78,28 @@ USB_ST_INTERNALERROR
USB_ST_CRC
-EILSEQ CRC mismatch
+USB_ST_STALL
-EPIPE a) babble detect
b) endpoint stalled
-USB_ST_BUFFERUNDERRUN
--ENOST buffer error
+USB_ST_BUFFEROVERRUN
+-ECOMM During an IN transfer, the host controller
+ received data from an endpoint faster than it
+ could be written to system memory
+USB_ST_BUFFERUNDERRUN
+-ENOSR During an OUT transfer, the host controller
+ could not retrieve data from system memory fast
+ enough to keep up with the USB data rate
+
+USB_ST_DATAOVERRUN
+-EOVERFLOW The amount of data returned by the endpoint was
+ greater than either the max packet size of the
+ endpoint or the remaining buffer size
+
+USB_ST_DATAUNDERRUN
+-EREMOTEIO The endpoint returned less than max packet size
+ and that amount did not fill the specified buffer
USB_ST_NORESPONSE
USB_ST_TIMEOUT
-ETIMEDOUT transfer timed out, NAK
@@ -104,14 +125,7 @@ USB_ST_URB_INVALID_ERROR
**************************************************************************
usb_register():
-USB_ST_NOTSUPPORTED
-EINVAL error during registering new driver
-usb_terminate_bulk():
-USB_ST_REMOVED
--ENODEV urb already removed
-
usb_get_*/usb_set_*():
All USB errors (submit/status) can occur
-
-
diff --git a/Documentation/usb/usb-help.txt b/Documentation/usb/usb-help.txt
index 5ad2aaa57..98ade189e 100644
--- a/Documentation/usb/usb-help.txt
+++ b/Documentation/usb/usb-help.txt
@@ -7,6 +7,7 @@ linux/Documentation/usb/*, see the following:
Linux-USB project: http://www.linux-usb.org
mirrors at http://www.suse.cz/development/linux-usb/
and http://usb.in.tum.de/linux-usb/
+ and http://it.linux-usb.org
Linux USB Guide: http://linux-usb.sourceforge.net
Linux-USB device overview (working devices and drivers):
http://www.qbik.ch/usb/devices/
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
index a6efeefa5..2fc5ac8eb 100644
--- a/Documentation/usb/usb-serial.txt
+++ b/Documentation/usb/usb-serial.txt
@@ -139,6 +139,9 @@ Digi AccelePort Driver
(plus a parallel port) and 4 port USB serial converters. The driver
does NOT yet support the Digi AccelePort USB 8.
+ This driver works under SMP with the usb-uhci driver. It does not
+ work under SMP with the uhci driver.
+
The driver is generally working, though we still have a few more ioctls
to implement and final testing and debugging to do. The paralled port
on the USB 2 is supported as a serial to parallel converter; in other
@@ -182,6 +185,33 @@ TO DO List:
-- Add everything else that is missing :)
+Empeg empeg-car Mark I/II Driver (empeg.c)
+
+ This is an experimental driver to provide connectivity support for the
+ client synchronization tools for an Empeg empeg-car mp3 player.
+
+ Tips:
+
+ * Don't forget to create the device nodes for ttyUSB{0,1,2,...}
+ * modprobe empeg (modprobe is your friend)
+ * emptool --usb /dev/ttyUSB0 (or whatever you named your device node)
+
+ The driver is still pretty new, so some testing 'in the wild' would be
+ helpful. :)
+
+
+MCT USB Single Port Serial Adapter U232
+
+ This driver is for the MCT USB-RS232 Converter (25 pin, Model No.
+ U232-P25) from Magic Control Technology Corp. (there is also a 9 pin
+ Model No. U232-P9). More information about this device can be found
+ at the manufacture's web-site: http://www.mct.com.tw.
+
+ The driver is generally working, though it still needs some more
+ testing. It is derived from the Belkin USB Serial Adapter F5U103
+ driver and its TODO list is valid for this driver as well.
+
+
Generic Serial driver
If your device is not one of the above listed devices, compatible with
diff --git a/MAINTAINERS b/MAINTAINERS
index 072d1da5d..16e3b02a6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -216,6 +216,13 @@ M: jgarzik@mandrakesoft.com
L: linux-fbdev@vuser.vu.union.edu
S: Odd Fixes
+CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
+P: Cirrus Logic Corporation (kernel 2.2 driver)
+M: Cirrus Logic Corporation, Thomas Woller <twoller@crystal.cirrus.com>
+P: Nils Faerber (port to kernel 2.4)
+M: Nils Faerber <nils@kernelconcepts.de>
+S: Maintained
+
COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
P: Amy Vanzant-Hodge
M: Amy Vanzant-Hodge (fibrechannel@compaq.com)
@@ -393,7 +400,7 @@ S: Maintained
EATA ISA/EISA/PCI SCSI DRIVER
P: Dario Ballabio
-M: dario@milano.europe.dg.com
+M: ballabio_dario@emc.com
L: linux-scsi@vger.kernel.org
S: Maintained
@@ -633,7 +640,7 @@ M: jgarzik@mandrakesoft.com
W: http://sourceforge.net/projects/gkernel/
S: Maintained
-INTEL P6 MICROCODE UPDATE SUPPORT
+INTEL IA32 MICROCODE UPDATE SUPPORT
P: Tigran Aivazian
M: tigran@veritas.com
S: Maintained
@@ -651,9 +658,9 @@ S: Maintained
IRDA SUBSYSTEM
P: Dag Brattli
-M: Dag Brattli <dagb@cs.uit.no>
+M: Dag Brattli <dag@brattli.net>
L: linux-irda@pasta.cs.uit.no
-W: http://www.cs.uit.no/linux-irda/
+W: http://irda.sourceforge.net/
S: Maintained
ISAPNP
@@ -1223,7 +1230,7 @@ S: Maintained
U14-34F SCSI DRIVER
P: Dario Ballabio
-M: dario@milano.europe.dg.com
+M: ballabio_dario@emc.com
L: linux-scsi@vger.kernel.org
S: Maintained
@@ -1325,7 +1332,7 @@ M: pberger@brimson.com
M: alborchers@steinerpoint.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
-S: Supported
+S: Maintained
USB SERIAL KEYSPAN DRIVER
P: Hugh Blemings
@@ -1351,6 +1358,13 @@ L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
+USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
+P: Gary Brubaker
+M: xavyer@ix.netcom.com
+L: linux-usb-users@lists.sourceforge.net
+L: linux-usb-devel@lists.sourceforge.net
+S: Maintained
+
USB MASS STORAGE DRIVER
P: Matthew Dharm
M: mdharm-usb@one-eyed-alien.net
diff --git a/Makefile b/Makefile
index 6de1193ef..d673a5db4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 0
-EXTRAVERSION = -test11
+EXTRAVERSION = -test12
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
@@ -206,7 +206,6 @@ MRPROPER_FILES = \
drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h \
drivers/net/hamradio/soundmodem/sm_tbl_{afsk2400_7,afsk2400_8}.h \
drivers/net/hamradio/soundmodem/gentbl \
- drivers/char/hfmodem/gentbl drivers/char/hfmodem/tables.h \
drivers/sound/*_boot.h drivers/sound/.*.boot \
drivers/sound/msndinit.c \
drivers/sound/msndperm.c \
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 44ae94a99..c07b25764 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -36,6 +36,10 @@ ifeq ($(have_mcpu),y)
CFLAGS := $(CFLAGS) -mcpu=ev5
mcpu_done := y
endif
+ ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy)
+ CFLAGS := $(CFLAGS) -mcpu=pca56
+ mcpu_done := y
+ endif
ifeq ($(mcpu_done)$(CONFIG_ALPHA_PYXIS),ny)
CFLAGS := $(CFLAGS) -mcpu=ev56
mcpu_done := y
@@ -48,14 +52,14 @@ ifeq ($(have_mcpu),y)
endif
mcpu_done := y
endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_NAUTILUS)$(have_mcpu_ev67),nyy)
- CFLAGS := $(CFLAGS) -mcpu=ev67
- mcpu_done := y
- endif
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny)
CFLAGS := $(CFLAGS) -mcpu=ev4
mcpu_done := y
endif
+ ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy)
+ CFLAGS := $(CFLAGS) -mcpu=ev67
+ mcpu_done := y
+ endif
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny)
ifeq ($(have_mcpu_ev6),y)
CFLAGS := $(CFLAGS) -mcpu=ev6
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index da5c361c9..649047e66 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -56,7 +56,7 @@ choice 'Alpha system type' \
Wildfire CONFIG_ALPHA_WILDFIRE" Generic
# clear all implied options (don't want default values for those):
-unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
+unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 CONFIG_ALPHA_EV67
unset CONFIG_ALPHA_EISA
unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS
@@ -138,16 +138,12 @@ if [ "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_EIGER" = "y" ]
then
define_bool CONFIG_ALPHA_EV6 y
define_bool CONFIG_ALPHA_TSUNAMI y
+ bool 'EV67 (or later) CPU (speed > 600MHz)?' CONFIG_ALPHA_EV67
fi
-if [ "$CONFIG_ALPHA_WILDFIRE" = "y" ]
+if [ "$CONFIG_ALPHA_WILDFIRE" = "y" -o "$CONFIG_ALPHA_TITAN" = "y" ]
then
- define_bool CONFIG_PCI y
- define_bool CONFIG_ALPHA_EV6 y
-fi
-if [ "$CONFIG_ALPHA_TITAN" = "y" ]
-then
- define_bool CONFIG_PCI y
define_bool CONFIG_ALPHA_EV6 y
+ define_bool CONFIG_ALPHA_EV67 y
fi
if [ "$CONFIG_ALPHA_RAWHIDE" = "y" ]
then
@@ -165,8 +161,9 @@ then
fi
if [ "$CONFIG_ALPHA_NAUTILUS" = "y" ]
then
- define_bool CONFIG_ALPHA_EV6 y
define_bool CONFIG_ALPHA_IRONGATE y
+ define_bool CONFIG_ALPHA_EV6 y
+ define_bool CONFIG_ALPHA_EV67 y
fi
if [ "$CONFIG_ALPHA_JENSEN" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
index 1b1f46867..6203b0247 100644
--- a/arch/alpha/kernel/core_cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -119,6 +119,7 @@ conf_read(unsigned long addr, unsigned char type1)
stat0 = *(vip)CIA_IOC_CIA_ERR;
*(vip)CIA_IOC_CIA_ERR = stat0;
mb();
+ *(vip)CIA_IOC_CIA_ERR; /* re-read to force write */
/* If Type1 access, must set CIA CFG. */
if (type1) {
@@ -128,6 +129,7 @@ conf_read(unsigned long addr, unsigned char type1)
*(vip)CIA_IOC_CFG;
}
+ mb();
draina();
mcheck_expected(0) = 1;
mcheck_taken(0) = 0;
@@ -171,6 +173,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
stat0 = *(vip)CIA_IOC_CIA_ERR;
*(vip)CIA_IOC_CIA_ERR = stat0;
mb();
+ *(vip)CIA_IOC_CIA_ERR; /* re-read to force write */
/* If Type1 access, must set CIA CFG. */
if (type1) {
@@ -180,6 +183,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
*(vip)CIA_IOC_CFG;
}
+ mb();
draina();
mcheck_expected(0) = 1;
mcheck_taken(0) = 0;
@@ -188,7 +192,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
/* Access configuration space. */
*(vip)addr = value;
mb();
- mb(); /* magic */
+ *(vip)addr; /* read back to force the write */
mcheck_expected(0) = 0;
mb();
@@ -606,7 +610,8 @@ do_init_arch(int is_pyxis)
*(vip)CIA_IOC_ERR_MASK = temp;
/* Clear all currently pending errors. */
- *(vip)CIA_IOC_CIA_ERR = 0;
+ temp = *(vip)CIA_IOC_CIA_ERR;
+ *(vip)CIA_IOC_CIA_ERR = temp;
/* Turn on mchecks. */
temp = *(vip)CIA_IOC_CIA_CTRL;
@@ -695,11 +700,11 @@ do_init_arch(int is_pyxis)
*(vip)CIA_IOC_PCI_W1_BASE = 0x40000000 | 1;
*(vip)CIA_IOC_PCI_W1_MASK = (0x40000000 - 1) & 0xfff00000;
- *(vip)CIA_IOC_PCI_T1_BASE = 0;
+ *(vip)CIA_IOC_PCI_T1_BASE = 0 >> 2;
*(vip)CIA_IOC_PCI_W2_BASE = 0x80000000 | 1;
*(vip)CIA_IOC_PCI_W2_MASK = (0x40000000 - 1) & 0xfff00000;
- *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000;
+ *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000 >> 2;
*(vip)CIA_IOC_PCI_W3_BASE = 0;
}
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 1b83bdfb9..ddf3d9755 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -8,6 +8,11 @@
/* 2.3.x PCI/resources, 1999 Andrea Arcangeli <andrea@suse.de> */
+/*
+ * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+ * PCI-PCI bridges cleanup
+ */
+
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -51,13 +56,13 @@ struct pci_controler *pci_isa_hose;
static void __init
quirk_eisa_bridge(struct pci_dev *dev)
{
- dev->class = PCI_CLASS_BRIDGE_EISA;
+ dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
static void __init
quirk_isa_bridge(struct pci_dev *dev)
{
- dev->class = PCI_CLASS_BRIDGE_ISA;
+ dev->class = PCI_CLASS_BRIDGE_ISA << 8;
}
static void __init
@@ -71,6 +76,24 @@ quirk_ali_ide_ports(struct pci_dev *dev)
dev->resource[3].end = dev->resource[3].start + 7;
}
+/*
+ * Notorious Cy82C693 chip. One of its numerous bugs: although
+ * Cypress IDE controller doesn't support native mode, it has
+ * programmable addresses of IDE command/control registers.
+ * This violates PCI specifications, confuses IDE subsystem
+ * and causes resource conflict between primary HD_CMD register
+ * and floppy controller. Ugh.
+ * Fix that.
+ */
+static void __init
+quirk_cypress_ide_ports(struct pci_dev *dev)
+{
+ if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE)
+ return;
+ dev->resource[0].flags = 0;
+ dev->resource[1].flags = 0;
+}
+
static void __init
quirk_vga_enable_rom(struct pci_dev *dev)
{
@@ -78,7 +101,6 @@ quirk_vga_enable_rom(struct pci_dev *dev)
But if its a Cirrus 543x/544x DISABLE it, since
enabling ROM disables the memory... */
if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA &&
- /* But if its a Cirrus 543x/544x DISABLE it */
(dev->vendor != PCI_VENDOR_ID_CIRRUS ||
(dev->device < 0x00a0) || (dev->device > 0x00ac)))
{
@@ -98,6 +120,8 @@ struct pci_fixup pcibios_fixups[] __initdata = {
quirk_isa_bridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229,
quirk_ali_ide_ports },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
+ quirk_cypress_ide_ports },
{ PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_vga_enable_rom },
{ 0 }
};
@@ -122,18 +146,12 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size)
start = PCIBIOS_MIN_IO + hose->io_space->start;
/*
- * Aligning to 0x800 rather than the minimum base of
- * 0x400 is an attempt to avoid having devices in
- * any 0x?C?? range, which is where the de4x5 driver
- * probes for EISA cards.
- *
- * Adaptecs, especially, resent such intrusions.
- *
- * The de4x5 driver has the eisa probe conditionalized
- * out for Alpha, so lower the minimum base back to 0x400.
+ * Put everything into 0x00-0xff region modulo 0x400
*/
- alignto = MAX(0x400, size);
- start = ALIGN(start, alignto);
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
}
else if (res->flags & IORESOURCE_MEM) {
/* Make sure we start at our min on all hoses */
@@ -181,44 +199,6 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size)
#undef MB
#undef GB
-/*
- * Pre-layout host-independant device initialization.
- */
-
-static void __init
-pcibios_assign_special(struct pci_dev * dev)
-{
- int i;
-
- /* The first three resources of an IDE controler are often magic,
- so leave them unchanged. This is true, for instance, of the
- Contaq 82C693 as seen on SX164 and DP264. */
-
- if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
- /* Resource 1 of IDE controller is the address of HD_CMD
- register which actually occupies a single byte (0x3f6
- for ide0) in reported 0x3f4-3f7 range. We have to fix
- that to avoid resource conflict with AT-style floppy
- controller. */
- dev->resource[1].start += 2;
- dev->resource[1].end = dev->resource[1].start;
- for (i = 0; i < PCI_NUM_RESOURCES; i++)
- if (dev->resource[i].flags && dev->resource[i].start)
- pci_claim_resource(dev, i);
- }
- /*
- * We don't have code that will init the CYPRESS bridge correctly
- * so we do the next best thing, and depend on the previous
- * console code to do the right thing, and ignore it here... :-\
- */
- else if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
- dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
- for (i = 0; i < PCI_NUM_RESOURCES; i++)
- if (dev->resource[i].flags && dev->resource[i].start)
- pci_claim_resource(dev, i);
-}
-
-
void __init
pcibios_init(void)
{
@@ -257,7 +237,6 @@ pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
pcibios_fixup_resource(&dev->resource[i],
hose->mem_space);
}
- pcibios_assign_special(dev);
}
void __init
@@ -265,17 +244,33 @@ pcibios_fixup_bus(struct pci_bus *bus)
{
/* Propogate hose info into the subordinate devices. */
- struct pci_controler *hose = (struct pci_controler *) bus->sysdata;
+ struct pci_controler *hose = bus->sysdata;
struct list_head *ln;
+ struct pci_dev *dev = bus->self;
- /* ???? */
- bus->resource[0] = hose->io_space;
- bus->resource[1] = hose->mem_space;
+ if (!dev) {
+ /* Root bus */
+ bus->resource[0] = hose->io_space;
+ bus->resource[1] = hose->mem_space;
+ } else {
+ /* This is a bridge. Do not care how it's initialized,
+ just link its resources to the bus ones */
+ int i;
- /* If this is a bridge, get the current bases */
- if (bus->self) {
- pci_read_bridge_bases(bus);
- pcibios_fixup_device_resources(bus->self, bus->parent);
+ for(i=0; i<3; i++) {
+ bus->resource[i] =
+ &dev->resource[PCI_BRIDGE_RESOURCES+i];
+ bus->resource[i]->name = bus->name;
+ }
+ bus->resource[0]->flags |= pci_bridge_check_io(dev);
+ bus->resource[1]->flags |= IORESOURCE_MEM;
+ /* For now, propogate hose limits to the bus;
+ we'll adjust them later. */
+ bus->resource[0]->end = hose->io_space->end;
+ bus->resource[1]->end = hose->mem_space->end;
+ /* Turn off downstream PF memory address range by default */
+ bus->resource[2]->start = 1024*1024;
+ bus->resource[2]->end = bus->resource[2]->start - 1;
}
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
@@ -285,7 +280,7 @@ pcibios_fixup_bus(struct pci_bus *bus)
}
}
-void __init
+void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
@@ -385,99 +380,6 @@ pcibios_set_master(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
}
-#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
-
-static void __init
-pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
-{
- struct pbus_set_ranges_data inner;
- struct pci_dev *dev;
- struct pci_dev *bridge = bus->self;
- struct pci_controler *hose = bus->sysdata;
- struct list_head *ln;
-
- if (!bridge)
- return; /* host bridge, nothing to do */
-
- /* set reasonable default locations for pcibios_align_resource */
- inner.io_start = hose->io_space->start + PCIBIOS_MIN_IO;
- inner.mem_start = hose->mem_space->start + PCIBIOS_MIN_MEM;
- inner.io_end = inner.io_start;
- inner.mem_end = inner.mem_start;
-
- /* Collect information about how our direct children are layed out. */
- for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
- int i;
- dev = pci_dev_b(ln);
-
- /* Skip bridges for now */
- if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
- continue;
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource res;
- unsigned long size;
-
- memcpy(&res, &dev->resource[i], sizeof(res));
- size = res.end - res.start + 1;
-
- if (res.flags & IORESOURCE_IO) {
- res.start = inner.io_end;
- pcibios_align_resource(dev, &res, size);
- inner.io_end = res.start + size;
- } else if (res.flags & IORESOURCE_MEM) {
- res.start = inner.mem_end;
- pcibios_align_resource(dev, &res, size);
- inner.mem_end = res.start + size;
- }
- }
- }
-
- /* And for all of the subordinate busses. */
- for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
- pcibios_size_bridge(pci_bus_b(ln), &inner);
-
- /* turn the ending locations into sizes (subtract start) */
- inner.io_end -= inner.io_start;
- inner.mem_end -= inner.mem_start;
-
- /* Align the sizes up by bridge rules */
- inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1;
- inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1;
-
- /* Adjust the bridge's allocation requirements */
- bridge->resource[0].end = bridge->resource[0].start + inner.io_end;
- bridge->resource[1].end = bridge->resource[1].start + inner.mem_end;
-
- bridge->resource[PCI_BRIDGE_RESOURCES].end =
- bridge->resource[PCI_BRIDGE_RESOURCES].start + inner.io_end;
- bridge->resource[PCI_BRIDGE_RESOURCES+1].end =
- bridge->resource[PCI_BRIDGE_RESOURCES+1].start + inner.mem_end;
-
- /* adjust parent's resource requirements */
- if (outer) {
- outer->io_end = ROUND_UP(outer->io_end, 4*1024);
- outer->io_end += inner.io_end;
-
- outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024);
- outer->mem_end += inner.mem_end;
- }
-}
-
-#undef ROUND_UP
-
-static void __init
-pcibios_size_bridges(void)
-{
- struct list_head *ln1, *ln2;
-
- for(ln1=pci_root_buses.next; ln1 != &pci_root_buses; ln1=ln1->next)
- for(ln2 = pci_bus_b(ln1)->children.next;
- ln2 != &pci_bus_b(ln1)->children;
- ln2 = ln2->next)
- pcibios_size_bridge(pci_bus_b(ln2), NULL);
-}
-
void __init
common_init_pci(void)
{
@@ -495,10 +397,8 @@ common_init_pci(void)
next_busno += 1;
}
- pcibios_size_bridges();
pci_assign_unassigned_resources();
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
- pci_set_bus_ranges();
}
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 3b727631a..d4eb6a5d9 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -613,10 +613,10 @@ pci_dma_supported(struct pci_dev *pdev, dma_addr_t mask)
/* Check that we have a scatter-gather arena that fits. */
hose = pdev ? pdev->sysdata : pci_isa_hose;
arena = hose->sg_isa;
- if (arena && arena->dma_base + arena->size <= mask)
+ if (arena && arena->dma_base + arena->size - 1 <= mask)
return 1;
arena = hose->sg_pci;
- if (arena && arena->dma_base + arena->size <= mask)
+ if (arena && arena->dma_base + arena->size - 1 <= mask)
return 1;
return 0;
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 54fc93387..c9a2e79a4 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -56,9 +56,9 @@ ruffian_init_irq(void)
init_i8259a_irqs();
- /* Not interested in the bogus interrupts (0,3,4,6),
+ /* Not interested in the bogus interrupts (0,3,6),
NMI (1), HALT (2), flash (5), or 21142 (8). */
- init_pyxis_irqs(0x17f0000);
+ init_pyxis_irqs(0x16f0000);
common_init_isa_dma();
}
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 913331a95..cb23a987d 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -3,32 +3,63 @@
#
.S.s:
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+ $(CPP) -D__ASSEMBLY__ $(CFLAGS) -o $*.s $<
.S.o:
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
-
-OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
- checksum.o csum_partial_copy.o strlen.o \
- strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
- strchr.o strrchr.o memchr.o \
- copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
- csum_ipv6_magic.o strcasecmp.o fpreg.o \
+ $(CC) -D__ASSEMBLY__ $(CFLAGS) -c -o $*.o $<
+
+# Many of these routines have implementations tuned for ev6.
+# Choose them iff we're targeting ev6 specifically.
+ev6 :=
+ifeq ($(CONFIG_ALPHA_EV6),y)
+ ev6 := ev6-
+endif
+
+# Several make use of the cttz instruction introduced in ev67.
+ev67 :=
+ifeq ($(CONFIG_ALPHA_EV67),y)
+ ev67 := ev67-
+endif
+
+OBJS = __divqu.o __remqu.o __divlu.o __remlu.o \
+ $(ev6)memset.o \
+ $(ev6)memcpy.o \
+ memmove.o \
+ io.o \
+ checksum.o \
+ csum_partial_copy.o \
+ $(ev67)strlen.o \
+ $(ev67)strcat.o \
+ strcpy.o \
+ $(ev67)strncat.o \
+ strncpy.o \
+ $(ev6)stxcpy.o \
+ $(ev6)stxncpy.o \
+ $(ev67)strchr.o \
+ strrchr.o \
+ $(ev6)memchr.o \
+ $(ev6)copy_user.o \
+ $(ev6)clear_user.o \
+ $(ev6)strncpy_from_user.o \
+ $(ev67)strlen_user.o \
+ $(ev6)csum_ipv6_magic.o \
+ strcasecmp.o \
+ fpreg.o \
callback_srm.o srm_puts.o srm_printk.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
-__divqu.o: divide.S
- $(CC) $(AFLAGS) -DDIV -c -o __divqu.o divide.S
+__divqu.o: $(ev6)divide.S
+ $(CC) $(AFLAGS) -DDIV -c -o __divqu.o $(ev6)divide.S
-__remqu.o: divide.S
- $(CC) $(AFLAGS) -DREM -c -o __remqu.o divide.S
+__remqu.o: $(ev6)divide.S
+ $(CC) $(AFLAGS) -DREM -c -o __remqu.o $(ev6)divide.S
-__divlu.o: divide.S
- $(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o divide.S
+__divlu.o: $(ev6)divide.S
+ $(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o $(ev6)divide.S
-__remlu.o: divide.S
- $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o divide.S
+__remlu.o: $(ev6)divide.S
+ $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o $(ev6)divide.S
dep:
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
index 5165279f0..7f29ac81c 100644
--- a/arch/alpha/lib/checksum.c
+++ b/arch/alpha/lib/checksum.c
@@ -3,6 +3,10 @@
*
* This file contains network checksum routines that are better done
* in an architecture-specific manner due to speed..
+ * Comments in other versions indicate that the algorithms are from RFC1071
+ *
+ * accellerated versions (and 21264 assembly versions ) contributed by
+ * Rick Gorton <rick.gorton@alpha-processor.com>
*/
#include <linux/string.h>
@@ -11,15 +15,25 @@
static inline unsigned short from64to16(unsigned long x)
{
- /* add up 32-bit words for 33 bits */
- x = (x & 0xffffffff) + (x >> 32);
- /* add up 16-bit and 17-bit words for 17+c bits */
- x = (x & 0xffff) + (x >> 16);
- /* add up 16-bit and 2-bit for 16+c bit */
- x = (x & 0xffff) + (x >> 16);
- /* add up carry.. */
- x = (x & 0xffff) + (x >> 16);
- return x;
+ /* Using extract instructions is a bit more efficient
+ than the original shift/bitmask version. */
+
+ union {
+ unsigned long ul;
+ unsigned int ui[2];
+ unsigned short us[4];
+ } in_v, tmp_v, out_v;
+
+ in_v.ul = x;
+ tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1];
+
+ /* Since the bits of tmp_v.sh[3] are going to always be zero,
+ we don't have to bother to add that in. */
+ out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1]
+ + (unsigned long) tmp_v.us[2];
+
+ /* Similarly, out_v.us[2] is always zero for the final add. */
+ return out_v.us[0] + out_v.us[1];
}
/*
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
index 5638a1a0c..f8129b5f5 100644
--- a/arch/alpha/lib/csum_partial_copy.c
+++ b/arch/alpha/lib/csum_partial_copy.c
@@ -2,6 +2,8 @@
* csum_partial_copy - do IP checksumming and copy
*
* (C) Copyright 1996 Linus Torvalds
+ * accellerated versions (and 21264 assembly versions ) contributed by
+ * Rick Gorton <rick.gorton@alpha-processor.com>
*
* Don't look at this too closely - you'll go mad. The things
* we do for performance..
@@ -68,6 +70,31 @@ __asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y))
})
+static inline unsigned short from64to16(unsigned long x)
+{
+ /* Using extract instructions is a bit more efficient
+ than the original shift/bitmask version. */
+
+ union {
+ unsigned long ul;
+ unsigned int ui[2];
+ unsigned short us[4];
+ } in_v, tmp_v, out_v;
+
+ in_v.ul = x;
+ tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1];
+
+ /* Since the bits of tmp_v.sh[3] are going to always be zero,
+ we don't have to bother to add that in. */
+ out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1]
+ + (unsigned long) tmp_v.us[2];
+
+ /* Similarly, out_v.us[2] is always zero for the final add. */
+ return out_v.us[0] + out_v.us[1];
+}
+
+
+
/*
* Ok. This isn't fun, but this is the EASY case.
*/
@@ -335,13 +362,7 @@ do_csum_partial_copy_from_user(const char *src, char *dst, int len,
soff, doff, len-8, checksum,
partial_dest, errp);
}
- /* 64 -> 33 bits */
- checksum = (checksum & 0xffffffff) + (checksum >> 32);
- /* 33 -> < 32 bits */
- checksum = (checksum & 0xffff) + (checksum >> 16);
- /* 32 -> 16 bits */
- checksum = (checksum & 0xffff) + (checksum >> 16);
- checksum = (checksum & 0xffff) + (checksum >> 16);
+ checksum = from64to16 (checksum);
}
return checksum;
}
diff --git a/arch/alpha/lib/ev6-clear_user.S b/arch/alpha/lib/ev6-clear_user.S
new file mode 100644
index 000000000..090f06063
--- /dev/null
+++ b/arch/alpha/lib/ev6-clear_user.S
@@ -0,0 +1,228 @@
+/*
+ * arch/alpha/lib/ev6-clear_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Zero user space, handling exceptions as we go.
+ *
+ * We have to make sure that $0 is always up-to-date and contains the
+ * right "bytes left to zero" value (and that it is updated only _after_
+ * a successful copy). There is also some rather minor exception setup
+ * stuff.
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics
+ * are different:
+ *
+ * Inputs:
+ * length in $0
+ * destination address in $6
+ * exception pointer in $7
+ * return address in $28 (exceptions expect it there)
+ *
+ * Outputs:
+ * bytes left to copy in $0
+ *
+ * Clobbers:
+ * $1,$2,$3,$4,$5,$6
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Determining actual stalls (other than slotting) doesn't appear to be easy to do.
+ * From perusing the source code context where this routine is called, it is
+ * a fair assumption that significant fractions of entire pages are zeroed, so
+ * it's going to be worth the effort to hand-unroll a big loop, and use wh64.
+ * ASSUMPTION:
+ * The believed purpose of only updating $0 after a store is that a signal
+ * may come along during the execution of this chunk of code, and we don't
+ * want to leave a hole (and we also want to avoid repeating lots of work)
+ */
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EX(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda $31, $exception-99b($31); \
+ .previous
+
+ .set noat
+ .set noreorder
+ .align 4
+
+ .globl __do_clear_user
+ .ent __do_clear_user
+ .frame $30, 0, $28
+ .prologue 0
+
+ # Pipeline info : Slotting & Comments
+__do_clear_user:
+ ldgp $29,0($27) # we do exceptions -- we need the gp.
+ # Macro instruction becomes ldah/lda
+ # .. .. E E :
+ and $6, 7, $4 # .. E .. .. : find dest head misalignment
+ beq $0, $zerolength # U .. .. .. : U L U L
+
+ addq $0, $4, $1 # .. .. .. E : bias counter
+ and $1, 7, $2 # .. .. E .. : number of misaligned bytes in tail
+# Note - we never actually use $2, so this is a moot computation
+# and we can rewrite this later...
+ srl $1, 3, $1 # .. E .. .. : number of quadwords to clear
+ beq $4, $headalign # U .. .. .. : U L U L
+
+/*
+ * Head is not aligned. Write (8 - $4) bytes to head of destination
+ * This means $6 is known to be misaligned
+ */
+ EX( ldq_u $5, 0($6) ) # .. .. .. L : load dst word to mask back in
+ beq $1, $onebyte # .. .. U .. : sub-word store?
+ mskql $5, $6, $5 # .. U .. .. : take care of misaligned head
+ addq $6, 8, $6 # E .. .. .. : L U U L
+
+ EX( stq_u $5, -8($6) ) # .. .. .. L :
+ subq $1, 1, $1 # .. .. E .. :
+ addq $0, $4, $0 # .. E .. .. : bytes left -= 8 - misalignment
+ subq $0, 8, $0 # E .. .. .. : U L U L
+
+ .align 4
+/*
+ * (The .align directive ought to be a moot point)
+ * values upon initial entry to the loop
+ * $1 is number of quadwords to clear (zero is a valid value)
+ * $2 is number of trailing bytes (0..7) ($2 never used...)
+ * $6 is known to be aligned 0mod8
+ */
+$headalign:
+ subq $1, 16, $4 # .. .. .. E : If < 16, we can not use the huge loop
+ and $6, 0x3f, $2 # .. .. E .. : Forward work for huge loop
+ subq $2, 0x40, $3 # .. E .. .. : bias counter (huge loop)
+ blt $4, $trailquad # U .. .. .. : U L U L
+
+/*
+ * We know that we're going to do at least 16 quads, which means we are
+ * going to be able to use the large block clear loop at least once.
+ * Figure out how many quads we need to clear before we are 0mod64 aligned
+ * so we can use the wh64 instruction.
+ */
+
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ beq $3, $bigalign # U .. .. .. : U L U L : Aligned 0mod64
+
+$alignmod64:
+ EX( stq_u $31, 0($6) ) # .. .. .. L
+ addq $3, 8, $3 # .. .. E ..
+ subq $0, 8, $0 # .. E .. ..
+ nop # E .. .. .. : U L U L
+
+ nop # .. .. .. E
+ subq $1, 1, $1 # .. .. E ..
+ addq $6, 8, $6 # .. E .. ..
+ blt $3, $alignmod64 # U .. .. .. : U L U L
+
+$bigalign:
+/*
+ * $0 is the number of bytes left
+ * $1 is the number of quads left
+ * $6 is aligned 0mod64
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * We are _not_ going to update $0 after every single store. That
+ * would be silly, because there will be cross-cluster dependencies
+ * no matter how the code is scheduled. By doing it in slightly
+ * staggered fashion, we can still do this loop in 5 fetches
+ * The worse case will be doing two extra quads in some future execution,
+ * in the event of an interrupted clear.
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+ nop # E :
+ nop # E :
+ nop # E :
+ bis $6,$6,$3 # E : U L U L : Initial wh64 address is dest
+ /* This might actually help for the current trip... */
+
+$do_wh64:
+ wh64 ($3) # .. .. .. L1 : memory subsystem hint
+ subq $1, 16, $4 # .. .. E .. : Forward calculation - repeat the loop?
+ EX( stq_u $31, 0($6) ) # .. L .. ..
+ subq $0, 8, $0 # E .. .. .. : U L U L
+
+ addq $6, 128, $3 # E : Target address of wh64
+ EX( stq_u $31, 8($6) ) # L :
+ EX( stq_u $31, 16($6) ) # L :
+ subq $0, 16, $0 # E : U L L U
+
+ nop # E :
+ EX( stq_u $31, 24($6) ) # L :
+ EX( stq_u $31, 32($6) ) # L :
+ subq $0, 168, $5 # E : U L L U : two trips through the loop left?
+ /* 168 = 192 - 24, since we've already completed some stores */
+
+ subq $0, 16, $0 # E :
+ EX( stq_u $31, 40($6) ) # L :
+ EX( stq_u $31, 48($6) ) # L :
+ cmovlt $5, $6, $3 # E : U L L U : Latency 2, extra mapping cycle
+
+ subq $1, 8, $1 # E :
+ subq $0, 16, $0 # E :
+ EX( stq_u $31, 56($6) ) # L :
+ nop # E : U L U L
+
+ nop # E :
+ subq $0, 8, $0 # E :
+ addq $6, 64, $6 # E :
+ bge $4, $do_wh64 # U : U L U L
+
+$trailquad:
+ # zero to 16 quadwords left to store, plus any trailing bytes
+ # $1 is the number of quadwords left to go.
+ #
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ beq $1, $trailbytes # U .. .. .. : U L U L : Only 0..7 bytes to go
+
+$onequad:
+ EX( stq_u $31, 0($6) ) # .. .. .. L
+ subq $1, 1, $1 # .. .. E ..
+ subq $0, 8, $0 # .. E .. ..
+ nop # E .. .. .. : U L U L
+
+ nop # .. .. .. E
+ nop # .. .. E ..
+ addq $6, 8, $6 # .. E .. ..
+ bgt $1, $onequad # U .. .. .. : U L U L
+
+ # We have an unknown number of bytes left to go.
+$trailbytes:
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ beq $0, $zerolength # U .. .. .. : U L U L
+
+ # $0 contains the number of bytes left to copy (0..31)
+ # so we will use $0 as the loop counter
+ # We know for a fact that $0 > 0 zero due to previous context
+$onebyte:
+ EX( stb $31, 0($6) ) # .. .. .. L
+ subq $0, 1, $0 # .. .. E .. :
+ addq $6, 1, $6 # .. E .. .. :
+ bgt $0, $onebyte # U .. .. .. : U L U L
+
+$zerolength:
+$exception: # Destination for exception recovery(?)
+ nop # .. .. .. E :
+ nop # .. .. E .. :
+ nop # .. E .. .. :
+ ret $31, ($28), 1 # L0 .. .. .. : L U L U
+ .end __do_clear_user
+
diff --git a/arch/alpha/lib/ev6-copy_user.S b/arch/alpha/lib/ev6-copy_user.S
new file mode 100644
index 000000000..a30f7324c
--- /dev/null
+++ b/arch/alpha/lib/ev6-copy_user.S
@@ -0,0 +1,262 @@
+/*
+ * arch/alpha/lib/ev6-copy_user.S
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Copy to/from user space, handling exceptions as we go.. This
+ * isn't exactly pretty.
+ *
+ * This is essentially the same as "memcpy()", but with a few twists.
+ * Notably, we have to make sure that $0 is always up-to-date and
+ * contains the right "bytes left to copy" value (and that it is updated
+ * only _after_ a successful copy). There is also some rather minor
+ * exception setup stuff..
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics are
+ * different:
+ *
+ * Inputs:
+ * length in $0
+ * destination address in $6
+ * source address in $7
+ * return address in $28
+ *
+ * Outputs:
+ * bytes left to copy in $0
+ *
+ * Clobbers:
+ * $1,$2,$3,$4,$5,$6,$7
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ */
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EXI(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda $31, $exitin-99b($31); \
+ .previous
+
+#define EXO(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda $31, $exitout-99b($31); \
+ .previous
+
+ .set noat
+ .align 4
+ .globl __copy_user
+ .ent __copy_user
+ # Pipeline info: Slotting & Comments
+__copy_user:
+ ldgp $29,0($27) # we do exceptions -- we need the gp.
+ # Macro instruction becomes ldah/lda
+ # .. .. E E
+ .prologue 1
+ subq $0, 32, $1 # .. E .. .. : Is this going to be a small copy?
+ beq $0, $zerolength # U .. .. .. : U L U L
+
+ and $6,7,$3 # .. .. .. E : is leading dest misalignment
+ ble $1, $onebyteloop # .. .. U .. : 1st branch : small amount of data
+ beq $3, $destaligned # .. U .. .. : 2nd (one cycle fetcher stall)
+ subq $3, 8, $3 # E .. .. .. : L U U L : trip counter
+/*
+ * The fetcher stall also hides the 1 cycle cross-cluster stall for $3 (L --> U)
+ * This loop aligns the destination a byte at a time
+ * We know we have at least one trip through this loop
+ */
+$aligndest:
+ EXI( ldbu $1,0($7) ) # .. .. .. L : Keep loads separate from stores
+ addq $6,1,$6 # .. .. E .. : Section 3.8 in the CWG
+ addq $3,1,$3 # .. E .. .. :
+ nop # E .. .. .. : U L U L
+
+/*
+ * the -1 is to compensate for the inc($6) done in a previous quadpack
+ * which allows us zero dependencies within either quadpack in the loop
+ */
+ EXO( stb $1,-1($6) ) # .. .. .. L :
+ addq $7,1,$7 # .. .. E .. : Section 3.8 in the CWG
+ subq $0,1,$0 # .. E .. .. :
+ bne $3, $aligndest # U .. .. .. : U L U L
+
+/*
+ * If we fell through into here, we have a minimum of 33 - 7 bytes
+ * If we arrived via branch, we have a minimum of 32 bytes
+ */
+$destaligned:
+ and $7,7,$1 # .. .. .. E : Check _current_ source alignment
+ bic $0,7,$4 # .. .. E .. : number bytes as a quadword loop
+ EXI( ldq_u $3,0($7) ) # .. L .. .. : Forward fetch for fallthrough code
+ beq $1,$quadaligned # U .. .. .. : U L U L
+
+/*
+ * In the worst case, we've just executed an ldq_u here from 0($7)
+ * and we'll repeat it once if we take the branch
+ */
+
+/* Misaligned quadword loop - not unrolled. Leave it that way. */
+$misquad:
+ EXI( ldq_u $2,8($7) ) # .. .. .. L :
+ subq $4,8,$4 # .. .. E .. :
+ extql $3,$7,$3 # .. U .. .. :
+ extqh $2,$7,$1 # U .. .. .. : U U L L
+
+ bis $3,$1,$1 # .. .. .. E :
+ EXO( stq $1,0($6) ) # .. .. L .. :
+ addq $7,8,$7 # .. E .. .. :
+ subq $0,8,$0 # E .. .. .. : U L L U
+
+ addq $6,8,$6 # .. .. .. E :
+ bis $2,$2,$3 # .. .. E .. :
+ nop # .. E .. .. :
+ bne $4,$misquad # U .. .. .. : U L U L
+
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ beq $0,$zerolength # U .. .. .. : U L U L
+
+/* We know we have at least one trip through the byte loop */
+ EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad
+ addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG)
+ nop # .. E .. .. :
+ br $31, $dirtyentry # L0 .. .. .. : L U U L
+/* Do the trailing byte loop load, then hop into the store part of the loop */
+
+/*
+ * A minimum of (33 - 7) bytes to do a quad at a time.
+ * Based upon the usage context, it's worth the effort to unroll this loop
+ * $0 - number of bytes to be moved
+ * $4 - number of bytes to move as quadwords
+ * $6 is current destination address
+ * $7 is current source address
+ */
+$quadaligned:
+ subq $4, 32, $2 # .. .. .. E : do not unroll for small stuff
+ nop # .. .. E ..
+ nop # .. E .. ..
+ blt $2, $onequad # U .. .. .. : U L U L
+
+/*
+ * There is a significant assumption here that the source and destination
+ * addresses differ by more than 32 bytes. In this particular case, a
+ * sparsity of registers further bounds this to be a minimum of 8 bytes.
+ * But if this isn't met, then the output result will be incorrect.
+ * Furthermore, due to a lack of available registers, we really can't
+ * unroll this to be an 8x loop (which would enable us to use the wh64
+ * instruction memory hint instruction).
+ */
+$unroll4:
+ EXI( ldq $1,0($7) ) # .. .. .. L
+ EXI( ldq $2,8($7) ) # .. .. L ..
+ subq $4,32,$4 # .. E .. ..
+ nop # E .. .. .. : U U L L
+
+ addq $7,16,$7 # .. .. .. E
+ EXO( stq $1,0($6) ) # .. .. L ..
+ EXO( stq $2,8($6) ) # .. L .. ..
+ subq $0,16,$0 # E .. .. .. : U L L U
+
+ addq $6,16,$6 # .. .. .. E
+ EXI( ldq $1,0($7) ) # .. .. L ..
+ EXI( ldq $2,8($7) ) # .. L .. ..
+ subq $4, 32, $3 # E .. .. .. : U U L L : is there enough for another trip?
+
+ EXO( stq $1,0($6) ) # .. .. .. L
+ EXO( stq $2,8($6) ) # .. .. L ..
+ subq $0,16,$0 # .. E .. ..
+ addq $7,16,$7 # E .. .. .. : U L L U
+
+ nop # .. .. .. E
+ nop # .. .. E ..
+ addq $6,16,$6 # .. E .. ..
+ bgt $3,$unroll4 # U .. .. .. : U L U L
+
+ nop
+ nop
+ nop
+ beq $4, $noquads
+
+$onequad:
+ EXI( ldq $1,0($7) )
+ subq $4,8,$4
+ addq $7,8,$7
+ nop
+
+ EXO( stq $1,0($6) )
+ subq $0,8,$0
+ addq $6,8,$6
+ bne $4,$onequad
+
+$noquads:
+ nop
+ nop
+ nop
+ beq $0,$zerolength
+
+/*
+ * For small copies (or the tail of a larger copy), do a very simple byte loop.
+ * There's no point in doing a lot of complex alignment calculations to try to
+ * to quadword stuff for a small amount of data.
+ * $0 - remaining number of bytes left to copy
+ * $6 - current dest addr
+ * $7 - current source addr
+ */
+
+$onebyteloop:
+ EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad
+ addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG)
+ nop # .. E .. .. :
+ nop # E .. .. .. : U L U L
+
+$dirtyentry:
+/*
+ * the -1 is to compensate for the inc($6) done in a previous quadpack
+ * which allows us zero dependencies within either quadpack in the loop
+ */
+ EXO ( stb $2,-1($6) ) # .. .. .. L :
+ addq $7,1,$7 # .. .. E .. : quadpack as the load
+ subq $0,1,$0 # .. E .. .. : change count _after_ copy
+ bgt $0,$onebyteloop # U .. .. .. : U L U L
+
+$zerolength:
+$exitout: # Destination for exception recovery(?)
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ ret $31,($28),1 # L0 .. .. .. : L U L U
+
+$exitin:
+
+ /* A stupid byte-by-byte zeroing of the rest of the output
+ buffer. This cures security holes by never leaving
+ random kernel data around to be copied elsewhere. */
+
+ nop
+ nop
+ nop
+ mov $0,$1
+
+$101:
+ EXO ( stb $31,0($6) ) # L
+ subq $1,1,$1 # E
+ addq $6,1,$6 # E
+ bgt $1,$101 # U
+
+ nop
+ nop
+ nop
+ ret $31,($28),1 # L0
+
+ .end __copy_user
+
diff --git a/arch/alpha/lib/ev6-csum_ipv6_magic.S b/arch/alpha/lib/ev6-csum_ipv6_magic.S
new file mode 100644
index 000000000..de1948a69
--- /dev/null
+++ b/arch/alpha/lib/ev6-csum_ipv6_magic.S
@@ -0,0 +1,126 @@
+/*
+ * arch/alpha/lib/ev6-csum_ipv6_magic.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
+ * struct in6_addr *daddr,
+ * __u32 len,
+ * unsigned short proto,
+ * unsigned int csum);
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Determining actual stalls (other than slotting) doesn't appear to be easy to do.
+ *
+ * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
+ * struct in6_addr *daddr,
+ * __u32 len,
+ * unsigned short proto,
+ * unsigned int csum);
+ *
+ * Swap <proto> (takes form 0xaabb)
+ * Then shift it left by 48, so result is:
+ * 0xbbaa0000 00000000
+ * Then turn it back into a sign extended 32-bit item
+ * 0xbbaa0000
+ *
+ * Swap <len> (an unsigned int) using Mike Burrows' 7-instruction sequence
+ * (we can't hide the 3-cycle latency of the unpkbw in the 6-instruction sequence)
+ * Assume input takes form 0xAABBCCDD
+ *
+ * Finally, original 'folding' approach is to split the long into 4 unsigned shorts
+ * add 4 ushorts, resulting in ushort/carry
+ * add carry bits + ushort --> ushort
+ * add carry bits + ushort --> ushort (in case the carry results in an overflow)
+ * Truncate to a ushort. (took 13 instructions)
+ * From doing some testing, using the approach in checksum.c:from64to16()
+ * results in the same outcome:
+ * split into 2 uints, add those, generating a ulong
+ * add the 3 low ushorts together, generating a uint
+ * a final add of the 2 lower ushorts
+ * truncating the result.
+ */
+
+ .globl csum_ipv6_magic
+ .align 4
+ .ent csum_ipv6_magic
+ .frame $30,0,$26,0
+csum_ipv6_magic:
+ .prologue 0
+
+ ldq $0,0($16) # L : Latency: 3
+ inslh $18,7,$4 # U : 0000000000AABBCC
+ ldq $1,8($16) # L : Latency: 3
+ sll $19,8,$7 # U : U L U L : 0x00000000 00aabb00
+
+ zapnot $20,15,$20 # U : zero extend incoming csum
+ ldq $2,0($17) # L : Latency: 3
+ sll $19,24,$19 # U : U L L U : 0x000000aa bb000000
+ inswl $18,3,$18 # U : 000000CCDD000000
+
+ ldq $3,8($17) # L : Latency: 3
+ bis $18,$4,$18 # E : 000000CCDDAABBCC
+ addl $19,$7,$19 # E : <sign bits>bbaabb00
+ nop # E : U L U L
+
+ addq $20,$0,$20 # E : begin summing the words
+ srl $18,16,$4 # U : 0000000000CCDDAA
+ zap $19,0x3,$19 # U : <sign bits>bbaa0000
+ nop # E : L U U L
+
+ cmpult $20,$0,$0 # E :
+ addq $20,$1,$20 # E :
+ zapnot $18,0xa,$18 # U : 00000000DD00BB00
+ zap $4,0xa,$4 # U : U U L L : 0000000000CC00AA
+
+ or $18,$4,$18 # E : 00000000DDCCBBAA
+ nop # E :
+ cmpult $20,$1,$1 # E :
+ addq $20,$2,$20 # E : U L U L
+
+ cmpult $20,$2,$2 # E :
+ addq $20,$3,$20 # E :
+ cmpult $20,$3,$3 # E : (1 cycle stall on $20)
+ addq $20,$18,$20 # E : U L U L (1 cycle stall on $20)
+
+ cmpult $20,$18,$18 # E :
+ addq $20,$19,$20 # E : (1 cycle stall on $20)
+ addq $0,$1,$0 # E : merge the carries back into the csum
+ addq $2,$3,$2 # E :
+
+ cmpult $20,$19,$19 # E :
+ addq $18,$19,$18 # E : (1 cycle stall on $19)
+ addq $0,$2,$0 # E :
+ addq $20,$18,$20 # E : U L U L :
+ /* (1 cycle stall on $18, 2 cycles on $20) */
+
+ addq $0,$20,$0 # E :
+ zapnot $0,15,$1 # U : Start folding output (1 cycle stall on $0)
+ nop # E :
+ srl $0,32,$0 # U : U L U L : (1 cycle stall on $0)
+
+ addq $1,$0,$1 # E : Finished generating ulong
+ extwl $1,2,$2 # U : ushort[1] (1 cycle stall on $1)
+ zapnot $1,3,$0 # U : ushort[0] (1 cycle stall on $1)
+ extwl $1,4,$1 # U : ushort[2] (1 cycle stall on $1)
+
+ addq $0,$2,$0 # E
+ addq $0,$1,$3 # E : Finished generating uint
+ /* (1 cycle stall on $0) */
+ extwl $3,2,$1 # U : ushort[1] (1 cycle stall on $3)
+ nop # E : L U L U
+
+ addq $1,$3,$0 # E : Final carry
+ not $0,$4 # E : complement (1 cycle stall on $0)
+ zapnot $4,3,$0 # U : clear upper garbage bits
+ /* (1 cycle stall on $4) */
+ ret # L0 : L U L U
+
+ .end csum_ipv6_magic
diff --git a/arch/alpha/lib/ev6-divide.S b/arch/alpha/lib/ev6-divide.S
new file mode 100644
index 000000000..2a82b9be9
--- /dev/null
+++ b/arch/alpha/lib/ev6-divide.S
@@ -0,0 +1,259 @@
+/*
+ * arch/alpha/lib/ev6-divide.S
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Alpha division..
+ */
+
+/*
+ * The alpha chip doesn't provide hardware division, so we have to do it
+ * by hand. The compiler expects the functions
+ *
+ * __divqu: 64-bit unsigned long divide
+ * __remqu: 64-bit unsigned long remainder
+ * __divqs/__remqs: signed 64-bit
+ * __divlu/__remlu: unsigned 32-bit
+ * __divls/__remls: signed 32-bit
+ *
+ * These are not normal C functions: instead of the normal
+ * calling sequence, these expect their arguments in registers
+ * $24 and $25, and return the result in $27. Register $28 may
+ * be clobbered (assembly temporary), anything else must be saved.
+ *
+ * In short: painful.
+ *
+ * This is a rather simple bit-at-a-time algorithm: it's very good
+ * at dividing random 64-bit numbers, but the more usual case where
+ * the divisor is small is handled better by the DEC algorithm
+ * using lookup tables. This uses much less memory, though, and is
+ * nicer on the cache.. Besides, I don't know the copyright status
+ * of the DEC code.
+ */
+
+/*
+ * My temporaries:
+ * $0 - current bit
+ * $1 - shifted divisor
+ * $2 - modulus/quotient
+ *
+ * $23 - return address
+ * $24 - dividend
+ * $25 - divisor
+ *
+ * $27 - quotient/modulus
+ * $28 - compare status
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#define halt .long 0
+
+/*
+ * Select function type and registers
+ */
+#define mask $0
+#define divisor $1
+#define compare $28
+#define tmp1 $3
+#define tmp2 $4
+
+#ifdef DIV
+#define DIV_ONLY(x,y...) x,##y
+#define MOD_ONLY(x,y...)
+#define func(x) __div##x
+#define modulus $2
+#define quotient $27
+#define GETSIGN(x) xor $24,$25,x
+#define STACK 48
+#else
+#define DIV_ONLY(x,y...)
+#define MOD_ONLY(x,y...) x,##y
+#define func(x) __rem##x
+#define modulus $27
+#define quotient $2
+#define GETSIGN(x) bis $24,$24,x
+#define STACK 32
+#endif
+
+/*
+ * For 32-bit operations, we need to extend to 64-bit
+ */
+#ifdef INTSIZE
+#define ufunction func(lu)
+#define sfunction func(l)
+#define LONGIFY(x) zapnot x,15,x
+#define SLONGIFY(x) addl x,0,x
+#else
+#define ufunction func(qu)
+#define sfunction func(q)
+#define LONGIFY(x)
+#define SLONGIFY(x)
+#endif
+
+.set noat
+.align 4
+.globl ufunction
+.ent ufunction
+ufunction:
+ subq $30,STACK,$30 # E :
+ .frame $30,STACK,$23
+ .prologue 0
+
+7: stq $1, 0($30) # L :
+ bis $25,$25,divisor # E :
+ stq $2, 8($30) # L : L U L U
+
+ bis $24,$24,modulus # E :
+ stq $0,16($30) # L :
+ bis $31,$31,quotient # E :
+ LONGIFY(divisor) # E : U L L U
+
+ stq tmp1,24($30) # L :
+ LONGIFY(modulus) # E :
+ bis $31,1,mask # E :
+ DIV_ONLY(stq tmp2,32($30)) # L : L U U L
+
+ beq divisor, 9f /* div by zero */
+ /*
+ * In spite of the DIV_ONLY being either a non-instruction
+ * or an actual stq, the addition of the .align directive
+ * below ensures that label 1 is going to be nicely aligned
+ */
+
+ .align 4
+#ifdef INTSIZE
+ /*
+ * shift divisor left, using 3-bit shifts for
+ * 32-bit divides as we can't overflow. Three-bit
+ * shifts will result in looping three times less
+ * here, but can result in two loops more later.
+ * Thus using a large shift isn't worth it (and
+ * s8add pairs better than a sll..)
+ */
+1: cmpult divisor,modulus,compare # E :
+ s8addq divisor,$31,divisor # E :
+ s8addq mask,$31,mask # E :
+ bne compare,1b # U : U L U L
+#else
+1: cmpult divisor,modulus,compare # E :
+ nop # E :
+ nop # E :
+ blt divisor, 2f # U : U L U L
+
+ addq divisor,divisor,divisor # E :
+ addq mask,mask,mask # E :
+ unop # E :
+ bne compare,1b # U : U L U L
+#endif
+
+ /* ok, start to go right again.. */
+2:
+ /*
+ * Keep things nicely bundled... use a nop instead of not
+ * having an instruction for DIV_ONLY
+ */
+#ifdef DIV
+ DIV_ONLY(addq quotient,mask,tmp2) # E :
+#else
+ nop # E :
+#endif
+ srl mask,1,mask # U :
+ cmpule divisor,modulus,compare # E :
+ subq modulus,divisor,tmp1 # E :
+
+#ifdef DIV
+ DIV_ONLY(cmovne compare,tmp2,quotient) # E : Latency 2, extra map slot
+ nop # E : as part of the cmovne
+ srl divisor,1,divisor # U :
+ nop # E : L U L U
+
+ nop # E :
+ cmovne compare,tmp1,modulus # E : Latency 2, extra map slot
+ nop # E : as part of the cmovne
+ bne mask,2b # U : U L U L
+#else
+ srl divisor,1,divisor # U :
+ cmovne compare,tmp1,modulus # E : Latency 2, extra map slot
+ nop # E : as part of the cmovne
+ bne mask,2b # U : U L L U
+#endif
+
+9: ldq $1, 0($30) # L :
+ ldq $2, 8($30) # L :
+ nop # E :
+ nop # E : U U L L
+
+ ldq $0,16($30) # L :
+ ldq tmp1,24($30) # L :
+ nop # E :
+ nop # E :
+
+#ifdef DIV
+ DIV_ONLY(ldq tmp2,32($30)) # L :
+#else
+ nop # E :
+#endif
+ addq $30,STACK,$30 # E :
+ ret $31,($23),1 # L0 : L U U L
+ .end ufunction
+
+/*
+ * Uhh.. Ugly signed division. I'd rather not have it at all, but
+ * it's needed in some circumstances. There are different ways to
+ * handle this, really. This does:
+ * -a / b = a / -b = -(a / b)
+ * -a % b = -(a % b)
+ * a % -b = a % b
+ * which is probably not the best solution, but at least should
+ * have the property that (x/y)*y + (x%y) = x.
+ */
+.align 4
+.globl sfunction
+.ent sfunction
+sfunction:
+ subq $30,STACK,$30 # E :
+ .frame $30,STACK,$23
+ .prologue 0
+ bis $24,$25,$28 # E :
+ SLONGIFY($28) # E :
+ bge $28,7b # U :
+
+ stq $24,0($30) # L :
+ subq $31,$24,$28 # E :
+ stq $25,8($30) # L :
+ nop # E : U L U L
+
+ cmovlt $24,$28,$24 /* abs($24) */ # E : Latency 2, extra map slot
+ nop # E : as part of the cmov
+ stq $23,16($30) # L :
+ subq $31,$25,$28 # E : U L U L
+
+ stq tmp1,24($30) # L :
+ cmovlt $25,$28,$25 /* abs($25) */ # E : Latency 2, extra map slot
+ nop # E :
+ bsr $23,ufunction # L0: L U L U
+
+ ldq $24,0($30) # L :
+ ldq $25,8($30) # L :
+ GETSIGN($28) # E :
+ subq $31,$27,tmp1 # E : U U L L
+
+ SLONGIFY($28) # E :
+ ldq $23,16($30) # L :
+ cmovlt $28,tmp1,$27 # E : Latency 2, extra map slot
+ nop # E : U L L U : as part of the cmov
+
+ ldq tmp1,24($30) # L :
+ nop # E : as part of the cmov
+ addq $30,STACK,$30 # E :
+ ret $31,($23),1 # L0 : L U U L
+ .end sfunction
diff --git a/arch/alpha/lib/ev6-memchr.S b/arch/alpha/lib/ev6-memchr.S
new file mode 100644
index 000000000..a8e843dbc
--- /dev/null
+++ b/arch/alpha/lib/ev6-memchr.S
@@ -0,0 +1,191 @@
+/*
+ * arch/alpha/lib/ev6-memchr.S
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Finds characters in a memory area. Optimized for the Alpha:
+ *
+ * - memory accessed as aligned quadwords only
+ * - uses cmpbge to compare 8 bytes in parallel
+ * - does binary search to find 0 byte in last
+ * quadword (HAKMEM needed 12 instructions to
+ * do this instead of the 9 instructions that
+ * binary search needs).
+ *
+ * For correctness consider that:
+ *
+ * - only minimum number of quadwords may be accessed
+ * - the third argument is an unsigned long
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+ .set noreorder
+ .set noat
+
+ .align 4
+ .globl memchr
+ .ent memchr
+memchr:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ # Hack -- if someone passes in (size_t)-1, hoping to just
+ # search til the end of the address space, we will overflow
+ # below when we find the address of the last byte. Given
+ # that we will never have a 56-bit address space, cropping
+ # the length is the easiest way to avoid trouble.
+ zap $18, 0x80, $5 # U : Bound length
+ beq $18, $not_found # U :
+ ldq_u $1, 0($16) # L : load first quadword Latency=3
+ and $17, 0xff, $17 # E : L L U U : 00000000000000ch
+
+ insbl $17, 1, $2 # U : 000000000000ch00
+ cmpult $18, 9, $4 # E : small (< 1 quad) string?
+ or $2, $17, $17 # E : 000000000000chch
+ lda $3, -1($31) # E : U L L U
+
+ sll $17, 16, $2 # U : 00000000chch0000
+ addq $16, $5, $5 # E : Max search address
+ or $2, $17, $17 # E : 00000000chchchch
+ sll $17, 32, $2 # U : U L L U : chchchch00000000
+
+ or $2, $17, $17 # E : chchchchchchchch
+ extql $1, $16, $7 # U : $7 is upper bits
+ beq $4, $first_quad # U :
+ ldq_u $6, -1($5) # L : L U U L : eight or less bytes to search Latency=3
+
+ extqh $6, $16, $6 # U : 2 cycle stall for $6
+ mov $16, $0 # E :
+ nop # E :
+ or $7, $6, $1 # E : L U L U $1 = quadword starting at $16
+
+ # Deal with the case where at most 8 bytes remain to be searched
+ # in $1. E.g.:
+ # $18 = 6
+ # $1 = ????c6c5c4c3c2c1
+$last_quad:
+ negq $18, $6 # E :
+ xor $17, $1, $1 # E :
+ srl $3, $6, $6 # U : $6 = mask of $18 bits set
+ cmpbge $31, $1, $2 # E : L U L U
+
+ nop
+ nop
+ and $2, $6, $2 # E :
+ beq $2, $not_found # U : U L U L
+
+$found_it:
+#if defined(__alpha_fix__) && defined(__alpha_cix__)
+ /*
+ * Since we are guaranteed to have set one of the bits, we don't
+ * have to worry about coming back with a 0x40 out of cttz...
+ */
+ cttz $2, $3 # U0 :
+ addq $0, $3, $0 # E : All done
+ nop # E :
+ ret # L0 : L U L U
+#else
+ /*
+ * Slow and clunky. It can probably be improved.
+ * An exercise left for others.
+ */
+ negq $2, $3 # E :
+ and $2, $3, $2 # E :
+ and $2, 0x0f, $1 # E :
+ addq $0, 4, $3 # E :
+
+ cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
+ nop # E : keep with cmov
+ and $2, 0x33, $1 # E :
+ addq $0, 2, $3 # E : U L U L : 2 cycle stall on $0
+
+ cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
+ nop # E : keep with cmov
+ and $2, 0x55, $1 # E :
+ addq $0, 1, $3 # E : U L U L : 2 cycle stall on $0
+
+ cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
+ nop
+ nop
+ ret # L0 : L U L U
+#endif
+
+ # Deal with the case where $18 > 8 bytes remain to be
+ # searched. $16 may not be aligned.
+ .align 4
+$first_quad:
+ andnot $16, 0x7, $0 # E :
+ insqh $3, $16, $2 # U : $2 = 0000ffffffffffff ($16<0:2> ff)
+ xor $1, $17, $1 # E :
+ or $1, $2, $1 # E : U L U L $1 = ====ffffffffffff
+
+ cmpbge $31, $1, $2 # E :
+ bne $2, $found_it # U :
+ # At least one byte left to process.
+ ldq $1, 8($0) # L :
+ subq $5, 1, $18 # E : U L U L
+
+ addq $0, 8, $0 # E :
+ # Make $18 point to last quad to be accessed (the
+ # last quad may or may not be partial).
+ andnot $18, 0x7, $18 # E :
+ cmpult $0, $18, $2 # E :
+ beq $2, $final # U : U L U L
+
+ # At least two quads remain to be accessed.
+
+ subq $18, $0, $4 # E : $4 <- nr quads to be processed
+ and $4, 8, $4 # E : odd number of quads?
+ bne $4, $odd_quad_count # U :
+ # At least three quads remain to be accessed
+ mov $1, $4 # E : L U L U : move prefetched value to correct reg
+
+ .align 4
+$unrolled_loop:
+ ldq $1, 8($0) # L : prefetch $1
+ xor $17, $4, $2 # E :
+ cmpbge $31, $2, $2 # E :
+ bne $2, $found_it # U : U L U L
+
+ addq $0, 8, $0 # E :
+ nop # E :
+ nop # E :
+ nop # E :
+
+$odd_quad_count:
+ xor $17, $1, $2 # E :
+ ldq $4, 8($0) # L : prefetch $4
+ cmpbge $31, $2, $2 # E :
+ addq $0, 8, $6 # E :
+
+ bne $2, $found_it # U :
+ cmpult $6, $18, $6 # E :
+ addq $0, 8, $0 # E :
+ nop # E :
+
+ bne $6, $unrolled_loop # U :
+ mov $4, $1 # E : move prefetched value into $1
+ nop # E :
+ nop # E :
+
+$final: subq $5, $0, $18 # E : $18 <- number of bytes left to do
+ nop # E :
+ nop # E :
+ bne $18, $last_quad # U :
+
+$not_found:
+ mov $31, $0 # E :
+ nop # E :
+ nop # E :
+ ret # L0 :
+
+ .end memchr
diff --git a/arch/alpha/lib/ev6-memcpy.S b/arch/alpha/lib/ev6-memcpy.S
new file mode 100644
index 000000000..7ebcbc27b
--- /dev/null
+++ b/arch/alpha/lib/ev6-memcpy.S
@@ -0,0 +1,248 @@
+/*
+ * arch/alpha/lib/ev6-memcpy.S
+ * 21264 version by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Reasonably optimized memcpy() routine for the Alpha 21264
+ *
+ * - memory accessed as aligned quadwords only
+ * - uses bcmpge to compare 8 bytes in parallel
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ *
+ * Temp usage notes:
+ * $1,$2, - scratch
+ */
+
+ .set noreorder
+ .set noat
+
+ .align 4
+ .globl memcpy
+ .ent memcpy
+memcpy:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ mov $16, $0 # E : copy dest to return
+ ble $18, $nomoredata # U : done with the copy?
+ xor $16, $17, $1 # E : are source and dest alignments the same?
+ and $1, 7, $1 # E : are they the same mod 8?
+
+ bne $1, $misaligned # U : Nope - gotta do this the slow way
+ /* source and dest are same mod 8 address */
+ and $16, 7, $1 # E : Are both 0mod8?
+ beq $1, $both_0mod8 # U : Yes
+ nop # E :
+
+ /*
+ * source and dest are same misalignment. move a byte at a time
+ * until a 0mod8 alignment for both is reached.
+ * At least one byte more to move
+ */
+
+$head_align:
+ ldbu $1, 0($17) # L : grab a byte
+ subq $18, 1, $18 # E : count--
+ addq $17, 1, $17 # E : src++
+ stb $1, 0($16) # L :
+ addq $16, 1, $16 # E : dest++
+ and $16, 7, $1 # E : Are we at 0mod8 yet?
+ ble $18, $nomoredata # U : done with the copy?
+ bne $1, $head_align # U :
+
+$both_0mod8:
+ cmple $18, 127, $1 # E : Can we unroll the loop?
+ bne $1, $no_unroll # U :
+ and $16, 63, $1 # E : get mod64 alignment
+ beq $1, $do_unroll # U : no single quads to fiddle
+
+$single_head_quad:
+ ldq $1, 0($17) # L : get 8 bytes
+ subq $18, 8, $18 # E : count -= 8
+ addq $17, 8, $17 # E : src += 8
+ nop # E :
+
+ stq $1, 0($16) # L : store
+ addq $16, 8, $16 # E : dest += 8
+ and $16, 63, $1 # E : get mod64 alignment
+ bne $1, $single_head_quad # U : still not fully aligned
+
+$do_unroll:
+ addq $16, 64, $7 # E : Initial (+1 trip) wh64 address
+ cmple $18, 63, $1 # E : Can we go through the unrolled loop?
+ bne $1, $tail_quads # U : Nope
+ nop # E :
+
+$unroll_body:
+ wh64 ($7) # L1 : memory subsystem hint: 64 bytes at
+ # ($7) are about to be over-written
+ ldq $6, 0($17) # L0 : bytes 0..7
+ nop # E :
+ nop # E :
+
+ ldq $4, 8($17) # L : bytes 8..15
+ ldq $5, 16($17) # L : bytes 16..23
+ addq $7, 64, $7 # E : Update next wh64 address
+ nop # E :
+
+ ldq $3, 24($17) # L : bytes 24..31
+ addq $16, 64, $1 # E : fallback value for wh64
+ nop # E :
+ nop # E :
+
+ addq $17, 32, $17 # E : src += 32 bytes
+ stq $6, 0($16) # L : bytes 0..7
+ nop # E :
+ nop # E :
+
+ stq $4, 8($16) # L : bytes 8..15
+ stq $5, 16($16) # L : bytes 16..23
+ subq $18, 192, $2 # E : At least two more trips to go?
+ nop # E :
+
+ stq $3, 24($16) # L : bytes 24..31
+ addq $16, 32, $16 # E : dest += 32 bytes
+ nop # E :
+ nop # E :
+
+ ldq $6, 0($17) # L : bytes 0..7
+ ldq $4, 8($17) # L : bytes 8..15
+ cmovlt $2, $1, $7 # E : Latency 2, extra map slot - Use
+ # fallback wh64 address if < 2 more trips
+ nop # E :
+
+ ldq $5, 16($17) # L : bytes 16..23
+ ldq $3, 24($17) # L : bytes 24..31
+ addq $16, 32, $16 # E : dest += 32
+ subq $18, 64, $18 # E : count -= 64
+
+ addq $17, 32, $17 # E : src += 32
+ stq $6, -32($16) # L : bytes 0..7
+ stq $4, -24($16) # L : bytes 8..15
+ cmple $18, 63, $1 # E : At least one more trip?
+
+ stq $5, -16($16) # L : bytes 16..23
+ stq $3, -8($16) # L : bytes 24..31
+ nop # E :
+ beq $1, $unroll_body
+
+$tail_quads:
+$no_unroll:
+ .align 4
+ subq $18, 8, $18 # E : At least a quad left?
+ blt $18, $less_than_8 # U : Nope
+ nop # E :
+ nop # E :
+
+$move_a_quad:
+ ldq $1, 0($17) # L : fetch 8
+ subq $18, 8, $18 # E : count -= 8
+ addq $17, 8, $17 # E : src += 8
+ nop # E :
+
+ stq $1, 0($16) # L : store 8
+ addq $16, 8, $16 # E : dest += 8
+ bge $18, $move_a_quad # U :
+ nop # E :
+
+$less_than_8:
+ .align 4
+ addq $18, 8, $18 # E : add back for trailing bytes
+ ble $18, $nomoredata # U : All-done
+ nop # E :
+ nop # E :
+
+ /* Trailing bytes */
+$tail_bytes:
+ subq $18, 1, $18 # E : count--
+ ldbu $1, 0($17) # L : fetch a byte
+ addq $17, 1, $17 # E : src++
+ nop # E :
+
+ stb $1, 0($16) # L : store a byte
+ addq $16, 1, $16 # E : dest++
+ bgt $18, $tail_bytes # U : more to be done?
+ nop # E :
+
+ /* branching to exit takes 3 extra cycles, so replicate exit here */
+ ret $31, ($26), 1 # L0 :
+ nop # E :
+ nop # E :
+ nop # E :
+
+$misaligned:
+ mov $0, $4 # E : dest temp
+ and $0, 7, $1 # E : dest alignment mod8
+ beq $1, $dest_0mod8 # U : life doesnt totally suck
+ nop
+
+$aligndest:
+ ble $18, $nomoredata # U :
+ ldbu $1, 0($17) # L : fetch a byte
+ subq $18, 1, $18 # E : count--
+ addq $17, 1, $17 # E : src++
+
+ stb $1, 0($4) # L : store it
+ addq $4, 1, $4 # E : dest++
+ and $4, 7, $1 # E : dest 0mod8 yet?
+ bne $1, $aligndest # U : go until we are aligned.
+
+ /* Source has unknown alignment, but dest is known to be 0mod8 */
+$dest_0mod8:
+ subq $18, 8, $18 # E : At least a quad left?
+ blt $18, $misalign_tail # U : Nope
+ ldq_u $3, 0($17) # L : seed (rotating load) of 8 bytes
+ nop # E :
+
+$mis_quad:
+ ldq_u $16, 8($17) # L : Fetch next 8
+ extql $3, $17, $3 # U : masking
+ extqh $16, $17, $1 # U : masking
+ bis $3, $1, $1 # E : merged bytes to store
+
+ subq $18, 8, $18 # E : count -= 8
+ addq $17, 8, $17 # E : src += 8
+ stq $1, 0($4) # L : store 8 (aligned)
+ mov $16, $3 # E : "rotate" source data
+
+ addq $4, 8, $4 # E : dest += 8
+ bge $18, $mis_quad # U : More quads to move
+ nop
+ nop
+
+$misalign_tail:
+ addq $18, 8, $18 # E : account for tail stuff
+ ble $18, $nomoredata # U :
+ nop
+ nop
+
+$misalign_byte:
+ ldbu $1, 0($17) # L : fetch 1
+ subq $18, 1, $18 # E : count--
+ addq $17, 1, $17 # E : src++
+ nop # E :
+
+ stb $1, 0($4) # L : store
+ addq $4, 1, $4 # E : dest++
+ bgt $18, $misalign_byte # U : more to go?
+ nop
+
+
+$nomoredata:
+ ret $31, ($26), 1 # L0 :
+ nop # E :
+ nop # E :
+ nop # E :
+
+ .end memcpy
+
+/* For backwards module compatability. */
+__memcpy = memcpy
+.globl __memcpy
diff --git a/arch/alpha/lib/ev6-memset.S b/arch/alpha/lib/ev6-memset.S
new file mode 100644
index 000000000..626929fc5
--- /dev/null
+++ b/arch/alpha/lib/ev6-memset.S
@@ -0,0 +1,596 @@
+/*
+ * arch/alpha/lib/ev6-memset.S
+ *
+ * This is an efficient (and relatively small) implementation of the C library
+ * "memset()" function for the 21264 implementation of Alpha.
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * The algorithm for the leading and trailing quadwords remains the same,
+ * however the loop has been unrolled to enable better memory throughput,
+ * and the code has been replicated for each of the entry points: __memset
+ * and __memsetw to permit better scheduling to eliminate the stalling
+ * encountered during the mask replication.
+ * A future enhancement might be to put in a byte store loop for really
+ * small (say < 32 bytes) memset()s. Whether or not that change would be
+ * a win in the kernel would depend upon the contextual usage.
+ * WARNING: Maintaining this is going to be more work than the above version,
+ * as fixes will need to be made in multiple places. The performance gain
+ * is worth it.
+ */
+
+ .set noat
+ .set noreorder
+.text
+ .globl __memset
+ .globl __memsetw
+ .globl __constant_c_memset
+ .globl memset
+
+ .ent __memset
+.align 5
+__memset:
+memset:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ /*
+ * Serious stalling happens. The only way to mitigate this is to
+ * undertake a major re-write to interleave the constant materialization
+ * with other parts of the fall-through code. This is important, even
+ * though it makes maintenance tougher.
+ * Do this later.
+ */
+ and $17,255,$1 # E : 00000000000000ch
+ insbl $17,1,$2 # U : 000000000000ch00
+ bis $16,$16,$0 # E : return value
+ ble $18,end_b # U : zero length requested?
+
+ addq $18,$16,$6 # E : max address to write to
+ bis $1,$2,$17 # E : 000000000000chch
+ insbl $1,2,$3 # U : 0000000000ch0000
+ insbl $1,3,$4 # U : 00000000ch000000
+
+ or $3,$4,$3 # E : 00000000chch0000
+ inswl $17,4,$5 # U : 0000chch00000000
+ xor $16,$6,$1 # E : will complete write be within one quadword?
+ inswl $17,6,$2 # U : chch000000000000
+
+ or $17,$3,$17 # E : 00000000chchchch
+ or $2,$5,$2 # E : chchchch00000000
+ bic $1,7,$1 # E : fit within a single quadword?
+ and $16,7,$3 # E : Target addr misalignment
+
+ or $17,$2,$17 # E : chchchchchchchch
+ beq $1,within_quad_b # U :
+ nop # E :
+ beq $3,aligned_b # U : target is 0mod8
+
+ /*
+ * Target address is misaligned, and won't fit within a quadword
+ */
+ ldq_u $4,0($16) # L : Fetch first partial
+ bis $16,$16,$5 # E : Save the address
+ insql $17,$16,$2 # U : Insert new bytes
+ subq $3,8,$3 # E : Invert (for addressing uses)
+
+ addq $18,$3,$18 # E : $18 is new count ($3 is negative)
+ mskql $4,$16,$4 # U : clear relevant parts of the quad
+ subq $16,$3,$16 # E : $16 is new aligned destination
+ bis $2,$4,$1 # E : Final bytes
+
+ nop
+ stq_u $1,0($5) # L : Store result
+ nop
+ nop
+
+.align 4
+aligned_b:
+ /*
+ * We are now guaranteed to be quad aligned, with at least
+ * one partial quad to write.
+ */
+
+ sra $18,3,$3 # U : Number of remaining quads to write
+ and $18,7,$18 # E : Number of trailing bytes to write
+ bis $16,$16,$5 # E : Save dest address
+ beq $3,no_quad_b # U : tail stuff only
+
+ /*
+ * it's worth the effort to unroll this and use wh64 if possible
+ * Lifted a bunch of code from clear_user.S
+ * At this point, entry values are:
+ * $16 Current destination address
+ * $5 A copy of $16
+ * $6 The max quadword address to write to
+ * $18 Number trailer bytes
+ * $3 Number quads to write
+ */
+
+ and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
+ subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
+ subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
+ blt $4, loop_b # U :
+
+ /*
+ * We know we've got at least 16 quads, minimum of one trip
+ * through unrolled loop. Do a quad at a time to get us 0mod64
+ * aligned.
+ */
+
+ nop # E :
+ nop # E :
+ nop # E :
+ beq $1, $bigalign_b # U :
+
+$alignmod64_b:
+ stq $17, 0($5) # L :
+ subq $3, 1, $3 # E : For consistency later
+ addq $1, 8, $1 # E : Increment towards zero for alignment
+ addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
+
+ nop
+ nop
+ addq $5, 8, $5 # E : Inc address
+ blt $1, $alignmod64_b # U :
+
+$bigalign_b:
+ /*
+ * $3 - number quads left to go
+ * $5 - target address (aligned 0mod64)
+ * $17 - mask of stuff to store
+ * Scratch registers available: $7, $2, $4, $1
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+
+$do_wh64_b:
+ wh64 ($4) # L1 : memory subsystem write hint
+ subq $3, 24, $2 # E : For determining future wh64 addresses
+ stq $17, 0($5) # L :
+ nop # E :
+
+ addq $5, 128, $4 # E : speculative target of next wh64
+ stq $17, 8($5) # L :
+ stq $17, 16($5) # L :
+ addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
+
+ stq $17, 24($5) # L :
+ stq $17, 32($5) # L :
+ cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
+ nop
+
+ stq $17, 40($5) # L :
+ stq $17, 48($5) # L :
+ subq $3, 16, $2 # E : Repeat the loop at least once more?
+ nop
+
+ stq $17, 56($5) # L :
+ addq $5, 64, $5 # E :
+ subq $3, 8, $3 # E :
+ bge $2, $do_wh64_b # U :
+
+ nop
+ nop
+ nop
+ beq $3, no_quad_b # U : Might have finished already
+
+.align 4
+ /*
+ * Simple loop for trailing quadwords, or for small amounts
+ * of data (where we can't use an unrolled loop and wh64)
+ */
+loop_b:
+ stq $17,0($5) # L :
+ subq $3,1,$3 # E : Decrement number quads left
+ addq $5,8,$5 # E : Inc address
+ bne $3,loop_b # U : more?
+
+no_quad_b:
+ /*
+ * Write 0..7 trailing bytes.
+ */
+ nop # E :
+ beq $18,end_b # U : All done?
+ ldq $7,0($5) # L :
+ mskqh $7,$6,$2 # U : Mask final quad
+
+ insqh $17,$6,$4 # U : New bits
+ bis $2,$4,$1 # E : Put it all together
+ stq $1,0($5) # L : And back to memory
+ ret $31,($26),1 # L0 :
+
+within_quad_b:
+ ldq_u $1,0($16) # L :
+ insql $17,$16,$2 # U : New bits
+ mskql $1,$16,$4 # U : Clear old
+ bis $2,$4,$2 # E : New result
+
+ mskql $2,$6,$4 # U :
+ mskqh $1,$6,$2 # U :
+ bis $2,$4,$1 # E :
+ stq_u $1,0($16) # L :
+
+end_b:
+ nop
+ nop
+ nop
+ ret $31,($26),1 # L0 :
+ .end __memset
+
+ /*
+ * This is the original body of code, prior to replication and
+ * rescheduling. Leave it here, as there may be calls to this
+ * entry point.
+ */
+.align 4
+ .ent __memset
+__constant_c_memset:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ addq $18,$16,$6 # E : max address to write to
+ bis $16,$16,$0 # E : return value
+ xor $16,$6,$1 # E : will complete write be within one quadword?
+ ble $18,end # U : zero length requested?
+
+ bic $1,7,$1 # E : fit within a single quadword
+ beq $1,within_one_quad # U :
+ and $16,7,$3 # E : Target addr misalignment
+ beq $3,aligned # U : target is 0mod8
+
+ /*
+ * Target address is misaligned, and won't fit within a quadword
+ */
+ ldq_u $4,0($16) # L : Fetch first partial
+ bis $16,$16,$5 # E : Save the address
+ insql $17,$16,$2 # U : Insert new bytes
+ subq $3,8,$3 # E : Invert (for addressing uses)
+
+ addq $18,$3,$18 # E : $18 is new count ($3 is negative)
+ mskql $4,$16,$4 # U : clear relevant parts of the quad
+ subq $16,$3,$16 # E : $16 is new aligned destination
+ bis $2,$4,$1 # E : Final bytes
+
+ nop
+ stq_u $1,0($5) # L : Store result
+ nop
+ nop
+
+.align 4
+aligned:
+ /*
+ * We are now guaranteed to be quad aligned, with at least
+ * one partial quad to write.
+ */
+
+ sra $18,3,$3 # U : Number of remaining quads to write
+ and $18,7,$18 # E : Number of trailing bytes to write
+ bis $16,$16,$5 # E : Save dest address
+ beq $3,no_quad # U : tail stuff only
+
+ /*
+ * it's worth the effort to unroll this and use wh64 if possible
+ * Lifted a bunch of code from clear_user.S
+ * At this point, entry values are:
+ * $16 Current destination address
+ * $5 A copy of $16
+ * $6 The max quadword address to write to
+ * $18 Number trailer bytes
+ * $3 Number quads to write
+ */
+
+ and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
+ subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
+ subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
+ blt $4, loop # U :
+
+ /*
+ * We know we've got at least 16 quads, minimum of one trip
+ * through unrolled loop. Do a quad at a time to get us 0mod64
+ * aligned.
+ */
+
+ nop # E :
+ nop # E :
+ nop # E :
+ beq $1, $bigalign # U :
+
+$alignmod64:
+ stq $17, 0($5) # L :
+ subq $3, 1, $3 # E : For consistency later
+ addq $1, 8, $1 # E : Increment towards zero for alignment
+ addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
+
+ nop
+ nop
+ addq $5, 8, $5 # E : Inc address
+ blt $1, $alignmod64 # U :
+
+$bigalign:
+ /*
+ * $3 - number quads left to go
+ * $5 - target address (aligned 0mod64)
+ * $17 - mask of stuff to store
+ * Scratch registers available: $7, $2, $4, $1
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+
+$do_wh64:
+ wh64 ($4) # L1 : memory subsystem write hint
+ subq $3, 24, $2 # E : For determining future wh64 addresses
+ stq $17, 0($5) # L :
+ nop # E :
+
+ addq $5, 128, $4 # E : speculative target of next wh64
+ stq $17, 8($5) # L :
+ stq $17, 16($5) # L :
+ addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
+
+ stq $17, 24($5) # L :
+ stq $17, 32($5) # L :
+ cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
+ nop
+
+ stq $17, 40($5) # L :
+ stq $17, 48($5) # L :
+ subq $3, 16, $2 # E : Repeat the loop at least once more?
+ nop
+
+ stq $17, 56($5) # L :
+ addq $5, 64, $5 # E :
+ subq $3, 8, $3 # E :
+ bge $2, $do_wh64 # U :
+
+ nop
+ nop
+ nop
+ beq $3, no_quad # U : Might have finished already
+
+.align 4
+ /*
+ * Simple loop for trailing quadwords, or for small amounts
+ * of data (where we can't use an unrolled loop and wh64)
+ */
+loop:
+ stq $17,0($5) # L :
+ subq $3,1,$3 # E : Decrement number quads left
+ addq $5,8,$5 # E : Inc address
+ bne $3,loop # U : more?
+
+no_quad:
+ /*
+ * Write 0..7 trailing bytes.
+ */
+ nop # E :
+ beq $18,end # U : All done?
+ ldq $7,0($5) # L :
+ mskqh $7,$6,$2 # U : Mask final quad
+
+ insqh $17,$6,$4 # U : New bits
+ bis $2,$4,$1 # E : Put it all together
+ stq $1,0($5) # L : And back to memory
+ ret $31,($26),1 # L0 :
+
+within_one_quad:
+ ldq_u $1,0($16) # L :
+ insql $17,$16,$2 # U : New bits
+ mskql $1,$16,$4 # U : Clear old
+ bis $2,$4,$2 # E : New result
+
+ mskql $2,$6,$4 # U :
+ mskqh $1,$6,$2 # U :
+ bis $2,$4,$1 # E :
+ stq_u $1,0($16) # L :
+
+end:
+ nop
+ nop
+ nop
+ ret $31,($26),1 # L0 :
+ .end __constant_c_memset
+
+ /*
+ * This is a replicant of the __constant_c_memset code, rescheduled
+ * to mask stalls. Note that entry point names also had to change
+ */
+ .align 5
+ .ent __memsetw
+
+__memsetw:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ inswl $17,0,$5 # U : 000000000000c1c2
+ inswl $17,2,$2 # U : 00000000c1c20000
+ bis $16,$16,$0 # E : return value
+ addq $18,$16,$6 # E : max address to write to
+
+ ble $18, end_w # U : zero length requested?
+ inswl $17,4,$3 # U : 0000c1c200000000
+ inswl $17,6,$4 # U : c1c2000000000000
+ xor $16,$6,$1 # E : will complete write be within one quadword?
+
+ or $2,$5,$2 # E : 00000000c1c2c1c2
+ or $3,$4,$17 # E : c1c2c1c200000000
+ bic $1,7,$1 # E : fit within a single quadword
+ and $16,7,$3 # E : Target addr misalignment
+
+ or $17,$2,$17 # E : c1c2c1c2c1c2c1c2
+ beq $1,within_quad_w # U :
+ nop
+ beq $3,aligned_w # U : target is 0mod8
+
+ /*
+ * Target address is misaligned, and won't fit within a quadword
+ */
+ ldq_u $4,0($16) # L : Fetch first partial
+ bis $16,$16,$5 # E : Save the address
+ insql $17,$16,$2 # U : Insert new bytes
+ subq $3,8,$3 # E : Invert (for addressing uses)
+
+ addq $18,$3,$18 # E : $18 is new count ($3 is negative)
+ mskql $4,$16,$4 # U : clear relevant parts of the quad
+ subq $16,$3,$16 # E : $16 is new aligned destination
+ bis $2,$4,$1 # E : Final bytes
+
+ nop
+ stq_u $1,0($5) # L : Store result
+ nop
+ nop
+
+.align 4
+aligned_w:
+ /*
+ * We are now guaranteed to be quad aligned, with at least
+ * one partial quad to write.
+ */
+
+ sra $18,3,$3 # U : Number of remaining quads to write
+ and $18,7,$18 # E : Number of trailing bytes to write
+ bis $16,$16,$5 # E : Save dest address
+ beq $3,no_quad_w # U : tail stuff only
+
+ /*
+ * it's worth the effort to unroll this and use wh64 if possible
+ * Lifted a bunch of code from clear_user.S
+ * At this point, entry values are:
+ * $16 Current destination address
+ * $5 A copy of $16
+ * $6 The max quadword address to write to
+ * $18 Number trailer bytes
+ * $3 Number quads to write
+ */
+
+ and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
+ subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
+ subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
+ blt $4, loop_w # U :
+
+ /*
+ * We know we've got at least 16 quads, minimum of one trip
+ * through unrolled loop. Do a quad at a time to get us 0mod64
+ * aligned.
+ */
+
+ nop # E :
+ nop # E :
+ nop # E :
+ beq $1, $bigalign_w # U :
+
+$alignmod64_w:
+ stq $17, 0($5) # L :
+ subq $3, 1, $3 # E : For consistency later
+ addq $1, 8, $1 # E : Increment towards zero for alignment
+ addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
+
+ nop
+ nop
+ addq $5, 8, $5 # E : Inc address
+ blt $1, $alignmod64_w # U :
+
+$bigalign_w:
+ /*
+ * $3 - number quads left to go
+ * $5 - target address (aligned 0mod64)
+ * $17 - mask of stuff to store
+ * Scratch registers available: $7, $2, $4, $1
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+
+$do_wh64_w:
+ wh64 ($4) # L1 : memory subsystem write hint
+ subq $3, 24, $2 # E : For determining future wh64 addresses
+ stq $17, 0($5) # L :
+ nop # E :
+
+ addq $5, 128, $4 # E : speculative target of next wh64
+ stq $17, 8($5) # L :
+ stq $17, 16($5) # L :
+ addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
+
+ stq $17, 24($5) # L :
+ stq $17, 32($5) # L :
+ cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
+ nop
+
+ stq $17, 40($5) # L :
+ stq $17, 48($5) # L :
+ subq $3, 16, $2 # E : Repeat the loop at least once more?
+ nop
+
+ stq $17, 56($5) # L :
+ addq $5, 64, $5 # E :
+ subq $3, 8, $3 # E :
+ bge $2, $do_wh64_w # U :
+
+ nop
+ nop
+ nop
+ beq $3, no_quad_w # U : Might have finished already
+
+.align 4
+ /*
+ * Simple loop for trailing quadwords, or for small amounts
+ * of data (where we can't use an unrolled loop and wh64)
+ */
+loop_w:
+ stq $17,0($5) # L :
+ subq $3,1,$3 # E : Decrement number quads left
+ addq $5,8,$5 # E : Inc address
+ bne $3,loop_w # U : more?
+
+no_quad_w:
+ /*
+ * Write 0..7 trailing bytes.
+ */
+ nop # E :
+ beq $18,end_w # U : All done?
+ ldq $7,0($5) # L :
+ mskqh $7,$6,$2 # U : Mask final quad
+
+ insqh $17,$6,$4 # U : New bits
+ bis $2,$4,$1 # E : Put it all together
+ stq $1,0($5) # L : And back to memory
+ ret $31,($26),1 # L0 :
+
+within_quad_w:
+ ldq_u $1,0($16) # L :
+ insql $17,$16,$2 # U : New bits
+ mskql $1,$16,$4 # U : Clear old
+ bis $2,$4,$2 # E : New result
+
+ mskql $2,$6,$4 # U :
+ mskqh $1,$6,$2 # U :
+ bis $2,$4,$1 # E :
+ stq_u $1,0($16) # L :
+
+end_w:
+ nop
+ nop
+ nop
+ ret $31,($26),1 # L0 :
+
+ .end __memsetw
diff --git a/arch/alpha/lib/ev6-strncpy_from_user.S b/arch/alpha/lib/ev6-strncpy_from_user.S
new file mode 100644
index 000000000..8d446778b
--- /dev/null
+++ b/arch/alpha/lib/ev6-strncpy_from_user.S
@@ -0,0 +1,425 @@
+/*
+ * arch/alpha/lib/ev6-strncpy_from_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Just like strncpy except in the return value:
+ *
+ * -EFAULT if an exception occurs before the terminator is copied.
+ * N if the buffer filled.
+ *
+ * Otherwise the length of the string is returned.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * A bunch of instructions got moved and temp registers were changed
+ * to aid in scheduling. Control flow was also re-arranged to eliminate
+ * branches, and to provide longer code sequences to enable better scheduling.
+ * A total rewrite (using byte load/stores for start & tail sequences)
+ * is desirable, but very difficult to do without a from-scratch rewrite.
+ * Save that for the future.
+ */
+
+
+#include <asm/errno.h>
+#include <alpha/regdef.h>
+
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EX(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda $31, $exception-99b($0); \
+ .previous
+
+
+ .set noat
+ .set noreorder
+ .text
+
+ .globl __strncpy_from_user
+ .ent __strncpy_from_user
+ .frame $30, 0, $26
+ .prologue 1
+
+ .align 4
+__strncpy_from_user:
+ ldgp $29, 0($27) # E E : becomes 2 instructions (for exceptions)
+ and a0, 7, t3 # E : find dest misalignment
+ beq a2, $zerolength # U :
+
+ /* Are source and destination co-aligned? */
+ mov a0, v0 # E : save the string start
+ xor a0, a1, t4 # E :
+ EX( ldq_u t1, 0(a1) ) # L : Latency=3 load first quadword
+ ldq_u t0, 0(a0) # L : load first (partial) aligned dest quadword
+
+ addq a2, t3, a2 # E : bias count by dest misalignment
+ subq a2, 1, a3 # E :
+ addq zero, 1, t10 # E :
+ and t4, 7, t4 # E : misalignment between the two
+
+ and a3, 7, t6 # E : number of tail bytes
+ sll t10, t6, t10 # E : t10 = bitmask of last count byte
+ bne t4, $unaligned # U :
+ lda t2, -1 # E : build a mask against false zero
+
+ /*
+ * We are co-aligned; take care of a partial first word.
+ * On entry to this basic block:
+ * t0 == the first destination word for masking back in
+ * t1 == the first source word.
+ */
+
+ srl a3, 3, a2 # E : a2 = loop counter = (count - 1)/8
+ addq a1, 8, a1 # E :
+ mskqh t2, a1, t2 # U : detection in the src word
+ nop
+
+ /* Create the 1st output word and detect 0's in the 1st input word. */
+ mskqh t1, a1, t3 # U :
+ mskql t0, a1, t0 # U : assemble the first output word
+ ornot t1, t2, t2 # E :
+ nop
+
+ cmpbge zero, t2, t8 # E : bits set iff null found
+ or t0, t3, t0 # E :
+ beq a2, $a_eoc # U :
+ bne t8, $a_eos # U : 2nd branch in a quad. Bad.
+
+ /* On entry to this basic block:
+ * t0 == a source quad not containing a null.
+ * a0 - current aligned destination address
+ * a1 - current aligned source address
+ * a2 - count of quadwords to move.
+ * NOTE: Loop improvement - unrolling this is going to be
+ * a huge win, since we're going to stall otherwise.
+ * Fix this later. For _really_ large copies, look
+ * at using wh64 on a look-ahead basis. See the code
+ * in clear_user.S and copy_user.S.
+ * Presumably, since (a0) and (a1) do not overlap (by C definition)
+ * Lots of nops here:
+ * - Separate loads from stores
+ * - Keep it to 1 branch/quadpack so the branch predictor
+ * can train.
+ */
+$a_loop:
+ stq_u t0, 0(a0) # L :
+ addq a0, 8, a0 # E :
+ nop
+ subq a2, 1, a2 # E :
+
+ EX( ldq_u t0, 0(a1) ) # L :
+ addq a1, 8, a1 # E :
+ cmpbge zero, t0, t8 # E : Stall 2 cycles on t0
+ beq a2, $a_eoc # U :
+
+ beq t8, $a_loop # U :
+ nop
+ nop
+ nop
+
+ /* Take care of the final (partial) word store. At this point
+ * the end-of-count bit is set in t8 iff it applies.
+ *
+ * On entry to this basic block we have:
+ * t0 == the source word containing the null
+ * t8 == the cmpbge mask that found it.
+ */
+$a_eos:
+ negq t8, t12 # E : find low bit set
+ and t8, t12, t12 # E :
+
+ /* We're doing a partial word store and so need to combine
+ our source and original destination words. */
+ ldq_u t1, 0(a0) # L :
+ subq t12, 1, t6 # E :
+
+ or t12, t6, t8 # E :
+ zapnot t0, t8, t0 # U : clear src bytes > null
+ zap t1, t8, t1 # U : clear dst bytes <= null
+ or t0, t1, t0 # E :
+
+ stq_u t0, 0(a0) # L :
+ br $finish_up # L0 :
+ nop
+ nop
+
+ /* Add the end-of-count bit to the eos detection bitmask. */
+ .align 4
+$a_eoc:
+ or t10, t8, t8
+ br $a_eos
+ nop
+ nop
+
+
+/* The source and destination are not co-aligned. Align the destination
+ and cope. We have to be very careful about not reading too much and
+ causing a SEGV. */
+
+ .align 4
+$u_head:
+ /* We know just enough now to be able to assemble the first
+ full source word. We can still find a zero at the end of it
+ that prevents us from outputting the whole thing.
+
+ On entry to this basic block:
+ t0 == the first dest word, unmasked
+ t1 == the shifted low bits of the first source word
+ t6 == bytemask that is -1 in dest word bytes */
+
+ EX( ldq_u t2, 8(a1) ) # L : load second src word
+ addq a1, 8, a1 # E :
+ mskql t0, a0, t0 # U : mask trailing garbage in dst
+ extqh t2, a1, t4 # U :
+
+ or t1, t4, t1 # E : first aligned src word complete
+ mskqh t1, a0, t1 # U : mask leading garbage in src
+ or t0, t1, t0 # E : first output word complete
+ or t0, t6, t6 # E : mask original data for zero test
+
+ cmpbge zero, t6, t8 # E :
+ beq a2, $u_eocfin # U :
+ bne t8, $u_final # U : bad news - 2nd branch in a quad
+ lda t6, -1 # E : mask out the bits we have
+
+ mskql t6, a1, t6 # U : already seen
+ stq_u t0, 0(a0) # L : store first output word
+ or t6, t2, t2 # E :
+ cmpbge zero, t2, t8 # E : find nulls in second partial
+
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+ bne t8, $u_late_head_exit # U :
+ nop
+
+ /* Finally, we've got all the stupid leading edge cases taken care
+ of and we can set up to enter the main loop. */
+
+ extql t2, a1, t1 # U : position hi-bits of lo word
+ EX( ldq_u t2, 8(a1) ) # L : read next high-order source word
+ addq a1, 8, a1 # E :
+ cmpbge zero, t2, t8 # E :
+
+ beq a2, $u_eoc # U :
+ bne t8, $u_eos # U :
+ nop
+ nop
+
+ /* Unaligned copy main loop. In order to avoid reading too much,
+ the loop is structured to detect zeros in aligned source words.
+ This has, unfortunately, effectively pulled half of a loop
+ iteration out into the head and half into the tail, but it does
+ prevent nastiness from accumulating in the very thing we want
+ to run as fast as possible.
+
+ On entry to this basic block:
+ t1 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word
+
+ We further know that t2 does not contain a null terminator. */
+
+ /*
+ * Extra nops here:
+ * separate load quads from store quads
+ * only one branch/quad to permit predictor training
+ */
+
+ .align 4
+$u_loop:
+ extqh t2, a1, t0 # U : extract high bits for current word
+ addq a1, 8, a1 # E :
+ extql t2, a1, t3 # U : extract low bits for next time
+ addq a0, 8, a0 # E :
+
+ or t0, t1, t0 # E : current dst word now complete
+ EX( ldq_u t2, 0(a1) ) # L : load high word for next time
+ subq a2, 1, a2 # E :
+ nop
+
+ stq_u t0, -8(a0) # L : save the current word
+ mov t3, t1 # E :
+ cmpbge zero, t2, t8 # E : test new word for eos
+ beq a2, $u_eoc # U :
+
+ beq t8, $u_loop # U :
+ nop
+ nop
+ nop
+
+ /* We've found a zero somewhere in the source word we just read.
+ If it resides in the lower half, we have one (probably partial)
+ word to write out, and if it resides in the upper half, we
+ have one full and one partial word left to write out.
+
+ On entry to this basic block:
+ t1 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word. */
+ .align 4
+$u_eos:
+ extqh t2, a1, t0 # U :
+ or t0, t1, t0 # E : first (partial) source word complete
+ cmpbge zero, t0, t8 # E : is the null in this first bit?
+ nop
+
+ bne t8, $u_final # U :
+ stq_u t0, 0(a0) # L : the null was in the high-order bits
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+
+ .align 4
+$u_late_head_exit:
+ extql t2, a1, t0 # U :
+ cmpbge zero, t0, t8 # E :
+ or t8, t10, t6 # E :
+ cmoveq a2, t6, t8 # E :
+
+ /* Take care of a final (probably partial) result word.
+ On entry to this basic block:
+ t0 == assembled source word
+ t8 == cmpbge mask that found the null. */
+ .align 4
+$u_final:
+ negq t8, t6 # E : isolate low bit set
+ and t6, t8, t12 # E :
+ ldq_u t1, 0(a0) # L :
+ subq t12, 1, t6 # E :
+
+ or t6, t12, t8 # E :
+ zapnot t0, t8, t0 # U : kill source bytes > null
+ zap t1, t8, t1 # U : kill dest bytes <= null
+ or t0, t1, t0 # E :
+
+ stq_u t0, 0(a0) # E :
+ br $finish_up # U :
+ nop
+ nop
+
+ .align 4
+$u_eoc: # end-of-count
+ extqh t2, a1, t0 # U :
+ or t0, t1, t0 # E :
+ cmpbge zero, t0, t8 # E :
+ nop
+
+ .align 4
+$u_eocfin: # end-of-count, final word
+ or t10, t8, t8 # E :
+ br $u_final # U :
+ nop
+ nop
+
+ /* Unaligned copy entry point. */
+ .align 4
+$unaligned:
+
+ srl a3, 3, a2 # U : a2 = loop counter = (count - 1)/8
+ and a0, 7, t4 # E : find dest misalignment
+ and a1, 7, t5 # E : find src misalignment
+ mov zero, t0 # E :
+
+ /* Conditionally load the first destination word and a bytemask
+ with 0xff indicating that the destination byte is sacrosanct. */
+
+ mov zero, t6 # E :
+ beq t4, 1f # U :
+ ldq_u t0, 0(a0) # L :
+ lda t6, -1 # E :
+
+ mskql t6, a0, t6 # E :
+ nop
+ nop
+ nop
+
+ .align 4
+1:
+ subq a1, t4, a1 # E : sub dest misalignment from src addr
+ /* If source misalignment is larger than dest misalignment, we need
+ extra startup checks to avoid SEGV. */
+ cmplt t4, t5, t12 # E :
+ extql t1, a1, t1 # U : shift src into place
+ lda t2, -1 # E : for creating masks later
+
+ beq t12, $u_head # U :
+ mskqh t2, t5, t2 # U : begin src byte validity mask
+ cmpbge zero, t1, t8 # E : is there a zero?
+ nop
+
+ extql t2, a1, t2 # U :
+ or t8, t10, t5 # E : test for end-of-count too
+ cmpbge zero, t2, t3 # E :
+ cmoveq a2, t5, t8 # E : Latency=2, extra map slot
+
+ nop # E : goes with cmov
+ andnot t8, t3, t8 # E :
+ beq t8, $u_head # U :
+ nop
+
+ /* At this point we've found a zero in the first partial word of
+ the source. We need to isolate the valid source data and mask
+ it into the original destination data. (Incidentally, we know
+ that we'll need at least one byte of that original dest word.) */
+
+ ldq_u t0, 0(a0) # L :
+ negq t8, t6 # E : build bitmask of bytes <= zero
+ mskqh t1, t4, t1 # U :
+ and t6, t8, t12 # E :
+
+ subq t12, 1, t6 # E :
+ or t6, t12, t8 # E :
+ zapnot t2, t8, t2 # U : prepare source word; mirror changes
+ zapnot t1, t8, t1 # U : to source validity mask
+
+ andnot t0, t2, t0 # E : zero place for source to reside
+ or t0, t1, t0 # E : and put it there
+ stq_u t0, 0(a0) # L :
+ nop
+
+ .align 4
+$finish_up:
+ zapnot t0, t12, t4 # U : was last byte written null?
+ and t12, 0xf0, t3 # E : binary search for the address of the
+ cmovne t4, 1, t4 # E : Latency=2, extra map slot
+ nop # E : with cmovne
+
+ and t12, 0xcc, t2 # E : last byte written
+ and t12, 0xaa, t1 # E :
+ cmovne t3, 4, t3 # E : Latency=2, extra map slot
+ nop # E : with cmovne
+
+ bic a0, 7, t0
+ cmovne t2, 2, t2 # E : Latency=2, extra map slot
+ nop # E : with cmovne
+ nop
+
+ cmovne t1, 1, t1 # E : Latency=2, extra map slot
+ nop # E : with cmovne
+ addq t0, t3, t0 # E :
+ addq t1, t2, t1 # E :
+
+ addq t0, t1, t0 # E :
+ addq t0, t4, t0 # add one if we filled the buffer
+ subq t0, v0, v0 # find string length
+ ret # L0 :
+
+ .align 4
+$zerolength:
+ nop
+ nop
+ nop
+ clr v0
+
+$exception:
+ nop
+ nop
+ nop
+ ret
+
+ .end __strncpy_from_user
diff --git a/arch/alpha/lib/ev6-stxcpy.S b/arch/alpha/lib/ev6-stxcpy.S
new file mode 100644
index 000000000..f5b409e9a
--- /dev/null
+++ b/arch/alpha/lib/ev6-stxcpy.S
@@ -0,0 +1,321 @@
+/*
+ * arch/alpha/lib/ev6-stxcpy.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Copy a null-terminated string from SRC to DST.
+ *
+ * This is an internal routine used by strcpy, stpcpy, and strcat.
+ * As such, it uses special linkage conventions to make implementation
+ * of these public functions more efficient.
+ *
+ * On input:
+ * t9 = return address
+ * a0 = DST
+ * a1 = SRC
+ *
+ * On output:
+ * t12 = bitmask (with one bit set) indicating the last byte written
+ * a0 = unaligned address of the last *word* written
+ *
+ * Furthermore, v0, a3-a5, t11, and t12 are untouched.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+ .set noat
+ .set noreorder
+
+ .text
+
+/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
+ doesn't like putting the entry point for a procedure somewhere in the
+ middle of the procedure descriptor. Work around this by putting the
+ aligned copy in its own procedure descriptor */
+
+
+ .ent stxcpy_aligned
+ .align 4
+stxcpy_aligned:
+ .frame sp, 0, t9
+ .prologue 0
+
+ /* On entry to this basic block:
+ t0 == the first destination word for masking back in
+ t1 == the first source word. */
+
+ /* Create the 1st output word and detect 0's in the 1st input word. */
+ lda t2, -1 # E : build a mask against false zero
+ mskqh t2, a1, t2 # U : detection in the src word (stall)
+ mskqh t1, a1, t3 # U :
+ ornot t1, t2, t2 # E : (stall)
+
+ mskql t0, a1, t0 # U : assemble the first output word
+ cmpbge zero, t2, t8 # E : bits set iff null found
+ or t0, t3, t1 # E : (stall)
+ bne t8, $a_eos # U : (stall)
+
+ /* On entry to this basic block:
+ t0 == the first destination word for masking back in
+ t1 == a source word not containing a null. */
+ /* Nops here to separate store quads from load quads */
+
+$a_loop:
+ stq_u t1, 0(a0) # L :
+ addq a0, 8, a0 # E :
+ nop
+ nop
+
+ ldq_u t1, 0(a1) # L : Latency=3
+ addq a1, 8, a1 # E :
+ cmpbge zero, t1, t8 # E : (3 cycle stall)
+ beq t8, $a_loop # U : (stall for t8)
+
+ /* Take care of the final (partial) word store.
+ On entry to this basic block we have:
+ t1 == the source word containing the null
+ t8 == the cmpbge mask that found it. */
+$a_eos:
+ negq t8, t6 # E : find low bit set
+ and t8, t6, t12 # E : (stall)
+ /* For the sake of the cache, don't read a destination word
+ if we're not going to need it. */
+ and t12, 0x80, t6 # E : (stall)
+ bne t6, 1f # U : (stall)
+
+ /* We're doing a partial word store and so need to combine
+ our source and original destination words. */
+ ldq_u t0, 0(a0) # L : Latency=3
+ subq t12, 1, t6 # E :
+ zapnot t1, t6, t1 # U : clear src bytes >= null (stall)
+ or t12, t6, t8 # E : (stall)
+
+ zap t0, t8, t0 # E : clear dst bytes <= null
+ or t0, t1, t1 # E : (stall)
+ nop
+ nop
+
+1: stq_u t1, 0(a0) # L :
+ ret (t9) # L0 : Latency=3
+ nop
+ nop
+
+ .end stxcpy_aligned
+
+ .align 4
+ .ent __stxcpy
+ .globl __stxcpy
+__stxcpy:
+ .frame sp, 0, t9
+ .prologue 0
+
+ /* Are source and destination co-aligned? */
+ xor a0, a1, t0 # E :
+ unop # E :
+ and t0, 7, t0 # E : (stall)
+ bne t0, $unaligned # U : (stall)
+
+ /* We are co-aligned; take care of a partial first word. */
+ ldq_u t1, 0(a1) # L : load first src word
+ and a0, 7, t0 # E : take care not to load a word ...
+ addq a1, 8, a1 # E :
+ beq t0, stxcpy_aligned # U : ... if we wont need it (stall)
+
+ ldq_u t0, 0(a0) # L :
+ br stxcpy_aligned # L0 : Latency=3
+ nop
+ nop
+
+
+/* The source and destination are not co-aligned. Align the destination
+ and cope. We have to be very careful about not reading too much and
+ causing a SEGV. */
+
+ .align 4
+$u_head:
+ /* We know just enough now to be able to assemble the first
+ full source word. We can still find a zero at the end of it
+ that prevents us from outputting the whole thing.
+
+ On entry to this basic block:
+ t0 == the first dest word, for masking back in, if needed else 0
+ t1 == the low bits of the first source word
+ t6 == bytemask that is -1 in dest word bytes */
+
+ ldq_u t2, 8(a1) # L :
+ addq a1, 8, a1 # E :
+ extql t1, a1, t1 # U : (stall on a1)
+ extqh t2, a1, t4 # U : (stall on a1)
+
+ mskql t0, a0, t0 # U :
+ or t1, t4, t1 # E :
+ mskqh t1, a0, t1 # U : (stall on t1)
+ or t0, t1, t1 # E : (stall on t1)
+
+ or t1, t6, t6 # E :
+ cmpbge zero, t6, t8 # E : (stall)
+ lda t6, -1 # E : for masking just below
+ bne t8, $u_final # U : (stall)
+
+ mskql t6, a1, t6 # U : mask out the bits we have
+ or t6, t2, t2 # E : already extracted before (stall)
+ cmpbge zero, t2, t8 # E : testing eos (stall)
+ bne t8, $u_late_head_exit # U : (stall)
+
+ /* Finally, we've got all the stupid leading edge cases taken care
+ of and we can set up to enter the main loop. */
+
+ stq_u t1, 0(a0) # L : store first output word
+ addq a0, 8, a0 # E :
+ extql t2, a1, t0 # U : position ho-bits of lo word
+ ldq_u t2, 8(a1) # U : read next high-order source word
+
+ addq a1, 8, a1 # E :
+ cmpbge zero, t2, t8 # E : (stall for t2)
+ nop # E :
+ bne t8, $u_eos # U : (stall)
+
+ /* Unaligned copy main loop. In order to avoid reading too much,
+ the loop is structured to detect zeros in aligned source words.
+ This has, unfortunately, effectively pulled half of a loop
+ iteration out into the head and half into the tail, but it does
+ prevent nastiness from accumulating in the very thing we want
+ to run as fast as possible.
+
+ On entry to this basic block:
+ t0 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word
+
+ We further know that t2 does not contain a null terminator. */
+
+ .align 3
+$u_loop:
+ extqh t2, a1, t1 # U : extract high bits for current word
+ addq a1, 8, a1 # E : (stall)
+ extql t2, a1, t3 # U : extract low bits for next time (stall)
+ addq a0, 8, a0 # E :
+
+ or t0, t1, t1 # E : current dst word now complete
+ ldq_u t2, 0(a1) # L : Latency=3 load high word for next time
+ stq_u t1, -8(a0) # L : save the current word (stall)
+ mov t3, t0 # E :
+
+ cmpbge zero, t2, t8 # E : test new word for eos
+ beq t8, $u_loop # U : (stall)
+ nop
+ nop
+
+ /* We've found a zero somewhere in the source word we just read.
+ If it resides in the lower half, we have one (probably partial)
+ word to write out, and if it resides in the upper half, we
+ have one full and one partial word left to write out.
+
+ On entry to this basic block:
+ t0 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word. */
+$u_eos:
+ extqh t2, a1, t1 # U :
+ or t0, t1, t1 # E : first (partial) source word complete (stall)
+ cmpbge zero, t1, t8 # E : is the null in this first bit? (stall)
+ bne t8, $u_final # U : (stall)
+
+$u_late_head_exit:
+ stq_u t1, 0(a0) # L : the null was in the high-order bits
+ addq a0, 8, a0 # E :
+ extql t2, a1, t1 # U :
+ cmpbge zero, t1, t8 # E : (stall)
+
+ /* Take care of a final (probably partial) result word.
+ On entry to this basic block:
+ t1 == assembled source word
+ t8 == cmpbge mask that found the null. */
+$u_final:
+ negq t8, t6 # E : isolate low bit set
+ and t6, t8, t12 # E : (stall)
+ and t12, 0x80, t6 # E : avoid dest word load if we can (stall)
+ bne t6, 1f # U : (stall)
+
+ ldq_u t0, 0(a0) # E :
+ subq t12, 1, t6 # E :
+ or t6, t12, t8 # E : (stall)
+ zapnot t1, t6, t1 # U : kill source bytes >= null (stall)
+
+ zap t0, t8, t0 # U : kill dest bytes <= null (2 cycle data stall)
+ or t0, t1, t1 # E : (stall)
+ nop
+ nop
+
+1: stq_u t1, 0(a0) # L :
+ ret (t9) # L0 : Latency=3
+ nop
+ nop
+
+ /* Unaligned copy entry point. */
+ .align 4
+$unaligned:
+
+ ldq_u t1, 0(a1) # L : load first source word
+ and a0, 7, t4 # E : find dest misalignment
+ and a1, 7, t5 # E : find src misalignment
+ /* Conditionally load the first destination word and a bytemask
+ with 0xff indicating that the destination byte is sacrosanct. */
+ mov zero, t0 # E :
+
+ mov zero, t6 # E :
+ beq t4, 1f # U :
+ ldq_u t0, 0(a0) # L :
+ lda t6, -1 # E :
+
+ mskql t6, a0, t6 # U :
+ nop
+ nop
+ nop
+1:
+ subq a1, t4, a1 # E : sub dest misalignment from src addr
+ /* If source misalignment is larger than dest misalignment, we need
+ extra startup checks to avoid SEGV. */
+ cmplt t4, t5, t12 # E :
+ beq t12, $u_head # U :
+ lda t2, -1 # E : mask out leading garbage in source
+
+ mskqh t2, t5, t2 # U :
+ ornot t1, t2, t3 # E : (stall)
+ cmpbge zero, t3, t8 # E : is there a zero? (stall)
+ beq t8, $u_head # U : (stall)
+
+ /* At this point we've found a zero in the first partial word of
+ the source. We need to isolate the valid source data and mask
+ it into the original destination data. (Incidentally, we know
+ that we'll need at least one byte of that original dest word.) */
+
+ ldq_u t0, 0(a0) # L :
+ negq t8, t6 # E : build bitmask of bytes <= zero
+ and t6, t8, t12 # E : (stall)
+ and a1, 7, t5 # E :
+
+ subq t12, 1, t6 # E :
+ or t6, t12, t8 # E : (stall)
+ srl t12, t5, t12 # U : adjust final null return value
+ zapnot t2, t8, t2 # U : prepare source word; mirror changes (stall)
+
+ and t1, t2, t1 # E : to source validity mask
+ extql t2, a1, t2 # U :
+ extql t1, a1, t1 # U : (stall)
+ andnot t0, t2, t0 # .. e1 : zero place for source to reside (stall)
+
+ or t0, t1, t1 # e1 : and put it there
+ stq_u t1, 0(a0) # .. e0 : (stall)
+ ret (t9) # e1 :
+ nop
+
+ .end __stxcpy
+
diff --git a/arch/alpha/lib/ev6-stxncpy.S b/arch/alpha/lib/ev6-stxncpy.S
new file mode 100644
index 000000000..7848b4c80
--- /dev/null
+++ b/arch/alpha/lib/ev6-stxncpy.S
@@ -0,0 +1,399 @@
+/*
+ * arch/alpha/lib/ev6-stxncpy.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
+ *
+ * Copy no more than COUNT bytes of the null-terminated string from
+ * SRC to DST.
+ *
+ * This is an internal routine used by strncpy, stpncpy, and strncat.
+ * As such, it uses special linkage conventions to make implementation
+ * of these public functions more efficient.
+ *
+ * On input:
+ * t9 = return address
+ * a0 = DST
+ * a1 = SRC
+ * a2 = COUNT
+ *
+ * Furthermore, COUNT may not be zero.
+ *
+ * On output:
+ * t0 = last word written
+ * t10 = bitmask (with one bit set) indicating the byte position of
+ * the end of the range specified by COUNT
+ * t12 = bitmask (with one bit set) indicating the last byte written
+ * a0 = unaligned address of the last *word* written
+ * a2 = the number of full words left in COUNT
+ *
+ * Furthermore, v0, a3-a5, t11, t12, and $at are untouched.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+ .set noat
+ .set noreorder
+
+ .text
+
+/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
+ doesn't like putting the entry point for a procedure somewhere in the
+ middle of the procedure descriptor. Work around this by putting the
+ aligned copy in its own procedure descriptor */
+
+
+ .ent stxncpy_aligned
+ .align 4
+stxncpy_aligned:
+ .frame sp, 0, t9, 0
+ .prologue 0
+
+ /* On entry to this basic block:
+ t0 == the first destination word for masking back in
+ t1 == the first source word. */
+
+ /* Create the 1st output word and detect 0's in the 1st input word. */
+ lda t2, -1 # E : build a mask against false zero
+ mskqh t2, a1, t2 # U : detection in the src word (stall)
+ mskqh t1, a1, t3 # U :
+ ornot t1, t2, t2 # E : (stall)
+
+ mskql t0, a1, t0 # U : assemble the first output word
+ cmpbge zero, t2, t8 # E : bits set iff null found
+ or t0, t3, t0 # E : (stall)
+ beq a2, $a_eoc # U :
+
+ bne t8, $a_eos # U :
+ nop
+ nop
+ nop
+
+ /* On entry to this basic block:
+ t0 == a source word not containing a null. */
+
+ /*
+ * nops here to:
+ * separate store quads from load quads
+ * limit of 1 bcond/quad to permit training
+ */
+$a_loop:
+ stq_u t0, 0(a0) # L :
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+ nop
+
+ ldq_u t0, 0(a1) # L :
+ addq a1, 8, a1 # E :
+ cmpbge zero, t0, t8 # E :
+ beq a2, $a_eoc # U :
+
+ beq t8, $a_loop # U :
+ nop
+ nop
+ nop
+
+ /* Take care of the final (partial) word store. At this point
+ the end-of-count bit is set in t8 iff it applies.
+
+ On entry to this basic block we have:
+ t0 == the source word containing the null
+ t8 == the cmpbge mask that found it. */
+
+$a_eos:
+ negq t8, t12 # E : find low bit set
+ and t8, t12, t12 # E : (stall)
+ /* For the sake of the cache, don't read a destination word
+ if we're not going to need it. */
+ and t12, 0x80, t6 # E : (stall)
+ bne t6, 1f # U : (stall)
+
+ /* We're doing a partial word store and so need to combine
+ our source and original destination words. */
+ ldq_u t1, 0(a0) # L :
+ subq t12, 1, t6 # E :
+ or t12, t6, t8 # E : (stall)
+ zapnot t0, t8, t0 # U : clear src bytes > null (stall)
+
+ zap t1, t8, t1 # .. e1 : clear dst bytes <= null
+ or t0, t1, t0 # e1 : (stall)
+ nop
+ nop
+
+1: stq_u t0, 0(a0) # L :
+ ret (t9) # L0 : Latency=3
+ nop
+ nop
+
+ /* Add the end-of-count bit to the eos detection bitmask. */
+$a_eoc:
+ or t10, t8, t8 # E :
+ br $a_eos # L0 : Latency=3
+ nop
+ nop
+
+ .end stxncpy_aligned
+
+ .align 4
+ .ent __stxncpy
+ .globl __stxncpy
+__stxncpy:
+ .frame sp, 0, t9, 0
+ .prologue 0
+
+ /* Are source and destination co-aligned? */
+ xor a0, a1, t1 # E :
+ and a0, 7, t0 # E : find dest misalignment
+ and t1, 7, t1 # E : (stall)
+ addq a2, t0, a2 # E : bias count by dest misalignment (stall)
+
+ subq a2, 1, a2 # E :
+ and a2, 7, t2 # E : (stall)
+ srl a2, 3, a2 # U : a2 = loop counter = (count - 1)/8 (stall)
+ addq zero, 1, t10 # E :
+
+ sll t10, t2, t10 # U : t10 = bitmask of last count byte
+ bne t1, $unaligned # U :
+ /* We are co-aligned; take care of a partial first word. */
+ ldq_u t1, 0(a1) # L : load first src word
+ addq a1, 8, a1 # E :
+
+ beq t0, stxncpy_aligned # U : avoid loading dest word if not needed
+ ldq_u t0, 0(a0) # L :
+ nop
+ nop
+
+ br stxncpy_aligned # .. e1 :
+ nop
+ nop
+ nop
+
+
+
+/* The source and destination are not co-aligned. Align the destination
+ and cope. We have to be very careful about not reading too much and
+ causing a SEGV. */
+
+ .align 4
+$u_head:
+ /* We know just enough now to be able to assemble the first
+ full source word. We can still find a zero at the end of it
+ that prevents us from outputting the whole thing.
+
+ On entry to this basic block:
+ t0 == the first dest word, unmasked
+ t1 == the shifted low bits of the first source word
+ t6 == bytemask that is -1 in dest word bytes */
+
+ ldq_u t2, 8(a1) # L : Latency=3 load second src word
+ addq a1, 8, a1 # E :
+ mskql t0, a0, t0 # U : mask trailing garbage in dst
+ extqh t2, a1, t4 # U : (3 cycle stall on t2)
+
+ or t1, t4, t1 # E : first aligned src word complete (stall)
+ mskqh t1, a0, t1 # U : mask leading garbage in src (stall)
+ or t0, t1, t0 # E : first output word complete (stall)
+ or t0, t6, t6 # E : mask original data for zero test (stall)
+
+ cmpbge zero, t6, t8 # E :
+ beq a2, $u_eocfin # U :
+ nop
+ nop
+
+ bne t8, $u_final # U :
+ lda t6, -1 # E : mask out the bits we have
+ mskql t6, a1, t6 # U : already seen (stall)
+ stq_u t0, 0(a0) # L : store first output word
+
+ or t6, t2, t2 # E :
+ cmpbge zero, t2, t8 # E : find nulls in second partial (stall)
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+
+ bne t8, $u_late_head_exit # U :
+ /* Finally, we've got all the stupid leading edge cases taken care
+ of and we can set up to enter the main loop. */
+ extql t2, a1, t1 # U : position hi-bits of lo word
+ ldq_u t2, 8(a1) # L : read next high-order source word
+ addq a1, 8, a1 # E :
+
+ cmpbge zero, t2, t8 # E : (stall)
+ beq a2, $u_eoc # U :
+ nop
+ nop
+
+ bne t8, $u_eos # e1 :
+ nop
+ nop
+ nop
+
+ /* Unaligned copy main loop. In order to avoid reading too much,
+ the loop is structured to detect zeros in aligned source words.
+ This has, unfortunately, effectively pulled half of a loop
+ iteration out into the head and half into the tail, but it does
+ prevent nastiness from accumulating in the very thing we want
+ to run as fast as possible.
+
+ On entry to this basic block:
+ t1 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word
+
+ We further know that t2 does not contain a null terminator. */
+
+ .align 4
+$u_loop:
+ extqh t2, a1, t0 # U : extract high bits for current word
+ addq a1, 8, a1 # E :
+ extql t2, a1, t3 # U : extract low bits for next time
+ addq a0, 8, a0 # E :
+
+ or t0, t1, t0 # E : current dst word now complete
+ ldq_u t2, 0(a1) # U : Latency=3 load high word for next time
+ stq_u t0, -8(a0) # U : save the current word (stall)
+ mov t3, t1 # E :
+
+ subq a2, 1, a2 # E :
+ cmpbge zero, t2, t8 # E : test new word for eos (2 cycle stall for data)
+ beq a2, $u_eoc # U : (stall)
+ nop
+
+ beq t8, $u_loop # U :
+ nop
+ nop
+ nop
+
+ /* We've found a zero somewhere in the source word we just read.
+ If it resides in the lower half, we have one (probably partial)
+ word to write out, and if it resides in the upper half, we
+ have one full and one partial word left to write out.
+
+ On entry to this basic block:
+ t1 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word. */
+$u_eos:
+ extqh t2, a1, t0 # U :
+ or t0, t1, t0 # E : first (partial) source word complete (stall)
+ cmpbge zero, t0, t8 # E : is the null in this first bit? (stall)
+ bne t8, $u_final # U : (stall)
+
+ stq_u t0, 0(a0) # L : the null was in the high-order bits
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+ nop
+
+$u_late_head_exit:
+ extql t2, a1, t0 # U :
+ cmpbge zero, t0, t8 # E :
+ or t8, t10, t6 # E : (stall)
+ cmoveq a2, t6, t8 # E : Latency=2, extra map slot (stall)
+
+ /* Take care of a final (probably partial) result word.
+ On entry to this basic block:
+ t0 == assembled source word
+ t8 == cmpbge mask that found the null. */
+$u_final:
+ negq t8, t6 # E : isolate low bit set
+ and t6, t8, t12 # E : (stall)
+ and t12, 0x80, t6 # E : avoid dest word load if we can (stall)
+ bne t6, 1f # U : (stall)
+
+ ldq_u t1, 0(a0) # L :
+ subq t12, 1, t6 # E :
+ or t6, t12, t8 # E : (stall)
+ zapnot t0, t8, t0 # U : kill source bytes > null
+
+ zap t1, t8, t1 # U : kill dest bytes <= null
+ or t0, t1, t0 # E : (stall)
+ nop
+ nop
+
+1: stq_u t0, 0(a0) # L :
+ ret (t9) # L0 : Latency=3
+
+$u_eoc: # end-of-count
+ extqh t2, a1, t0 # U :
+ or t0, t1, t0 # E : (stall)
+ cmpbge zero, t0, t8 # E : (stall)
+ nop
+
+$u_eocfin: # end-of-count, final word
+ or t10, t8, t8 # E :
+ br $u_final # L0 : Latency=3
+ nop
+ nop
+
+ /* Unaligned copy entry point. */
+ .align 4
+$unaligned:
+
+ ldq_u t1, 0(a1) # L : load first source word
+ and a0, 7, t4 # E : find dest misalignment
+ and a1, 7, t5 # E : find src misalignment
+ /* Conditionally load the first destination word and a bytemask
+ with 0xff indicating that the destination byte is sacrosanct. */
+ mov zero, t0 # E :
+
+ mov zero, t6 # E :
+ beq t4, 1f # U :
+ ldq_u t0, 0(a0) # L :
+ lda t6, -1 # E :
+
+ mskql t6, a0, t6 # U :
+ nop
+ nop
+ nop
+1:
+ subq a1, t4, a1 # E : sub dest misalignment from src addr
+
+ /* If source misalignment is larger than dest misalignment, we need
+ extra startup checks to avoid SEGV. */
+
+ cmplt t4, t5, t12 # E :
+ extql t1, a1, t1 # U : shift src into place
+ lda t2, -1 # E : for creating masks later
+ beq t12, $u_head # U : (stall)
+
+ mskqh t2, t5, t2 # U : begin src byte validity mask
+ cmpbge zero, t1, t8 # E : is there a zero?
+ extql t2, a1, t2 # U :
+ or t8, t10, t5 # E : test for end-of-count too
+
+ cmpbge zero, t2, t3 # E :
+ cmoveq a2, t5, t8 # E : Latency=2, extra map slot
+ nop # E : keep with cmoveq
+ andnot t8, t3, t8 # E : (stall)
+
+ beq t8, $u_head # U :
+ /* At this point we've found a zero in the first partial word of
+ the source. We need to isolate the valid source data and mask
+ it into the original destination data. (Incidentally, we know
+ that we'll need at least one byte of that original dest word.) */
+ ldq_u t0, 0(a0) # L :
+ negq t8, t6 # E : build bitmask of bytes <= zero
+ mskqh t1, t4, t1 # U :
+
+ and t6, t8, t12 # E :
+ subq t12, 1, t6 # E : (stall)
+ or t6, t12, t8 # E : (stall)
+ zapnot t2, t8, t2 # U : prepare source word; mirror changes (stall)
+
+ zapnot t1, t8, t1 # U : to source validity mask
+ andnot t0, t2, t0 # E : zero place for source to reside
+ or t0, t1, t0 # E : and put it there (stall both t0, t1)
+ stq_u t0, 0(a0) # L : (stall)
+
+ ret (t9) # L0 : Latency=3
+ nop
+ nop
+ nop
+
+ .end __stxncpy
+
diff --git a/arch/alpha/lib/ev67-strcat.S b/arch/alpha/lib/ev67-strcat.S
new file mode 100644
index 000000000..c426fe3ed
--- /dev/null
+++ b/arch/alpha/lib/ev67-strcat.S
@@ -0,0 +1,54 @@
+/*
+ * arch/alpha/lib/ev67-strcat.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Append a null-terminated string from SRC to DST.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Commentary: It seems bogus to walk the input string twice - once
+ * to determine the length, and then again while doing the copy.
+ * A significant (future) enhancement would be to only read the input
+ * string once.
+ */
+
+
+ .text
+
+ .align 4
+ .globl strcat
+ .ent strcat
+strcat:
+ .frame $30, 0, $26
+ .prologue 0
+
+ mov $16, $0 # E : set up return value
+ /* Find the end of the string. */
+ ldq_u $1, 0($16) # L : load first quadword (a0 may be misaligned)
+ lda $2, -1 # E :
+ insqh $2, $16, $2 # U :
+
+ andnot $16, 7, $16 # E :
+ or $2, $1, $1 # E :
+ cmpbge $31, $1, $2 # E : bits set iff byte == 0
+ bne $2, $found # U :
+
+$loop: ldq $1, 8($16) # L :
+ addq $16, 8, $16 # E :
+ cmpbge $31, $1, $2 # E :
+ beq $2, $loop # U :
+
+$found: cttz $2, $3 # U0 :
+ addq $16, $3, $16 # E :
+ /* Now do the append. */
+ mov $26, $23 # E :
+ br __stxcpy # L0 :
+
+ .end strcat
diff --git a/arch/alpha/lib/ev67-strchr.S b/arch/alpha/lib/ev67-strchr.S
new file mode 100644
index 000000000..03c56d583
--- /dev/null
+++ b/arch/alpha/lib/ev67-strchr.S
@@ -0,0 +1,88 @@
+/*
+ * arch/alpha/lib/ev67-strchr.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Return the address of a given character within a null-terminated
+ * string, or null if it is not found.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+ .set noreorder
+ .set noat
+
+ .align 4
+ .globl strchr
+ .ent strchr
+strchr:
+ .frame sp, 0, ra
+ .prologue 0
+
+ ldq_u t0, 0(a0) # L : load first quadword Latency=3
+ and a1, 0xff, t3 # E : 00000000000000ch
+ insbl a1, 1, t5 # U : 000000000000ch00
+ insbl a1, 7, a2 # U : ch00000000000000
+
+ insbl t3, 6, a3 # U : 00ch000000000000
+ or t5, t3, a1 # E : 000000000000chch
+ andnot a0, 7, v0 # E : align our loop pointer
+ lda t4, -1 # E : build garbage mask
+
+ mskqh t4, a0, t4 # U : only want relevant part of first quad
+ or a2, a3, a2 # E : chch000000000000
+ inswl a1, 2, t5 # E : 00000000chch0000
+ inswl a1, 4, a3 # E : 0000chch00000000
+
+ or a1, a2, a1 # E : chch00000000chch
+ or a3, t5, t5 # E : 0000chchchch0000
+ cmpbge zero, t0, t2 # E : bits set iff byte == zero
+ cmpbge zero, t4, t4 # E : bits set iff byte is garbage
+
+ /* This quad is _very_ serialized. Lots of stalling happens */
+ or t5, a1, a1 # E : chchchchchchchch
+ xor t0, a1, t1 # E : make bytes == c zero
+ cmpbge zero, t1, t3 # E : bits set iff byte == c
+ or t2, t3, t0 # E : bits set iff char match or zero match
+
+ andnot t0, t4, t0 # E : clear garbage bits
+ cttz t0, a2 # U0 : speculative (in case we get a match)
+ nop # E :
+ bne t0, $found # U :
+
+ /*
+ * Yuk. This loop is going to stall like crazy waiting for the
+ * data to be loaded. Not much can be done about it unless it's
+ * unrolled multiple times - is that safe to do in kernel space?
+ * Or would exception handling recovery code do the trick here?
+ */
+$loop: ldq t0, 8(v0) # L : Latency=3
+ addq v0, 8, v0 # E :
+ xor t0, a1, t1 # E :
+ cmpbge zero, t0, t2 # E : bits set iff byte == 0
+
+ cmpbge zero, t1, t3 # E : bits set iff byte == c
+ or t2, t3, t0 # E :
+ cttz t3, a2 # U0 : speculative (in case we get a match)
+ beq t0, $loop # U :
+
+$found: negq t0, t1 # E : clear all but least set bit
+ and t0, t1, t0 # E :
+ and t0, t3, t1 # E : bit set iff byte was the char
+ addq v0, a2, v0 # E : Add in the bit number from above
+
+ cmoveq t1, $31, v0 # E : Two mapping slots, latency = 2
+ nop
+ nop
+ ret # L0 :
+
+ .end strchr
diff --git a/arch/alpha/lib/ev67-strlen.S b/arch/alpha/lib/ev67-strlen.S
new file mode 100644
index 000000000..503928072
--- /dev/null
+++ b/arch/alpha/lib/ev67-strlen.S
@@ -0,0 +1,49 @@
+/*
+ * arch/alpha/lib/ev67-strlen.S
+ * 21264 version by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Finds length of a 0-terminated string. Optimized for the
+ * Alpha architecture:
+ *
+ * - memory accessed as aligned quadwords only
+ * - uses bcmpge to compare 8 bytes in parallel
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ */
+
+ .set noreorder
+ .set noat
+
+ .globl strlen
+ .ent strlen
+ .align 4
+strlen:
+ ldq_u $1, 0($16) # L : load first quadword ($16 may be misaligned)
+ lda $2, -1($31) # E :
+ insqh $2, $16, $2 # U :
+ andnot $16, 7, $0 # E :
+
+ or $2, $1, $1 # E :
+ cmpbge $31, $1, $2 # E : $2 <- bitmask: bit i == 1 <==> i-th byte == 0
+ nop # E :
+ bne $2, $found # U :
+
+$loop: ldq $1, 8($0) # L :
+ addq $0, 8, $0 # E : addr += 8
+ cmpbge $31, $1, $2 # E :
+ beq $2, $loop # U :
+
+$found:
+ cttz $2, $3 # U0 :
+ addq $0, $3, $0 # E :
+ subq $0, $16, $0 # E :
+ ret $31, ($26) # L0 :
+
+ .end strlen
diff --git a/arch/alpha/lib/ev67-strlen_user.S b/arch/alpha/lib/ev67-strlen_user.S
new file mode 100644
index 000000000..67f1e9426
--- /dev/null
+++ b/arch/alpha/lib/ev67-strlen_user.S
@@ -0,0 +1,109 @@
+/*
+ * arch/alpha/lib/ev67-strlen_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
+ *
+ * Return the length of the string including the NULL terminator
+ * (strlen+1) or zero if an error occurred.
+ *
+ * In places where it is critical to limit the processing time,
+ * and the data is not trusted, strnlen_user() should be used.
+ * It will return a value greater than its second argument if
+ * that limit would be exceeded. This implementation is allowed
+ * to access memory beyond the limit, but will not cross a page
+ * boundary when doing so.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EX(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda v0, $exception-99b(zero); \
+ .previous
+
+
+ .set noreorder
+ .set noat
+ .text
+
+ .globl __strlen_user
+ .ent __strlen_user
+ .frame sp, 0, ra
+
+ .align 4
+__strlen_user:
+ ldah a1, 32767(zero) # do not use plain strlen_user() for strings
+ # that might be almost 2 GB long; you should
+ # be using strnlen_user() instead
+ nop
+ nop
+ nop
+
+ .globl __strnlen_user
+
+ .align 4
+__strnlen_user:
+ ldgp $29,0($27) # E E : we do exceptions -- we need the gp.
+ /* Decomposes into lda/ldah */
+ .prologue 1
+ EX( ldq_u t0, 0(a0) ) # L : load first quadword (a0 may be misaligned)
+ lda t1, -1(zero) # E :
+
+ insqh t1, a0, t1 # U :
+ andnot a0, 7, v0 # E :
+ or t1, t0, t0 # E :
+ subq a0, 1, a0 # E : get our +1 for the return
+
+ cmpbge zero, t0, t1 # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0
+ subq a1, 7, t2 # E :
+ subq a0, v0, t0 # E :
+ bne t1, $found # U :
+
+ addq t2, t0, t2 # E :
+ addq a1, 1, a1 # E :
+ nop # E :
+ nop # E :
+
+ .align 4
+$loop: ble t2, $limit # U :
+ EX( ldq t0, 8(v0) ) # L :
+ nop # E :
+ nop # E :
+
+ cmpbge zero, t0, t1 # E :
+ subq t2, 8, t2 # E :
+ addq v0, 8, v0 # E : addr += 8
+ beq t1, $loop # U :
+
+$found: cttz t1, t2 # U0 :
+ addq v0, t2, v0 # E :
+ subq v0, a0, v0 # E :
+ ret # L0 :
+
+$exception:
+ nop
+ nop
+ nop
+ ret
+
+ .align 4 # currently redundant
+$limit:
+ nop
+ nop
+ subq a1, t2, v0
+ ret
+
+ .end __strlen_user
diff --git a/arch/alpha/lib/ev67-strncat.S b/arch/alpha/lib/ev67-strncat.S
new file mode 100644
index 000000000..4ae716cd2
--- /dev/null
+++ b/arch/alpha/lib/ev67-strncat.S
@@ -0,0 +1,94 @@
+/*
+ * arch/alpha/lib/ev67-strncat.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
+ *
+ * Append no more than COUNT characters from the null-terminated string SRC
+ * to the null-terminated string DST. Always null-terminate the new DST.
+ *
+ * This differs slightly from the semantics in libc in that we never write
+ * past count, whereas libc may write to count+1. This follows the generic
+ * implementation in lib/string.c and is, IMHO, more sensible.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+
+ .text
+
+ .align 4
+ .globl strncat
+ .ent strncat
+strncat:
+ .frame $30, 0, $26
+ .prologue 0
+
+ mov $16, $0 # set up return value
+ beq $18, $zerocount # U :
+ /* Find the end of the string. */
+ ldq_u $1, 0($16) # L : load first quadword ($16 may be misaligned)
+ lda $2, -1($31) # E :
+
+ insqh $2, $0, $2 # U :
+ andnot $16, 7, $16 # E :
+ nop # E :
+ or $2, $1, $1 # E :
+
+ nop # E :
+ nop # E :
+ cmpbge $31, $1, $2 # E : bits set iff byte == 0
+ bne $2, $found # U :
+
+$loop: ldq $1, 8($16) # L :
+ addq $16, 8, $16 # E :
+ cmpbge $31, $1, $2 # E :
+ beq $2, $loop # U :
+
+$found: cttz $2, $3 # U0 :
+ addq $16, $3, $16 # E :
+ nop # E :
+ bsr $23, __stxncpy # L0 :/* Now do the append. */
+
+ /* Worry about the null termination. */
+
+ zapnot $1, $27, $2 # U : was last byte a null?
+ cmplt $27, $24, $5 # E : did we fill the buffer completely?
+ bne $2, 0f # U :
+ ret # L0 :
+
+0: or $5, $18, $2 # E :
+ nop
+ bne $2, 2f # U :
+ and $24, 0x80, $3 # E : no zero next byte
+
+ nop # E :
+ bne $3, 1f # U :
+ /* Here there are bytes left in the current word. Clear one. */
+ addq $24, $24, $24 # E : end-of-count bit <<= 1
+ nop # E :
+
+2: zap $1, $24, $1 # U :
+ nop # E :
+ stq_u $1, 0($16) # L :
+ ret # L0 :
+
+1: /* Here we must clear the first byte of the next DST word */
+ stb $31, 8($16) # L :
+ nop # E :
+ nop # E :
+ ret # L0 :
+
+$zerocount:
+ nop # E :
+ nop # E :
+ nop # E :
+ ret # L0 :
+
+ .end strncat
diff --git a/arch/alpha/lib/memcpy.c b/arch/alpha/lib/memcpy.c
index d715f0219..64083fc73 100644
--- a/arch/alpha/lib/memcpy.c
+++ b/arch/alpha/lib/memcpy.c
@@ -161,24 +161,3 @@ void * memcpy(void * dest, const void *src, size_t n)
/* For backward modules compatibility, define __memcpy. */
asm("__memcpy = memcpy; .globl __memcpy");
-
-void *memmove (void *dest, const void *src, size_t n)
-{
- if (dest <= src) {
- if (!(((unsigned long) dest ^ (unsigned long) src) & 7))
- __memcpy_aligned_up ((unsigned long) dest,
- (unsigned long) src, n);
- else
- __memcpy_unaligned_up ((unsigned long) dest,
- (unsigned long) src, n);
- }
- else {
- if (!(((unsigned long) dest ^ (unsigned long) src) & 7))
- __memcpy_aligned_dn ((unsigned long) dest,
- (unsigned long) src, n);
- else
- __memcpy_unaligned_dn ((unsigned long) dest,
- (unsigned long) src, n);
- }
- return dest;
-}
diff --git a/arch/alpha/lib/memmove.S b/arch/alpha/lib/memmove.S
new file mode 100644
index 000000000..3c8567e4e
--- /dev/null
+++ b/arch/alpha/lib/memmove.S
@@ -0,0 +1,103 @@
+/*
+ * arch/alpha/lib/memmove.S
+ *
+ * Barely optimized memmove routine for Alpha EV5.
+ *
+ * This is hand-massaged output from the original memcpy.c. We defer to
+ * memcpy whenever possible; the backwards copy loops are not unrolled.
+ */
+
+ .set noat
+ .set noreorder
+ .text
+
+ .align 4
+ .globl memmove
+ .ent memmove
+memmove:
+ addq $16,$18,$4
+ addq $17,$18,$5
+ cmpule $4,$17,$1 /* dest + n <= src */
+ cmpule $5,$16,$2 /* dest >= src + n */
+
+ bis $1,$2,$1
+ mov $16,$0
+ xor $16,$17,$2
+ bne $1,memcpy
+
+ and $2,7,$2 /* Test for src/dest co-alignment. */
+ bne $2,$misaligned
+
+ and $4,7,$1
+ beq $1,$skip_aligned_byte_loop_head
+
+$aligned_byte_loop_head:
+ lda $4,-1($4)
+ lda $5,-1($5)
+ unop
+ ble $18,$egress
+
+ ldq_u $3,0($5)
+ ldq_u $2,0($4)
+ lda $18,-1($18)
+ extbl $3,$5,$1
+
+ insbl $1,$4,$1
+ mskbl $2,$4,$2
+ bis $1,$2,$1
+ and $4,7,$6
+
+ stq_u $1,0($4)
+ bne $6,$aligned_byte_loop_head
+
+$skip_aligned_byte_loop_head:
+ lda $18,-8($18)
+ blt $18,$skip_aligned_word_loop
+
+$aligned_word_loop:
+ ldq $1,-8($5)
+ nop
+ lda $5,-8($5)
+ lda $18,-8($18)
+
+ stq $1,-8($4)
+ nop
+ lda $4,-8($4)
+ bge $18,$aligned_word_loop
+
+$skip_aligned_word_loop:
+ lda $18,8($18)
+ bgt $18,$byte_loop_tail
+ unop
+ ret $31,($26),1
+
+ .align 4
+$misaligned:
+ nop
+ fnop
+ unop
+ beq $18,$egress
+
+$byte_loop_tail:
+ ldq_u $3,-1($5)
+ ldq_u $2,-1($4)
+ lda $5,-1($5)
+ lda $4,-1($4)
+
+ lda $18,-1($18)
+ extbl $3,$5,$1
+ insbl $1,$4,$1
+ mskbl $2,$4,$2
+
+ bis $1,$2,$1
+ stq_u $1,0($4)
+ nop
+ bgt $18,$byte_loop_tail
+
+$egress:
+ ret $31,($26),1
+ nop
+ nop
+ nop
+
+ .end memmove
diff --git a/arch/alpha/lib/strcpy.S b/arch/alpha/lib/strcpy.S
index dd21b5208..e0728e4ad 100644
--- a/arch/alpha/lib/strcpy.S
+++ b/arch/alpha/lib/strcpy.S
@@ -17,6 +17,7 @@ strcpy:
mov $16, $0 # set up return value
mov $26, $23 # set up return address
+ unop
br __stxcpy # do the copy
.end strcpy
diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S
index dbc011c34..7d64d21d5 100644
--- a/arch/alpha/lib/strncpy.S
+++ b/arch/alpha/lib/strncpy.S
@@ -27,6 +27,10 @@ strncpy:
beq $18, 0f
mov $26, $23 # set return address
br __stxncpy # do the work of the copy
+
0: ret
+ nop
+ nop
+ nop
.end strncpy
diff --git a/arch/alpha/lib/stxcpy.S b/arch/alpha/lib/stxcpy.S
index b7b9da482..5a427634d 100644
--- a/arch/alpha/lib/stxcpy.S
+++ b/arch/alpha/lib/stxcpy.S
@@ -1,4 +1,5 @@
-/* stxcpy.S
+/*
+ * arch/alpha/lib/stxcpy.S
* Contributed by Richard Henderson (rth@tamu.edu)
*
* Copy a null-terminated string from SRC to DST.
diff --git a/arch/alpha/lib/stxncpy.S b/arch/alpha/lib/stxncpy.S
index 5bab622e0..d7cddb074 100644
--- a/arch/alpha/lib/stxncpy.S
+++ b/arch/alpha/lib/stxncpy.S
@@ -1,4 +1,5 @@
-/* stxncpy.S
+/*
+ * arch/alpha/lib/stxncpy.S
* Contributed by Richard Henderson (rth@tamu.edu)
*
* Copy no more than COUNT bytes of the null-terminated string from
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 52e2b36f7..3b0ae7011 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -185,7 +185,7 @@ show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!atomic_read(&mem_map[i].count))
+ else if (!page_count(mem_map+i))
free++;
else
shared += atomic_read(&mem_map[i].count) - 1;
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 6fbdb5ea1..f74033b36 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -35,16 +35,21 @@ INITRD_PHYS = 0x00800000
INITRD_VIRT = 0xc0800000
endif
+ifeq ($(CONFIG_ARCH_SHARK),y)
+ZTEXTADDR = 0x08508000
+ZRELADDR = 0x08008000
+endif
+
ifeq ($(CONFIG_FOOTBRIDGE),y)
ZTEXTADDR = 0x00008000
-PARAMS = 0x00000100
+PARAMS_PHYS = 0x00000100
INITRD_PHYS = 0x00800000
INITRD_VIRT = 0xc0800000
endif
ifeq ($(CONFIG_ARCH_INTEGRATOR),y)
ZTEXTADDR = 0x00008000
-PARAMS = 0x00000100
+PARAMS_PHYS = 0x00000100
INITRD_PHYS = 0x00800000
INITRD_VIRT = 0xc0800000
endif
@@ -65,6 +70,14 @@ ZRELADDR = 0xf0008000
ZBSSADDR = 0xf03e0000
endif
+ifeq ($(CONFIG_ARCH_P720T),y)
+ZTEXTADDR = 0xc0018000
+ZRELADDR = 0xc0018000
+PARAMS_PHYS = 0xc0000100
+INITRD_PHYS = 0xc0400000
+INITRD_VIRT = 0xc0400000
+endif
+
ifeq ($(CONFIG_ARCH_SA1100),y)
ZTEXTADDR = 0xc0008000
ZRELADDR = 0xc0008000
@@ -72,8 +85,9 @@ ifeq ($(CONFIG_SA1100_VICTOR),y)
ZTEXTADDR = 0x00002000
ZBSSADDR = 0xc0100000
endif
-ifeq ($(CONFIG_SA1100_THINCLIENT),y)
- ZTEXTADDR = 0xC0200000
+ifeq ($(CONFIG_SA1100_SHERMAN),y)
+ ZTEXTADDR = 0x00050000
+ ZBSSADDR = 0xc0100000
endif
ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
ZTEXTADDR = 0xC0200000
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 46b754ec5..bf8f1c947 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -18,6 +18,7 @@ ZLDFLAGS = -p -X -T vmlinux.lds
#
ifeq ($(CONFIG_ARCH_ACORN),y)
OBJS += ll_char_wr.o font.o
+ZLDFLAGS += -defsym params=$(PARAMS_PHYS)
endif
ifeq ($(CONFIG_ARCH_NETWINDER),y)
@@ -36,6 +37,11 @@ ifeq ($(CONFIG_ARCH_L7200),y)
OBJS += head-l7200.o
endif
+ifeq ($(CONFIG_ARCH_P720T),y)
+# Borrow this code from SA1100
+OBJS += head-sa1100.o
+endif
+
ifeq ($(CONFIG_ARCH_SA1100),y)
OBJS += head-sa1100.o setup-sa1100.o
ifeq ($(CONFIG_SA1100_NANOENGINE),y)
diff --git a/arch/arm/def-configs/a5k b/arch/arm/def-configs/a5k
index 11a1dfd67..c8ede2f80 100644
--- a/arch/arm/def-configs/a5k
+++ b/arch/arm/def-configs/a5k
@@ -2,36 +2,72 @@
# Automatically generated make config: don't edit
#
CONFIG_ARM=y
+# CONFIG_SBUS is not set
+CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_OBSOLETE=y
#
-# System and processor type
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+CONFIG_ARCH_ARCA5K=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Archimedes/A5000 Implementations (select only ONE)
#
# CONFIG_ARCH_ARC is not set
CONFIG_ARCH_A5K=y
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_FOOTBRIDGE is not set
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
CONFIG_ARCH_ACORN=y
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
# CONFIG_CPU_32 is not set
CONFIG_CPU_26=y
# CONFIG_PAGESIZE_16 is not set
-# CONFIG_ISA_DMA is not set
#
-# Loadable module support
+# Processor Type
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=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
@@ -42,9 +78,15 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_ELF is not set
# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+
+#
+# Parallel port support
+#
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_PC_FIFO is not set
+CONFIG_PARPORT_PC_SUPERIO=y
# CONFIG_PARPORT_ARC is not set
# CONFIG_PARPORT_AMIGA is not set
# CONFIG_PARPORT_MFC3 is not set
@@ -54,14 +96,9 @@ CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_1284 is not set
#
-# I2O device support
+# Memory Technology Devices (MTD)
#
-# 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
+# CONFIG_MTD is not set
#
# Plug and Play configuration
@@ -73,37 +110,16 @@ CONFIG_PARPORT_PC=m
# Block devices
#
CONFIG_BLK_DEV_FD=y
-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_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-CONFIG_BLK_DEV_IDE_ICSIDE=y
-# CONFIG_BLK_DEV_IDEDMA_ICS is not set
-# CONFIG_BLK_DEV_IDE_RAPIDE is not set
-# CONFIG_IDE_CHIPSETS 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_MD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=m
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
#
# Acorn-specific block devices
@@ -113,100 +129,6 @@ CONFIG_BLK_DEV_MFM=m
CONFIG_BLK_DEV_MFM_AUTODETECT=y
#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_ATOMWIDE_SERIAL is not set
-# CONFIG_DUALSP_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV 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_DRM is not set
-# CONFIG_DRM_TDFX is not set
-
-#
-# PCMCIA character device support
-#
-# CONFIG_PCMCIA_SERIAL_CS is not set
-# CONFIG_AGP is not set
-
-#
-# Support for USB
-#
-# CONFIG_USB is not set
-
-#
-# Console drivers
-#
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_ACORN=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-
-#
# Networking options
#
# CONFIG_PACKET is not set
@@ -218,16 +140,10 @@ CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-# CONFIG_SKB_LARGE is not set
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
@@ -238,9 +154,9 @@ CONFIG_INET=y
# 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_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -253,16 +169,6 @@ CONFIG_INET=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -272,7 +178,9 @@ CONFIG_NETDEVICES=y
#
# 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_NET_SB1000 is not set
#
@@ -286,19 +194,18 @@ CONFIG_ARM_ETHER3=y
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_DM9102 is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
-# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC 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
@@ -312,7 +219,7 @@ CONFIG_ARM_ETHER3=y
# CONFIG_NET_RADIO is not set
#
-# Token Ring driver support
+# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
@@ -325,9 +232,62 @@ CONFIG_ARM_ETHER3=y
# CONFIG_WAN is not set
#
-# PCMCIA network device support
+# 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
+
+#
+# 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 is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
#
-# CONFIG_NET_PCMCIA 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_IDE_ICSIDE=y
+# CONFIG_BLK_DEV_IDEDMA_ICS is not set
+# CONFIG_IDEDMA_ICS_AUTO is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_IDE_RAPIDE 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
#
# SCSI support
@@ -335,16 +295,90 @@ CONFIG_ARM_ETHER3=y
# CONFIG_SCSI is not set
#
-# Sound
+# I2O device support
#
-# CONFIG_SOUND is not set
+# 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_ATOMWIDE_SERIAL is not set
+# CONFIG_DUALSP_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_PHILIPSPAR is not set
+# CONFIG_I2C_ELV is not set
+# CONFIG_I2C_VELLEMAN is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_CHARDEV=y
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+# CONFIG_PSMOUSE is not set
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# 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
#
-# Filesystems
+# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
CONFIG_ADFS_FS=y
+# 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
@@ -353,37 +387,60 @@ CONFIG_MSDOS_FS=m
# 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_CRAMFS is not set
+# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_MINIX_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 is not set
# 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_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 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_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
CONFIG_ACORN_PARTITION=y
CONFIG_ACORN_PARTITION_ADFS=y
CONFIG_ACORN_PARTITION_ICS=y
@@ -394,6 +451,7 @@ 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
@@ -410,6 +468,10 @@ CONFIG_NLS=y
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -422,6 +484,45 @@ CONFIG_NLS=y
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_ACORN=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
#
# Kernel hacking
diff --git a/arch/arm/def-configs/assabet b/arch/arm/def-configs/assabet
index 7a4cd1778..8cf335a9f 100644
--- a/arch/arm/def-configs/assabet
+++ b/arch/arm/def-configs/assabet
@@ -12,57 +12,75 @@ 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_ARC is not set
-# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_RPC is not set
CONFIG_ARCH_SA1100=y
#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
# SA11x0 Implementations
#
CONFIG_SA1100_ASSABET=y
# CONFIG_ASSABET_NEPONSET is not set
# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_THINCLIENT is not set
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_PANGOLIN is not set
CONFIG_ANGELBOOT=y
-# CONFIG_SA1100_FREQUENCY_SCALE is not set
+CONFIG_SA1100_FREQUENCY_SCALE=y
# CONFIG_SA1100_VOLTAGE_SCALE is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA1100=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_DISCONTIGMEM=y
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
#
-# Loadable module support
+# Processor Type
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA1100=y
+CONFIG_DISCONTIGMEM=y
#
# General setup
#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
CONFIG_HOTPLUG=y
#
-# PC Card support
+# PCMCIA/CardBus support
#
CONFIG_PCMCIA=y
# CONFIG_PCMCIA_DEBUG is not set
@@ -135,16 +153,10 @@ CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
@@ -181,13 +193,13 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# 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_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
@@ -320,13 +332,14 @@ CONFIG_BLK_DEV_IDECS=y
#
CONFIG_VT=y
# CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_TOUCHSCREEN_SA1100 is not set
-# CONFIG_TOUCHSCREEN_BITSY is not set
# CONFIG_SERIAL is not set
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=9600
+CONFIG_TOUCHSCREEN_UCB1200=y
+# CONFIG_TOUCHSCREEN_BITSY is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=32
@@ -345,6 +358,10 @@ CONFIG_UNIX98_PTY_COUNT=32
# Joysticks
#
# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
@@ -354,11 +371,6 @@ CONFIG_UNIX98_PTY_COUNT=32
# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -367,10 +379,9 @@ CONFIG_UNIX98_PTY_COUNT=32
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_PCMCIA_SERIAL is not set
-# CONFIG_AGP is not set
#
# File systems
@@ -451,12 +462,14 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION 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
@@ -473,6 +486,10 @@ CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -485,6 +502,7 @@ CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
#
# Console drivers
@@ -497,7 +515,9 @@ CONFIG_FB=y
#
CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
CONFIG_FB_SA1100=y
+# CONFIG_FB_MQ200 is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB2=y
@@ -517,8 +537,10 @@ CONFIG_FONT_8x8=y
#
CONFIG_SOUND=y
CONFIG_SOUND_UDA1341=y
+# CONFIG_SOUND_SA1100_SSP is not set
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_ESSSOLO1 is not set
diff --git a/arch/arm/def-configs/brutus b/arch/arm/def-configs/brutus
index 34391812a..bdd14f552 100644
--- a/arch/arm/def-configs/brutus
+++ b/arch/arm/def-configs/brutus
@@ -12,10 +12,17 @@ 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_ARC is not set
-# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
@@ -27,33 +34,30 @@ CONFIG_ARCH_SA1100=y
#
# CONFIG_SA1100_ASSABET is not set
CONFIG_SA1100_BRUTUS=y
+# CONFIG_SA1100_CERF is not set
# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
# CONFIG_SA1100_THINCLIENT is not set
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
CONFIG_ANGELBOOT=y
# CONFIG_SA1100_FREQUENCY_SCALE is not set
# CONFIG_SA1100_VOLTAGE_SCALE is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA1100=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_32v4=y
+CONFIG_CPU_SA1100=y
CONFIG_DISCONTIGMEM=y
# CONFIG_PCI is not set
# CONFIG_ISA is not set
# CONFIG_ISA_DMA is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_PC_KEYMAP=y
#
# General setup
@@ -147,7 +151,7 @@ CONFIG_VT=y
# CONFIG_VT_CONSOLE is not set
CONFIG_SERIAL_SA1100=y
CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_TOUCHSCREEN_SA1100 is not set
+# CONFIG_TOUCHSCREEN_UCB1200 is not set
# CONFIG_TOUCHSCREEN_BITSY is not set
# CONFIG_SERIAL is not set
# CONFIG_SERIAL_EXTENDED is not set
@@ -192,9 +196,8 @@ CONFIG_UNIX98_PTY_COUNT=32
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
+# CONFIG_DRM is not set
#
# File systems
@@ -256,6 +259,7 @@ CONFIG_FB=y
#
CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
CONFIG_FB_SA1100=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
diff --git a/arch/arm/def-configs/cerf b/arch/arm/def-configs/cerf
index accb50b3f..e2bf1e06a 100644
--- a/arch/arm/def-configs/cerf
+++ b/arch/arm/def-configs/cerf
@@ -21,8 +21,8 @@ CONFIG_MODULES=y
#
# System Type
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
@@ -35,34 +35,39 @@ CONFIG_ARCH_SA1100=y
# CONFIG_SA1100_ASSABET is not set
# CONFIG_SA1100_BRUTUS is not set
CONFIG_SA1100_CERF=y
+CONFIG_SA1100_CERF_32MB=y
# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
# CONFIG_SA1100_THINCLIENT is not set
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
# CONFIG_ANGELBOOT is not set
# CONFIG_SA1100_FREQUENCY_SCALE is not set
# CONFIG_SA1100_VOLTAGE_SCALE is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA1100=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_32v4=y
+CONFIG_CPU_SA1100=y
CONFIG_DISCONTIGMEM=y
# CONFIG_PCI is not set
# CONFIG_ISA is not set
# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
#
# General setup
#
+# CONFIG_SA1100_CERF_CMDLINE is not set
CONFIG_HOTPLUG=y
#
-# PC Card support
+# PCMCIA/CardBus support
#
CONFIG_PCMCIA=y
# CONFIG_PCMCIA_DEBUG is not set
@@ -70,7 +75,7 @@ CONFIG_SA1100_PCMCIA=y
CONFIG_VIRTUAL_BUS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
CONFIG_NWFPE=y
CONFIG_KCORE_ELF=y
@@ -80,7 +85,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="keepinitrd"
+CONFIG_CMDLINE="console=ttyS0,38400"
CONFIG_LEDS=y
CONFIG_LEDS_TIMER=y
CONFIG_LEDS_CPU=y
@@ -126,7 +131,9 @@ CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
@@ -282,10 +289,11 @@ CONFIG_BLK_DEV_IDECS=y
#
# Character devices
#
-# CONFIG_VT is not set
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
CONFIG_SERIAL_SA1100=y
CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_TOUCHSCREEN_UCB1200 is not set
+CONFIG_TOUCHSCREEN_UCB1200=y
# CONFIG_TOUCHSCREEN_BITSY is not set
# CONFIG_SERIAL is not set
# CONFIG_SERIAL_EXTENDED is not set
@@ -329,9 +337,9 @@ CONFIG_UNIX98_PTY_COUNT=32
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_PCMCIA_SERIAL is not set
-# CONFIG_AGP is not set
#
# File systems
@@ -345,6 +353,7 @@ CONFIG_UNIX98_PTY_COUNT=32
# CONFIG_BFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -367,6 +376,7 @@ CONFIG_EXT2_FS=y
# CONFIG_CODA_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_SUNRPC=y
CONFIG_LOCKD=y
@@ -376,36 +386,37 @@ CONFIG_LOCKD=y
#
# 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_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# 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_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 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_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND is not set
#
# USB support
diff --git a/arch/arm/def-configs/ebsa110 b/arch/arm/def-configs/ebsa110
index c2c7e0dcc..8f7981934 100644
--- a/arch/arm/def-configs/ebsa110
+++ b/arch/arm/def-configs/ebsa110
@@ -1,53 +1,79 @@
#
-# Automatically generated by make menuconfig: don't edit
+# 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
#
# 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_ARC is not set
-# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
CONFIG_ARCH_EBSA110=y
# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA110=y
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
# CONFIG_ARCH_ACORN is not set
# CONFIG_FOOTBRIDGE is not set
# CONFIG_FOOTBRIDGE_HOST is not set
# CONFIG_FOOTBRIDGE_ADDIN is not set
-# CONFIG_DISCONTIGMEM is not set
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
#
-# Loadable module support
+# Processor Type
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA110=y
+# CONFIG_DISCONTIGMEM is not set
#
# General setup
#
+# CONFIG_ANGELBOOT is not set
+# 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_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_NWFPE is not set
CONFIG_KCORE_ELF=y
@@ -55,6 +81,7 @@ CONFIG_KCORE_ELF=y
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="root=/dev/nfs rw mem=16M console=ttyS1,38400n8"
CONFIG_LEDS=y
@@ -66,7 +93,7 @@ CONFIG_LEDS_TIMER=y
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
CONFIG_PARPORT_PC_FIFO=y
-CONFIG_PARPORT_PC_SUPERIO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
# CONFIG_PARPORT_ARC is not set
# CONFIG_PARPORT_AMIGA is not set
# CONFIG_PARPORT_MFC3 is not set
@@ -76,6 +103,11 @@ CONFIG_PARPORT_PC_SUPERIO=y
CONFIG_PARPORT_1284=y
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Plug and Play configuration
#
# CONFIG_PNP is not set
@@ -88,15 +120,12 @@ CONFIG_PARPORT_1284=y
# 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_LVM is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
#
@@ -126,14 +155,12 @@ CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
CONFIG_SYN_COOKIES=y
-# CONFIG_SKB_LARGE is not set
#
# IP: Netfilter Configuration
@@ -164,9 +191,25 @@ CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_COMPAT_IPCHAINS=m
CONFIG_IP_NF_NAT_NEEDED=y
# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_EUI64=y
+# CONFIG_IPV6_NO_PB is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
# 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
@@ -174,6 +217,7 @@ CONFIG_IP_NF_NAT_NEEDED=y
# 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
@@ -196,6 +240,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
# CONFIG_NET_SB1000 is not set
@@ -217,8 +262,9 @@ CONFIG_ARM_AM79C961A=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC 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
@@ -287,6 +333,11 @@ CONFIG_PPP_BSDCOMP=m
# CONFIG_ISDN is not set
#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -299,7 +350,8 @@ CONFIG_SERIAL_EXTENDED=y
# CONFIG_SERIAL_MULTIPORT is not set
# CONFIG_HUB6 is not set
# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
@@ -319,6 +371,10 @@ CONFIG_PRINTER=m
# Joysticks
#
# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
@@ -326,19 +382,17 @@ CONFIG_PRINTER=m
#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SOFT_WATCHDOG=y
# CONFIG_WDT is not set
# CONFIG_WDTPCI is not set
-CONFIG_SOFT_WATCHDOG=y
# CONFIG_PCWATCHDOG is not set
# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_60XX_WDT is not set
# CONFIG_MIXCOMWD is not set
+# CONFIG_I810_TCO is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -347,9 +401,13 @@ CONFIG_SOFT_WATCHDOG=y
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
#
# File systems
@@ -367,6 +425,7 @@ CONFIG_AUTOFS4_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_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -400,7 +459,6 @@ CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
@@ -427,6 +485,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_MAC_PARTITION is not set
# CONFIG_MSDOS_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
@@ -438,7 +497,7 @@ CONFIG_PARTITION_ADVANCED=y
#
# Kernel hacking
#
-# CONFIG_FRAME_POINTER is not set
+CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_INFO is not set
diff --git a/arch/arm/def-configs/footbridge b/arch/arm/def-configs/footbridge
index af2ccd01a..255c99945 100644
--- a/arch/arm/def-configs/footbridge
+++ b/arch/arm/def-configs/footbridge
@@ -2,54 +2,82 @@
# 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
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
#
-# System and Processor Type
+# Loadable module support
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-# CONFIG_ARCH_RPC is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-CONFIG_FOOTBRIDGE=y
-CONFIG_HOST_FOOTBRIDGE=y
-# CONFIG_ADDIN_FOOTBRIDGE is not set
+CONFIG_ARCH_FOOTBRIDGE=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
#
# Footbridge Implementations
#
-CONFIG_ARCH_EBSA285=y
# CONFIG_ARCH_CATS is not set
-CONFIG_ARCH_NETWINDER=y
# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+CONFIG_ARCH_EBSA285_HOST=y
+CONFIG_ARCH_NETWINDER=y
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
# CONFIG_ARCH_ACORN is not set
+CONFIG_FOOTBRIDGE=y
+CONFIG_FOOTBRIDGE_HOST=y
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_ARCH_EBSA285=y
CONFIG_CPU_32=y
# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA110=y
-CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
-CONFIG_ISA=y
-CONFIG_ISA_DMA=y
-# CONFIG_SBUS is not set
-# CONFIG_PCMCIA is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Loadable module support
+# Processor Type
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA110=y
+# CONFIG_DISCONTIGMEM is not set
#
# General setup
#
+# CONFIG_ANGELBOOT is not set
+CONFIG_PCI=y
+CONFIG_ISA=y
+CONFIG_ISA_DMA=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
@@ -60,7 +88,12 @@ CONFIG_KCORE_ELF=y
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_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
#
# Parallel port support
@@ -76,25 +109,11 @@ CONFIG_PARPORT_PC_FIFO=y
# CONFIG_PARPORT_SUNBPP is not set
# CONFIG_PARPORT_OTHER is not set
CONFIG_PARPORT_1284=y
-CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-# CONFIG_LEDS_CPU is not set
#
-# IEEE 1394 (FireWire) support
+# Memory Technology Devices (MTD)
#
-# 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
+# CONFIG_MTD is not set
#
# Plug and Play configuration
@@ -137,185 +156,13 @@ CONFIG_PARIDE_KTTI=m
CONFIG_PARIDE_ON20=m
CONFIG_PARIDE_ON26=m
# 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=m
-# CONFIG_BLK_DEV_LVM is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
CONFIG_BLK_DEV_RAM=y
-# CONFIG_BLK_DEV_INITRD is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
-CONFIG_SERIAL_NONSTANDARD=y
-# CONFIG_COMPUTONE is not set
-# CONFIG_ROCKETPORT is not set
-# CONFIG_CYCLADES is not set
-CONFIG_SERIAL_21285=y
-CONFIG_SERIAL_21285_CONSOLE=y
-# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
-# CONFIG_ESPSERIAL is not set
-# CONFIG_MOXA_INTELLIO is not set
-# CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
-# CONFIG_N_HDLC is not set
-# CONFIG_RISCOM8 is not set
-# CONFIG_SPECIALIX is not set
-# CONFIG_SX is not set
-# CONFIG_STALDRV is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_CHARDEV 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_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-CONFIG_SOFT_WATCHDOG=y
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_MIXCOMWD is not set
-CONFIG_21285_WATCHDOG=m
-CONFIG_977_WATCHDOG=m
-CONFIG_DS1620=y
-CONFIG_NWBUTTON=y
-CONFIG_NWBUTTON_REBOOT=y
-CONFIG_NWFLASH=m
-CONFIG_NVRAM=m
-CONFIG_RTC=y
-
-#
-# Video For Linux
-#
-CONFIG_VIDEO_DEV=y
-# CONFIG_I2C_PARPORT is not set
-
-#
-# Radio Adapters
-#
-# CONFIG_RADIO_CADET is not set
-# CONFIG_RADIO_RTRACK is not set
-# CONFIG_RADIO_RTRACK2 is not set
-# CONFIG_RADIO_AZTECH is not set
-# CONFIG_RADIO_GEMTEK is not set
-# CONFIG_RADIO_MIROPCM20 is not set
-# CONFIG_RADIO_SF16FMI is not set
-# CONFIG_RADIO_TERRATEC is not set
-# CONFIG_RADIO_TRUST is not set
-# CONFIG_RADIO_TYPHOON is not set
-# CONFIG_RADIO_ZOLTRIX is not set
-
-#
-# Video Adapters
-#
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_BWQCAM is not set
-# CONFIG_VIDEO_CQCAM is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_ZORAN is not set
-# CONFIG_VIDEO_BUZ is not set
-# CONFIG_VIDEO_ZR36120 is not set
-CONFIG_VIDEO_CYBERPRO=m
-# 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_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
-CONFIG_FB_CYBER2000=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-CONFIG_FBCON_VGA=y
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
#
# Networking options
@@ -327,24 +174,21 @@ CONFIG_PACKET_MMAP=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-CONFIG_IP_ALIAS=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_INET_ECN is not set
CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
-# CONFIG_SKB_LARGE is not set
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
+CONFIG_ATM=y
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
#
#
@@ -352,10 +196,11 @@ CONFIG_SYN_COOKIES=y
# 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_BRIDGE 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
@@ -367,55 +212,6 @@ CONFIG_SYN_COOKIES=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-CONFIG_IRDA_OPTIONS=y
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-# CONFIG_IRDA_COMPRESSION is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-# CONFIG_IRTTY_SIR is not set
-# CONFIG_IRPORT_SIR is not set
-
-#
-# FIR device drivers
-#
-# CONFIG_NSC_FIR is not set
-CONFIG_WINBOND_FIR=m
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -427,13 +223,13 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# 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_NET_VENDOR_3COM=y
# CONFIG_EL1 is not set
# CONFIG_EL2 is not set
@@ -441,12 +237,15 @@ CONFIG_NET_VENDOR_3COM=y
# CONFIG_EL16 is not set
# CONFIG_EL3 is not set
# CONFIG_3C515 is not set
+# CONFIG_ELMC is not set
+# CONFIG_ELMC_II is not set
CONFIG_VORTEX=y
# 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=y
# CONFIG_PCNET32 is not set
@@ -454,28 +253,34 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
-# CONFIG_DE4X5 is not set
CONFIG_TULIP=m
+# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
# CONFIG_DM9102 is not set
# CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PM is not set
# CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
+# CONFIG_NATSEMI is not set
CONFIG_NE2K_PCI=y
-# CONFIG_RTL8129 is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
# CONFIG_8139TOO is not set
+# CONFIG_RTL8129 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_ES3210 is not set
-# CONFIG_EPIC100 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
-# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC 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
@@ -511,6 +316,55 @@ CONFIG_SLIP_MODE_SLIP6=y
# CONFIG_WAN is not set
#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+CONFIG_IRDA_OPTIONS=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+# CONFIG_IRPORT_SIR is not set
+
+#
+# FIR device drivers
+#
+# CONFIG_NSC_FIR is not set
+CONFIG_WINBOND_FIR=m
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
# ATA/IDE/MFM/RLL support
#
CONFIG_IDE=y
@@ -527,6 +381,15 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
# CONFIG_BLK_DEV_IDECS is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
@@ -546,7 +409,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
CONFIG_BLK_DEV_OFFBOARD=y
CONFIG_IDEDMA_PCI_AUTO=y
CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
# CONFIG_BLK_DEV_AEC62XX is not set
@@ -556,26 +418,25 @@ CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_BLK_DEV_AMD7409 is not set
# CONFIG_AMD7409_OVERRIDE is not set
# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_CMD64X_RAID is not set
CONFIG_BLK_DEV_CY82C693=y
# 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_HPT366_FIP is not set
-# CONFIG_HPT366_MODE3 is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_PDC202XX=y
# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_MASTER is not set
+# CONFIG_BLK_DEV_OSB4 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_VIA82CXXX_TUNING is not set
CONFIG_BLK_DEV_SL82C105=y
# 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
#
@@ -584,52 +445,164 @@ CONFIG_BLK_DEV_IDE_MODES=y
# CONFIG_SCSI is not set
#
-# Sound
+# IEEE 1394 (FireWire) support
#
-CONFIG_SOUND=m
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 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_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_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-CONFIG_SOUND_ADLIB=m
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_SOFTOSS is not set
-CONFIG_SOUND_SB=m
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-# CONFIG_SOUND_VIDC is not set
-CONFIG_SOUND_WAVEARTIST=m
+# 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+CONFIG_SERIAL_21285=y
+CONFIG_SERIAL_21285_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_CHARDEV 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_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_I810_TCO is not set
+CONFIG_21285_WATCHDOG=m
+CONFIG_977_WATCHDOG=m
+CONFIG_DS1620=y
+CONFIG_NWBUTTON=y
+CONFIG_NWBUTTON_REBOOT=y
+CONFIG_NWFLASH=m
+# CONFIG_INTEL_RNG is not set
+CONFIG_NVRAM=m
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+CONFIG_VIDEO_PROC_FS=y
+# CONFIG_I2C_PARPORT is not set
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_BUZ is not set
+# CONFIG_VIDEO_ZR36120 is not set
+CONFIG_VIDEO_CYBERPRO=m
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
#
# File systems
@@ -647,6 +620,7 @@ CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=m
@@ -713,12 +687,14 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
@@ -735,6 +711,10 @@ CONFIG_NLS_CODEPAGE_852=m
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
# CONFIG_NLS_ISO8859_3 is not set
@@ -747,6 +727,110 @@ CONFIG_NLS_ISO8859_2=m
# CONFIG_NLS_ISO8859_14 is not set
CONFIG_NLS_ISO8859_15=m
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYB=y
+CONFIG_PC_KEYMAP=y
+CONFIG_VGA_CONSOLE=y
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_CLGEN is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_ACORN is not set
+# CONFIG_FB_CLPS711X is not set
+CONFIG_FB_CYBER2000=y
+# CONFIG_FB_SA1100 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+# CONFIG_FBCON_CFB32 is not set
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA_PLANES is not set
+CONFIG_FBCON_VGA=y
+# CONFIG_FBCON_HGA is not set
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_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_SOUND_OSS=m
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+CONFIG_SOUND_ADLIB=m
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
+# CONFIG_SOUND_PSS is not set
+CONFIG_SOUND_SB=m
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_WAVEARTIST=m
+# CONFIG_SOUND_TVMIXER is not set
#
# USB support
@@ -757,7 +841,8 @@ CONFIG_USB_DEBUG=y
#
# Miscellaneous USB options
#
-# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
#
# USB Controllers
@@ -770,7 +855,8 @@ CONFIG_USB_OHCI=m
# USB Devices
#
CONFIG_USB_PRINTER=m
-CONFIG_USB_SCANNER=m
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
CONFIG_USB_AUDIO=m
# CONFIG_USB_ACM is not set
# CONFIG_USB_SERIAL is not set
@@ -785,19 +871,16 @@ CONFIG_USB_AUDIO=m
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_DSBR is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_NET1080 is not set
+
+#
+# USB Human Interface Devices (HID)
+#
#
-# USB HID
+# Input core support is needed for USB HID
#
-# CONFIG_USB_HID is not set
-CONFIG_USB_KBD=m
-CONFIG_USB_MOUSE=m
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE 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
#
# Kernel hacking
diff --git a/arch/arm/def-configs/graphicsclient b/arch/arm/def-configs/graphicsclient
index 11415b363..92079d370 100644
--- a/arch/arm/def-configs/graphicsclient
+++ b/arch/arm/def-configs/graphicsclient
@@ -2,48 +2,88 @@
# Automatically generated make config: don't edit
#
CONFIG_ARM=y
+# CONFIG_SBUS is not set
+CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
#
-# System and processor type
+# Loadable module support
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-# CONFIG_ARCH_RPC is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_FOOTBRIDGE is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
CONFIG_ARCH_SA1100=y
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_EMPEG is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_PLEB is not set
CONFIG_SA1100_GRAPHICSCLIENT=y
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_TIFON is not set
-CONFIG_DISCONTIGMEM=y
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_ANGELBOOT is not set
+# CONFIG_SA1100_FREQUENCY_SCALE is not set
+# CONFIG_SA1100_VOLTAGE_SCALE 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_32v4=y
CONFIG_CPU_SA1100=y
-# CONFIG_ISA_DMA is not set
-CONFIG_ALIGNMENT_TRAP=y
+CONFIG_DISCONTIGMEM=y
#
-# Loadable module support
+# General setup
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
+CONFIG_HOTPLUG=y
#
-# General setup
+# PCMCIA/CardBus support
#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_SA1100_PCMCIA=y
+CONFIG_VIRTUAL_BUS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
@@ -51,22 +91,24 @@ CONFIG_SYSCTL=y
CONFIG_NWFPE=y
CONFIG_KCORE_ELF=y
# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+# 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="root=nfs"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
# CONFIG_PARPORT is not set
-CONFIG_CMDLINE="ip=off"
#
-# I2O device support
+# Memory Technology Devices (MTD)
#
-# 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
+# CONFIG_MTD is not set
#
# Plug and Play configuration
@@ -78,118 +120,28 @@ CONFIG_CMDLINE="ip=off"
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_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_LVM is not set
# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV 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_DRM is not set
-# CONFIG_DRM_TDFX is not set
-
-#
-# PCMCIA character device support
-#
-# CONFIG_AGP is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Console drivers
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_SA1100=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX 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_FONTWIDTH8_ONLY=y
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_BLK_DEV_FLASH is not set
#
# Networking options
#
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
# CONFIG_NETLINK is not set
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
@@ -200,16 +152,10 @@ CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
@@ -220,9 +166,9 @@ CONFIG_SKB_LARGE=y
# 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_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -235,16 +181,6 @@ CONFIG_SKB_LARGE=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -254,7 +190,9 @@ CONFIG_NETDEVICES=y
#
# 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_NET_SB1000 is not set
#
@@ -270,12 +208,10 @@ CONFIG_NET_VENDOR_SMC=y
# CONFIG_ULTRA32 is not set
CONFIG_SMC9194=y
# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_DM9102 is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
# CONFIG_NET_POCKET is not set
#
@@ -295,7 +231,7 @@ CONFIG_SMC9194=y
# CONFIG_NET_RADIO is not set
#
-# Token Ring driver support
+# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
@@ -310,7 +246,70 @@ CONFIG_SMC9194=y
#
# PCMCIA network device support
#
-# CONFIG_NET_PCMCIA is not set
+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 is not set
+# CONFIG_PCMCIA_XIRC2PS 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 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=m
+# 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
#
# SCSI support
@@ -318,54 +317,221 @@ CONFIG_SMC9194=y
# CONFIG_SCSI is not set
#
-# Filesystems
+# 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
+
+#
+# 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
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=38400
+# CONFIG_TOUCHSCREEN_UCB1200 is not set
+# CONFIG_TOUCHSCREEN_BITSY is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=32
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# 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
+# CONFIG_PCMCIA_SERIAL is not set
+
+#
+# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS 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_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
+CONFIG_RAMFS=y
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_MINIX_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_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 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_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_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_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 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_8 is not set
+# CONFIG_NLS_ISO8859_9 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_UTF8 is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
+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=y
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# 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
+
+#
+# USB support
+#
+# CONFIG_USB is not set
#
# Kernel hacking
@@ -373,6 +539,6 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/integrator b/arch/arm/def-configs/integrator
new file mode 100644
index 000000000..07133bff5
--- /dev/null
+++ b/arch/arm/def-configs/integrator
@@ -0,0 +1,511 @@
+#
+# 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
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_INTEGRATOR=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
+# 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_32v4=y
+CONFIG_CPU_ARM720=y
+CONFIG_CPU_ARM920=y
+CONFIG_CPU_ARM920_CPU_IDLE=y
+CONFIG_CPU_ARM920_I_CACHE_ON=y
+CONFIG_CPU_ARM920_D_CACHE_ON=y
+# CONFIG_CPU_ARM920_WRITETHROUGH is not set
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_ANGELBOOT is not set
+CONFIG_PCI_INTEGRATOR=y
+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_NWFPE=y
+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="root=1f04 mem=32M"
+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_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_MTDRAM is not set
+
+#
+# MTD drivers for mapped chips
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_JEDEC is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_PHYSMAP is not set
+
+#
+# Drivers for chip mappings
+#
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_VMAX is not set
+
+#
+# User modules and translation layers for MTD devices
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+CONFIG_MTD_ARM=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 is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD 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=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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_NET_SB1000 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=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+CONFIG_EEPRO100=y
+CONFIG_EEPRO100_PM=y
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139TOO is not set
+# CONFIG_RTL8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_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_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
+
+#
+# IEEE 1394 (FireWire) support
+#
+# 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_AMBA=y
+CONFIG_SERIAL_INTEGRATOR=y
+CONFIG_SERIAL_AMBA_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# 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_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_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_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_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=y
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 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_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS 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_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_NLS is not set
+
+#
+# Console drivers
+#
+CONFIG_KMI_KEYB=y
+CONFIG_PC_KEYMAP=y
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/def-configs/neponset b/arch/arm/def-configs/neponset
new file mode 100644
index 000000000..b77cbd143
--- /dev/null
+++ b/arch/arm/def-configs/neponset
@@ -0,0 +1,576 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_SBUS is not set
+CONFIG_UID16=y
+
+#
+# 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_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
+CONFIG_ARCH_SA1100=y
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+CONFIG_SA1100_ASSABET=y
+CONFIG_ASSABET_NEPONSET=y
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_BITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_XP860 is not set
+CONFIG_ANGELBOOT=y
+CONFIG_SA1111=y
+CONFIG_SA1100_FREQUENCY_SCALE=y
+# CONFIG_SA1100_VOLTAGE_SCALE 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_32v4=y
+CONFIG_CPU_SA1100=y
+CONFIG_DISCONTIGMEM=y
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_SA1100_PCMCIA=y
+CONFIG_VIRTUAL_BUS=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_NWFPE=y
+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="keepinitrd"
+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 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_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_FLASH 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_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_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_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A 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_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_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# 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=y
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS 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
+#
+# 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
+
+#
+# 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=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
+
+#
+# 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
+
+#
+# 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
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=9600
+CONFIG_TOUCHSCREEN_UCB1200=y
+# CONFIG_TOUCHSCREEN_BITSY is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=32
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# 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
+# CONFIG_PCMCIA_SERIAL is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS 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_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_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_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_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 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_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS 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_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION 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_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 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_8 is not set
+# CONFIG_NLS_ISO8859_9 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_UTF8 is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_MQ200 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=y
+CONFIG_SOUND_UDA1341=y
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION 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_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_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/thinclient b/arch/arm/def-configs/pangolin
index 5ad898616..6aebc40f8 100644
--- a/arch/arm/def-configs/thinclient
+++ b/arch/arm/def-configs/pangolin
@@ -1,57 +1,86 @@
#
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
#
CONFIG_ARM=y
+# CONFIG_SBUS is not set
CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
#
-# System and processor type
+# Loadable module support
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-# CONFIG_ARCH_RPC is not set
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_FOOTBRIDGE is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
CONFIG_ARCH_SA1100=y
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
# CONFIG_SA1100_ASSABET is not set
# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_EMPEG is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_CERF is not set
# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_PLEB is not set
-CONFIG_SA1100_THINCLIENT=y
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_TIFON is not set
-CONFIG_DISCONTIGMEM=y
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_XP860 is not set
+CONFIG_SA1100_PANGOLIN=y
+# CONFIG_ANGELBOOT is not set
+# CONFIG_SA1100_FREQUENCY_SCALE is not set
+# CONFIG_SA1100_VOLTAGE_SCALE 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_32v4=y
CONFIG_CPU_SA1100=y
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCMCIA is not set
-CONFIG_ALIGNMENT_TRAP=y
+CONFIG_DISCONTIGMEM=y
#
-# Loadable module support
+# General setup
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
+CONFIG_HOTPLUG=y
#
-# General setup
+# PCMCIA/CardBus support
#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_SA1100_PCMCIA=y
+CONFIG_VIRTUAL_BUS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
@@ -59,26 +88,48 @@ CONFIG_SYSCTL=y
CONFIG_NWFPE=y
CONFIG_KCORE_ELF=y
# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+# 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="keepinitrd"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
#
# Parallel port support
#
# CONFIG_PARPORT is not set
-CONFIG_CMDLINE="root=nfs"
-# CONFIG_LEDS 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
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_JEDEC is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_VMAX is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
#
# Plug and Play configuration
@@ -94,95 +145,20 @@ CONFIG_CMDLINE="root=nfs"
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_STRIPED is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
CONFIG_BLK_DEV_FLASH=y
#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV 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_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-
-#
-# Console drivers
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
-
-#
-# 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_FONTWIDTH8_ONLY=y
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-
-#
# Networking options
#
CONFIG_PACKET=y
@@ -194,32 +170,20 @@ 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_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
+# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
# 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_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -232,16 +196,6 @@ CONFIG_SKB_LARGE=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -250,9 +204,10 @@ CONFIG_NETDEVICES=y
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_NET_SB1000 is not set
#
@@ -262,11 +217,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_ARM_AM79C961A 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_ULTRA is not set
-# CONFIG_ULTRA32 is not set
-CONFIG_SMC9194=y
+# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -304,11 +255,65 @@ CONFIG_SMC9194=y
# 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 is not set
+# CONFIG_PCMCIA_XIRC2PS 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
+#
+# 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_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=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
+# 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
#
# SCSI support
@@ -316,6 +321,72 @@ CONFIG_SMC9194=y
# 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
+
+#
+# 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
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=115200
+# CONFIG_TOUCHSCREEN_UCB1200 is not set
+# CONFIG_TOUCHSCREEN_BITSY is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=32
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK 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
+# CONFIG_PCMCIA_SERIAL is not set
+
+#
# File systems
#
# CONFIG_QUOTA is not set
@@ -331,8 +402,10 @@ CONFIG_SMC9194=y
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_RAMFS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=1
+CONFIG_CRAMFS=y
+CONFIG_RAMFS=y
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
@@ -361,7 +434,7 @@ CONFIG_EXT2_FS=y
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
-CONFIG_ROOT_NFS=y
+# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
@@ -387,6 +460,22 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_FB is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
# USB support
#
# CONFIG_USB is not set
@@ -397,6 +486,6 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/rpc b/arch/arm/def-configs/rpc
index afbfda2da..6d744d34d 100644
--- a/arch/arm/def-configs/rpc
+++ b/arch/arm/def-configs/rpc
@@ -2,45 +2,77 @@
# 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
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
#
-# System and Processor Type
+# Loadable module support
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-CONFIG_ARCH_RPC=y
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_FOOTBRIDGE is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_RPC=y
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
CONFIG_ARCH_ACORN=y
+# 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=y
CONFIG_CPU_ARM6=y
CONFIG_CPU_ARM7=y
CONFIG_CPU_SA110=y
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_ALIGNMENT_TRAP is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_DISCONTIGMEM is not set
#
# General setup
#
+# CONFIG_ANGELBOOT is not set
+# 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
@@ -51,7 +83,9 @@ CONFIG_KCORE_ELF=y
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_ALIGNMENT_TRAP is not set
#
# Parallel port support
@@ -69,13 +103,9 @@ CONFIG_PARPORT_PC_SUPERIO=y
# CONFIG_PARPORT_1284 is not set
#
-# I2O device support
+# Memory Technology Devices (MTD)
#
-# 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
+# CONFIG_MTD is not set
#
# Plug and Play configuration
@@ -90,15 +120,12 @@ CONFIG_BLK_DEV_FD=y
# 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_LVM is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
#
@@ -106,114 +133,6 @@ CONFIG_BLK_DEV_INITRD=y
#
#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ATOMWIDE_SERIAL=y
-CONFIG_DUALSP_SERIAL=y
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_CHARDEV=y
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_LOGIBUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_MOUSE=y
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV 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_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-CONFIG_RPCMOUSE=y
-
-#
-# Console drivers
-#
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_ACORN=y
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_VGA is not set
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-
-#
# Networking options
#
# CONFIG_PACKET is not set
@@ -222,19 +141,14 @@ CONFIG_FONT_ACORN_8x8=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
@@ -245,10 +159,11 @@ CONFIG_SKB_LARGE=y
# 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_BRIDGE 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
@@ -260,16 +175,6 @@ CONFIG_SKB_LARGE=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -281,14 +186,15 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# 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_ETHER1=m
-CONFIG_ARM_ETHER3=m
+CONFIG_ARM_ETHER1=y
+CONFIG_ARM_ETHER3=y
CONFIG_ARM_ETHERH=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
@@ -303,8 +209,9 @@ CONFIG_ARM_ETHERH=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC 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
@@ -337,6 +244,16 @@ CONFIG_PPPOE=m
# 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
@@ -353,6 +270,15 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
@@ -372,6 +298,8 @@ CONFIG_BLK_DEV_IDEDMA=y
CONFIG_BLK_DEV_IDE_RAPIDE=y
# 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 is not set
#
@@ -427,14 +355,14 @@ CONFIG_SCSI_IMM=m
# CONFIG_SCSI_IZIP_EPP16 is not set
# CONFIG_SCSI_IZIP_SLOW_CTR is not set
# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_DEBUG is not set
@@ -444,7 +372,7 @@ CONFIG_SCSI_ACORNSCSI_SYNC=y
CONFIG_SCSI_ARXESCSI=m
CONFIG_SCSI_CUMANA_2=m
CONFIG_SCSI_EESOXSCSI=m
-CONFIG_SCSI_POWERTECSCSI=m
+CONFIG_SCSI_POWERTECSCSI=y
#
# The following drivers are not fully supported
@@ -453,52 +381,101 @@ CONFIG_SCSI_CUMANA_1=m
CONFIG_SCSI_OAK1=m
#
-# Sound
+# I2O device support
#
-CONFIG_SOUND=m
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 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_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_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
-# CONFIG_SOUND_PSS is not set
-CONFIG_SOUND_SOFTOSS=m
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-CONFIG_SOUND_VIDC=m
-# CONFIG_SOUND_WAVEARTIST is not set
+# 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_ATOMWIDE_SERIAL=y
+CONFIG_DUALSP_SERIAL=y
+CONFIG_SERIAL_EXTENDED=y
+# CONFIG_SERIAL_MANY_PORTS is not set
+CONFIG_SERIAL_SHARE_IRQ=y
+# CONFIG_SERIAL_DETECT_IRQ is not set
+# CONFIG_SERIAL_MULTIPORT is not set
+# CONFIG_HUB6 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_PHILIPSPAR is not set
+# CONFIG_I2C_ELV is not set
+# CONFIG_I2C_VELLEMAN is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_CHARDEV=y
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
+# CONFIG_PSMOUSE is not set
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# 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
+CONFIG_RPCMOUSE=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
#
# File systems
@@ -516,6 +493,7 @@ CONFIG_ADFS_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_CRAMFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
@@ -582,12 +560,14 @@ CONFIG_BSD_DISKLABEL=y
CONFIG_SOLARIS_X86_PARTITION=y
# CONFIG_UNIXWARE_DISKLABEL is not set
CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
CONFIG_SUN_PARTITION=y
CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_737=m
CONFIG_NLS_CODEPAGE_775=m
@@ -604,6 +584,10 @@ CONFIG_NLS_CODEPAGE_865=m
CONFIG_NLS_CODEPAGE_866=m
CONFIG_NLS_CODEPAGE_869=m
CONFIG_NLS_CODEPAGE_874=m
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
CONFIG_NLS_ISO8859_3=m
@@ -616,6 +600,99 @@ CONFIG_NLS_ISO8859_9=m
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
CONFIG_NLS_KOI8_R=m
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_ACORN=y
+# CONFIG_FB_CLPS711X is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_SA1100 is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FBCON_ADVANCED=y
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA_PLANES is not set
+# CONFIG_FBCON_VGA is not set
+# CONFIG_FBCON_HGA is not set
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_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_SOUND_OSS=m
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_VIDC=m
+# CONFIG_SOUND_TVMIXER is not set
#
# USB support
@@ -627,7 +704,7 @@ CONFIG_NLS_KOI8_R=m
#
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_INFO is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_LL=y
diff --git a/arch/arm/def-configs/sherman b/arch/arm/def-configs/sherman
new file mode 100644
index 000000000..453fbf20f
--- /dev/null
+++ b/arch/arm/def-configs/sherman
@@ -0,0 +1,210 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+
+#
+# System and processor type
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_FOOTBRIDGE is not set
+CONFIG_ARCH_SA1100=y
+CONFIG_CPU_SA1100=y
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_EMPEG is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_VICTOR is not set
+CONFIG_SA1100_SHERMAN=y
+# CONFIG_VICTOR_BOARD1 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM2 is not set
+# CONFIG_CPU_ARM3 is not set
+# CONFIG_CPU_ARM6 is not set
+# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_SA110=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ALIGNMENT_TRAP is not set
+# CONFIG_TEXT_SECTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# General setup
+#
+# CONFIG_NET is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_NWFPE=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+# CONFIG_PARPORT is not set
+CONFIG_CMDLINE=""
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_IDE is not set
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE_PARPORT is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_FLASH=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+# 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_874 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_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index e79dd71e6..868fbd4a7 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -451,7 +451,6 @@ void __init pcibios_init(void)
*/
pci_assign_unassigned_resources();
pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq);
- pci_set_bus_ranges();
}
char * __init pcibios_setup(char *str)
@@ -463,8 +462,29 @@ char * __init pcibios_setup(char *str)
return str;
}
+/*
+ * From arch/i386/kernel/pci-i386.c:
+ *
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
{
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long start = res->start;
+
+ if (start & 0x300)
+ res->start = (start + 0x3ff) & ~0x3ff;
+ }
}
/**
diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c
index 8c427b379..bf265fab3 100644
--- a/arch/arm/kernel/dec21285.c
+++ b/arch/arm/kernel/dec21285.c
@@ -258,17 +258,21 @@ static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs)
void __init dc21285_init(struct arm_pci_sysdata *sysdata)
{
unsigned long cntl;
- unsigned int mem_size;
+ unsigned int mem_size, mem_mask;
unsigned int pci_cmd = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
int cfn_mode;
+ mem_size = (unsigned int)high_memory - PAGE_OFFSET;
+ for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
+ if (mem_mask >= mem_size)
+ break;
+
/*
* These registers need to be set up whether we're the
* central function or not.
*/
- mem_size = (unsigned int)high_memory - PAGE_OFFSET;
- *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000;
+ *CSR_SDRAMBASEMASK = (mem_mask - 1) & 0x0ffc0000;
*CSR_SDRAMBASEOFFSET = 0;
*CSR_ROMBASEMASK = 0x80000000;
*CSR_CSRBASEMASK = 0;
diff --git a/arch/arm/kernel/dma-arc.c b/arch/arm/kernel/dma-arc.c
index 2ad2edf3b..121a2792b 100644
--- a/arch/arm/kernel/dma-arc.c
+++ b/arch/arm/kernel/dma-arc.c
@@ -156,7 +156,7 @@ static void a5k_floppy_enable_dma(dmach_t channel, dma_t *dma)
memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
regs.ARM_r9 = dma->buf.length;
regs.ARM_r10 = dma->buf.address;
- regs.ARM_fp = (int)PCIO_FLOPPYDMABASE;
+ regs.ARM_fp = FLOPPYDMA_BASE;
set_fiq_regs(&regs);
enable_irq(dma->dma_irq);
}
@@ -191,7 +191,7 @@ static struct dma_ops sound_dma_ops = {
void __init arch_dma_init(dma_t *dma)
{
#if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE)
- if (machine_is_arc()) {
+ if (machine_is_archimedes()) {
dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
dma[DMA_VIRTUAL_FLOPPY0].d_ops = &arc_floppy_data_dma_ops;
dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index c8c737404..e659b966d 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -84,7 +84,7 @@
strb r12, [r12, #0x38] @ Disable FIQ register
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #ioc_base_high @ point at IOC
.if ioc_base_low
orr r4, r4, #ioc_base_low
@@ -165,36 +165,23 @@ irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
- mov r4, #0xf3000000
- ldrb \irqstat, [r4] @ get interrupts
- adr \base, irq_prio_ebsa110
-
- teq \irqstat, #0
- ldrneb \irqnr, [\base, \irqstat] @ get IRQ number
+ .macro get_irqnr_and_base, irqnr, stat, base, tmp
+ mov \base, #IRQ_STAT
+ ldrb \stat, [\base] @ get interrupts
+ mov \irqnr, #0
+ tst \stat, #15
+ addeq \irqnr, \irqnr, #4
+ moveq \stat, \stat, lsr #4
+ tst \stat, #3
+ addeq \irqnr, \irqnr, #2
+ moveq \stat, \stat, lsr #2
+ tst \stat, #1
+ addeq \irqnr, \irqnr, #1
+ moveq \stat, \stat, lsr #1
+ tst \stat, #1 @ bit 0 should be set
.endm
.macro irq_prio_table
-irq_prio_ebsa110:
- .byte 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2
- .byte 4, 4, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2
- .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2
- .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2
-
- .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
- .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
- .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
- .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
-
- .byte 7, 0, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2
- .byte 4, 4, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2
- .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2
- .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2
-
- .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
- .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
- .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
- .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2
.endm
#elif defined(CONFIG_ARCH_SHARK)
@@ -202,7 +189,7 @@ irq_prio_ebsa110:
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #0xe0000000
orr r4, r4, #0x20
@@ -238,7 +225,7 @@ irq_prio_ebsa110:
.equ dc21285_high, ARMCSR_BASE & 0xff000000
.equ dc21285_low, ARMCSR_BASE & 0x00ffffff
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #dc21285_high
.if dc21285_low
orr r4, r4, #dc21285_low
@@ -334,7 +321,7 @@ irq_prio_ebsa110:
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \irqstat, =INTCONT_BASE
ldr \base, =soft_irq_mask
ldr \irqstat, [\irqstat] @ get interrupts
@@ -362,7 +349,7 @@ ENTRY(soft_irq_mask)
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \irqstat, =0xffff7000
ldr \irqstat, [\irqstat] @ get interrupts
ldr \base, =soft_irq_mask
@@ -390,7 +377,7 @@ ENTRY(soft_irq_mask)
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #0xfa000000 @ ICIP = 0xfa050000
add r4, r4, #0x00050000
ldr \irqstat, [r4] @ get irqs
@@ -428,7 +415,7 @@ ENTRY(soft_irq_mask)
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov \irqstat, #irq_base_addr @ Virt addr IRQ regs
add \irqstat, \irqstat, #0x00001000 @ Status reg
ldr \irqstat, [\irqstat, #0] @ get interrupts
@@ -449,7 +436,7 @@ ENTRY(soft_irq_mask)
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
/* FIXME: should not be using soo many LDRs here */
ldr \irqnr, =IO_ADDRESS(INTEGRATOR_IC_BASE)
ldr \irqstat, [\irqnr, #IRQ_STATUS] @ get masked status
@@ -470,6 +457,50 @@ ENTRY(soft_irq_mask)
.macro irq_prio_table
.endm
+#elif defined(CONFIG_ARCH_P720T)
+
+ .macro disable_fiq
+ .endm
+
+#if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
+#error INTSR stride != INTMR stride
+#endif
+
+ .macro get_irqnr_and_base, irqnr, stat, base, mask
+ mov \base, #CLPS7111_BASE
+ ldr \stat, [\base, #INTSR1]
+ ldr \mask, [\base, #INTMR1]
+ mov \irqnr, #4
+ mov \mask, \mask, lsl #16
+ and \stat, \stat, \mask, lsr #16
+ movs \stat, \stat, lsr #4
+ bne 1001f
+
+ add \base, \base, #INTSR2 - INTSR1
+ ldr \stat, [\base, #INTSR1]
+ ldr \mask, [\base, #INTMR1]
+ mov \irqnr, #16
+ mov \mask, \mask, lsl #16
+ and \stat, \stat, \mask, lsr #16
+
+1001: tst \stat, #255
+ addeq \irqnr, \irqnr, #8
+ moveq \stat, \stat, lsr #8
+ tst \stat, #15
+ addeq \irqnr, \irqnr, #4
+ moveq \stat, \stat, lsr #4
+ tst \stat, #3
+ addeq \irqnr, \irqnr, #2
+ moveq \stat, \stat, lsr #2
+ tst \stat, #1
+ addeq \irqnr, \irqnr, #1
+ moveq \stat, \stat, lsr #1
+ tst \stat, #1 @ bit 0 should be set
+ .endm
+
+ .macro irq_prio_table
+ .endm
+
#else
#error Unknown architecture
#endif
@@ -594,7 +625,7 @@ fpe_not_present:
adr r10, wfs_mask_data
ldmia r10, {r4, r5, r6, r7, r8}
ldr r10, [sp, #S_PC] @ Load PC
- sub r10, r10, #-4
+ sub r10, r10, #4
mask_pc r10, r10
ldrt r10, [r10] @ get instruction
and r5, r10, r5
@@ -660,7 +691,7 @@ __irq_svc: sub sp, sp, #S_FRAME_SIZE
add r4, sp, #S_SP
mov r6, lr
stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
-1: get_irqnr_and_base r0, r6, r5
+1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@@ -695,6 +726,28 @@ __und_svc: sub sp, sp, #S_FRAME_SIZE
ldmia sp, {r0 - pc}^ @ Restore SVC registers
.align 5
+__pabt_svc: sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - r12} @ save r0 - r12
+ ldr r2, .LCabt
+ add r0, sp, #S_FRAME_SIZE
+ ldmia r2, {r2 - r4} @ get pc, cpsr
+ add r5, sp, #S_SP
+ 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
+ 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
+ msr cpsr_c, r0
+ ldr r0, [sp, #S_PSR]
+ msr spsr, r0
+ ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+
+ .align 5
.LCirq: .word __temp_irq
.LCund: .word __temp_und
.LCabt: .word __temp_abt
@@ -744,7 +797,7 @@ __irq_usr: sub sp, sp, #S_FRAME_SIZE
stmdb r8, {sp, lr}^
alignment_trap r4, r7, __temp_irq
zero_fp
-1: get_irqnr_and_base r0, r6, r5
+1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
adrsvc ne, lr, 1b
@
@@ -762,7 +815,7 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
add r8, sp, #S_PC
ldmia r4, {r5 - r7}
stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
- stmdb r8, {sp, lr}^ @ Save user r0 - r12
+ stmdb r8, {sp, lr}^ @ Save user sp, lr
alignment_trap r4, r7, __temp_und
zero_fp
adrsvc al, r9, ret_from_sys_call @ r9 = normal FP return
@@ -960,12 +1013,25 @@ vector_prefetch:
msr spsr_c, r13 @ switch to SVC_32 mode
ands lr, lr, #15
- ldreq lr, .LCtab_pabt
- ldrne lr, .LCtab_pabt + 4
+ ldr lr, [pc, lr, lsl #2]
movs pc, lr
-.LCtab_pabt: .word __pabt_usr
- .word __pabt_invalid
+.LCtab_pabt: .word __pabt_usr @ 0 (USR_26 / USR_32)
+ .word __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
+ .word __pabt_invalid @ 2 (IRQ_26 / IRQ_32)
+ .word __pabt_svc @ 3 (SVC_26 / SVC_32)
+ .word __pabt_invalid @ 4
+ .word __pabt_invalid @ 5
+ .word __pabt_invalid @ 6
+ .word __pabt_invalid @ 7
+ .word __pabt_invalid @ 8
+ .word __pabt_invalid @ 9
+ .word __pabt_invalid @ a
+ .word __pabt_invalid @ b
+ .word __pabt_invalid @ c
+ .word __pabt_invalid @ d
+ .word __pabt_invalid @ e
+ .word __pabt_invalid @ f
.align 5
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index b74d7550f..1be23e8fb 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -131,15 +131,14 @@ void set_fiq_regs(struct pt_regs *regs)
#endif
#ifdef CONFIG_CPU_32
"mrs %0, cpsr
- bic %1, %0, #0xf
- orr %1, %1, #0xc1
- msr cpsr, %1 @ select FIQ mode
+ mov %1, #0xc1
+ msr cpsr_c, %1 @ select FIQ mode
mov r0, r0
ldmia %2, {r8 - r14}
- msr cpsr, %0 @ return to SVC mode
+ msr cpsr_c, %0 @ return to SVC mode
mov r0, r0"
#endif
- : "=r" (tmp), "=r" (tmp2)
+ : "=&r" (tmp), "=&r" (tmp2)
: "r" (&regs->ARM_r8)
/* These registers aren't modified by the above code in a way
visible to the compiler, but we mark them as clobbers anyway
@@ -164,15 +163,14 @@ void get_fiq_regs(struct pt_regs *regs)
#endif
#ifdef CONFIG_CPU_32
"mrs %0, cpsr
- bic %1, %0, #0xf
- orr %1, %1, #0xc1
- msr cpsr, %1 @ select FIQ mode
+ mov %1, #0xc1
+ msr cpsr_c, %1 @ select FIQ mode
mov r0, r0
stmia %2, {r8 - r14}
- msr cpsr, %0 @ return to SVC mode
+ msr cpsr_c, %0 @ return to SVC mode
mov r0, r0"
#endif
- : "=r" (tmp), "=r" (tmp2)
+ : "=&r" (tmp), "=&r" (tmp2)
: "r" (&regs->ARM_r8)
/* These registers aren't modified by the above code in a way
visible to the compiler, but we mark them as clobbers anyway
diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/kernel/head-armo.S
index f42f3337d..13dd0d09e 100644
--- a/arch/arm/kernel/head-armo.S
+++ b/arch/arm/kernel/head-armo.S
@@ -21,7 +21,6 @@
*/
.section ".text.init",#alloc,#execinstr
ENTRY(stext)
-ENTRY(_stext)
__entry: cmp pc, #0x02000000
ldrlt pc, LC0 @ if 0x01800000, call at 0x02080000
teq r0, #0 @ Check for old calling method
diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S
index 5e141bf51..5e529e702 100644
--- a/arch/arm/kernel/head-armv.S
+++ b/arch/arm/kernel/head-armv.S
@@ -16,28 +16,33 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#if (TEXTADDR & 0xffff) != 0x8000
-#error TEXTADDR must start at 0xXXXX8000
-#endif
-
#define K(a,b,c) ((a) << 24 | (b) << 12 | (c))
/*
- * swapper_pg_dir is the virtual address of the "init_task" page tables.
- * SWAPPER_PGDIR_OFFSET is the offset from the start of memory of the
- * page tables.
+ * We place the page tables 16K below TEXTADDR. Therefore, we must make sure
+ * that TEXTADDR is correctly set. Currently, we expect the least significant
+ * "short" to be 0x8000, but we could probably relax this restriction to
+ * TEXTADDR > PAGE_OFFSET + 0x4000
*
- * Note that at the moment, we assume TEXTADDR is the virtual equivalent
- * of start of memory + 0x8000
+ * Note that swapper_pg_dir is the virtual address of the page tables, and
+ * pgtbl gives us a position-independent reference to these tables. We can
+ * do this because stext == TEXT_ADDR
*/
-#define SWAPPER_PGDIR_OFFSET 0x4000
+#if (TEXTADDR & 0xffff) != 0x8000
+#error TEXTADDR must start at 0xXXXX8000
+#endif
+
.globl SYMBOL_NAME(swapper_pg_dir)
- .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x8000 + SWAPPER_PGDIR_OFFSET
+ .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000
+
+ .macro pgtbl, reg
+ adr \reg, stext
+ sub \reg, \reg, #0x4000
+ .endm
.section ".text.init",#alloc,#execinstr
.type stext, #function
ENTRY(stext)
-ENTRY(_stext)
/*
* Entry point. The general rules are:
* should be called with r0 == 0
@@ -185,7 +190,7 @@ __mmap_switched:
* r8 = page table flags
*/
__create_page_tables:
- add r4, r5, #SWAPPER_PGDIR_OFFSET
+ pgtbl r4
mov r0, r4
mov r3, #0
add r2, r0, #0x4000 @ 16k of page table
diff --git a/arch/arm/kernel/oldlatches.c b/arch/arm/kernel/oldlatches.c
index fe40c58b5..7d8858b9e 100644
--- a/arch/arm/kernel/oldlatches.c
+++ b/arch/arm/kernel/oldlatches.c
@@ -26,12 +26,12 @@ static unsigned char latch_b_copy;
/* newval=(oldval & ~mask)|newdata */
void oldlatch_aupdate(unsigned char mask,unsigned char newdata)
{
- if (machine_is_arc()) {
+ if (machine_is_archimedes()) {
latch_a_copy = (latch_a_copy & ~mask) | newdata;
printk("Latch: A = 0x%02x\n", latch_a_copy);
- outb(latch_a_copy, LATCHAADDR);
+ __raw_writeb(latch_a_copy, LATCHA_BASE);
} else
BUG();
}
@@ -40,19 +40,19 @@ void oldlatch_aupdate(unsigned char mask,unsigned char newdata)
/* newval=(oldval & ~mask)|newdata */
void oldlatch_bupdate(unsigned char mask,unsigned char newdata)
{
- if (machine_is_arc()) {
+ if (machine_is_archimedes()) {
latch_b_copy = (latch_b_copy & ~mask) | newdata;
printk("Latch: B = 0x%02x\n", latch_b_copy);
- outb(latch_b_copy, LATCHBADDR);
+ __raw_writeb(latch_b_copy, LATCHB_BASE);
} else
BUG();
}
static void __init oldlatch_init(void)
{
- if (machine_is_arc()) {
+ if (machine_is_archimedes()) {
oldlatch_aupdate(0xff, 0xff);
/* Thats no FDC reset...*/
oldlatch_bupdate(0xff, LATCHB_FDCRESET);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 8e8e3675f..9d0cc5c69 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -31,6 +31,7 @@
#include "ptrace.h"
extern void c_backtrace (unsigned long fp, int pmode);
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
const char *processor_modes[]=
{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -41,12 +42,6 @@ const char *processor_modes[]=
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
-static inline void console_verbose(void)
-{
- extern int console_loglevel;
- console_loglevel = 15;
-}
-
/*
* Stack pointers should always be within the kernels view of
* physical memory. If it is not there, then we can't dump
@@ -72,10 +67,14 @@ void dump_mem(unsigned long bottom, unsigned long top)
printk("%08lx: ", p);
for (i = 0; i < 8; i++, p += 4) {
+ unsigned int val;
+
if (p < bottom || p >= top)
printk(" ");
- else
- printk("%08lx ", *(unsigned long *)p);
+ else {
+ __get_user(val, (unsigned long *)p);
+ printk("%08x ", val);
+ }
if (i == 3)
printk(" ");
}
@@ -91,45 +90,57 @@ void dump_mem(unsigned long bottom, unsigned long top)
#define VMALLOC_OFFSET (8*1024*1024)
#define MODULE_RANGE (8*1024*1024)
-static void dump_instr(unsigned long pc, int user)
+static void dump_instr(struct pt_regs *regs)
{
- int pmin = -2, pmax = 3, ok = 0;
- extern char start_kernel, _etext;
-
- if (!user) {
- unsigned long module_start, module_end;
- unsigned long kernel_start, kernel_end;
-
- module_start = VMALLOC_START;
- module_end = module_start + MODULE_RANGE;
-
- kernel_start = (unsigned long)&start_kernel;
- kernel_end = (unsigned long)&_etext;
-
- if (pc >= kernel_start && pc < kernel_end) {
- if (pc + pmin < kernel_start)
- pmin = kernel_start - pc;
- if (pc + pmax > kernel_end)
- pmax = kernel_end - pc;
- ok = 1;
- } else if (pc >= module_start && pc < module_end) {
- if (pc + pmin < module_start)
- pmin = module_start - pc;
- if (pc + pmax > module_end)
- pmax = module_end - pc;
- ok = 1;
+ unsigned long addr = instruction_pointer(regs);
+ const int thumb = thumb_mode(regs);
+ const int width = thumb ? 4 : 8;
+ int i;
+
+ printk("Code: ");
+ for (i = -2; i < 3; i++) {
+ unsigned int val, bad;
+
+ if (thumb)
+ bad = __get_user(val, &((u16 *)addr)[i]);
+ else
+ bad = __get_user(val, &((u32 *)addr)[i]);
+
+ if (!bad)
+ printk(i == 0 ? "(%0*x) " : "%0*x", width, val);
+ else {
+ printk("bad PC value.");
+ break;
}
- } else
- ok = verify_area(VERIFY_READ, (void *)(pc + pmin), pmax - pmin) == 0;
-
- printk ("Code: ");
- if (ok) {
- int i;
- for (i = pmin; i < pmax; i++)
- printk(i == 0 ? "(%08lx) " : "%08lx ", ((unsigned long *)pc)[i]);
- printk ("\n");
- } else
- printk ("pc not in code space\n");
+ }
+ printk("\n");
+}
+
+static void dump_stack(struct task_struct *tsk, unsigned long sp)
+{
+ printk("Stack:\n");
+ dump_mem(sp - 16, 8192+(unsigned long)tsk);
+}
+
+static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
+{
+ unsigned int fp;
+ int ok = 1;
+
+ printk("Backtrace: ");
+ fp = regs->ARM_fp;
+ if (!fp) {
+ printk("no frame pointer");
+ ok = 0;
+ } else if (verify_stack(fp)) {
+ printk("invalid frame pointer %08lx", fp);
+ ok = 0;
+ } else if (fp < 4096+(unsigned long)tsk)
+ printk("frame pointer underflow");
+ printk("\n");
+
+ if (ok)
+ c_backtrace(fp, processor_mode(regs));
}
spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
@@ -141,9 +152,9 @@ void die(const char *str, struct pt_regs *regs, int err)
{
struct task_struct *tsk = current;
+ console_verbose();
spin_lock_irq(&die_lock);
- console_verbose();
printk("Internal error: %s: %x\n", str, err);
printk("CPU: %d\n", smp_processor_id());
show_regs(regs);
@@ -151,39 +162,22 @@ void die(const char *str, struct pt_regs *regs, int err)
current->comm, current->pid, 4096+(unsigned long)tsk);
if (!user_mode(regs)) {
- unsigned long sp = (unsigned long)(regs + 1);
- unsigned long fp;
- int dump_info = 1;
-
- printk("Stack: ");
- if (verify_stack(sp)) {
- printk("invalid kernel stack pointer %08lx", sp);
- dump_info = 0;
- } else if (sp < 4096+(unsigned long)tsk)
- printk("kernel stack pointer underflow");
- printk("\n");
-
- if (dump_info)
- dump_mem(sp - 16, 8192+(unsigned long)tsk);
-
- dump_info = 1;
-
- printk("Backtrace: ");
- fp = regs->ARM_fp;
- if (!fp) {
- printk("no frame pointer");
- dump_info = 0;
- } else if (verify_stack(fp)) {
- printk("invalid frame pointer %08lx", fp);
- dump_info = 0;
- } else if (fp < 4096+(unsigned long)tsk)
- printk("frame pointer underflow");
- printk("\n");
-
- if (dump_info)
- c_backtrace(fp, processor_mode(regs));
-
- dump_instr(instruction_pointer(regs), 0);
+ mm_segment_t fs;
+
+ /*
+ * 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);
+
+ dump_instr(regs);
+ dump_stack(tsk, (unsigned long)(regs + 1));
+ dump_backtrace(regs, tsk);
+
+ set_fs(fs);
}
spin_unlock_irq(&die_lock);
@@ -206,6 +200,7 @@ asmlinkage void do_undefinstr(int address, struct pt_regs *regs, int mode)
#ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
current->comm, current->pid, addr);
+ dump_instr(regs);
#endif
current->thread.error_code = 0;
@@ -228,6 +223,7 @@ asmlinkage void do_excpt(int address, struct pt_regs *regs, int mode)
#ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n",
current->comm, current->pid, instruction_pointer(regs));
+ dump_instr(regs);
#endif
current->thread.error_code = 0;
@@ -275,7 +271,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
die("Oops", regs, 0);
cli();
- while(1);
+ panic("bad mode");
}
/*
@@ -332,6 +328,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
* something catastrophic has happened
*/
printk("[%d] %s: arm syscall %d\n", current->pid, current->comm, no);
+ dump_instr(regs);
if (user_mode(regs)) {
show_regs(regs);
c_backtrace(regs->ARM_fp, processor_mode(regs));
@@ -359,8 +356,9 @@ asmlinkage void deferred(int n, struct pt_regs *regs)
}
#ifdef CONFIG_DEBUG_USER
- printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", current->pid,
- current->comm, n);
+ printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
+ current->pid, current->comm, n);
+ dump_instr(regs);
#endif
force_sig(SIGILL, current);
die_if_kernel("Oops", regs, n);
@@ -384,21 +382,10 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
siginfo_t info;
#ifdef CONFIG_DEBUG_USER
- dump_instr(addr, 1);
- {
- pgd_t *pgd;
-
- pgd = pgd_offset(current->mm, addr);
- printk ("*pgd = %08lx", pgd_val (*pgd));
- if (!pgd_none (*pgd)) {
- pmd_t *pmd;
- pmd = pmd_offset (pgd, addr);
- printk (", *pmd = %08lx", pmd_val (*pmd));
- if (!pmd_none (*pmd))
- printk (", *pte = %08lx", pte_val(*pte_offset (pmd, addr)));
- }
- printk ("\n");
- }
+ printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
+ current->pid, current->comm, code, instr);
+ dump_instr(regs);
+ show_pte(current->mm, addr);
#endif
info.si_signo = SIGILL;
diff --git a/arch/arm/kernel/via82c505.c b/arch/arm/kernel/via82c505.c
index 42a2bb448..ab97b6e80 100644
--- a/arch/arm/kernel/via82c505.c
+++ b/arch/arm/kernel/via82c505.c
@@ -76,7 +76,7 @@ static struct pci_ops via82c505_ops = {
#ifdef CONFIG_ARCH_SHARK
-static char size_wanted = 0;
+static char size_wanted;
static int
dummy_read_config_byte(struct pci_dev *dev, int where, u8 *value)
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index b7e29ca55..fa7f10117 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -13,19 +13,35 @@ L_OBJS := changebit.o csumipv6.o csumpartial.o csumpartialcopy.o \
strncpy_from_user.o strnlen_user.o strchr.o strrchr.o \
testchangebit.o testclearbit.o testsetbit.o uaccess.o
+l-obj-y :=
+l-obj-n :=
+
O_TARGET := lib.o
O_OBJS := backtrace.o delay.o
-L_OBJS_arc := io-acorn.o floppydma.o
-L_OBJS_rpc := io-acorn.o floppydma.o
+ifeq ($(CONFIG_ARCH_ACORN),y)
+ half := n
+ full := y
+else
+ half := y
+ full := n
+endif
+
+L_OBJS_arc := ecard.o io-acorn.o floppydma.o
+L_OBJS_rpc := ecard.o io-acorn.o floppydma.o
L_OBJS_clps7500 := io-acorn.o
-L_OBJS_ebsa110 := io-ebsa110.o
-L_OBJS_footbridge := io-footbridge.o
+L_OBJS_footbridge := io-pcio.o
L_OBJS_l7200 := io-acorn.o
-L_OBJS_nexuspci := io-footbridge.o
-L_OBJS_sa1100 := io-footbridge.o
+L_OBJS_nexuspci := io-pcio.o
+L_OBJS_sa1100 := io-pcio.o
L_OBJS_shark := io-shark.o
-L_OBJS_integrator := io-shark.o
+L_OBJS_integrator := io-pcio.o
+L_OBJS_clps711x := io-shark.o
+
+l-obj-y += io-readsb.o io-writesb.o
+l-obj-$(full) += io-readsw-armv3.o io-writesw-armv3.o
+l-obj-$(half) += io-readsw-armv4.o io-writesw-armv4.o
+l-obj-y += io-readsl.o io-writesl.o
ifeq ($(PROCESSOR),armo)
L_OBJS += uaccess-armo.o
@@ -35,7 +51,7 @@ ifneq ($(MACHINE),ebsa110)
OX_OBJS += io.o
endif
-L_OBJS += $(L_OBJS_$(MACHINE))
+L_OBJS += $(L_OBJS_$(MACHINE)) $(l-obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/arm/lib/ecard.S b/arch/arm/lib/ecard.S
new file mode 100644
index 000000000..9b0452d01
--- /dev/null
+++ b/arch/arm/lib/ecard.S
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/arm/lib/ecard.S
+ *
+ * Copyright (C) 1995, 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.
+ */
+#include <linux/config.h> /* for CONFIG_CPU_nn */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+#if defined(CONFIG_CPU_26)
+#define CPSR2SPSR(rt)
+#else
+#define CPSR2SPSR(rt) \
+ mrs rt, cpsr; \
+ msr spsr, rt
+#endif
+
+@ Purpose: call an expansion card loader to read bytes.
+@ Proto : char read_loader(int offset, char *card_base, char *loader);
+@ Returns: byte read
+
+ENTRY(ecard_loader_read)
+ stmfd sp!, {r4 - r12, lr}
+ mov r11, r1
+ mov r1, r0
+ CPSR2SPSR(r0)
+ mov lr, pc
+ mov pc, r2
+ LOADREGS(fd, sp!, {r4 - r12, pc})
+
+@ Purpose: call an expansion card loader to reset the card
+@ Proto : void read_loader(int card_base, char *loader);
+@ Returns: byte read
+
+ENTRY(ecard_loader_reset)
+ stmfd sp!, {r4 - r12, lr}
+ mov r11, r0
+ CPSR2SPSR(r0)
+ mov lr, pc
+ add pc, r1, #8
+ LOADREGS(fd, sp!, {r4 - r12, pc})
+
diff --git a/arch/arm/lib/io-acorn.S b/arch/arm/lib/io-acorn.S
index bc40496ac..a40272fdb 100644
--- a/arch/arm/lib/io-acorn.S
+++ b/arch/arm/lib/io-acorn.S
@@ -40,8 +40,6 @@
addeq \rd, \rd, #diff_pcio_base
.endm
-.iosw_bad_align_msg:
- .ascii "insw: bad buffer alignment (%p), called from %08lX\n\0"
.iosl_warning:
.ascii "<4>insl/outsl not implemented, called from %08lX\0"
.align
@@ -56,422 +54,38 @@ ENTRY(outsl)
mov r1, lr
b SYMBOL_NAME(printk)
-.iosw_bad_alignment:
- adr r0, .iosw_bad_align_msg
- mov r2, lr
- b SYMBOL_NAME(panic)
-
-
/* Purpose: read a block of data from a hardware register to memory.
* Proto : void insw(int from_port, void *to, int len_in_words);
* Notes : increment to, 'to' must be 16-bit aligned
*/
-.insw_align: tst r1, #1
- bne .iosw_bad_alignment
-
- ldr r3, [r0]
- strb r3, [r1], #1
- mov r3, r3, lsr #8
- strb r3, [r1], #1
-
- subs r2, r2, #1
- bne .insw_aligned
-
ENTRY(insw)
teq r2, #0
- RETINSTR(moveq,pc,lr)
+ RETINSTR(moveq, pc, lr)
addr r0
- tst r1, #3
- bne .insw_align
-
-.insw_aligned: mov ip, #0xff
- orr ip, ip, ip, lsl #8
- stmfd sp!, {r4, r5, r6, lr}
-
- subs r2, r2, #8
- bmi .no_insw_8
-
-.insw_8_lp: ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- ldr r4, [r0]
- and r4, r4, ip
- ldr r5, [r0]
- orr r4, r4, r5, lsl #16
-
- ldr r5, [r0]
- and r5, r5, ip
- ldr r6, [r0]
- orr r5, r5, r6, lsl #16
-
- ldr r6, [r0]
- and r6, r6, ip
- ldr lr, [r0]
- orr r6, r6, lr, lsl #16
-
- stmia r1!, {r3 - r6}
- subs r2, r2, #8
- bpl .insw_8_lp
- tst r2, #7
- LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
+ b __arch_readsw
-.no_insw_8: tst r2, #4
- beq .no_insw_4
-
- ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- ldr r4, [r0]
- and r4, r4, ip
- ldr r5, [r0]
- orr r4, r4, r5, lsl #16
-
- stmia r1!, {r3, r4}
-
-.no_insw_4: tst r2, #2
- beq .no_insw_2
-
- ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- str r3, [r1], #4
-
-.no_insw_2: tst r2, #1
- ldrne r3, [r0]
- strneb r3, [r1], #1
- movne r3, r3, lsr #8
- strneb r3, [r1]
- LOADREGS(fd, sp!, {r4, r5, r6, pc})
+ENTRY(insb)
+ teq r2, #0
+ RETINSTR(moveq, pc, lr)
+ addr r0
+ b __arch_readsb
@ Purpose: write a block of data from memory to a hardware register.
@ Proto : outsw(int to_reg, void *from, int len_in_words);
@ Notes : increments from
-.outsw_align: tst r1, #1
- bne .iosw_bad_alignment
-
- add r1, r1, #2
-
- ldr r3, [r1, #-4]
- mov r3, r3, lsr #16
- orr r3, r3, r3, lsl #16
- str r3, [r0]
- subs r2, r2, #1
- bne .outsw_aligned
-
ENTRY(outsw)
teq r2, #0
- RETINSTR(moveq,pc,lr)
- addr r0
- tst r1, #3
- bne .outsw_align
-
-.outsw_aligned: stmfd sp!, {r4, r5, r6, lr}
-
- subs r2, r2, #8
- bmi .no_outsw_8
-.outsw_8_lp: ldmia r1!, {r3, r4, r5, r6}
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r4, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r4, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r5, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r5, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r6, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r6, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- subs r2, r2, #8
- bpl .outsw_8_lp
- tst r2, #7
- LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
-
-.no_outsw_8: tst r2, #4
- beq .no_outsw_4
-
- ldmia r1!, {r3, r4}
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r4, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r4, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
-.no_outsw_4: tst r2, #2
- beq .no_outsw_2
-
- ldr r3, [r1], #4
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
-.no_outsw_2: tst r2, #1
-
- ldrne r3, [r1]
-
- movne ip, r3, lsl #16
- orrne ip, ip, ip, lsr #16
- strne ip, [r0]
-
- LOADREGS(fd, sp!, {r4, r5, r6, pc})
-
-.insb_align: rsb ip, ip, #4
- cmp ip, r2
- movgt ip, r2
- cmp ip, #2
- ldrb r3, [r0]
- strb r3, [r1], #1
- ldrgeb r3, [r0]
- strgeb r3, [r1], #1
- ldrgtb r3, [r0]
- strgtb r3, [r1], #1
- subs r2, r2, ip
- bne .insb_aligned
-
-ENTRY(insb)
- teq r2, #0
- moveq pc, lr
+ RETINSTR(moveq, pc, lr)
addr r0
- ands ip, r1, #3
- bne .insb_align
-
-.insb_aligned: stmfd sp!, {r4 - r6, lr}
-
- subs r2, r2, #16
- bmi .insb_no_16
-
-.insb_16_lp: ldrb r3, [r0]
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #8
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #16
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #24
- ldrb r4, [r0]
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #8
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #16
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #24
- ldrb r5, [r0]
- ldrb r6, [r0]
- orr r5, r5, r6, lsl #8
- ldrb r6, [r0]
- orr r5, r5, r6, lsl #16
- ldrb r6, [r0]
- orr r5, r5, r6, lsl #24
- ldrb r6, [r0]
- ldrb ip, [r0]
- orr r6, r6, ip, lsl #8
- ldrb ip, [r0]
- orr r6, r6, ip, lsl #16
- ldrb ip, [r0]
- orr r6, r6, ip, lsl #24
- stmia r1!, {r3 - r6}
- subs r2, r2, #16
- bpl .insb_16_lp
-
- tst r2, #15
- LOADREGS(eqfd, sp!, {r4 - r6, pc})
-
-.insb_no_16: tst r2, #8
- beq .insb_no_8
-
- ldrb r3, [r0]
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #8
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #16
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #24
- ldrb r4, [r0]
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #8
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #16
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #24
- stmia r1!, {r3, r4}
-
-.insb_no_8: tst r2, #4
- bne .insb_no_4
-
- ldrb r3, [r0]
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #8
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #16
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #24
- str r3, [r1], #4
-
-.insb_no_4: ands r2, r2, #3
- LOADREGS(eqfd, sp!, {r4 - r6, pc})
- cmp r2, #2
- ldrb r3, [r0]
- strb r3, [r1], #1
- ldrgeb r3, [r0]
- strgeb r3, [r1], #1
- ldrgtb r3, [r0]
- strgtb r3, [r1]
- LOADREGS(fd, sp!, {r4 - r6, pc})
-
-
-
-.outsb_align: rsb ip, ip, #4
- cmp ip, r2
- mov ip, r2
- cmp ip, #2
- ldrb r3, [r1], #1
- strb r3, [r0]
- ldrgeb r3, [r1], #1
- strgeb r3, [r0]
- ldrgtb r3, [r1], #1
- strgtb r3, [r0]
- subs r2, r2, ip
- bne .outsb_aligned
+ b __arch_writesw
ENTRY(outsb)
teq r2, #0
- moveq pc, lr
+ RETINSTR(moveq, pc, lr)
addr r0
- ands ip, r1, #3
- bne .outsb_align
-
-.outsb_aligned: stmfd sp!, {r4 - r6, lr}
-
- subs r2, r2, #16
- bmi .outsb_no_16
-
-.outsb_16_lp: ldmia r1!, {r3 - r6}
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
-
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
-
- strb r5, [r0]
- mov r5, r5, lsr #8
- strb r5, [r0]
- mov r5, r5, lsr #8
- strb r5, [r0]
- mov r5, r5, lsr #8
- strb r5, [r0]
-
- strb r6, [r0]
- mov r6, r6, lsr #8
- strb r6, [r0]
- mov r6, r6, lsr #8
- strb r6, [r0]
- mov r6, r6, lsr #8
- strb r6, [r0]
- subs r2, r2, #16
- bpl .outsb_16_lp
-
- tst r2, #15
- LOADREGS(eqfd, sp!, {r4 - r6, pc})
-
-.outsb_no_16: tst r2, #8
- beq .outsb_no_8
-
- ldmia r1, {r3, r4}
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
-
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
-
-.outsb_no_8: tst r2, #4
- bne .outsb_no_4
-
- ldr r3, [r1], #4
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
-
-.outsb_no_4: ands r2, r2, #3
- LOADREGS(eqfd, sp!, {r4 - r6, pc})
- cmp r2, #2
- ldrb r3, [r1], #1
- strb r3, [r0]
- ldrgeb r3, [r1], #1
- strgeb r3, [r0]
- ldrgtb r3, [r1]
- strgtb r3, [r0]
- LOADREGS(fd, sp!, {r4 - r6, pc})
-
-
-
+ b __arch_writesb
@ Purpose: write a memc register
@ Proto : void memc_write(int register, int value);
@@ -488,146 +102,5 @@ ENTRY(memc_write)
add r0, r0, #0x03600000
strb r0, [r0]
RETINSTR(mov,pc,lr)
-#define CPSR2SPSR(rt)
-#else
-#define CPSR2SPSR(rt) \
- mrs rt, cpsr; \
- msr spsr, rt
-#endif
-
-@ Purpose: call an expansion card loader to read bytes.
-@ Proto : char read_loader(int offset, char *card_base, char *loader);
-@ Returns: byte read
-
-ENTRY(ecard_loader_read)
- stmfd sp!, {r4 - r12, lr}
- mov r11, r1
- mov r1, r0
- CPSR2SPSR(r0)
- mov lr, pc
- mov pc, r2
- LOADREGS(fd, sp!, {r4 - r12, pc})
-
-@ Purpose: call an expansion card loader to reset the card
-@ Proto : void read_loader(int card_base, char *loader);
-@ Returns: byte read
-
-ENTRY(ecard_loader_reset)
- stmfd sp!, {r4 - r12, lr}
- mov r11, r0
- CPSR2SPSR(r0)
- mov lr, pc
- add pc, r1, #8
- LOADREGS(fd, sp!, {r4 - r12, pc})
-
-
-#if 0
- mov r2, r2, lsl#1
- mov ip, sp
- stmfd sp!, {r4 - r10, fp, ip, lr, pc}
- sub fp, ip, #4
- addr r3, r0
- add r0, r3, r0, lsl #2
- tst r1, #3
- beq Linswok
- tst r1, #1
- bne Linsw_notaligned
- cmp r2, #1
- ldrge r4, [r0]
- strgeb r4, [r1], #1
- movgt r4, r4, LSR#8
- strgtb r4, [r1], #1
- LOADREGS(leea, fp, {r4 - r10, fp, sp, pc})
- sub r2, r2, #2
-Linswok: mov ip, #0xFF
- orr ip, ip, ip, lsl #8
-Linswlp: subs r2, r2, #64
- bmi Linsw_toosmall
- IN(r3)
- IN(r4)
- IN(r5)
- IN(r6)
- IN(r7)
- IN(r8)
- IN(r9)
- IN(r10)
- stmia r1!, {r3 - r10}
- IN(r3)
- IN(r4)
- IN(r5)
- IN(r6)
- IN(r7)
- IN(r8)
- IN(r9)
- IN(r10)
- stmia r1!, {r3 - r10}
- bne Linswlp
- LOADREGS(ea, fp, {r4 - r10, fp, sp, pc})
-Linsw_toosmall:
- adds r2, r2, #32
- bmi Linsw_toosmall2
-Linsw2lp: IN(r3)
- IN(r4)
- IN(r5)
- IN(r6)
- IN(r7)
- IN(r8)
- IN(r9)
- IN(r10)
- stmia r1!, {r3 - r10}
- LOADREGS(eqea, fp, {r4 - r10, fp, sp, pc})
- b Linsw_notaligned
-Linsw_toosmall2:
- add r2, r2, #32
-Linsw_notaligned:
- cmp r2, #1
- LOADREGS(ltea, fp, {r4 - r10, fp, sp, pc})
- ldr r4, [r0]
- strb r4, [r1], #1
- movgt r4, r4, LSR#8
- strgtb r4, [r1], #1
- subs r2, r2, #2
- bgt Linsw_notaligned
- LOADREGS(ea, fp, {r4 - r10, fp, sp, pc})
-
-
-ENTRY(outsw)
- mov r2, r2, lsl#1
- mov ip, sp
- stmfd sp!, {r4 - r8, fp, ip, lr, pc}
- sub fp, ip, #4
- addr r3, r0
- tst r1, #2
- beq 1f
- ldr r4, [r1], #2
- mov r4, r4, lsl #16
- orr r4, r4, r4, lsr #16
- str r4, [r3, r0, lsl #2]
- subs r2, r2, #2
- LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc})
-1: subs r2, r2, #32
- blt 2f
- ldmia r1!, {r4, r5, r6, r7}
- OUT(r4)
- OUT(r5)
- OUT(r6)
- OUT(r7)
- ldmia r1!, {r4, r5, r6, r7}
- OUT(r4)
- OUT(r5)
- OUT(r6)
- OUT(r7)
- bne 1b
- LOADREGS(ea, fp, {r4 - r8, fp, sp, pc})
-2: adds r2, r2, #32
- LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc})
-3: ldr r4, [r1],#2
- mov r4, r4, lsl#16
- orr r4, r4, r4, lsr#16
- str r4, [r3, r0, lsl#2]
- subs r2, r2, #2
- bgt 3b
- LOADREGS(ea, fp, {r4 - r8, fp, sp, pc})
-
#endif
diff --git a/arch/arm/lib/io-ebsa110.S b/arch/arm/lib/io-ebsa110.S
deleted file mode 100644
index b1c507886..000000000
--- a/arch/arm/lib/io-ebsa110.S
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * linux/arch/arm/lib/io-ebsa.S
- *
- * Copyright (C) 1995, 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.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
- .text
- .align
-
-#define OUT(reg) \
- mov r8, reg, lsl $16 ;\
- orr r8, r8, r8, lsr $16 ;\
- str r8, [r3, r0, lsl $2] ;\
- mov r8, reg, lsr $16 ;\
- orr r8, r8, r8, lsl $16 ;\
- str r8, [r3, r0, lsl $2]
-
-#define IN(reg) \
- ldr reg, [r0] ;\
- and reg, reg, ip ;\
- ldr lr, [r0] ;\
- orr reg, reg, lr, lsl $16
-
-/*
- * These make no sense on these machines.
- * Print a warning message.
- */
-ENTRY(insl)
-ENTRY(outsl)
-ENTRY(insb)
-ENTRY(outsb)
- adr r0, io_long_warning
- mov r1, lr
- b SYMBOL_NAME(printk)
-
-io_long_warning:
- .ascii "<4>ins?/outs? not implemented on this architecture\0"
- .align
-
-@ Purpose: read a block of data from a hardware register to memory.
-@ Proto : insw(int from_port, void *to, int len_in_words);
-@ Proto : inswb(int from_port, void *to, int len_in_bytes);
-@ Notes : increment to
-
-ENTRY(insw)
- mov r2, r2, lsl#1
-ENTRY(inswb)
- mov ip, sp
- stmfd sp!, {r4 - r10 ,fp ,ip ,lr ,pc}
- sub fp, ip, #4
- cmp r0, #0x00c00000
- movge r3, #0
- movlt r3, #0xf0000000
- add r0, r3, r0, lsl #2
- tst r1, #3
- beq Linswok
- tst r1, #1
- bne Linsw_notaligned
- cmp r2, #1
- ldrge r4, [r0]
- strgeb r4, [r1], #1
- movgt r4, r4, LSR#8
- strgtb r4, [r1], #1
- ldmleea fp, {r4 - r10, fp, sp, pc}^
- sub r2, r2, #2
-Linswok: mov ip, #0xFF
- orr ip, ip, ip, lsl #8
-Linswlp: subs r2, r2, #64
- bmi Linsw_toosmall
- IN(r3)
- IN(r4)
- IN(r5)
- IN(r6)
- IN(r7)
- IN(r8)
- IN(r9)
- IN(r10)
- stmia r1!, {r3 - r10}
- IN(r3)
- IN(r4)
- IN(r5)
- IN(r6)
- IN(r7)
- IN(r8)
- IN(r9)
- IN(r10)
- stmia r1!, {r3 - r10}
- bne Linswlp
- LOADREGS(ea, fp, {r4 - r10, fp, sp, pc})
-Linsw_toosmall:
- add r2, r2, #32
- bmi Linsw_toosmall2
-Linsw2lp: IN(r3)
- IN(r4)
- IN(r5)
- IN(r6)
- IN(r7)
- IN(r8)
- IN(r9)
- IN(r10)
- stmia r1!, {r3 - r10}
- LOADREGS(eqea, fp, {r4 - r10, fp, sp, pc})
- b Linsw_notaligned
-Linsw_toosmall2:
- add r2, r2, #32
-Linsw_notaligned:
- cmp r2, #1
- LOADREGS(ltea, fp, {r4 - r10, fp, sp, pc})
- ldr r4, [r0]
- strb r4, [r1], #1
- movgt r4, r4, LSR#8
- strgtb r4, [r1], #1
- subs r2, r2, #2
- bgt Linsw_notaligned
- LOADREGS(ea, fp, {r4 - r10, fp, sp, pc})
-
-@ Purpose: write a block of data from memory to a hardware register.
-@ Proto : outsw(int to_reg, void *from, int len_in_words);
-@ Proto : outswb(int to_reg, void *from, int len_in_bytes);
-@ Notes : increments from
-
-ENTRY(outsw)
- mov r2, r2, LSL#1
-ENTRY(outswb)
- mov ip, sp
- stmfd sp!, {r4 - r8, fp, ip, lr, pc}
- sub fp, ip, #4
- cmp r0, #0x00c00000
- movge r3, #0
- movlt r3, #0xf0000000
- tst r1, #2
- beq Loutsw32lp
- ldr r4, [r1], #2
- mov r4, r4, lsl #16
- orr r4, r4, r4, lsr #16
- str r4, [r3, r0, lsl #2]
- sub r2, r2, #2
- teq r2, #0
- LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc})
-Loutsw32lp: subs r2,r2,#32
- blt Loutsw_toosmall
- ldmia r1!,{r4,r5,r6,r7}
- OUT(r4)
- OUT(r5)
- OUT(r6)
- OUT(r7)
- ldmia r1!,{r4,r5,r6,r7}
- OUT(r4)
- OUT(r5)
- OUT(r6)
- OUT(r7)
- LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc})
- b Loutsw32lp
-Loutsw_toosmall:
- adds r2,r2,#32
- LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc})
-Llpx: ldr r4,[r1],#2
- mov r4,r4,LSL#16
- orr r4,r4,r4,LSR#16
- str r4,[r3,r0,LSL#2]
- subs r2,r2,#2
- bgt Llpx
- LOADREGS(ea, fp, {r4 - r8, fp, sp, pc})
-
diff --git a/arch/arm/lib/io-footbridge.S b/arch/arm/lib/io-footbridge.S
deleted file mode 100644
index 98f751258..000000000
--- a/arch/arm/lib/io-footbridge.S
+++ /dev/null
@@ -1,202 +0,0 @@
-#include <linux/linkage.h>
-#include <asm/hardware.h>
-
- .equ pcio_high, PCIO_BASE & 0xff000000
- .equ pcio_low, PCIO_BASE & 0x00ffffff
-
- .macro ioaddr, rd,rn
- add \rd, \rn, #pcio_high
- .if pcio_low
- add \rd, \rd, #pcio_low
- .endif
- .endm
-
-ENTRY(insl)
- ioaddr r0, r0
- ands ip, r1, #3
- bne 2f
-
-1: ldr r3, [r0]
- str r3, [r1], #4
- subs r2, r2, #1
- bne 1b
- mov pc, lr
-
-2: cmp ip, #2
- ldr ip, [r0]
- blt 4f
- bgt 6f
-
- strh ip, [r1], #2
- mov ip, ip, lsr #16
-3: subs r2, r2, #1
- ldrne r3, [r0]
- orrne ip, ip, r3, lsl #16
- strne ip, [r1], #4
- movne ip, r3, lsr #16
- bne 3b
- strh ip, [r1], #2
- mov pc, lr
-
-4: strb ip, [r1], #1
- mov ip, ip, lsr #8
- strh ip, [r1], #2
- mov ip, ip, lsr #16
-5: subs r2, r2, #1
- ldrne r3, [r0]
- orrne ip, ip, r3, lsl #8
- strne ip, [r1], #4
- movne ip, r3, lsr #24
- bne 5b
- strb ip, [r1], #1
- mov pc, lr
-
-6: strb ip, [r1], #1
- mov ip, ip, lsr #8
-7: subs r2, r2, #1
- ldrne r3, [r0]
- orrne ip, ip, r3, lsl #24
- strne ip, [r1], #4
- movne ip, r3, lsr #8
- bne 7b
- strb ip, [r1], #1
- mov ip, ip, lsr #8
- strh ip, [r1], #2
- mov pc, lr
-
-ENTRY(outsl)
- ioaddr r0, r0
- ands ip, r1, #3
- bne 2f
-
-1: ldr r3, [r1], #4
- str r3, [r0]
- subs r2, r2, #1
- bne 1b
- mov pc, lr
-
-2: bic r1, r1, #3
- cmp ip, #2
- ldr ip, [r1], #4
- mov ip, ip, lsr #16
- blt 4f
- bgt 5f
-
-3: ldr r3, [r1], #4
- orr ip, ip, r3, lsl #16
- str ip, [r0]
- mov ip, r3, lsr #16
- subs r2, r2, #1
- bne 3b
- mov pc, lr
-
-4: ldr r3, [r1], #4
- orr ip, ip, r3, lsl #8
- str ip, [r0]
- mov ip, r3, lsr #24
- subs r2, r2, #1
- bne 4b
- mov pc, lr
-
-5: ldr r3, [r1], #4
- orr ip, ip, r3, lsl #24
- str ip, [r0]
- mov ip, r3, lsr #8
- subs r2, r2, #1
- bne 5b
- mov pc, lr
-
- /* Nobody could say these are optimal, but not to worry. */
-
-ENTRY(outswb)
- mov r2, r2, lsr #1
-ENTRY(outsw)
- ioaddr r0, r0
-1: subs r2, r2, #1
- ldrgeh r3, [r1], #2
- strgeh r3, [r0]
- bgt 1b
- mov pc, lr
-
-ENTRY(inswb)
- mov r2, r2, lsr #1
-ENTRY(insw)
- stmfd sp!, {r4, r5, lr}
- ioaddr r0, r0
- @ + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17
- subs ip, r2, #8
- blo too_little
- @ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
- ands lr, r1, #3 @ check alignment
- beq 1f
-
- ldrh r3, [r0]
- strh r3, [r1], #2
- sub ip, ip, #1
- cmn ip, #8
- blo too_little
-
-1: ldrh r2, [r0]
- ldrh r3, [r0]
- orr r2, r2, r3, lsl #16
- ldrh r3, [r0]
- ldrh r4, [r0]
- orr r3, r3, r4, lsl #16
- ldrh r4, [r0]
- ldrh r5, [r0]
- orr r4, r4, r5, lsl #16
- ldrh r5, [r0]
- ldrh lr, [r0]
- orr r5, r5, lr, lsl #16
- stmia r1!, {r2, r3, r4, r5}
- subs ip, ip, #8
- @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 + 0 + 1
- bhs 1b
- @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 8 - 7
- cmn ip, #4
- ldrhsh r2, [r0] @ ... ... ... ... - 4 - 3 - 2 - 1 ... ...
- ldrhsh r3, [r0]
- orrhs r2, r2, r3, lsl #16
- ldrhsh r3, [r0]
- ldrhsh r4, [r0]
- orrhs r3, r3, r4, lsl #16
- stmhsia r1!, {r2, r3}
-
- tst ip, #2
- ldrneh r2, [r0] @ ... ... - 6 - 5 ... ... - 2 - 1 ... ...
- ldrneh r3, [r0]
- orrne r2, r2, r3, lsl #16
- strne r2, [r1], #4
-
- tst ip, #1
- ldrneh r2, [r0]
- strneh r2, [r1], #2
-
- ldmfd sp!, {r4, r5, pc}
-
-too_little: subs r2, r2, #1
- ldrgeh r3, [r0]
- strgeh r3, [r1], #2
- bgt too_little
-
- ldmfd sp!, {r4, r5, pc}
-
-
-ENTRY(insb)
- ioaddr r0, r0
-1: teq r2, #0
- ldrneb r3, [r0]
- strneb r3, [r1], #1
- subne r2, r2, #1
- bne 1b
- mov pc, lr
-
-
-ENTRY(outsb)
- ioaddr r0, r0
-1: teq r2, #0
- ldrneb r3, [r1], #1
- strneb r3, [r0]
- subne r2, r2, #1
- bne 1b
- mov pc, lr
diff --git a/arch/arm/lib/io-pcio.S b/arch/arm/lib/io-pcio.S
new file mode 100644
index 000000000..f57abfc10
--- /dev/null
+++ b/arch/arm/lib/io-pcio.S
@@ -0,0 +1,38 @@
+#include <linux/linkage.h>
+#include <asm/hardware.h>
+
+ .equ pcio_high, PCIO_BASE & 0xff000000
+ .equ pcio_low, PCIO_BASE & 0x00ffffff
+
+ .macro ioaddr, rd,rn
+ add \rd, \rn, #pcio_high
+ .if pcio_low
+ add \rd, \rd, #pcio_low
+ .endif
+ .endm
+
+ENTRY(insl)
+ ioaddr r0, r0
+ b __arch_readsl
+
+ENTRY(outsl)
+ ioaddr r0, r0
+ b __arch_writesl
+
+ /* Nobody could say these are optimal, but not to worry. */
+
+ENTRY(outsw)
+ ioaddr r0, r0
+ b __arch_writesw
+
+ENTRY(insw)
+ ioaddr r0, r0
+ b __arch_readsw
+
+ENTRY(insb)
+ ioaddr r0, r0
+ b __arch_readsb
+
+ENTRY(outsb)
+ ioaddr r0, r0
+ b __arch_writesb
diff --git a/arch/arm/lib/io-readsb.S b/arch/arm/lib/io-readsb.S
new file mode 100644
index 000000000..23cca8929
--- /dev/null
+++ b/arch/arm/lib/io-readsb.S
@@ -0,0 +1,111 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.insb_align: rsb ip, ip, #4
+ cmp ip, r2
+ movgt ip, r2
+ cmp ip, #2
+ ldrb r3, [r0]
+ strb r3, [r1], #1
+ ldrgeb r3, [r0]
+ strgeb r3, [r1], #1
+ ldrgtb r3, [r0]
+ strgtb r3, [r1], #1
+ subs r2, r2, ip
+ bne .insb_aligned
+
+ENTRY(__arch_readsb)
+ ands ip, r1, #3
+ bne .insb_align
+
+.insb_aligned: stmfd sp!, {r4 - r6, lr}
+
+ subs r2, r2, #16
+ bmi .insb_no_16
+
+.insb_16_lp: ldrb r3, [r0]
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #8
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #16
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #24
+ ldrb r4, [r0]
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #8
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #16
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #24
+ ldrb r5, [r0]
+ ldrb r6, [r0]
+ orr r5, r5, r6, lsl #8
+ ldrb r6, [r0]
+ orr r5, r5, r6, lsl #16
+ ldrb r6, [r0]
+ orr r5, r5, r6, lsl #24
+ ldrb r6, [r0]
+ ldrb ip, [r0]
+ orr r6, r6, ip, lsl #8
+ ldrb ip, [r0]
+ orr r6, r6, ip, lsl #16
+ ldrb ip, [r0]
+ orr r6, r6, ip, lsl #24
+ stmia r1!, {r3 - r6}
+ subs r2, r2, #16
+ bpl .insb_16_lp
+
+ tst r2, #15
+ LOADREGS(eqfd, sp!, {r4 - r6, pc})
+
+.insb_no_16: tst r2, #8
+ beq .insb_no_8
+
+ ldrb r3, [r0]
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #8
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #16
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #24
+ ldrb r4, [r0]
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #8
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #16
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #24
+ stmia r1!, {r3, r4}
+
+.insb_no_8: tst r2, #4
+ bne .insb_no_4
+
+ ldrb r3, [r0]
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #8
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #16
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #24
+ str r3, [r1], #4
+
+.insb_no_4: ands r2, r2, #3
+ LOADREGS(eqfd, sp!, {r4 - r6, pc})
+ cmp r2, #2
+ ldrb r3, [r0]
+ strb r3, [r1], #1
+ ldrgeb r3, [r0]
+ strgeb r3, [r1], #1
+ ldrgtb r3, [r0]
+ strgtb r3, [r1]
+ LOADREGS(fd, sp!, {r4 - r6, pc})
diff --git a/arch/arm/lib/io-readsl.S b/arch/arm/lib/io-readsl.S
new file mode 100644
index 000000000..530175485
--- /dev/null
+++ b/arch/arm/lib/io-readsl.S
@@ -0,0 +1,65 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+ENTRY(__arch_readsl)
+ ands ip, r1, #3
+ bne 2f
+
+1: ldr r3, [r0]
+ str r3, [r1], #4
+ subs r2, r2, #1
+ bne 1b
+ mov pc, lr
+
+2: cmp ip, #2
+ ldr ip, [r0]
+ blt 4f
+ bgt 6f
+
+ strh ip, [r1], #2
+ mov ip, ip, lsr #16
+3: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #16
+ strne ip, [r1], #4
+ movne ip, r3, lsr #16
+ bne 3b
+ strh ip, [r1], #2
+ mov pc, lr
+
+4: strb ip, [r1], #1
+ mov ip, ip, lsr #8
+ strh ip, [r1], #2
+ mov ip, ip, lsr #16
+5: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #8
+ strne ip, [r1], #4
+ movne ip, r3, lsr #24
+ bne 5b
+ strb ip, [r1], #1
+ mov pc, lr
+
+6: strb ip, [r1], #1
+ mov ip, ip, lsr #8
+7: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #24
+ strne ip, [r1], #4
+ movne ip, r3, lsr #8
+ bne 7b
+ strb ip, [r1], #1
+ mov ip, ip, lsr #8
+ strh ip, [r1], #2
+ mov pc, lr
+
diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S
new file mode 100644
index 000000000..65fb94e2f
--- /dev/null
+++ b/arch/arm/lib/io-readsw-armv3.S
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.insw_bad_alignment:
+ adr r0, .insw_bad_align_msg
+ mov r2, lr
+ b SYMBOL_NAME(panic)
+.insw_bad_align_msg:
+ .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
+ .align
+
+.insw_align: tst r1, #1
+ bne .insw_bad_alignment
+
+ ldr r3, [r0]
+ strb r3, [r1], #1
+ mov r3, r3, lsr #8
+ strb r3, [r1], #1
+
+ subs r2, r2, #1
+ RETINSTR(moveq, pc, lr)
+
+ENTRY(__arch_readsw)
+ tst r1, #3
+ bne .insw_align
+
+.insw_aligned: mov ip, #0xff
+ orr ip, ip, ip, lsl #8
+ stmfd sp!, {r4, r5, r6, lr}
+
+ subs r2, r2, #8
+ bmi .no_insw_8
+
+.insw_8_lp: ldr r3, [r0]
+ and r3, r3, ip
+ ldr r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ ldr r4, [r0]
+ and r4, r4, ip
+ ldr r5, [r0]
+ orr r4, r4, r5, lsl #16
+
+ ldr r5, [r0]
+ and r5, r5, ip
+ ldr r6, [r0]
+ orr r5, r5, r6, lsl #16
+
+ ldr r6, [r0]
+ and r6, r6, ip
+ ldr lr, [r0]
+ orr r6, r6, lr, lsl #16
+
+ stmia r1!, {r3 - r6}
+ subs r2, r2, #8
+ bpl .insw_8_lp
+ tst r2, #7
+ LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
+
+.no_insw_8: tst r2, #4
+ beq .no_insw_4
+
+ ldr r3, [r0]
+ and r3, r3, ip
+ ldr r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ ldr r4, [r0]
+ and r4, r4, ip
+ ldr r5, [r0]
+ orr r4, r4, r5, lsl #16
+
+ stmia r1!, {r3, r4}
+
+.no_insw_4: tst r2, #2
+ beq .no_insw_2
+
+ ldr r3, [r0]
+ and r3, r3, ip
+ ldr r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ str r3, [r1], #4
+
+.no_insw_2: tst r2, #1
+ ldrne r3, [r0]
+ strneb r3, [r1], #1
+ movne r3, r3, lsr #8
+ strneb r3, [r1]
+ LOADREGS(fd, sp!, {r4, r5, r6, pc})
+
+
diff --git a/arch/arm/lib/io-readsw-armv4.S b/arch/arm/lib/io-readsw-armv4.S
new file mode 100644
index 000000000..6f1750a49
--- /dev/null
+++ b/arch/arm/lib/io-readsw-armv4.S
@@ -0,0 +1,87 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.insw_bad_alignment:
+ adr r0, .insw_bad_align_msg
+ mov r2, lr
+ b SYMBOL_NAME(panic)
+.insw_bad_align_msg:
+ .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
+ .align
+
+.insw_align: tst r1, #1
+ bne .insw_bad_alignment
+
+ ldrh r3, [r0]
+ strh r3, [r1], #2
+
+ subs r2, r2, #1
+ RETINSTR(moveq, pc, lr)
+
+ENTRY(__arch_readsw)
+ tst r1, #3
+ bne .insw_align
+
+ stmfd sp!, {r4, r5, lr}
+
+ subs r2, r2, #8
+ bmi .no_insw_8
+
+.insw_8_lp: ldrh r3, [r0]
+ ldrh r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ ldrh r4, [r0]
+ ldrh r5, [r0]
+ orr r4, r4, r5, lsl #16
+
+ ldrh r5, [r0]
+ ldrh r6, [r0]
+ orr r5, r5, r6, lsl #16
+
+ ldrh ip, [r0]
+ ldrh lr, [r0]
+ orr ip, ip, lr, lsl #16
+
+ stmia r1!, {r3 - r5, ip}
+ subs r2, r2, #8
+ bpl .insw_8_lp
+ tst r2, #7
+ LOADREGS(eqfd, sp!, {r4, r5, pc})
+
+.no_insw_8: tst r2, #4
+ beq .no_insw_4
+
+ ldrh r3, [r0]
+ ldrh r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ ldrh r4, [r0]
+ ldrh ip, [r0]
+ orr r4, r4, ip, lsl #16
+
+ stmia r1!, {r3, r4}
+
+.no_insw_4: tst r2, #2
+ beq .no_insw_2
+
+ ldrh r3, [r0]
+ ldrh ip, [r0]
+ orr r3, r3, ip, lsl #16
+
+ str r3, [r1], #4
+
+.no_insw_2: tst r2, #1
+ ldrneh r3, [r0]
+ strneh r3, [r1]
+ LOADREGS(fd, sp!, {r4, r5, pc})
diff --git a/arch/arm/lib/io-writesb.S b/arch/arm/lib/io-writesb.S
new file mode 100644
index 000000000..b919fdaad
--- /dev/null
+++ b/arch/arm/lib/io-writesb.S
@@ -0,0 +1,115 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.outsb_align: rsb ip, ip, #4
+ cmp ip, r2
+ mov ip, r2
+ cmp ip, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0]
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0]
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0]
+ subs r2, r2, ip
+ bne .outsb_aligned
+
+ENTRY(__arch_writesb)
+ ands ip, r1, #3
+ bne .outsb_align
+
+.outsb_aligned: stmfd sp!, {r4 - r6, lr}
+
+ subs r2, r2, #16
+ bmi .outsb_no_16
+
+.outsb_16_lp: ldmia r1!, {r3 - r6}
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+
+ strb r5, [r0]
+ mov r5, r5, lsr #8
+ strb r5, [r0]
+ mov r5, r5, lsr #8
+ strb r5, [r0]
+ mov r5, r5, lsr #8
+ strb r5, [r0]
+
+ strb r6, [r0]
+ mov r6, r6, lsr #8
+ strb r6, [r0]
+ mov r6, r6, lsr #8
+ strb r6, [r0]
+ mov r6, r6, lsr #8
+ strb r6, [r0]
+ subs r2, r2, #16
+ bpl .outsb_16_lp
+
+ tst r2, #15
+ LOADREGS(eqfd, sp!, {r4 - r6, pc})
+
+.outsb_no_16: tst r2, #8
+ beq .outsb_no_8
+
+ ldmia r1, {r3, r4}
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+
+.outsb_no_8: tst r2, #4
+ bne .outsb_no_4
+
+ ldr r3, [r1], #4
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+
+.outsb_no_4: ands r2, r2, #3
+ LOADREGS(eqfd, sp!, {r4 - r6, pc})
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0]
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0]
+ ldrgtb r3, [r1]
+ strgtb r3, [r0]
+ LOADREGS(fd, sp!, {r4 - r6, pc})
diff --git a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S
new file mode 100644
index 000000000..ccda08c39
--- /dev/null
+++ b/arch/arm/lib/io-writesl.S
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+ENTRY(__arch_writesl)
+ ands ip, r1, #3
+ bne 2f
+
+1: ldr r3, [r1], #4
+ str r3, [r0]
+ subs r2, r2, #1
+ bne 1b
+ mov pc, lr
+
+2: bic r1, r1, #3
+ cmp ip, #2
+ ldr ip, [r1], #4
+ mov ip, ip, lsr #16
+ blt 4f
+ bgt 5f
+
+3: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #16
+ str ip, [r0]
+ mov ip, r3, lsr #16
+ subs r2, r2, #1
+ bne 3b
+ mov pc, lr
+
+4: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #8
+ str ip, [r0]
+ mov ip, r3, lsr #24
+ subs r2, r2, #1
+ bne 4b
+ mov pc, lr
+
+5: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #24
+ str ip, [r0]
+ mov ip, r3, lsr #8
+ subs r2, r2, #1
+ bne 5b
+ mov pc, lr
+
+
diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S
new file mode 100644
index 000000000..29c94cc3d
--- /dev/null
+++ b/arch/arm/lib/io-writesw-armv3.S
@@ -0,0 +1,125 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.outsw_bad_alignment:
+ adr r0, .outsw_bad_align_msg
+ mov r2, lr
+ b SYMBOL_NAME(panic)
+.outsw_bad_align_msg:
+ .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
+ .align
+
+.outsw_align: tst r1, #1
+ bne .outsw_bad_alignment
+
+ add r1, r1, #2
+
+ ldr r3, [r1, #-4]
+ mov r3, r3, lsr #16
+ orr r3, r3, r3, lsl #16
+ str r3, [r0]
+ subs r2, r2, #1
+ RETINSTR(moveq, pc, lr)
+
+ENTRY(__arch_writesw)
+ tst r1, #3
+ bne .outsw_align
+
+.outsw_aligned: stmfd sp!, {r4, r5, r6, lr}
+
+ subs r2, r2, #8
+ bmi .no_outsw_8
+.outsw_8_lp: ldmia r1!, {r3, r4, r5, r6}
+
+ mov ip, r3, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r3, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ mov ip, r4, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r4, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ mov ip, r5, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r5, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ mov ip, r6, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r6, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ subs r2, r2, #8
+ bpl .outsw_8_lp
+ tst r2, #7
+ LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
+
+.no_outsw_8: tst r2, #4
+ beq .no_outsw_4
+
+ ldmia r1!, {r3, r4}
+
+ mov ip, r3, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r3, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ mov ip, r4, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r4, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+.no_outsw_4: tst r2, #2
+ beq .no_outsw_2
+
+ ldr r3, [r1], #4
+
+ mov ip, r3, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r3, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+.no_outsw_2: tst r2, #1
+
+ ldrne r3, [r1]
+
+ movne ip, r3, lsl #16
+ orrne ip, ip, ip, lsr #16
+ strne ip, [r0]
+
+ LOADREGS(fd, sp!, {r4, r5, r6, pc})
+
+
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
new file mode 100644
index 000000000..0f96d1325
--- /dev/null
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -0,0 +1,79 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.outsw_bad_alignment:
+ adr r0, .outsw_bad_align_msg
+ mov r2, lr
+ b SYMBOL_NAME(panic)
+.outsw_bad_align_msg:
+ .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
+ .align
+
+.outsw_align: tst r1, #1
+ bne .outsw_bad_alignment
+
+ ldrh r3, [r1], #2
+ strh r3, [r0]
+
+ subs r2, r2, #1
+ RETINSTR(moveq, pc, lr)
+
+ENTRY(__arch_writesw)
+ tst r1, #3
+ bne .outsw_align
+
+ subs r2, r2, #8
+ bmi .no_outsw_8
+
+ stmfd sp!, {r4, r5, lr}
+
+.outsw_8_lp: ldmia r1!, {r3, r4, r5, ip}
+
+ strh r3, [r0]
+ mov r3, r3, lsr #16
+ strh r3, [r0]
+ strh r4, [r0]
+ mov r4, r4, lsr #16
+ strh r4, [r0]
+ strh r5, [r0]
+ mov r5, r5, lsr #16
+ strh r5, [r0]
+ strh ip, [r0]
+ mov ip, ip, lsr #16
+ strh ip, [r0]
+
+ subs r2, r2, #8
+ bpl .outsw_8_lp
+ ldmfd sp!, {r4, r5, lr}
+ tst r2, #7
+ RETINSTR(moveq, pc, lr)
+
+.no_outsw_8: tst r2, #4
+ ldmneia r1!, {r3, ip}
+ strneh r3, [r0]
+ movne r3, r3, lsr #16
+ strneh r3, [r0]
+ strneh ip, [r0]
+ movne ip, ip, lsr #16
+ strneh ip, [r0]
+ tst r2, #2
+ ldrne r3, [r1], #4
+ strneh r3, [r0]
+ movne r3, r3, lsr #16
+ strneh r3, [r0]
+ tst r2, #1
+ ldrneh r3, [r1]
+ strneh r3, [r0]
+ RETINSTR(mov, pc, lr)
+
+
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index 4b47b6e47..1a7a790cc 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -65,9 +65,9 @@ static inline void wb977_ww(int reg, int val)
*/
spinlock_t gpio_lock = SPIN_LOCK_UNLOCKED;
-static unsigned int current_gpio_op = 0;
-static unsigned int current_gpio_io = 0;
-static unsigned int current_cpld = 0;
+static unsigned int current_gpio_op;
+static unsigned int current_gpio_io;
+static unsigned int current_cpld;
void gpio_modify_op(int mask, int set)
{
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index 0e198ab8a..1cbdd7790 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -126,6 +126,39 @@ out:
return fault;
}
+static int __do_vmalloc_fault(unsigned long addr, struct mm_struct *mm)
+{
+ /* Synchronise this task's top level page-table
+ * with the 'reference' page table.
+ */
+ int offset = __pgd_offset(addr);
+ pgd_t *pgd, *pgd_k;
+ pmd_t *pmd, *pmd_k;
+
+ pgd_k = init_mm.pgd + offset;
+ if (!pgd_present(*pgd_k))
+ goto bad_area;
+
+ pgd = mm->pgd + offset;
+#if 0 /* note that we are two-level */
+ if (!pgd_present(*pgd))
+ set_pgd(pgd, *pgd_k);
+#endif
+
+ pmd_k = pmd_offset(pgd_k, addr);
+ if (pmd_none(*pmd_k))
+ goto bad_area;
+
+ pmd = pmd_offset(pgd, addr);
+ if (!pmd_none(*pmd))
+ goto bad_area;
+ set_pmd(pmd, *pmd_k);
+ return 1;
+
+bad_area:
+ return -2;
+}
+
static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
{
struct task_struct *tsk;
@@ -137,6 +170,18 @@ static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
mm = tsk->mm;
/*
+ * We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ */
+ if (addr >= TASK_SIZE)
+ goto vmalloc_fault;
+
+ /*
* If we're in an interrupt or have no user
* context, we must not take the fault..
*/
@@ -147,6 +192,7 @@ static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
fault = __do_page_fault(mm, addr, mode, tsk);
up(&mm->mmap_sem);
+ret:
/*
* Handle the "normal" case first
*/
@@ -240,4 +286,8 @@ no_context:
do_exit(SIGKILL);
return 0;
+
+vmalloc_fault:
+ fault = __do_vmalloc_fault(addr, mm);
+ goto ret;
}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index ea833c58d..bfa085a52 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -377,34 +377,48 @@ static int __init check_initrd(struct meminfo *mi)
/*
* Reserve the various regions of node 0
*/
-static inline void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages)
+static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages)
{
+ pg_data_t *pgdat = NODE_DATA(0);
+
/*
* Register the kernel text and data with bootmem.
* Note that this can only be in node 0.
*/
- reserve_bootmem_node(NODE_DATA(0), __pa(&_stext), &_end - &_stext);
+ reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
#ifdef CONFIG_CPU_32
/*
* Reserve the page tables. These are already in use,
* and can only be in node 0.
*/
- reserve_bootmem_node(NODE_DATA(0), __pa(swapper_pg_dir),
+ reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
PTRS_PER_PGD * sizeof(void *));
-#else
- /*
- * Stop this memory from being grabbed - its special DMA
- * memory that is required for the screen.
- */
- reserve_bootmem_node(NODE_DATA(0), 0x02000000, 0x00080000);
#endif
/*
* And don't forget to reserve the allocator bitmap,
* which will be freed later.
*/
- reserve_bootmem_node(NODE_DATA(0), bootmap_pfn << PAGE_SHIFT,
+ reserve_bootmem_node(pgdat, bootmap_pfn << PAGE_SHIFT,
bootmap_pages << PAGE_SHIFT);
+
+ /*
+ * Hmm... This should go elsewhere, but we really really
+ * need to stop things allocating the low memory; we need
+ * a better implementation of GFP_DMA which does not assume
+ * that DMA-able memory starts at zero.
+ */
+ if (machine_is_integrator())
+ reserve_bootmem_node(pgdat, 0, __pa(swapper_pg_dir));
+ /*
+ * These should likewise go elsewhere. They pre-reserve
+ * the screen memory region at the start of main system
+ * memory.
+ */
+ if (machine_is_archimedes() || machine_is_a5k())
+ reserve_bootmem_node(pgdat, 0x02000000, 0x00080000);
+ if (machine_is_p720t())
+ reserve_bootmem_node(pgdat, 0xc0000000, 0x00014000);
}
/*
@@ -412,11 +426,12 @@ static inline void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot
*/
static inline void free_bootmem_node_bank(int node, struct meminfo *mi)
{
+ pg_data_t *pgdat = NODE_DATA(node);
int bank;
for (bank = 0; bank < mi->nr_banks; bank++)
if (mi->bank[bank].node == node)
- free_bootmem_node(NODE_DATA(node), mi->bank[bank].start,
+ free_bootmem_node(pgdat, mi->bank[bank].start,
mi->bank[bank].size);
}
@@ -632,9 +647,11 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s)
void free_initmem(void)
{
- free_area((unsigned long)(&__init_begin),
- (unsigned long)(&__init_end),
- "init");
+ if (!machine_is_integrator()) {
+ free_area((unsigned long)(&__init_begin),
+ (unsigned long)(&__init_end),
+ "init");
+ }
}
#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 2ace55d47..d96fcbccb 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -361,6 +361,7 @@ void __init memtable_init(struct meminfo *mi)
p ++;
}
+#ifdef FLUSH_BASE
p->physical = FLUSH_BASE_PHYS;
p->virtual = FLUSH_BASE;
p->length = PGDIR_SIZE;
@@ -371,6 +372,7 @@ void __init memtable_init(struct meminfo *mi)
p->bufferable = 1;
p ++;
+#endif
#ifdef FLUSH_BASE_MINICACHE
p->physical = FLUSH_BASE_PHYS + PGDIR_SIZE;
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 13620ad5f..e6fc86bd1 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -139,7 +139,7 @@ Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit
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, #15
+ and r3, r3, #255
mov pc, lr
ENTRY(cpu_arm720_data_abort)
@@ -155,7 +155,7 @@ ENTRY(cpu_arm720_data_abort)
b Ldata_unknown
b Ldata_unknown
b Ldata_lateldrpostconst @ ldr rd, [rn], #m
- b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal
+ 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>
@@ -177,25 +177,14 @@ Ldata_lateldrhpre:
tst r4, #1 << 21 @ check writeback bit
beq Ldata_simple
Ldata_lateldrhpost:
- tst r4, #1 << 22 @ check if register or immediate offset
- beq Ldata_lateldrhpostreg
-Ldata_lateldrhpostconst:
- and r2, r4, #0xf @ load and clear low nibble of const offset
- and r5, r4, #0xf00 @ load and clear high nibble of const offset
- orrs r2, r2, r5, lsr #4 @ create offset
- beq Ldata_simple @ don't have to do anything if zero
- and r5, r4, #0xf << 16 @ get Rn
- ldr r0, [sp, r5, lsr #14]
+ 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, lsr #20
- addeq r7, r0, r2, lsr #20
- b Ldata_saver7
-Ldata_lateldrhpostreg:
- and r5, r4, #0xf
- ldr r2, [sp, r5, lsl #2] @ get Rm
- and r5, r4, #0xf << 16
- ldr r0, [sp, r5, lsr #14] @ get Rn
- tst r4, #1 << 23
subne r7, r0, r2
addeq r7, r0, r2
b Ldata_saver7
@@ -385,7 +374,7 @@ ENTRY(cpu_arm720_reset)
cpu_armvlsi_name:
- .asciz "ARM/VLSI"
+ .asciz "ARM"
cpu_arm720_name:
.asciz "ARM720T"
.align
@@ -471,8 +460,8 @@ cpu_elf_name: .asciz "v4"
__arm720_proc_info:
.long 0x41807200 @ cpu_val
.long 0xffffff00 @ cpu_mask
- .long 0x00000c0e @ __cpu_mmu_flags
- b __arm720_setup @ --cpu_flush
+ .long 0x00000c1e @ section_mmu_flags
+ b __arm720_setup @ cpu_flush
.long cpu_arch_name @ arch_name
.long cpu_elf_name @ elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT @ elf_hwcap
diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c
index 0415f31e0..5e5d4fdcf 100644
--- a/arch/arm/nwfpe/double_cpdo.c
+++ b/arch/arm/nwfpe/double_cpdo.c
@@ -44,7 +44,7 @@ unsigned int DoubleCPDO(const unsigned int opcode)
float64 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
- //fp_printk("DoubleCPDO(0x%08x)\n",opcode);
+ //printk("DoubleCPDO(0x%08x)\n",opcode);
Fm = getFm(opcode);
if (CONSTANT_FM(opcode))
@@ -65,7 +65,7 @@ unsigned int DoubleCPDO(const unsigned int opcode)
case typeExtended:
// !! patb
- //fp_printk("not implemented! why not?\n");
+ //printk("not implemented! why not?\n");
//!! ScottB
// should never get here, if extended involved
// then other operand should be promoted then
diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c
index 810f57102..762b1a0ef 100644
--- a/arch/arm/nwfpe/extended_cpdo.c
+++ b/arch/arm/nwfpe/extended_cpdo.c
@@ -42,7 +42,7 @@ unsigned int ExtendedCPDO(const unsigned int opcode)
floatx80 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
- //fp_printk("ExtendedCPDO(0x%08x)\n",opcode);
+ //printk("ExtendedCPDO(0x%08x)\n",opcode);
Fm = getFm(opcode);
if (CONSTANT_FM(opcode))
diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c
index fd39a59f7..b2eaf1aad 100644
--- a/arch/arm/nwfpe/fpa11_cpdo.c
+++ b/arch/arm/nwfpe/fpa11_cpdo.c
@@ -30,7 +30,7 @@ unsigned int EmulateCPDO(const unsigned int opcode)
{
unsigned int Fd, nType, nDest, nRc = 1;
- //fp_printk("EmulateCPDO(0x%08x)\n",opcode);
+ //printk("EmulateCPDO(0x%08x)\n",opcode);
/* Get the destination size. If not valid let Linux perform
an invalid instruction trap. */
diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
index 0bad18769..d6a7bdc4a 100644
--- a/arch/arm/nwfpe/fpa11_cpdt.c
+++ b/arch/arm/nwfpe/fpa11_cpdt.c
@@ -189,7 +189,7 @@ unsigned int PerformLDF(const unsigned int opcode)
unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
write_back = WRITE_BACK(opcode);
- //fp_printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
+ //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
pBase = (unsigned int*)readRegister(getRn(opcode));
if (REG_PC == getRn(opcode))
@@ -223,7 +223,7 @@ unsigned int PerformSTF(const unsigned int opcode)
unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
write_back = WRITE_BACK(opcode);
- //fp_printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
+ //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
SetRoundingMode(ROUND_TO_NEAREST);
pBase = (unsigned int*)readRegister(getRn(opcode));
@@ -322,7 +322,7 @@ unsigned int EmulateCPDT(const unsigned int opcode)
{
unsigned int nRc = 0;
- //fp_printk("EmulateCPDT(0x%08x)\n",opcode);
+ //printk("EmulateCPDT(0x%08x)\n",opcode);
if (LDF_OP(opcode))
{
diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c
index d479ee932..c17c69465 100644
--- a/arch/arm/nwfpe/fpa11_cprt.c
+++ b/arch/arm/nwfpe/fpa11_cprt.c
@@ -44,7 +44,7 @@ unsigned int EmulateCPRT(const unsigned int opcode)
{
unsigned int nRc = 1;
- //fp_printk("EmulateCPRT(0x%08x)\n",opcode);
+ //printk("EmulateCPRT(0x%08x)\n",opcode);
if (opcode & 0x800000)
{
@@ -188,7 +188,7 @@ static unsigned int PerformComparison(const unsigned int opcode)
int n_flag = opcode & 0x200000; /* 1 if CNxx */
unsigned int flags = 0;
- //fp_printk("PerformComparison(0x%08x)\n",opcode);
+ //printk("PerformComparison(0x%08x)\n",opcode);
Fn = getFn(opcode);
Fm = getFm(opcode);
@@ -201,21 +201,21 @@ static unsigned int PerformComparison(const unsigned int opcode)
switch (fpa11->fType[Fn])
{
case typeSingle:
- //fp_printk("single.\n");
+ //printk("single.\n");
if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
goto unordered;
rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
break;
case typeDouble:
- //fp_printk("double.\n");
+ //printk("double.\n");
if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
goto unordered;
rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
break;
case typeExtended:
- //fp_printk("extended.\n");
+ //printk("extended.\n");
if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
goto unordered;
rFn = fpa11->fpreg[Fn].fExtended;
@@ -226,32 +226,32 @@ static unsigned int PerformComparison(const unsigned int opcode)
if (CONSTANT_FM(opcode))
{
- //fp_printk("Fm is a constant: #%d.\n",Fm);
+ //printk("Fm is a constant: #%d.\n",Fm);
rFm = getExtendedConstant(Fm);
if (floatx80_is_nan(rFm))
goto unordered;
}
else
{
- //fp_printk("Fm = r%d which contains a ",Fm);
+ //printk("Fm = r%d which contains a ",Fm);
switch (fpa11->fType[Fm])
{
case typeSingle:
- //fp_printk("single.\n");
+ //printk("single.\n");
if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
goto unordered;
rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
break;
case typeDouble:
- //fp_printk("double.\n");
+ //printk("double.\n");
if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
goto unordered;
rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
break;
case typeExtended:
- //fp_printk("extended.\n");
+ //printk("extended.\n");
if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
goto unordered;
rFm = fpa11->fpreg[Fm].fExtended;
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index 9d4f1570d..24fa2775f 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -46,7 +46,6 @@ extern FPA11 *fpa11;
typedef struct task_struct* PTASK;
#ifdef MODULE
-int fp_printk(const char *,...);
void fp_send_sig(unsigned long sig, PTASK p, int priv);
#if LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
@@ -54,7 +53,6 @@ MODULE_DESCRIPTION("NWFPE floating point emulator");
#endif
#else
-#define fp_printk printk
#define fp_send_sig send_sig
#define kern_fp_enter fp_enter
#endif
@@ -74,23 +72,14 @@ extern void nwfpe_enter(void);
/* Address of user registers on the kernel stack. */
unsigned int *userRegisters;
-void __init fpe_version(void)
-{
- static const char szTitle[] = "<4>NetWinder Floating Point Emulator ";
- static const char szVersion[] = "V0.95 ";
- static const char szCopyright[] = "(c) 1998-1999 Rebel.com\n";
- fp_printk(szTitle);
- fp_printk(szVersion);
- fp_printk(szCopyright);
-}
-
int __init fpe_init(void)
{
if (sizeof(FPA11) > sizeof(union fp_state))
printk(KERN_ERR "nwfpe: bad structure size\n");
else {
/* Display title, version and copyright information. */
- fpe_version();
+ printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 "
+ "(c) 1998-1999 Rebel.com\n");
/* Save pointer to the old FP handler and then patch ourselves in */
orig_fp_enter = kern_fp_enter;
diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c
index a7fc76cc8..a6e000011 100644
--- a/arch/arm/nwfpe/softfloat.c
+++ b/arch/arm/nwfpe/softfloat.c
@@ -39,7 +39,7 @@ and exception flags.
*/
int8 float_rounding_mode = float_round_nearest_even;
int8 floatx80_rounding_precision = 80;
-int8 float_exception_flags = 0;
+int8 float_exception_flags;
/*
-------------------------------------------------------------------------------
@@ -418,9 +418,8 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
|| ( ( zExp == 0x7FD )
&& ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
) {
- //register int lr;
- //__asm__("mov %0, lr" :: "g" (lr));
- //fp_printk("roundAndPackFloat64 called from 0x%08x\n",lr);
+ //register int lr = __builtin_return_address(0);
+ //printk("roundAndPackFloat64 called from 0x%08x\n",lr);
float_raise( float_flag_overflow | float_flag_inexact );
return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
}
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index f3d1fb0b1..ff7ccec77 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1,7 +1,10 @@
# Database of machine macros and numbers
#
-# To add an entry into this database, please see
-# Documentation/arm/README
+# Please do not send patches to this file; it is automatically generated!
+# To add an entry into this database, please see Documentation/arm/README,
+# or contact rmk@arm.linux.org.uk
+#
+# Last update: Mon Nov 20 22:59:11 2000
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -14,7 +17,7 @@ cats ARCH_CATS CATS 6
tbox ARCH_TBOX TBOX 7
co285 ARCH_CO285 CO285 8
clps7110 ARCH_CLPS7110 CLPS7110 9
-arc ARCH_ARC ARCHIMEDES 10
+archimedes ARCH_ARC ARCHIMEDES 10
a5k ARCH_A5K A5K 11
etoile ARCH_ETOILE ETOILE 12
lacie_nas ARCH_LACIE_NAS LACIE_NAS 13
@@ -28,7 +31,7 @@ pleb SA1100_PLEB PLEB 20
integrator ARCH_INTEGRATOR INTEGRATOR 21
bitsy SA1100_BITSY BITSY 22
ixp1200 ARCH_IXP1200 IXP1200 23
-thinclient SA1100_THINCLIENT THINCLIENT 24
+p720t ARCH_P720T P720T 24
assabet SA1100_ASSABET ASSABET 25
victor SA1100_VICTOR VICTOR 26
lart SA1100_LART LART 27
@@ -42,8 +45,16 @@ extenex1 SA1100_EXTENEX1 EXTENEX1 34
sherman SA1100_SHERMAN SHERMAN 35
accelent_sa SA1100_ACCELENT ACCELENT_SA 36
accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37
+netport SA1100_NETPORT NETPORT 38
+pangolin SA1100_PANGOLIN PANGOLIN 39
+yopy SA1100_YOPY YOPY 40
+sa1100 SA1100_SA1100 SA1100 41
+huw_webpanel ARCH_HUW_WEBPANEL HUW_WEBPANEL 42
+spotme ARCH_SPOTME SPOTME 43
+freebird ARCH_FREEBIRD FREEBIRD 44
+ti925 ARCH_TI925 TI925 45
+riscstation ARCH_RISCSTATION RISCSTATION 46
+cavy SA1100_CAVY CAVY 47
# The following are unallocated
empeg SA1100_EMPEG EMPEG
-tifon SA1100_TIFON TIFON
-penny SA1100_PENNY PENNY
diff --git a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
index 5353e7f8f..0c0e720aa 100644
--- a/arch/arm/vmlinux-armo.lds.in
+++ b/arch/arm/vmlinux-armo.lds.in
@@ -9,6 +9,7 @@ SECTIONS
. = TEXTADDR;
.init : {
+ _stext = .;
__init_begin = .; /* Init code and data */
*(.text.init)
__proc_info_begin = .;
diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
index b54f2bd92..b0398852d 100644
--- a/arch/arm/vmlinux-armv.lds.in
+++ b/arch/arm/vmlinux-armv.lds.in
@@ -8,6 +8,7 @@ SECTIONS
{
. = TEXTADDR;
.init : { /* Init code and data */
+ _stext = .;
__init_begin = .;
*(.text.init)
__proc_info_begin = .;
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 0da4e866e..c52b170ec 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -825,10 +825,18 @@ bootsect_panic_mess:
#
# Some machines have delusions that the keyboard buffer is always full
# with no keyboard attached...
+#
+# If there is no keyboard controller, we will usually get 0xff
+# to all the reads. With each IO taking a microsecond and
+# a timeout of 100,000 iterations, this can take about half a
+# second ("delay" == outb to port 0x80). That should be ok,
+# and should also be plenty of time for a real keyboard controller
+# to empty.
+#
empty_8042:
pushl %ecx
- movl $0x00FFFFFF, %ecx
+ movl $100000, %ecx
empty_8042_loop:
decl %ecx
@@ -867,7 +875,7 @@ gettime:
# Delay is needed after doing I/O
delay:
- jmp .+2 # jmp $+2
+ outb %al,$0x80
ret
# Descriptor tables
diff --git a/arch/i386/config.in b/arch/i386/config.in
index d6c63a8b8..87fc106f8 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -140,7 +140,7 @@ if [ "$CONFIG_MWINCHIP3D" = "y" ]; then
fi
tristate 'Toshiba Laptop support' CONFIG_TOSHIBA
-tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
+tristate '/dev/cpu/microcode - Intel IA32 CPU microcode support' CONFIG_MICROCODE
tristate '/dev/cpu/*/msr - Model-specific register support' CONFIG_X86_MSR
tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 9f8625c6e..bdcf8cf6b 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -649,20 +649,15 @@ CONFIG_USB_UHCI_ALT=y
# CONFIG_USB_OHCI is not set
#
-# USB Devices
+# USB Device Class drivers
#
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SCANNER is not set
# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_BLUETOOTH is not set
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_USS720 is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
# USB Human Interface Devices (HID)
@@ -673,6 +668,44 @@ CONFIG_USB_STORAGE=y
#
#
+# 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
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_PLUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_NET1080 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB misc drivers
+#
+# CONFIG_USB_RIO500 is not set
+
+#
# Kernel hacking
#
# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index fc54896f8..4179c8f13 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -220,66 +220,19 @@ void __init setup_local_APIC (void)
BUG();
/*
- * Set up LVT0, LVT1:
- *
- * set up through-local-APIC on the BP's LINT0. This is not
- * strictly necessery in pure symmetric-IO mode, but sometimes
- * we delegate interrupts to the 8259A.
- */
- /*
- * TODO: set up through-local-APIC from through-I/O-APIC? --macro
- */
- value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
- if (!smp_processor_id() && (pic_mode || !value)) {
- value = APIC_DM_EXTINT;
- printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
- } else {
- value = APIC_DM_EXTINT | APIC_LVT_MASKED;
- printk("masked ExtINT on CPU#%d\n", smp_processor_id());
- }
- apic_write_around(APIC_LVT0, value);
-
- /*
- * only the BP should see the LINT1 NMI signal, obviously.
+ * Intel recommends to set DFR, LDR and TPR before enabling
+ * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
+ * document number 292116). So here it goes...
*/
- if (!smp_processor_id())
- value = APIC_DM_NMI;
- else
- value = APIC_DM_NMI | APIC_LVT_MASKED;
- if (!APIC_INTEGRATED(ver)) /* 82489DX */
- value |= APIC_LVT_LEVEL_TRIGGER;
- apic_write_around(APIC_LVT1, value);
-
- if (APIC_INTEGRATED(ver)) { /* !82489DX */
- maxlvt = get_maxlvt();
- if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
- apic_write(APIC_ESR, 0);
- value = apic_read(APIC_ESR);
- printk("ESR value before enabling vector: %08lx\n", value);
-
- value = ERROR_APIC_VECTOR; // enables sending errors
- apic_write_around(APIC_LVTERR, value);
- /*
- * spec says clear errors after enabling vector.
- */
- if (maxlvt > 3)
- apic_write(APIC_ESR, 0);
- value = apic_read(APIC_ESR);
- printk("ESR value after enabling vector: %08lx\n", value);
- } else
- printk("No ESR for 82489DX.\n");
/*
- * Set Task Priority to 'accept all'. We never change this
- * later on.
+ * Put the APIC into flat delivery mode.
+ * Must be "all ones" explicitly for 82489DX.
*/
- value = apic_read(APIC_TASKPRI);
- value &= ~APIC_TPRI_MASK;
- apic_write_around(APIC_TASKPRI, value);
+ apic_write_around(APIC_DFR, 0xffffffff);
/*
- * Set up the logical destination ID and put the
- * APIC into flat delivery mode.
+ * Set up the logical destination ID.
*/
value = apic_read(APIC_LDR);
value &= ~APIC_LDR_MASK;
@@ -287,9 +240,12 @@ void __init setup_local_APIC (void)
apic_write_around(APIC_LDR, value);
/*
- * Must be "all ones" explicitly for 82489DX.
+ * Set Task Priority to 'accept all'. We never change this
+ * later on.
*/
- apic_write_around(APIC_DFR, 0xffffffff);
+ value = apic_read(APIC_TASKPRI);
+ value &= ~APIC_TPRI_MASK;
+ apic_write_around(APIC_TASKPRI, value);
/*
* Now that we are all set up, enable the APIC
@@ -326,6 +282,56 @@ void __init setup_local_APIC (void)
*/
value |= SPURIOUS_APIC_VECTOR;
apic_write_around(APIC_SPIV, value);
+
+ /*
+ * Set up LVT0, LVT1:
+ *
+ * set up through-local-APIC on the BP's LINT0. This is not
+ * strictly necessery in pure symmetric-IO mode, but sometimes
+ * we delegate interrupts to the 8259A.
+ */
+ /*
+ * TODO: set up through-local-APIC from through-I/O-APIC? --macro
+ */
+ value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
+ if (!smp_processor_id() && (pic_mode || !value)) {
+ value = APIC_DM_EXTINT;
+ printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
+ } else {
+ value = APIC_DM_EXTINT | APIC_LVT_MASKED;
+ printk("masked ExtINT on CPU#%d\n", smp_processor_id());
+ }
+ apic_write_around(APIC_LVT0, value);
+
+ /*
+ * only the BP should see the LINT1 NMI signal, obviously.
+ */
+ if (!smp_processor_id())
+ value = APIC_DM_NMI;
+ else
+ value = APIC_DM_NMI | APIC_LVT_MASKED;
+ if (!APIC_INTEGRATED(ver)) /* 82489DX */
+ value |= APIC_LVT_LEVEL_TRIGGER;
+ apic_write_around(APIC_LVT1, value);
+
+ if (APIC_INTEGRATED(ver)) { /* !82489DX */
+ maxlvt = get_maxlvt();
+ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
+ apic_write(APIC_ESR, 0);
+ value = apic_read(APIC_ESR);
+ printk("ESR value before enabling vector: %08lx\n", value);
+
+ value = ERROR_APIC_VECTOR; // enables sending errors
+ apic_write_around(APIC_LVTERR, value);
+ /*
+ * spec says clear errors after enabling vector.
+ */
+ if (maxlvt > 3)
+ apic_write(APIC_ESR, 0);
+ value = apic_read(APIC_ESR);
+ printk("ESR value after enabling vector: %08lx\n", value);
+ } else
+ printk("No ESR for 82489DX.\n");
}
void __init init_apic_mappings(void)
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index dc47528cd..9703e3304 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -37,6 +37,7 @@
* Nov 1999, Version 1.11
* Jan 2000, Version 1.12
* Feb 2000, Version 1.13
+ * Nov 2000, Version 1.14
*
* History:
* 0.6b: first version in official kernel, Linux 1.3.46
@@ -144,6 +145,9 @@
* <tmh@magenta-logic.com> and <zlatko@iskon.hr>) modified by sfr.
* Remove CONFIG_APM_SUSPEND_BOUNCE. The bounce ignore
* interval is now configurable.
+ * 1.14: Make connection version persist across module unload/load.
+ * Enable and engage power management earlier.
+ * Disengage power management on module unload.
*
* APM 1.1 Reference:
*
@@ -344,9 +348,9 @@ static int kapmd_running;
static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-static struct apm_user * user_list = NULL;
+static struct apm_user * user_list;
-static char driver_version[] = "1.13"; /* no spaces */
+static char driver_version[] = "1.14"; /* no spaces */
static char * apm_event_name[] = {
"system standby",
@@ -527,7 +531,7 @@ static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
&dummy, &dummy))
return (eax >> 8) & 0xff;
*event = ebx;
- if (apm_bios_info.version < 0x0102)
+ if (apm_info.connection_version < 0x0102)
*info = ~0; /* indicate info not valid */
else
*info = ecx;
@@ -559,7 +563,7 @@ static int apm_do_idle(void)
#ifdef ALWAYS_CALL_BUSY
clock_slowed = 1;
#else
- clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
+ clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
#endif
return 1;
}
@@ -670,15 +674,15 @@ static int apm_enable_power_management(int enable)
{
u32 eax;
- if ((enable == 0) && (apm_bios_info.flags & APM_BIOS_DISENGAGED))
+ if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
return APM_NOT_ENGAGED;
if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
enable, &eax))
return (eax >> 8) & 0xff;
if (enable)
- apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+ apm_info.bios.flags &= ~APM_BIOS_DISABLED;
else
- apm_bios_info.flags |= APM_BIOS_DISABLED;
+ apm_info.bios.flags |= APM_BIOS_DISABLED;
return APM_SUCCESS;
}
#endif
@@ -691,6 +695,8 @@ static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
u32 edx;
u32 dummy;
+ if (apm_info.get_power_status_broken)
+ return APM_32_UNSUPPORTED;
if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0,
&eax, &ebx, &ecx, &edx, &dummy))
return (eax >> 8) & 0xff;
@@ -710,7 +716,7 @@ static int apm_get_battery_status(u_short which, u_short *status,
u32 edx;
u32 esi;
- if (apm_bios_info.version < 0x0102) {
+ if (apm_info.connection_version < 0x0102) {
/* pretend we only have one battery. */
if (which != 1)
return APM_BAD_DEVICE;
@@ -734,15 +740,15 @@ static int apm_engage_power_management(u_short device, int enable)
u32 eax;
if ((enable == 0) && (device == APM_DEVICE_ALL)
- && (apm_bios_info.flags & APM_BIOS_DISABLED))
+ && (apm_info.bios.flags & APM_BIOS_DISABLED))
return APM_DISABLED;
if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
return (eax >> 8) & 0xff;
if (device == APM_DEVICE_ALL) {
if (enable)
- apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+ apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
else
- apm_bios_info.flags |= APM_BIOS_DISENGAGED;
+ apm_info.bios.flags |= APM_BIOS_DISENGAGED;
}
return APM_SUCCESS;
}
@@ -890,7 +896,7 @@ static int send_event(apm_event_t event)
printk(KERN_CRIT "apm: Critical suspend was vetoed, expect armageddon\n" );
return 0;
}
- if (apm_bios_info.version > 0x100)
+ if (apm_info.connection_version > 0x100)
apm_set_power_state(APM_STATE_REJECT);
return 0;
}
@@ -993,13 +999,13 @@ static void check_events(void)
case APM_USER_SUSPEND:
#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
- if (apm_bios_info.version > 0x100)
+ if (apm_info.connection_version > 0x100)
apm_set_power_state(APM_STATE_REJECT);
break;
#endif
case APM_SYS_SUSPEND:
if (ignore_bounce) {
- if (apm_bios_info.version > 0x100)
+ if (apm_info.connection_version > 0x100)
apm_set_power_state(APM_STATE_REJECT);
break;
}
@@ -1064,7 +1070,7 @@ static void apm_event_handler(void)
int err;
if ((standbys_pending > 0) || (suspends_pending > 0)) {
- if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
+ if ((apm_info.connection_version > 0x100) && (pending_count-- <= 0)) {
pending_count = 4;
if (debug)
printk(KERN_DEBUG "apm: setting state busy\n");
@@ -1334,7 +1340,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
unsigned short bx;
unsigned short cx;
unsigned short dx;
- unsigned short error;
+ int error;
unsigned short ac_line_status = 0xff;
unsigned short battery_status = 0xff;
unsigned short battery_flag = 0xff;
@@ -1351,7 +1357,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
if ((cx & 0xff) != 0xff)
percentage = cx & 0xff;
- if (apm_bios_info.version > 0x100) {
+ if (apm_info.connection_version > 0x100) {
battery_flag = (cx >> 8) & 0xff;
if (dx != 0xffff) {
units = (dx & 0x8000) ? "min" : "sec";
@@ -1399,9 +1405,9 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
driver_version,
- (apm_bios_info.version >> 8) & 0xff,
- apm_bios_info.version & 0xff,
- apm_bios_info.flags,
+ (apm_info.bios.version >> 8) & 0xff,
+ apm_info.bios.version & 0xff,
+ apm_info.bios.flags,
ac_line_status,
battery_status,
battery_flag,
@@ -1417,7 +1423,7 @@ static int apm(void *unused)
unsigned short bx;
unsigned short cx;
unsigned short dx;
- unsigned short error;
+ int error;
char * power_stat;
char * bat_stat;
@@ -1429,22 +1435,53 @@ static int apm(void *unused)
sigfillset(&current->blocked);
current->tty = NULL; /* get rid of controlling tty */
- if (apm_bios_info.version > 0x100) {
+ if (apm_info.connection_version == 0) {
+ apm_info.connection_version = apm_info.bios.version;
+ if (apm_info.connection_version > 0x100) {
+ /*
+ * We only support BIOSs up to version 1.2
+ */
+ if (apm_info.connection_version > 0x0102)
+ apm_info.connection_version = 0x0102;
+ error = apm_driver_version(&apm_info.connection_version);
+ if (error != APM_SUCCESS) {
+ apm_error("driver version", error);
+ /* Fall back to an APM 1.0 connection. */
+ apm_info.connection_version = 0x100;
+ }
+ }
+ }
+
+ if (debug)
+ printk(KERN_INFO "apm: Connection version %d.%d\n",
+ (apm_info.connection_version >> 8) & 0xff,
+ apm_info.connection_version & 0xff);
+
+#ifdef CONFIG_APM_DO_ENABLE
+ if (apm_info.bios.flags & APM_BIOS_DISABLED) {
/*
- * We only support BIOSs up to version 1.2
+ * This call causes my NEC UltraLite Versa 33/C to hang if it
+ * is booted with PM disabled but not in the docking station.
+ * Unfortunate ...
*/
- if (apm_bios_info.version > 0x0102)
- apm_bios_info.version = 0x0102;
- if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
- /* Fall back to an APM 1.0 connection. */
- apm_bios_info.version = 0x100;
+ error = apm_enable_power_management(1);
+ if (error) {
+ apm_error("enable power management", error);
+ return -1;
+ }
+ }
+#endif
+
+ if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
+ && (apm_info.connection_version > 0x0100)) {
+ error = apm_engage_power_management(APM_DEVICE_ALL, 1);
+ if (error) {
+ apm_error("engage power management", error);
+ return -1;
}
}
- if (debug && (smp_num_cpus == 1)) {
- printk(KERN_INFO "apm: Connection version %d.%d\n",
- (apm_bios_info.version >> 8) & 0xff,
- apm_bios_info.version & 0xff);
+ if (debug && (smp_num_cpus == 1)) {
error = apm_get_power_status(&bx, &cx, &dx);
if (error)
printk(KERN_INFO "apm: power status not available\n");
@@ -1469,7 +1506,7 @@ static int apm(void *unused)
printk("unknown\n");
else
printk("%d%%\n", cx & 0xff);
- if (apm_bios_info.version > 0x100) {
+ if (apm_info.connection_version > 0x100) {
printk(KERN_INFO
"apm: battery flag 0x%02x, battery life ",
(cx >> 8) & 0xff);
@@ -1483,29 +1520,6 @@ static int apm(void *unused)
}
}
-#ifdef CONFIG_APM_DO_ENABLE
- if (apm_bios_info.flags & APM_BIOS_DISABLED) {
- /*
- * This call causes my NEC UltraLite Versa 33/C to hang if it
- * is booted with PM disabled but not in the docking station.
- * Unfortunate ...
- */
- error = apm_enable_power_management(1);
- if (error) {
- apm_error("enable power management", error);
- return -1;
- }
- }
-#endif
- if ((apm_bios_info.flags & APM_BIOS_DISENGAGED)
- && (apm_bios_info.version > 0x0100)) {
- error = apm_engage_power_management(APM_DEVICE_ALL, 1);
- if (error) {
- apm_error("engage power management", error);
- return -1;
- }
- }
-
/* Install our power off handler.. */
if (power_off)
pm_power_off = apm_power_off;
@@ -1584,17 +1598,19 @@ static struct miscdevice apm_device = {
*/
static int __init apm_init(void)
{
- if (apm_bios_info.version == 0) {
+ struct proc_dir_entry *apm_proc;
+
+ if (apm_info.bios.version == 0) {
printk(KERN_INFO "apm: BIOS not found.\n");
return -ENODEV;
}
printk(KERN_INFO
"apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
- ((apm_bios_info.version >> 8) & 0xff),
- (apm_bios_info.version & 0xff),
- apm_bios_info.flags,
+ ((apm_info.bios.version >> 8) & 0xff),
+ (apm_info.bios.version & 0xff),
+ apm_info.bios.flags,
driver_version);
- if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
+ if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
printk(KERN_INFO "apm: no 32 bit BIOS support\n");
return -ENODEV;
}
@@ -1603,23 +1619,23 @@ static int __init apm_init(void)
* Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
* but is reportedly a 1.0 BIOS.
*/
- if (apm_bios_info.version == 0x001)
- apm_bios_info.version = 0x100;
+ if (apm_info.bios.version == 0x001)
+ apm_info.bios.version = 0x100;
/* BIOS < 1.2 doesn't set cseg_16_len */
- if (apm_bios_info.version < 0x102)
- apm_bios_info.cseg_16_len = 0; /* 64k */
+ if (apm_info.bios.version < 0x102)
+ apm_info.bios.cseg_16_len = 0; /* 64k */
if (debug) {
printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x",
- apm_bios_info.cseg, apm_bios_info.offset,
- apm_bios_info.cseg_16, apm_bios_info.dseg);
- if (apm_bios_info.version > 0x100)
+ apm_info.bios.cseg, apm_info.bios.offset,
+ apm_info.bios.cseg_16, apm_info.bios.dseg);
+ if (apm_info.bios.version > 0x100)
printk(" cseg len %x, dseg len %x",
- apm_bios_info.cseg_len,
- apm_bios_info.dseg_len);
- if (apm_bios_info.version > 0x101)
- printk(" cseg16 len %x", apm_bios_info.cseg_16_len);
+ apm_info.bios.cseg_len,
+ apm_info.bios.dseg_len);
+ if (apm_info.bios.version > 0x101)
+ printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
printk("\n");
}
@@ -1647,16 +1663,16 @@ static int __init apm_init(void)
__va((unsigned long)0x40 << 4));
_set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4));
- apm_bios_entry.offset = apm_bios_info.offset;
+ apm_bios_entry.offset = apm_info.bios.offset;
apm_bios_entry.segment = APM_CS;
set_base(gdt[APM_CS >> 3],
- __va((unsigned long)apm_bios_info.cseg << 4));
+ __va((unsigned long)apm_info.bios.cseg << 4));
set_base(gdt[APM_CS_16 >> 3],
- __va((unsigned long)apm_bios_info.cseg_16 << 4));
+ __va((unsigned long)apm_info.bios.cseg_16 << 4));
set_base(gdt[APM_DS >> 3],
- __va((unsigned long)apm_bios_info.dseg << 4));
+ __va((unsigned long)apm_info.bios.dseg << 4));
#ifndef APM_RELAX_SEGMENTS
- if (apm_bios_info.version == 0x100) {
+ if (apm_info.bios.version == 0x100) {
#endif
/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
@@ -1667,15 +1683,17 @@ static int __init apm_init(void)
#ifndef APM_RELAX_SEGMENTS
} else {
_set_limit((char *)&gdt[APM_CS >> 3],
- (apm_bios_info.cseg_len - 1) & 0xffff);
+ (apm_info.bios.cseg_len - 1) & 0xffff);
_set_limit((char *)&gdt[APM_CS_16 >> 3],
- (apm_bios_info.cseg_16_len - 1) & 0xffff);
+ (apm_info.bios.cseg_16_len - 1) & 0xffff);
_set_limit((char *)&gdt[APM_DS >> 3],
- (apm_bios_info.dseg_len - 1) & 0xffff);
+ (apm_info.bios.dseg_len - 1) & 0xffff);
}
#endif
- create_proc_info_entry("apm", 0, NULL, apm_get_info);
+ apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
+ if (apm_proc)
+ SET_MODULE_OWNER(apm_proc);
kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
@@ -1692,6 +1710,14 @@ static int __init apm_init(void)
static void __exit apm_exit(void)
{
+ int error;
+
+ if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
+ && (apm_info.connection_version > 0x0100)) {
+ error = apm_engage_power_management(APM_DEVICE_ALL, 0);
+ if (error)
+ apm_error("disengage power management", error);
+ }
misc_deregister(&apm_device);
remove_proc_entry("apm", NULL);
#ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
new file mode 100644
index 000000000..b439568c1
--- /dev/null
+++ b/arch/i386/kernel/dmi_scan.c
@@ -0,0 +1,182 @@
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/apm_bios.h>
+#include <asm/io.h>
+
+struct dmi_header
+{
+ u8 type;
+ u8 length;
+ u16 handle;
+};
+
+static char * __init dmi_string(struct dmi_header *dm, u8 s)
+{
+ u8 *bp=(u8 *)dm;
+ bp+=dm->length;
+ s--;
+ while(s>0)
+ {
+ bp+=strlen(bp);
+ bp++;
+ s--;
+ }
+ return bp;
+}
+
+static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
+{
+ u8 *buf;
+ struct dmi_header *dm;
+ u8 *data;
+ int i=1;
+ int last = 0;
+
+ buf = ioremap(base, len);
+ if(buf==NULL)
+ return -1;
+
+ data = buf;
+ while(i<num && (data - buf) < len)
+ {
+ dm=(struct dmi_header *)data;
+ if(dm->type < last)
+ break;
+ last = dm->type;
+ decode(dm);
+ data+=dm->length;
+ while(*data || data[1])
+ data++;
+ data+=2;
+ i++;
+ }
+ iounmap(buf);
+ return 0;
+}
+
+
+int __init dmi_iterate(void (*decode)(struct dmi_header *))
+{
+ unsigned char buf[20];
+ long fp=0xE0000L;
+ fp -= 16;
+
+ while( fp < 0xFFFFF)
+ {
+ fp+=16;
+ isa_memcpy_fromio(buf, fp, 20);
+ if(memcmp(buf, "_DMI_", 5)==0)
+ {
+ u16 num=buf[13]<<8|buf[12];
+ u16 len=buf[7]<<8|buf[6];
+ u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+
+ printk(KERN_INFO "DMI %d.%d present.\n",
+ buf[14]>>4, buf[14]&0x0F);
+ printk(KERN_INFO "%d structures occupying %d bytes.\n",
+ buf[13]<<8|buf[12],
+ buf[7]<<8|buf[6]);
+ printk(KERN_INFO "DMI table at 0x%08X.\n",
+ buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]);
+ if(dmi_table(base,len, num, decode)==0)
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+/*
+ * Process a DMI table entry. Right now all we care about are the BIOS
+ * and machine entries. For 2.4 we should pull the smbus controller info
+ * out of here.
+ */
+
+static void __init dmi_decode(struct dmi_header *dm)
+{
+ u8 *data = (u8 *)dm;
+ char *p;
+
+ switch(dm->type)
+ {
+ case 0:
+ p=dmi_string(dm,data[4]);
+
+ if(*p && *p!=' ')
+ {
+ printk("BIOS Vendor: %s\n", p);
+ printk("BIOS Version: %s\n",
+ dmi_string(dm, data[5]));
+ printk("BIOS Release: %s\n",
+ dmi_string(dm, data[8]));
+ }
+
+ /*
+ * Check for clue free BIOS implementations who use
+ * the following QA technique
+ *
+ * [ Write BIOS Code ]<------
+ * | ^
+ * < Does it Compile >----N--
+ * |Y ^
+ * < Does it Boot Win98 >-N--
+ * |Y
+ * [Ship It]
+ *
+ * Phoenix A04 08/24/2000 is known bad (Dell Inspiron 5000e)
+ * Phoenix A07 09/29/2000 is known good (Dell Inspiron 5000)
+ */
+
+ if(strcmp(dmi_string(dm, data[4]), "Phoenix Technologies LTD")==0)
+ {
+ if(strcmp(dmi_string(dm, data[5]), "A04")==0
+ && strcmp(dmi_string(dm, data[8]), "08/24/2000")==0)
+ {
+ apm_info.get_power_status_broken = 1;
+ printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
+ }
+ }
+ break;
+ case 1:
+ p=dmi_string(dm,data[4]);
+
+ if(*p && *p!=' ')
+ {
+ printk("System Vendor: %s.\n",p);
+ printk("Product Name: %s.\n",
+ dmi_string(dm, data[5]));
+ printk("Version %s.\n",
+ dmi_string(dm, data[6]));
+ printk("Serial Number %s.\n",
+ dmi_string(dm, data[7]));
+ }
+ break;
+ case 2:
+ p=dmi_string(dm,data[4]);
+
+ if(*p && *p!=' ')
+ {
+ printk("Board Vendor: %s.\n",p);
+ printk("Board Name: %s.\n",
+ dmi_string(dm, data[5]));
+ printk("Board Version: %s.\n",
+ dmi_string(dm, data[6]));
+ }
+ break;
+ case 3:
+ p=dmi_string(dm,data[8]);
+ if(*p && *p!=' ')
+ printk("Asset Tag: %s.\n", p);
+ break;
+ }
+}
+
+static int __init dmi_scan_machine(void)
+{
+ return dmi_iterate(dmi_decode);
+}
+
+module_init(dmi_scan_machine);
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index fdb488a15..c74b80135 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -119,12 +119,12 @@ startup_32:
/*
* Clear BSS first so that there are no surprises...
+ * No need to cld as DF is already clear from cld above...
*/
xorl %eax,%eax
movl $ SYMBOL_NAME(__bss_start),%edi
movl $ SYMBOL_NAME(_end),%ecx
subl %edi,%ecx
- cld
rep
stosb
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 3de4a76d1..071b3991a 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(pm_idle);
EXPORT_SYMBOL(pm_power_off);
EXPORT_SYMBOL(get_cmos_time);
-EXPORT_SYMBOL(apm_bios_info);
+EXPORT_SYMBOL(apm_info);
EXPORT_SYMBOL(gdt);
EXPORT_SYMBOL_NOVERS(__down_failed);
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 92ddd01f5..cf6878787 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -179,7 +179,7 @@ int get_irq_list(char *buf)
#ifdef CONFIG_SMP
unsigned char global_irq_holder = NO_PROC_ID;
-unsigned volatile int global_irq_lock;
+unsigned volatile long global_irq_lock; /* pendantic: long for set_bit --RR */
extern void show_stack(unsigned long* esp);
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 5f9925495..f0a88c20e 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -4,13 +4,13 @@
* Copyright (C) 2000 Tigran Aivazian
*
* This driver allows to upgrade microcode on Intel processors
- * belonging to P6 family - PentiumPro, Pentium II,
- * Pentium III, Xeon etc.
+ * belonging to IA-32 family - PentiumPro, Pentium II,
+ * Pentium III, Xeon, Pentium 4, etc.
*
- * Reference: Section 8.10 of Volume III, Intel Pentium III Manual,
- * Order Number 243192 or free download from:
+ * Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual,
+ * Order Number 245472 or free download from:
*
- * http://developer.intel.com/design/pentiumii/manuals/243192.htm
+ * http://developer.intel.com/design/pentium4/manuals/245472.htm
*
* For more information, go to http://www.urbanmyth.org/microcode
*
@@ -44,6 +44,9 @@
* to be 0 on my machine which is why it worked even when I
* disabled update by the BIOS)
* Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
+ * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
+ * Tigran Aivazian <tigran@veritas.com>
+ * Intel Pentium 4 processor support and bugfixes.
*/
#include <linux/init.h>
@@ -58,12 +61,20 @@
#include <asm/uaccess.h>
#include <asm/processor.h>
-#define MICROCODE_VERSION "1.07"
+#define MICROCODE_VERSION "1.08"
-MODULE_DESCRIPTION("Intel CPU (P6) microcode update driver");
+MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver");
MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
EXPORT_NO_SYMBOLS;
+#define MICRO_DEBUG 0
+
+#if MICRO_DEBUG
+#define printf(x...) printk(##x)
+#else
+#define printf(x...)
+#endif
+
/* VFS interface */
static int microcode_open(struct inode *, struct file *);
static ssize_t microcode_read(struct file *, char *, size_t, loff_t *);
@@ -81,6 +92,7 @@ static unsigned int microcode_num; /* number of chunks in microcode */
static char *mc_applied; /* array of applied microcode blocks */
static unsigned int mc_fsize; /* file size of /dev/cpu/microcode */
+/* we share file_operations between misc and devfs mechanisms */
static struct file_operations microcode_fops = {
owner: THIS_MODULE,
read: microcode_read,
@@ -99,23 +111,27 @@ static devfs_handle_t devfs_handle;
static int __init microcode_init(void)
{
- int error = 0;
+ int error;
- if (misc_register(&microcode_dev) < 0) {
+ error = misc_register(&microcode_dev);
+ if (error)
printk(KERN_WARNING
"microcode: can't misc_register on minor=%d\n",
MICROCODE_MINOR);
- error = 1;
- }
+
devfs_handle = devfs_register(NULL, "cpu/microcode",
DEVFS_FL_DEFAULT, 0, 0, S_IFREG | S_IRUSR | S_IWUSR,
&microcode_fops, NULL);
if (devfs_handle == NULL && error) {
printk(KERN_ERR "microcode: failed to devfs_register()\n");
- return -EINVAL;
+ goto out;
}
- printk(KERN_INFO "P6 Microcode Update Driver v%s\n", MICROCODE_VERSION);
- return 0;
+ printk(KERN_INFO
+ "IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n",
+ MICROCODE_VERSION);
+
+out:
+ return error;
}
static void __exit microcode_exit(void)
@@ -124,12 +140,12 @@ static void __exit microcode_exit(void)
devfs_unregister(devfs_handle);
if (mc_applied)
kfree(mc_applied);
- printk(KERN_INFO "P6 Microcode Update Driver v%s unregistered\n",
+ printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n",
MICROCODE_VERSION);
}
-module_init(microcode_init);
-module_exit(microcode_exit);
+module_init(microcode_init)
+module_exit(microcode_exit)
static int microcode_open(struct inode *unused1, struct file *unused2)
{
@@ -175,18 +191,19 @@ static void do_update_one(void *unused)
unsigned int pf = 0, val[2], rev, sig;
int i,found=0;
- req->err = 1; /* assume the worst */
+ req->err = 1; /* assume update will fail on this cpu */
- if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 != 6){
- printk(KERN_ERR "microcode: CPU%d not an Intel P6\n", cpu_num);
+ if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
+ test_bit(X86_FEATURE_IA64, &c->x86_capability)){
+ printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num);
return;
}
sig = c->x86_mask + (c->x86_model<<4) + (c->x86<<8);
- if (c->x86_model >= 5) {
- /* get processor flags from BBL_CR_OVRD MSR (0x17) */
- rdmsr(0x17, val[0], val[1]);
+ if ((c->x86_model >= 5) || (c->x86 > 6)) {
+ /* get processor flags from MSR 0x17 */
+ rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
pf = 1 << ((val[1] >> 18) & 7);
}
@@ -195,9 +212,28 @@ static void do_update_one(void *unused)
microcode[i].ldrver == 1 && microcode[i].hdrver == 1) {
found=1;
- wrmsr(0x8B, 0, 0);
+
+ printf("Microcode\n");
+ printf(" Header Revision %d\n",microcode[i].hdrver);
+ printf(" Date %x/%x/%x\n",
+ ((microcode[i].date >> 24 ) & 0xff),
+ ((microcode[i].date >> 16 ) & 0xff),
+ (microcode[i].date & 0xFFFF));
+ printf(" Type %x Family %x Model %x Stepping %x\n",
+ ((microcode[i].sig >> 12) & 0x3),
+ ((microcode[i].sig >> 8) & 0xf),
+ ((microcode[i].sig >> 4) & 0xf),
+ ((microcode[i].sig & 0xf)));
+ printf(" Checksum %x\n",microcode[i].cksum);
+ printf(" Loader Revision %x\n",microcode[i].ldrver);
+ printf(" Processor Flags %x\n\n",microcode[i].pf);
+
+ /* trick, to work even if there was no prior update by the BIOS */
+ wrmsr(MSR_IA32_UCODE_REV, 0, 0);
__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
- rdmsr(0x8B, val[0], rev);
+
+ /* get current (on-cpu) revision into rev (ignore val[0]) */
+ rdmsr(MSR_IA32_UCODE_REV, val[0], rev);
if (microcode[i].rev < rev) {
printk(KERN_ERR
"microcode: CPU%d not 'upgrading' to earlier revision"
@@ -219,13 +255,20 @@ static void do_update_one(void *unused)
break;
}
- wrmsr(0x79, (unsigned int)(m->bits), 0);
+ /* write microcode via MSR 0x79 */
+ wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0);
+
+ /* serialize */
__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
- rdmsr(0x8B, val[0], val[1]);
+ /* get the current revision from MSR 0x8B */
+ rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+
+ /* notify the caller of success on this cpu */
req->err = 0;
req->slot = i;
- printk(KERN_ERR "microcode: CPU%d updated from revision "
+
+ printk(KERN_INFO "microcode: CPU%d updated from revision "
"%d to %d, date=%08x\n",
cpu_num, rev, val[1], m->date);
}
@@ -239,18 +282,21 @@ static void do_update_one(void *unused)
static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
{
- if (*ppos >= mc_fsize)
- return 0;
+ ssize_t ret = 0;
+
down_read(&microcode_rwsem);
+ if (*ppos >= mc_fsize)
+ goto out;
if (*ppos + len > mc_fsize)
len = mc_fsize - *ppos;
- if (copy_to_user(buf, mc_applied + *ppos, len)) {
- up_read(&microcode_rwsem);
- return -EFAULT;
- }
+ ret = -EFAULT;
+ if (copy_to_user(buf, mc_applied + *ppos, len))
+ goto out;
*ppos += len;
+ ret = len;
+out:
up_read(&microcode_rwsem);
- return len;
+ return ret;
}
static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
@@ -267,8 +313,8 @@ static ssize_t microcode_write(struct file *file, const char *buf, size_t len, l
mc_applied = kmalloc(smp_num_cpus*sizeof(struct microcode),
GFP_KERNEL);
if (!mc_applied) {
- printk(KERN_ERR "microcode: out of memory for saved microcode\n");
up_write(&microcode_rwsem);
+ printk(KERN_ERR "microcode: out of memory for saved microcode\n");
return -ENOMEM;
}
}
@@ -307,10 +353,12 @@ static int microcode_ioctl(struct inode *inode, struct file *file,
case MICROCODE_IOCFREE:
down_write(&microcode_rwsem);
if (mc_applied) {
+ int bytes = smp_num_cpus * sizeof(struct microcode);
+
devfs_set_file_size(devfs_handle, 0);
kfree(mc_applied);
mc_applied = NULL;
- printk(KERN_INFO "microcode: freed %d bytes\n", mc_fsize);
+ printk(KERN_INFO "microcode: freed %d bytes\n", bytes);
mc_fsize = 0;
up_write(&microcode_rwsem);
return 0;
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index 47c83f58e..60764e3cd 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -480,12 +480,14 @@ static int have_wrcomb (void)
}
} /* End Function have_wrcomb */
+static u32 size_or_mask, size_and_mask;
+
static void intel_get_mtrr (unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type *type)
{
- unsigned long dummy, mask_lo, base_lo;
+ unsigned long mask_lo, mask_hi, base_lo, base_hi;
- rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy);
+ rdmsr (MTRRphysMask_MSR(reg), mask_lo, mask_hi);
if ( (mask_lo & 0x800) == 0 )
{
/* Invalid (i.e. free) range */
@@ -495,20 +497,17 @@ static void intel_get_mtrr (unsigned int reg, unsigned long *base,
return;
}
- rdmsr(MTRRphysBase_MSR(reg), base_lo, dummy);
+ rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);
- /* We ignore the extra address bits (32-35). If someone wants to
- run x86 Linux on a machine with >4GB memory, this will be the
- least of their problems. */
+ /* Work out the shifted address mask. */
+ mask_lo = size_or_mask | mask_hi << (32 - PAGE_SHIFT)
+ | mask_lo >> PAGE_SHIFT;
- /* Clean up mask_lo so it gives the real address mask. */
- mask_lo = (mask_lo & 0xfffff000UL);
/* This works correctly if size is a power of two, i.e. a
contiguous range. */
- *size = ~(mask_lo - 1);
-
- *base = (base_lo & 0xfffff000UL);
- *type = (base_lo & 0xff);
+ *size = -mask_lo;
+ *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
+ *type = base_lo & 0xff;
} /* End Function intel_get_mtrr */
static void cyrix_get_arr (unsigned int reg, unsigned long *base,
@@ -533,13 +532,13 @@ static void cyrix_get_arr (unsigned int reg, unsigned long *base,
/* Enable interrupts if it was enabled previously */
__restore_flags (flags);
shift = ((unsigned char *) base)[1] & 0x0f;
- *base &= 0xfffff000UL;
+ *base >>= PAGE_SHIFT;
/* Power of two, at least 4K on ARR0-ARR6, 256K on ARR7
* Note: shift==0xf means 4G, this is unsupported.
*/
if (shift)
- *size = (reg < 7 ? 0x800UL : 0x20000UL) << shift;
+ *size = (reg < 7 ? 0x1UL : 0x40UL) << shift;
else
*size = 0;
@@ -576,7 +575,7 @@ static void amd_get_mtrr (unsigned int reg, unsigned long *base,
/* Upper dword is region 1, lower is region 0 */
if (reg == 1) low = high;
/* The base masks off on the right alignment */
- *base = low & 0xFFFE0000;
+ *base = (low & 0xFFFE0000) >> PAGE_SHIFT;
*type = 0;
if (low & 1) *type = MTRR_TYPE_UNCACHABLE;
if (low & 2) *type = MTRR_TYPE_WRCOMB;
@@ -601,7 +600,7 @@ static void amd_get_mtrr (unsigned int reg, unsigned long *base,
* *128K ...
*/
low = (~low) & 0x1FFFC;
- *size = (low + 4) << 15;
+ *size = (low + 4) << (15 - PAGE_SHIFT);
return;
} /* End Function amd_get_mtrr */
@@ -614,8 +613,8 @@ static struct
static void centaur_get_mcr (unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type *type)
{
- *base = centaur_mcr[reg].high & 0xfffff000;
- *size = (~(centaur_mcr[reg].low & 0xfffff000))+1;
+ *base = centaur_mcr[reg].high >> PAGE_SHIFT;
+ *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT;
*type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */
} /* End Function centaur_get_mcr */
@@ -645,8 +644,10 @@ static void intel_set_mtrr_up (unsigned int reg, unsigned long base,
}
else
{
- wrmsr (MTRRphysBase_MSR (reg), base | type, 0);
- wrmsr (MTRRphysMask_MSR (reg), ~(size - 1) | 0x800, 0);
+ wrmsr (MTRRphysBase_MSR (reg), base << PAGE_SHIFT | type,
+ (base & size_and_mask) >> (32 - PAGE_SHIFT));
+ wrmsr (MTRRphysMask_MSR (reg), -size << PAGE_SHIFT | 0x800,
+ (-size & size_and_mask) >> (32 - PAGE_SHIFT));
}
if (do_safe) set_mtrr_done (&ctxt);
} /* End Function intel_set_mtrr_up */
@@ -660,7 +661,9 @@ static void cyrix_set_arr_up (unsigned int reg, unsigned long base,
arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */
/* count down from 32M (ARR0-ARR6) or from 2G (ARR7) */
- size >>= (reg < 7 ? 12 : 18);
+ if (reg >= 7)
+ size >>= 6;
+
size &= 0x7fff; /* make sure arr_size <= 14 */
for(arr_size = 0; size; arr_size++, size >>= 1);
@@ -685,6 +688,7 @@ static void cyrix_set_arr_up (unsigned int reg, unsigned long base,
}
if (do_safe) set_mtrr_prepare (&ctxt);
+ base <<= PAGE_SHIFT;
setCx86(arr, ((unsigned char *) &base)[3]);
setCx86(arr+1, ((unsigned char *) &base)[2]);
setCx86(arr+2, (((unsigned char *) &base)[1]) | arr_size);
@@ -704,34 +708,36 @@ static void amd_set_mtrr_up (unsigned int reg, unsigned long base,
[RETURNS] Nothing.
*/
{
- u32 low, high;
+ u32 regs[2];
struct set_mtrr_context ctxt;
if (do_safe) set_mtrr_prepare (&ctxt);
/*
* Low is MTRR0 , High MTRR 1
*/
- rdmsr (0xC0000085, low, high);
+ rdmsr (0xC0000085, regs[0], regs[1]);
/*
* Blank to disable
*/
if (size == 0)
- *(reg ? &high : &low) = 0;
+ regs[reg] = 0;
else
- /* Set the register to the base (already shifted for us), the
- type (off by one) and an inverted bitmask of the size
- The size is the only odd bit. We are fed say 512K
- We invert this and we get 111 1111 1111 1011 but
- if you subtract one and invert you get the desired
- 111 1111 1111 1100 mask
- */
- *(reg ? &high : &low)=(((~(size-1))>>15)&0x0001FFFC)|base|(type+1);
+ /* Set the register to the base, the type (off by one) and an
+ inverted bitmask of the size The size is the only odd
+ bit. We are fed say 512K We invert this and we get 111 1111
+ 1111 1011 but if you subtract one and invert you get the
+ desired 111 1111 1111 1100 mask
+
+ But ~(x - 1) == ~x + 1 == -x. Two's complement rocks! */
+ regs[reg] = (-size>>(15-PAGE_SHIFT) & 0x0001FFFC)
+ | (base<<PAGE_SHIFT) | (type+1);
+
/*
* The writeback rule is quite specific. See the manual. Its
* disable local interrupts, write back the cache, set the mtrr
*/
__asm__ __volatile__ ("wbinvd" : : : "memory");
- wrmsr (0xC0000085, low, high);
+ wrmsr (0xC0000085, regs[0], regs[1]);
if (do_safe) set_mtrr_done (&ctxt);
} /* End Function amd_set_mtrr_up */
@@ -751,9 +757,8 @@ static void centaur_set_mcr_up (unsigned int reg, unsigned long base,
}
else
{
- high = base & 0xfffff000; /* base works on 4K pages... */
- low = ((~(size-1))&0xfffff000);
- low |= 0x1f; /* only support write-combining... */
+ high = base << PAGE_SHIFT;
+ low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */
}
centaur_mcr[reg].high = high;
centaur_mcr[reg].low = low;
@@ -1058,7 +1063,7 @@ static int generic_get_free_region (unsigned long base, unsigned long size)
for (i = 0; i < max; ++i)
{
(*get_mtrr) (i, &lbase, &lsize, &ltype);
- if (lsize < 1) return i;
+ if (lsize == 0) return i;
}
return -ENOSPC;
} /* End Function generic_get_free_region */
@@ -1075,10 +1080,10 @@ static int cyrix_get_free_region (unsigned long base, unsigned long size)
unsigned long lbase, lsize;
/* If we are to set up a region >32M then look at ARR7 immediately */
- if (size > 0x2000000UL)
+ if (size > 0x2000)
{
cyrix_get_arr (7, &lbase, &lsize, &ltype);
- if (lsize < 1) return 7;
+ if (lsize == 0) return 7;
/* Else try ARR0-ARR6 first */
}
else
@@ -1087,11 +1092,11 @@ static int cyrix_get_free_region (unsigned long base, unsigned long size)
{
cyrix_get_arr (i, &lbase, &lsize, &ltype);
if ((i == 3) && arr3_protected) continue;
- if (lsize < 1) return i;
+ if (lsize == 0) return i;
}
/* ARR0-ARR6 isn't free, try ARR7 but its size must be at least 256K */
cyrix_get_arr (i, &lbase, &lsize, &ltype);
- if ((lsize < 1) && (size >= 0x40000)) return i;
+ if ((lsize == 0) && (size >= 0x40)) return i;
}
return -ENOSPC;
} /* End Function cyrix_get_free_region */
@@ -1100,9 +1105,9 @@ static int (*get_free_region) (unsigned long base,
unsigned long size) = generic_get_free_region;
/**
- * mtrr_add - Add a memory type region
- * @base: Physical base address of region
- * @size: Physical size of region
+ * mtrr_add_page - Add a memory type region
+ * @base: Physical base address of region in pages (4 KB)
+ * @size: Physical size of region in pages (4 KB)
* @type: Type of MTRR desired
* @increment: If this is true do usage counting on the region
*
@@ -1135,11 +1140,11 @@ static int (*get_free_region) (unsigned long base,
* failures and do not wish system log messages to be sent.
*/
-int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char increment)
+int mtrr_add_page(unsigned long base, unsigned long size, unsigned int type, char increment)
{
/* [SUMMARY] Add an MTRR entry.
- <base> The starting (base) address of the region.
- <size> The size (in bytes) of the region.
+ <base> The starting (base, in pages) address of the region.
+ <size> The size of the region. (in pages)
<type> The type of the new region.
<increment> If true and the region already exists, the usage count will be
incremented.
@@ -1164,7 +1169,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
o Power of 2 block
o base suitably aligned to the power
*/
- if ( type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
+ if ( type > MTRR_TYPE_WRCOMB || size < (1 << (17-PAGE_SHIFT)) ||
(size & ~(size-1))-size || ( base & (size-1) ) )
return -EINVAL;
break;
@@ -1176,9 +1181,9 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
boot_cpu_data.x86_model == 1 &&
boot_cpu_data.x86_mask <= 7 )
{
- if ( base & ((1 << 22)-1) )
+ if ( base & ((1 << (22-PAGE_SHIFT))-1) )
{
- printk (KERN_WARNING "mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
+ printk (KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
return -EINVAL;
}
}
@@ -1186,12 +1191,6 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
case MTRR_IF_CYRIX_ARR:
case MTRR_IF_CENTAUR_MCR:
- if ( (base & 0xfff) || (size & 0xfff) )
- {
- printk ("mtrr: size and base must be multiples of 4 kiB\n");
- printk ("mtrr: size: %lx base: %lx\n", size, base);
- return -EINVAL;
- }
if ( mtrr_if == MTRR_IF_CENTAUR_MCR )
{
if (type != MTRR_TYPE_WRCOMB)
@@ -1200,9 +1199,9 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
return -EINVAL;
}
}
- else if (base + size < 0x100000)
+ else if (base + size < 0x100)
{
- printk (KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx,0x%lx)\n",
+ printk (KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
base, size);
return -EINVAL;
}
@@ -1213,7 +1212,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
lbase = lbase >> 1, last = last >> 1);
if (lbase != last)
{
- printk (KERN_WARNING "mtrr: base(0x%lx) is not aligned on a size(0x%lx) boundary\n",
+ printk (KERN_WARNING "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n",
base, size);
return -EINVAL;
}
@@ -1228,12 +1227,20 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
printk ("mtrr: type: %u illegal\n", type);
return -EINVAL;
}
+
/* If the type is WC, check that this processor supports it */
if ( (type == MTRR_TYPE_WRCOMB) && !have_wrcomb () )
{
printk (KERN_WARNING "mtrr: your processor doesn't support write-combining\n");
return -ENOSYS;
}
+
+ if ( base & size_or_mask || size & size_or_mask )
+ {
+ printk ("mtrr: base or size exceeds the MTRR width\n");
+ return -EINVAL;
+ }
+
increment = increment ? 1 : 0;
max = get_num_var_ranges ();
/* Search for existing MTRR */
@@ -1247,7 +1254,8 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
if ( (base < lbase) || (base + size > lbase + lsize) )
{
up(&main_lock);
- printk (KERN_WARNING "mtrr: 0x%lx,0x%lx overlaps existing 0x%lx,0x%lx\n",
+ printk (KERN_WARNING "mtrr: 0x%lx000,0x%lx000 overlaps existing"
+ " 0x%lx000,0x%lx000\n",
base, size, lbase, lsize);
return -EINVAL;
}
@@ -1256,7 +1264,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
{
if (type == MTRR_TYPE_UNCACHABLE) continue;
up(&main_lock);
- printk ( "mtrr: type mismatch for %lx,%lx old: %s new: %s\n",
+ printk ( "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
base, size, attrib_to_str (ltype), attrib_to_str (type) );
return -EINVAL;
}
@@ -1278,10 +1286,67 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
compute_ascii ();
up(&main_lock);
return i;
+} /* End Function mtrr_add_page */
+
+/**
+ * mtrr_add - Add a memory type region
+ * @base: Physical base address of region
+ * @size: Physical size of region
+ * @type: Type of MTRR desired
+ * @increment: If this is true do usage counting on the region
+ *
+ * Memory type region registers control the caching on newer Intel and
+ * non Intel processors. This function allows drivers to request an
+ * MTRR is added. The details and hardware specifics of each processor's
+ * implementation are hidden from the caller, but nevertheless the
+ * caller should expect to need to provide a power of two size on an
+ * equivalent power of two boundary.
+ *
+ * If the region cannot be added either because all regions are in use
+ * or the CPU cannot support it a negative value is returned. On success
+ * the register number for this entry is returned, but should be treated
+ * as a cookie only.
+ *
+ * On a multiprocessor machine the changes are made to all processors.
+ * This is required on x86 by the Intel processors.
+ *
+ * The available types are
+ *
+ * %MTRR_TYPE_UNCACHEABLE - No caching
+ *
+ * %MTRR_TYPE_WRITEBACK - Write data back in bursts whenever
+ *
+ * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
+ *
+ * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes
+ *
+ * BUGS: Needs a quiet flag for the cases where drivers do not mind
+ * failures and do not wish system log messages to be sent.
+ */
+
+int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char increment)
+{
+/* [SUMMARY] Add an MTRR entry.
+ <base> The starting (base) address of the region.
+ <size> The size (in bytes) of the region.
+ <type> The type of the new region.
+ <increment> If true and the region already exists, the usage count will be
+ incremented.
+ [RETURNS] The MTRR register on success, else a negative number indicating
+ the error code.
+*/
+
+ if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ return -EINVAL;
+ }
+ return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type, increment);
} /* End Function mtrr_add */
/**
- * mtrr_del - delete a memory type region
+ * mtrr_del_page - delete a memory type region
* @reg: Register returned by mtrr_add
* @base: Physical base address
* @size: Size of region
@@ -1295,7 +1360,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
* code.
*/
-int mtrr_del (int reg, unsigned long base, unsigned long size)
+int mtrr_del_page (int reg, unsigned long base, unsigned long size)
/* [SUMMARY] Delete MTRR/decrement usage count.
<reg> The register. If this is less than 0 then <<base>> and <<size>> must
be supplied.
@@ -1320,7 +1385,7 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
for (i = 0; i < max; ++i)
{
(*get_mtrr) (i, &lbase, &lsize, &ltype);
- if ( (lbase == base) && (lsize == size) )
+ if (lbase == base && lsize == size)
{
reg = i;
break;
@@ -1329,7 +1394,7 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
if (reg < 0)
{
up(&main_lock);
- printk ("mtrr: no MTRR for %lx,%lx found\n", base, size);
+ printk ("mtrr: no MTRR for %lx000,%lx000 found\n", base, size);
return -EINVAL;
}
}
@@ -1365,12 +1430,46 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
compute_ascii ();
up (&main_lock);
return reg;
-} /* End Function mtrr_del */
+} /* End Function mtrr_del_page */
+
+/**
+ * mtrr_del - delete a memory type region
+ * @reg: Register returned by mtrr_add
+ * @base: Physical base address
+ * @size: Size of region
+ *
+ * If register is supplied then base and size are ignored. This is
+ * how drivers should call it.
+ *
+ * Releases an MTRR region. If the usage count drops to zero the
+ * register is freed and the region returns to default state.
+ * On success the register is returned, on failure a negative error
+ * code.
+ */
+
+int mtrr_del (int reg, unsigned long base, unsigned long size)
+/* [SUMMARY] Delete MTRR/decrement usage count.
+ <reg> The register. If this is less than 0 then <<base>> and <<size>> must
+ be supplied.
+ <base> The base address of the region. This is ignored if <<reg>> is >= 0.
+ <size> The size of the region. This is ignored if <<reg>> is >= 0.
+ [RETURNS] The register on success, else a negative number indicating
+ the error code.
+*/
+{
+ if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ return -EINVAL;
+ }
+ return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
+}
#ifdef USERSPACE_INTERFACE
static int mtrr_file_add (unsigned long base, unsigned long size,
- unsigned int type, char increment, struct file *file)
+ unsigned int type, char increment, struct file *file, int page)
{
int reg, max;
unsigned int *fcount = file->private_data;
@@ -1386,18 +1485,38 @@ static int mtrr_file_add (unsigned long base, unsigned long size,
memset (fcount, 0, max * sizeof *fcount);
file->private_data = fcount;
}
- reg = mtrr_add (base, size, type, 1);
+ if (!page) {
+ if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ return -EINVAL;
+ }
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
+ }
+ reg = mtrr_add_page (base, size, type, 1);
if (reg >= 0) ++fcount[reg];
return reg;
} /* End Function mtrr_file_add */
static int mtrr_file_del (unsigned long base, unsigned long size,
- struct file *file)
+ struct file *file, int page)
{
int reg;
unsigned int *fcount = file->private_data;
- reg = mtrr_del (-1, base, size);
+ if (!page) {
+ if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ return -EINVAL;
+ }
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
+ }
+ reg = mtrr_del_page (-1, base, size);
if (reg < 0) return reg;
if (fcount == NULL) return reg;
if (fcount[reg] < 1) return -EINVAL;
@@ -1418,12 +1537,13 @@ static ssize_t mtrr_read (struct file *file, char *buf, size_t len,
static ssize_t mtrr_write (struct file *file, const char *buf, size_t len,
loff_t *ppos)
/* Format of control line:
- "base=%lx size=%lx type=%s" OR:
+ "base=%Lx size=%Lx type=%s" OR:
"disable=%d"
*/
{
int i, err;
- unsigned long reg, base, size;
+ unsigned long reg;
+ unsigned long long base, size;
char *ptr;
char line[LINE_SIZE];
@@ -1438,7 +1558,7 @@ static ssize_t mtrr_write (struct file *file, const char *buf, size_t len,
if ( !strncmp (line, "disable=", 8) )
{
reg = simple_strtoul (line + 8, &ptr, 0);
- err = mtrr_del (reg, 0, 0);
+ err = mtrr_del_page (reg, 0, 0);
if (err < 0) return err;
return len;
}
@@ -1447,14 +1567,20 @@ static ssize_t mtrr_write (struct file *file, const char *buf, size_t len,
printk ("mtrr: no \"base=\" in line: \"%s\"\n", line);
return -EINVAL;
}
- base = simple_strtoul (line + 5, &ptr, 0);
+ base = simple_strtoull (line + 5, &ptr, 0);
for (; isspace (*ptr); ++ptr);
if ( strncmp (ptr, "size=", 5) )
{
printk ("mtrr: no \"size=\" in line: \"%s\"\n", line);
return -EINVAL;
}
- size = simple_strtoul (ptr + 5, &ptr, 0);
+ size = simple_strtoull (ptr + 5, &ptr, 0);
+ if ( (base & 0xfff) || (size & 0xfff) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%Lx base: 0x%Lx\n", size, base);
+ return -EINVAL;
+ }
for (; isspace (*ptr); ++ptr);
if ( strncmp (ptr, "type=", 5) )
{
@@ -1466,7 +1592,9 @@ static ssize_t mtrr_write (struct file *file, const char *buf, size_t len,
for (i = 0; i < MTRR_NUM_TYPES; ++i)
{
if ( strcmp (ptr, mtrr_strings[i]) ) continue;
- err = mtrr_add (base, size, i, 1);
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
+ err = mtrr_add_page ((unsigned long)base, (unsigned long)size, i, 1);
if (err < 0) return err;
return len;
}
@@ -1490,7 +1618,7 @@ static int mtrr_ioctl (struct inode *inode, struct file *file,
if ( !suser () ) return -EPERM;
if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
return -EFAULT;
- err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file);
+ err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file, 0);
if (err < 0) return err;
break;
case MTRRIOC_SET_ENTRY:
@@ -1504,7 +1632,7 @@ static int mtrr_ioctl (struct inode *inode, struct file *file,
if ( !suser () ) return -EPERM;
if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
return -EFAULT;
- err = mtrr_file_del (sentry.base, sentry.size, file);
+ err = mtrr_file_del (sentry.base, sentry.size, file, 0);
if (err < 0) return err;
break;
case MTRRIOC_KILL_ENTRY:
@@ -1519,7 +1647,54 @@ static int mtrr_ioctl (struct inode *inode, struct file *file,
return -EFAULT;
if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL;
(*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type);
+
+ /* Hide entries that go above 4GB */
+ if (gentry.base + gentry.size > 0x100000 || gentry.size == 0x100000)
+ gentry.base = gentry.size = gentry.type = 0;
+ else {
+ gentry.base <<= PAGE_SHIFT;
+ gentry.size <<= PAGE_SHIFT;
+ gentry.type = type;
+ }
+
+ if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) )
+ return -EFAULT;
+ break;
+ case MTRRIOC_ADD_PAGE_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file, 1);
+ if (err < 0) return err;
+ break;
+ case MTRRIOC_SET_PAGE_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);
+ if (err < 0) return err;
+ break;
+ case MTRRIOC_DEL_PAGE_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_file_del (sentry.base, sentry.size, file, 1);
+ if (err < 0) return err;
+ break;
+ case MTRRIOC_KILL_PAGE_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_del_page (-1, sentry.base, sentry.size);
+ if (err < 0) return err;
+ break;
+ case MTRRIOC_GET_PAGE_ENTRY:
+ if ( copy_from_user (&gentry, (void *) arg, sizeof gentry) )
+ return -EFAULT;
+ if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL;
+ (*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type);
gentry.type = type;
+
if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) )
return -EFAULT;
break;
@@ -1578,24 +1753,24 @@ static void compute_ascii (void)
for (i = 0; i < max; i++)
{
(*get_mtrr) (i, &base, &size, &type);
- if (size < 1) usage_table[i] = 0;
+ if (size == 0) usage_table[i] = 0;
else
{
- if (size < 0x100000)
+ if (size < (0x100000 >> PAGE_SHIFT))
{
- /* 1MB */
- factor = 'k';
- size >>= 10;
+ /* less than 1MB */
+ factor = 'K';
+ size <<= PAGE_SHIFT - 10;
}
else
{
factor = 'M';
- size >>= 20;
+ size >>= 20 - PAGE_SHIFT;
}
sprintf
(ascii_buffer + ascii_buf_bytes,
- "reg%02i: base=0x%08lx (%4liMB), size=%4li%cB: %s, count=%d\n",
- i, base, base>>20, size, factor,
+ "reg%02i: base=0x%05lx000 (%4liMB), size=%4li%cB: %s, count=%d\n",
+ i, base, base >> (20 - PAGE_SHIFT), size, factor,
attrib_to_str (type), usage_table[i]);
ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes);
}
@@ -1762,11 +1937,38 @@ static int __init mtrr_setup(void)
mtrr_if = MTRR_IF_INTEL;
get_mtrr = intel_get_mtrr;
set_mtrr_up = intel_set_mtrr_up;
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ /* The original Athlon docs said that
+ total addressable memory is 44 bits wide.
+ It was not really clear whether its MTRRs
+ follow this or not. (Read: 44 or 36 bits).
+ However, "x86-64_overview.pdf" explicitly
+ states that "previous implementations support
+ 36 bit MTRRs" and also provides a way to
+ query the width (in bits) of the physical
+ addressable memory on the Hammer family.
+ */
+ if (boot_cpu_data.x86 == 7 && (cpuid_eax(0x80000000) >= 0x80000008)) {
+ u32 phys_addr;
+ phys_addr = cpuid_eax(0x80000008) & 0xff ;
+ size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
+ size_and_mask = ~size_or_mask & 0xfff00000;
+ break;
+ }
+ default:
+ /* Intel, etc. */
+ size_or_mask = 0xff000000; /* 36 bits */
+ size_and_mask = 0x00f00000;
+ break;
+ }
} else if ( test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ) {
/* Pre-Athlon (K6) AMD CPU MTRRs */
mtrr_if = MTRR_IF_AMD_K6;
get_mtrr = amd_get_mtrr;
set_mtrr_up = amd_set_mtrr_up;
+ size_or_mask = 0xfff00000; /* 32 bits */
+ size_and_mask = 0;
} else if ( test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ) {
/* Cyrix ARRs */
mtrr_if = MTRR_IF_CYRIX_ARR;
@@ -1774,12 +1976,16 @@ static int __init mtrr_setup(void)
set_mtrr_up = cyrix_set_arr_up;
get_free_region = cyrix_get_free_region;
cyrix_arr_init();
+ size_or_mask = 0xfff00000; /* 32 bits */
+ size_and_mask = 0;
} else if ( test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) ) {
/* Centaur MCRs */
mtrr_if = MTRR_IF_CENTAUR_MCR;
get_mtrr = centaur_get_mcr;
set_mtrr_up = centaur_set_mcr_up;
centaur_mcr_init();
+ size_or_mask = 0xfff00000; /* 32 bits */
+ size_and_mask = 0;
} else {
/* No supported MTRR interface */
mtrr_if = MTRR_IF_NONE;
diff --git a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c
index 17a929bb2..cdf4fc827 100644
--- a/arch/i386/kernel/pci-irq.c
+++ b/arch/i386/kernel/pci-irq.c
@@ -176,7 +176,6 @@ static void pirq_ali_ide_interrupt(struct pci_dev *router, unsigned reg, unsigne
pci_read_config_byte(router, reg, &x);
x = (x & 0xe0) | val; /* clear the level->edge transform */
pci_write_config_byte(router, reg, x);
- eisa_set_level_irq(irq);
}
static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
@@ -196,7 +195,6 @@ static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
pirq_ali_ide_interrupt(router, 0x75, val, irq);
break;
}
- eisa_set_level_irq(irq);
return 1;
}
return 0;
@@ -279,6 +277,54 @@ static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
return 1;
}
+static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ u8 x;
+ int reg = 0x41 + (pirq - 'A') ;
+
+ pci_read_config_byte(router, reg, &x);
+ return (x & 0x80) ? 0 : (x & 0x0f);
+}
+
+static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+ u8 x;
+ int reg = 0x41 + (pirq - 'A') ;
+
+ pci_read_config_byte(router, reg, &x);
+ x = (pirq & 0x20) ? 0 : (irq & 0x0f);
+ pci_write_config_byte(router, reg, x);
+
+ return 1;
+}
+
+/*
+ * VLSI: nibble offset 0x74 - educated guess due to routing table and
+ * config space of VLSI 82C534 PCI-bridge/router (1004:0102)
+ * Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
+ * devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
+ * for the busbridge to the docking station.
+ */
+
+static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ if (pirq > 8) {
+ printk("VLSI router pirq escape (%d)\n", pirq);
+ return 0;
+ }
+ return read_config_nybble(router, 0x74, pirq-1);
+}
+
+static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+ if (pirq > 8) {
+ printk("VLSI router pirq escape (%d)\n", pirq);
+ return 0;
+ }
+ write_config_nybble(router, 0x74, pirq-1, irq);
+ return 1;
+}
+
#ifdef CONFIG_PCI_BIOS
static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
@@ -309,7 +355,8 @@ static struct irq_router pirq_routers[] = {
{ "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set },
{ "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set },
-
+ { "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set },
+ { "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set },
{ "default", 0, 0, NULL, NULL }
};
@@ -355,7 +402,7 @@ static void __init pirq_find_router(void)
pirq_router_dev->slot_name);
}
-static struct irq_info *pirq_get_info(struct pci_dev *dev, int pin)
+static struct irq_info *pirq_get_info(struct pci_dev *dev)
{
struct irq_routing_table *rt = pirq_table;
int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
@@ -373,25 +420,28 @@ static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs
static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
{
+ u8 pin;
struct irq_info *info;
- int i, pirq, pin, newirq;
+ int i, pirq, newirq;
int irq = 0;
u32 mask;
struct irq_router *r = pirq_router;
- struct pci_dev *dev2, *d;
+ struct pci_dev *dev2;
char *msg = NULL;
if (!pirq_table)
return 0;
/* Find IRQ routing entry */
- pin = pci_get_interrupt_pin(dev, &d);
- if (pin < 0) {
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (!pin) {
DBG(" -> no interrupt pin\n");
return 0;
}
- DBG("IRQ for %s(%d) via %s", dev->slot_name, pin, d->slot_name);
- info = pirq_get_info(d, pin);
+ pin = pin - 1;
+
+ DBG("IRQ for %s:%d", dev->slot_name, pin);
+ info = pirq_get_info(dev);
if (!info) {
DBG(" -> not found in routing table\n");
return 0;
@@ -405,9 +455,12 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
mask &= pcibios_irq_mask;
- /* Find the best IRQ to assign */
- newirq = 0;
- if (assign) {
+ /*
+ * Find the best IRQ to assign: use the one
+ * reported by the device if possible.
+ */
+ newirq = dev->irq;
+ if (!newirq && assign) {
for (i = 0; i < 16; i++) {
if (!(mask & (1 << i)))
continue;
@@ -417,16 +470,22 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
newirq = i;
}
}
- DBG(" -> newirq=%d", newirq);
}
+ DBG(" -> newirq=%d", newirq);
/* Try to get current IRQ */
- if (r->get && (irq = r->get(pirq_router_dev, d, pirq))) {
+ if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) {
DBG(" -> got IRQ %d\n", irq);
msg = "Found";
+ /* We refuse to override the dev->irq information. Give a warning! */
+ if (dev->irq && dev->irq != irq) {
+ printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n");
+ return 0;
+ }
} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
DBG(" -> assigning IRQ %d", newirq);
- if (r->set(pirq_router_dev, d, pirq, newirq)) {
+ if (r->set(pirq_router_dev, dev, pirq, newirq)) {
+ eisa_set_level_irq(newirq);
DBG(" ... OK\n");
msg = "Assigned";
irq = newirq;
@@ -445,9 +504,14 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
/* Update IRQ for all devices with the same pirq value */
pci_for_each_dev(dev2) {
- if ((pin = pci_get_interrupt_pin(dev2, &d)) >= 0 &&
- (info = pirq_get_info(d, pin)) &&
- info->irq[pin].link == pirq) {
+ pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
+ if (!pin)
+ continue;
+ pin--;
+ info = pirq_get_info(dev2);
+ if (!info)
+ continue;
+ if (info->irq[pin].link == pirq) {
dev2->irq = irq;
pirq_penalty[irq]++;
if (dev != dev2)
@@ -556,19 +620,17 @@ void pcibios_penalize_isa_irq(int irq)
void pcibios_enable_irq(struct pci_dev *dev)
{
- if (!dev->irq) {
- u8 pin;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
- if (pin && !pcibios_lookup_irq(dev, 1)) {
- char *msg;
- if (io_apic_assign_pci_irqs)
- msg = " Probably buggy MP table.";
- else if (pci_probe & PCI_BIOS_IRQ_SCAN)
- msg = "";
- else
- msg = " Please try using pci=biosirq.";
- printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
- 'A' + pin - 1, dev->slot_name, msg);
- }
+ u8 pin;
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+ char *msg;
+ if (io_apic_assign_pci_irqs)
+ msg = " Probably buggy MP table.";
+ else if (pci_probe & PCI_BIOS_IRQ_SCAN)
+ msg = "";
+ else
+ msg = " Please try using pci=biosirq.";
+ printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
+ 'A' + pin - 1, dev->slot_name, msg);
}
}
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 6d3cf4d9a..8e7176c32 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -496,9 +496,9 @@ void release_thread(struct task_struct *dead_task)
void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
{
struct mm_struct * old_mm = current->mm;
- void * old_ldt = old_mm->segments, * ldt = old_ldt;
+ void * old_ldt = old_mm->segments, * ldt;
- if (!old_mm->segments) {
+ if (!old_ldt) {
/*
* default LDT - use the one from init_task
*/
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 692965a06..fffe11398 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -126,7 +126,7 @@ unsigned int mca_pentium_flag;
*/
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
-struct apm_bios_info apm_bios_info;
+struct apm_info apm_info;
struct sys_desc_table_struct {
unsigned short length;
unsigned char table[0];
@@ -608,7 +608,7 @@ void __init setup_arch(char **cmdline_p)
ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
- apm_bios_info = APM_BIOS_INFO;
+ apm_info.bios = APM_BIOS_INFO;
if( SYS_DESC_TABLE.length != 0 ) {
MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
machine_id = SYS_DESC_TABLE.table[0];
@@ -1531,8 +1531,32 @@ static void __init init_intel(struct cpuinfo_x86 *c)
dh = des >> 4;
dl = des & 0x0F;
+ /* Black magic... */
+
switch ( dh )
{
+ case 0:
+ switch ( dl ) {
+ case 6:
+ /* L1 I cache */
+ l1i += 8;
+ break;
+ case 8:
+ /* L1 I cache */
+ l1i += 16;
+ break;
+ case 10:
+ /* L1 D cache */
+ l1d += 8;
+ break;
+ case 12:
+ /* L1 D cache */
+ l1d += 16;
+ break;
+ default:
+ /* TLB, or unknown */
+ }
+ break;
case 2:
if ( dl ) {
/* L3 cache */
@@ -1541,6 +1565,16 @@ static void __init init_intel(struct cpuinfo_x86 *c)
}
break;
case 4:
+ if ( c->x86 > 6 && dl ) {
+ /* P4 family */
+ if ( dl ) {
+ /* L3 cache */
+ cs = 128 << (dl-1);
+ l3 += cs;
+ break;
+ }
+ }
+ /* else same as 8 - fall through */
case 8:
if ( dl ) {
/* L2 cache */
@@ -1556,9 +1590,16 @@ static void __init init_intel(struct cpuinfo_x86 *c)
}
break;
case 7:
- /* L1 I cache */
- cs = dl ? (16 << (dl-1)) : 12;
- l1i += cs;
+ if ( dl >= 8 )
+ {
+ /* L2 cache */
+ cs = 64<<(dl-8);
+ l2 += cs;
+ } else {
+ /* L0 I cache, count as L1 */
+ cs = dl ? (16 << (dl-1)) : 12;
+ l1i += cs;
+ }
break;
default:
/* TLB, or something else we don't know about */
@@ -2066,8 +2107,8 @@ int get_cpuinfo(char * buffer)
/* Intel-defined */
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
- "pat", "pse36", "pn", "clflsh", NULL, "dtes", "acpi", "mmx",
- "fxsr", "sse", "sse2", "selfsnoop", NULL, "acc", "ia64", NULL,
+ "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
+ "fxsr", "sse", "sse2", "ss", NULL, "tm", "ia64", NULL,
/* AMD-defined */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -2113,7 +2154,7 @@ int get_cpuinfo(char * buffer)
p += sprintf(p, "stepping\t: unknown\n");
if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) {
- p += sprintf(p, "cpu MHz\t\t: %lu.%06lu\n",
+ p += sprintf(p, "cpu MHz\t\t: %lu.%03lu\n",
cpu_khz / 1000, (cpu_khz % 1000));
}
@@ -2131,7 +2172,7 @@ int get_cpuinfo(char * buffer)
"fpu_exception\t: %s\n"
"cpuid level\t: %d\n"
"wp\t\t: %s\n"
- "features\t:",
+ "flags\t\t:",
c->fdiv_bug ? "yes" : "no",
c->hlt_works_ok ? "no" : "yes",
c->f00f_bug ? "yes" : "no",
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 57a07765e..858e7dda0 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -886,8 +886,10 @@ void __init smp_boot_cpus(void)
/*
* If we couldn't find a local APIC, then get out of here now!
*/
- if (!verify_local_APIC()) {
- printk(KERN_ERR "BIOS bug, local APIC at 0x%lX not detected!...\n", mp_lapic_addr);
+ if (APIC_INTEGRATED(apic_version[boot_cpu_id]) &&
+ !test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)) {
+ printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+ boot_cpu_id);
printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
#ifndef CONFIG_VISWS
io_apic_irqs = 0;
@@ -897,6 +899,8 @@ void __init smp_boot_cpus(void)
goto smp_done;
}
+ verify_local_APIC();
+
/*
* If SMP should be disabled, then really disable it!
*/
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index b84421374..f2077f2f2 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -62,20 +62,8 @@ struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
*/
struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
-extern int console_loglevel;
extern void bust_spinlocks(void);
-static inline void console_silent(void)
-{
- console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
- if (console_loglevel)
- console_loglevel = 15;
-}
-
asmlinkage void divide_error(void);
asmlinkage void debug(void);
asmlinkage void nmi(void);
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 39a6ce0f8..b2e5a1bfc 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -198,7 +198,7 @@ void __init kmap_init(void)
void show_mem(void)
{
- int i,free = 0, total = 0, reserved = 0;
+ int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
int highmem = 0;
@@ -214,9 +214,7 @@ void show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!page_count(mem_map+i))
- free++;
- else
+ else if (page_count(mem_map+i))
shared += page_count(mem_map+i) - 1;
}
printk("%d pages of RAM\n", total);
@@ -437,7 +435,7 @@ void __init zap_low_mappings (void)
}
/*
- * paging_init() sets up the page tables - note that the first 4MB are
+ * paging_init() sets up the page tables - note that the first 8MB are
* already mapped by head.S.
*
* This routines also unmaps the page at virtual kernel address 0, so
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 30d4def40..b3646e275 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -181,7 +181,7 @@ int get_irq_list(char *buf)
#ifdef CONFIG_SMP
unsigned int global_irq_holder = NO_PROC_ID;
-volatile unsigned int global_irq_lock;
+volatile unsigned long global_irq_lock; /* long for set_bit --RR */
extern void show_stack(unsigned long* esp);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index b2cd880ad..bfbb2050e 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -245,7 +245,7 @@ si_meminfo (struct sysinfo *val)
void
show_mem (void)
{
- int i,free = 0,total = 0,reserved = 0;
+ int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
printk("Mem-info:\n");
@@ -258,9 +258,7 @@ show_mem (void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!page_count(mem_map + i))
- free++;
- else
+ else if (page_count(mem_map + i))
shared += page_count(mem_map + i) - 1;
}
printk("%d pages of RAM\n", total);
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
index e9fee546e..b7bd84c73 100644
--- a/arch/m68k/amiga/amiga_ksyms.c
+++ b/arch/m68k/amiga/amiga_ksyms.c
@@ -25,7 +25,6 @@ EXPORT_SYMBOL(amiga_audio_period);
EXPORT_SYMBOL(amiga_audio_min_period);
EXPORT_SYMBOL(amiga_do_irq);
EXPORT_SYMBOL(amiga_do_irq_list);
-EXPORT_SYMBOL(amiga_intena_vals);
#ifdef CONFIG_AMIGA_PCMCIA
EXPORT_SYMBOL(pcmcia_reset);
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index 58759ba36..0902518f9 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -58,7 +58,7 @@ extern int cia_get_irq_list(struct ciabase *base, char *buf);
/* irq node variables for amiga interrupt sources */
static irq_node_t *ami_irq_list[AMI_STD_IRQS];
-unsigned short amiga_intena_vals[AMI_STD_IRQS] = {
+static unsigned short amiga_intena_vals[AMI_STD_IRQS] = {
IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT,
IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER
};
@@ -106,7 +106,7 @@ void __init amiga_init_IRQ(void)
/* turn off PCMCIA interrupts */
if (AMIGAHW_PRESENT(PCMCIA))
- pcmcia_disable_irq();
+ gayle.inten = GAYLE_IRQ_IDE;
/* turn off all interrupts and enable the master interrupt bit */
custom.intena = 0x7fff;
@@ -352,67 +352,16 @@ inline void amiga_do_irq(int irq, struct pt_regs *fp)
ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
}
-void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
+void amiga_do_irq_list(int irq, struct pt_regs *fp)
{
- irq_node_t *node, *slow_nodes;
- unsigned short flags, intena;
+ irq_node_t *node;
kstat.irqs[0][SYS_IRQS + irq]++;
- if (server->count++)
- server->reentrance = 1;
-
- intena = amiga_intena_vals[irq];
- custom.intreq = intena;
-
- /* serve fast handler if present - there can only be one of these */
- node = ami_irq_list[irq];
- /*
- * Timer interrupts show up like this
- */
- if (!node) {
- server->count--;
- return;
- }
+ custom.intreq = amiga_intena_vals[irq];
- if (node && (node->flags & SA_INTERRUPT)) {
- save_flags(flags);
- cli();
+ for (node = ami_irq_list[irq]; node; node = node->next)
node->handler(irq, node->dev_id, fp);
- restore_flags(flags);
-
- server->count--;
- return;
- }
-
- /*
- * Disable the interrupt source in question and reenable all
- * other interrupts. No interrupt handler should ever touch
- * the intena flags directly!
- */
- custom.intena = intena;
- save_flags(flags);
-#if 0 /* def CPU_M68060_ONLY */
- sti();
-#else
- restore_flags((flags & ~0x0700) | (fp->sr & 0x0700));
-#endif
-
- slow_nodes = node;
- for (;;) {
- for (; node; node = node->next)
- node->handler(irq, node->dev_id, fp);
-
- if (!server->reentrance) {
- server->count--;
- restore_flags(flags);
- custom.intena = IF_SETCLR | intena;
- return;
- }
-
- server->reentrance = 0;
- node = slow_nodes;
- }
}
/*
@@ -445,7 +394,6 @@ static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
{
unsigned short ints = custom.intreqr & custom.intenar;
- static struct irq_server server = {0, 0};
/* if a blitter interrupt */
if (ints & IF_BLIT) {
@@ -461,7 +409,7 @@ static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
/* if a vertical blank interrupt */
if (ints & IF_VERTB)
- amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+ amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
}
static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 2210d05d6..4c94f7862 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -8,6 +8,7 @@
* for more details.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/init.h>
@@ -42,7 +43,9 @@ static u_long clock_constant;
void __init amiga_init_sound(void)
{
- snd_data = amiga_chip_alloc(sizeof(sine_data), "Beep");
+ static struct resource beep_res = { "Beep" };
+
+ snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res);
if (!snd_data) {
printk (KERN_CRIT "amiga init_sound: failed to allocate chipmem\n");
return;
@@ -51,6 +54,11 @@ void __init amiga_init_sound(void)
/* setup divisor */
clock_constant = (amiga_colorclock+DATA_SIZE/2)/DATA_SIZE;
+
+ /* without amifb, turn video off and enable high quality sound */
+#ifndef CONFIG_FB_AMIGA
+ amifb_video_off();
+#endif
}
static void nosound( unsigned long ignored );
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index b7f9f0508..dfae2b43f 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -3,173 +3,127 @@
**
** Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org>
** - 64-bit aligned allocations for full AGA compatibility
+**
+** Rewritten 15/9/2000 by Geert to use resource management
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/slab.h>
#include <asm/amigahw.h>
-struct chip_desc {
- unsigned first : 1;
- unsigned last : 1;
- unsigned alloced : 1;
- unsigned length : 24;
- long pad; /* We suppose this makes this struct 64 bits long!! */
-};
-
-#define DP(ptr) ((struct chip_desc *)(ptr))
+unsigned long amiga_chip_size;
-u_long amiga_chip_size;
+static struct resource chipram_res = { "Chip RAM", CHIP_PHYSADDR };
static unsigned long chipavail;
-static struct resource chipram = { "Chip RAM", 0 };
-unsigned long amiga_chip_avail( void )
+void __init amiga_chip_init(void)
{
-#ifdef DEBUG
- printk("chip_avail : %ld bytes\n",chipavail);
+ if (!AMIGAHW_PRESENT(CHIP_RAM))
+ return;
+
+#ifndef CONFIG_APUS_FAST_EXCEPT
+ /*
+ * Remove the first 4 pages where PPC exception handlers will be located
+ */
+ amiga_chip_size -= 0x4000;
#endif
- return chipavail;
-}
+ chipram_res.end = amiga_chip_size-1;
+ request_resource(&iomem_resource, &chipram_res);
+ chipavail = amiga_chip_size;
+}
-void __init amiga_chip_init (void)
+
+void *amiga_chip_alloc(unsigned long size, const char *name)
{
- struct chip_desc *dp;
-
- if (!AMIGAHW_PRESENT(CHIP_RAM))
- return;
+ struct resource *res;
- chipram.end = amiga_chip_size-1;
- request_resource(&iomem_resource, &chipram);
-
- /* initialize start boundary */
-
- dp = DP(chipaddr);
- dp->first = 1;
-
- dp->alloced = 0;
- dp->length = amiga_chip_size - 2*sizeof(*dp);
-
- /* initialize end boundary */
- dp = DP(chipaddr + amiga_chip_size) - 1;
- dp->last = 1;
-
- dp->alloced = 0;
- dp->length = amiga_chip_size - 2*sizeof(*dp);
- chipavail = dp->length; /*MILAN*/
+ /* round up */
+ size = PAGE_ALIGN(size);
#ifdef DEBUG
- printk ("chipram end boundary is %p, length is %d\n", dp,
- dp->length);
+ printk("amiga_chip_alloc: allocate %ld bytes\n", size);
#endif
+ res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+ if (!res)
+ return NULL;
+ memset(res, 0, sizeof(struct resource));
+ res->name = name;
+
+ if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
+ kfree(res);
+ return NULL;
+ }
+ chipavail -= size;
+#ifdef DEBUG
+ printk("amiga_chip_alloc: returning %lx\n", res->start);
+#endif
+ return (void *)ZTWO_VADDR(res->start);
}
-void *amiga_chip_alloc(long size, const char *name)
-{
- /* last chunk */
- struct chip_desc *dp;
- void *ptr;
- /* round off */
- size = (size + 7) & ~7;
+ /*
+ * Warning:
+ * amiga_chip_alloc_res is meant only for drivers that need to allocate
+ * Chip RAM before kmalloc() is functional. As a consequence, those
+ * drivers must not free that Chip RAM afterwards.
+ */
-#ifdef DEBUG
- printk("amiga_chip_alloc: allocate %ld bytes\n", size);
-#endif
+void * __init amiga_chip_alloc_res(unsigned long size, struct resource *res)
+{
+ unsigned long start;
+
+ /* round up */
+ size = PAGE_ALIGN(size);
+ /* dmesg into chipmem prefers memory at the safe end */
+ start = CHIP_PHYSADDR + chipavail - size;
- /*
- * get pointer to descriptor for last chunk by
- * going backwards from end chunk
- */
- dp = DP(chipaddr + amiga_chip_size) - 1;
- dp = DP((unsigned long)dp - dp->length) - 1;
-
- while ((dp->alloced || dp->length < size)
- && !dp->first)
- dp = DP ((unsigned long)dp - dp[-1].length) - 2;
-
- if (dp->alloced || dp->length < size) {
- printk ("no chipmem available for %ld allocation\n", size);
- return NULL;
- }
-
- if (dp->length < (size + 2*sizeof(*dp))) {
- /* length too small to split; allocate the whole thing */
- dp->alloced = 1;
- ptr = (void *)(dp+1);
- dp = DP((unsigned long)ptr + dp->length);
- dp->alloced = 1;
#ifdef DEBUG
- printk ("amiga_chip_alloc: no split\n");
+ printk("amiga_chip_alloc_res: allocate %ld bytes\n", size);
#endif
- } else {
- /* split the extent; use the end part */
- long newsize = dp->length - (2*sizeof(*dp) + size);
-
+ if (allocate_resource(&chipram_res, res, size, start, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
+ printk("amiga_chip_alloc_res: first alloc failed!\n");
+ if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0)
+ return NULL;
+ }
+ chipavail -= size;
#ifdef DEBUG
- printk ("amiga_chip_alloc: splitting %d to %ld\n", dp->length,
- newsize);
+ printk("amiga_chip_alloc_res: returning %lx\n", res->start);
#endif
- dp->length = newsize;
- dp = DP((unsigned long)(dp+1) + newsize);
- dp->first = dp->last = 0;
- dp->alloced = 0;
- dp->length = newsize;
- dp++;
- dp->first = dp->last = 0;
- dp->alloced = 1;
- dp->length = size;
- ptr = (void *)(dp+1);
- dp = DP((unsigned long)ptr + size);
- dp->alloced = 1;
- dp->length = size;
- }
+ return (void *)ZTWO_VADDR(res->start);
+}
+void amiga_chip_free(void *ptr)
+{
+ unsigned long start = ZTWO_PADDR(ptr);
+ struct resource **p, *res;
+ unsigned long size;
+
+ for (p = &chipram_res.child; (res = *p); p = &res->sibling) {
+ if (res->start != start)
+ continue;
+ *p = res->sibling;
+ size = res->end-start;
#ifdef DEBUG
- printk ("amiga_chip_alloc: returning %p\n", ptr);
+ printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr);
#endif
-
- if ((unsigned long)ptr & 7)
- panic("amiga_chip_alloc: alignment violation\n");
-
- chipavail -= size + (2*sizeof(*dp)); /*MILAN*/
-
- if (!request_mem_region(ZTWO_PADDR(ptr), size, name))
- printk(KERN_WARNING "amiga_chip_alloc: region of size %ld at 0x%08lx "
- "is busy\n", size, ZTWO_PADDR(ptr));
-
- return ptr;
+ chipavail += size;
+ kfree(res);
+ return;
+ }
+ printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
}
-void amiga_chip_free (void *ptr)
-{
- struct chip_desc *sdp = DP(ptr) - 1, *dp2;
- struct chip_desc *edp = DP((unsigned long)ptr + sdp->length);
- chipavail += sdp->length + (2* sizeof(sdp)); /*MILAN*/
+unsigned long amiga_chip_avail(void)
+{
#ifdef DEBUG
- printk("chip_free: free %ld bytes at %p\n",sdp->length,ptr);
+ printk("amiga_chip_avail : %ld bytes\n", chipavail);
#endif
- /* deallocate the chunk */
- sdp->alloced = edp->alloced = 0;
- release_mem_region(ZTWO_PADDR(ptr), sdp->length);
-
- /* check if we should merge with the previous chunk */
- if (!sdp->first && !sdp[-1].alloced) {
- dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2;
- dp2->length += sdp->length + 2*sizeof(*sdp);
- edp->length = dp2->length;
- sdp = dp2;
- }
-
- /* check if we should merge with the following chunk */
- if (!edp->last && !edp[1].alloced) {
- dp2 = DP((unsigned long)edp + edp[1].length) + 2;
- dp2->length += edp->length + 2*sizeof(*sdp);
- sdp->length = dp2->length;
- edp = dp2;
- }
+ return chipavail;
}
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index cda898699..d72d8af9f 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -27,18 +27,17 @@ struct ciabase {
u_short int_mask;
int handler_irq, cia_irq, server_irq;
char *name;
- struct irq_server server;
irq_handler_t irq_list[CIA_IRQS];
} ciaa_base = {
&ciaa, 0, 0, IF_PORTS,
IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA,
IRQ_AMIGA_PORTS,
- "CIAA handler", {0, 0}
+ "CIAA handler"
}, ciab_base = {
&ciab, 0, 0, IF_EXTER,
IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB,
IRQ_AMIGA_EXTER,
- "CIAB handler", {0, 0}
+ "CIAB handler"
};
/*
@@ -136,7 +135,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
}
ints >>= 1;
}
- amiga_do_irq_list(base->server_irq, fp, &base->server);
+ amiga_do_irq_list(base->server_irq, fp);
}
void __init cia_init_IRQ(struct ciabase *base)
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 528f206ff..618d9a618 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -31,6 +31,7 @@
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/irq.h>
+#include <asm/keyboard.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -43,17 +44,36 @@ unsigned char amiga_vblank;
unsigned char amiga_psfreq;
struct amiga_hw_present amiga_hw_present;
-static const char *amiga_models[] = {
- "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000",
- "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco"
+static const char s_a500[] __initdata = "A500";
+static const char s_a500p[] __initdata = "A500+";
+static const char s_a600[] __initdata = "A600";
+static const char s_a1000[] __initdata = "A1000";
+static const char s_a1200[] __initdata = "A1200";
+static const char s_a2000[] __initdata = "A2000";
+static const char s_a2500[] __initdata = "A2500";
+static const char s_a3000[] __initdata = "A3000";
+static const char s_a3000t[] __initdata = "A3000T";
+static const char s_a3000p[] __initdata = "A3000+";
+static const char s_a4000[] __initdata = "A4000";
+static const char s_a4000t[] __initdata = "A4000T";
+static const char s_cdtv[] __initdata = "CDTV";
+static const char s_cd32[] __initdata = "CD32";
+static const char s_draco[] __initdata = "Draco";
+static const char *amiga_models[] __initdata = {
+ s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000,
+ s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco,
};
+static char amiga_model_name[13] = "Amiga ";
+
extern char m68k_debug_device[];
static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
/* amiga specific keyboard functions */
extern int amiga_keyb_init(void);
extern int amiga_kbdrate (struct kbd_repeat *);
+extern int amiga_kbd_translate(unsigned char keycode, unsigned char *keycodep,
+ char raw_mode);
/* amiga specific irq functions */
extern void amiga_init_IRQ (void);
extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
@@ -127,6 +147,8 @@ static struct resource rtc_resource = {
NULL, 0x00dc0000, 0x00dcffff
};
+static struct resource ram_resource[NUM_MEMINFO];
+
/*
* Parse an Amiga-specific record in the bootinfo
@@ -200,8 +222,10 @@ static void __init amiga_identify(void)
memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
printk("Amiga hardware found: ");
- if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+ strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
+ }
switch(amiga_model) {
case AMI_UNKNOWN:
@@ -367,6 +391,8 @@ void __init config_amiga(void)
mach_sched_init = amiga_sched_init;
mach_keyb_init = amiga_keyb_init;
mach_kbdrate = amiga_kbdrate;
+ mach_kbd_translate = amiga_kbd_translate;
+ SYSRQ_KEY = 0xff;
mach_init_IRQ = amiga_init_IRQ;
mach_default_handler = &amiga_default_handler;
mach_request_irq = amiga_request_irq;
@@ -447,6 +473,17 @@ void __init config_amiga(void)
disabled_z2mem>>10);
}
+ /* request all RAM */
+ for (i = 0; i < m68k_num_memory; i++) {
+ ram_resource[i].name =
+ (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
+ (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
+ "16-bit Slow RAM";
+ ram_resource[i].start = m68k_memory[i].addr;
+ ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
+ request_resource(&iomem_resource, &ram_resource[i]);
+ }
+
/* initialize chipram allocator */
amiga_chip_init ();
@@ -478,8 +515,11 @@ static unsigned short jiffy_ticks;
static void __init amiga_sched_init(void (*timer_routine)(int, void *,
struct pt_regs *))
{
+ static struct resource sched_res = { "timer" };
jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
+ if (!request_mem_region(CIAB_PHYSADDR+0x400, 0x200, "timer"))
+ printk("Cannot allocate ciab.ta{lo,hi}\n");
ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */
ciab.talo = jiffy_ticks % 256;
ciab.tahi = jiffy_ticks / 256;
@@ -827,7 +867,9 @@ static void amiga_mem_console_write(struct console *co, const char *s,
static void amiga_savekmsg_init(void)
{
- savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM, "Debug");
+ static struct resource debug_res = { "Debug" };
+
+ savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
savekmsg->magic1 = SAVEKMSG_MAGIC1;
savekmsg->magic2 = SAVEKMSG_MAGIC2;
savekmsg->magicptr = virt_to_phys(savekmsg);
@@ -933,9 +975,7 @@ static void amiga_heartbeat(int on)
static void amiga_get_model(char *model)
{
- strcpy(model, "Amiga ");
- if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
- strcat(model, amiga_models[amiga_model-AMI_500]);
+ strcpy(model, amiga_model_name);
}
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index d7a64faea..f4f284a9a 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -13,6 +13,7 @@
* enhanced by Bjoern Brauel and Roman Hodek
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
@@ -24,6 +25,7 @@
#include <linux/random.h>
#include <linux/init.h>
#include <linux/kbd_ll.h>
+#include <linux/kbd_kern.h>
#include <asm/atariints.h>
#include <asm/atarihw.h>
@@ -362,7 +364,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
if (acia_stat & ACIA_RDRF) /* received a character */
{
scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */
- mark_bh(KEYBOARD_BH);
+ tasklet_schedule(&keyboard_tasklet);
interpret_scancode:
switch (kb_state.state)
{
@@ -860,3 +862,16 @@ int atari_kbdrate( struct kbd_repeat *k )
return( 0 );
}
+
+int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+ /* ALT+HELP pressed? */
+ if ((keycode == 98) && ((shift_state & 0xff) == 8))
+ *keycodep = 0xff;
+ else
+#endif
+ *keycodep = keycode;
+ return 1;
+}
+
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 3acfeff7a..70a32fb65 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -60,6 +60,8 @@ static int atari_get_hardware_list(char *buffer);
/* atari specific keyboard functions */
extern int atari_keyb_init(void);
extern int atari_kbdrate (struct kbd_repeat *);
+extern int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep,
+ char raw_mode);
extern void atari_kbd_leds (unsigned int);
/* atari specific irq functions */
extern void atari_init_IRQ (void);
@@ -253,6 +255,8 @@ void __init config_atari(void)
mach_sched_init = atari_sched_init;
mach_keyb_init = atari_keyb_init;
mach_kbdrate = atari_kbdrate;
+ mach_kbd_translate = atari_kbd_translate;
+ SYSRQ_KEY = 0xff;
mach_kbd_leds = atari_kbd_leds;
mach_init_IRQ = atari_init_IRQ;
mach_request_irq = atari_request_irq;
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index d0acdaaae..b4a797f2e 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -20,6 +20,7 @@
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/shm.h>
+#include <linux/bootmem.h>
#include <asm/setup.h>
#include <asm/machdep.h>
@@ -33,6 +34,7 @@
#ifdef CONFIG_STRAM_SWAP
#define MAJOR_NR Z2RAM_MAJOR
+#define do_z2_request do_stram_request
#include <linux/blk.h>
#undef DEVICE_NAME
#define DEVICE_NAME "stram"
@@ -123,6 +125,10 @@
unswap_by_move disabled because it does not handle swapped shm pages.
*/
+/* 2000-05-01: ++andreas
+ Integrated with bootmem. Remove all traces of unswap_by_move.
+*/
+
#ifdef CONFIG_STRAM_SWAP
#define ALIGN_IF_SWAP(x) PAGE_ALIGN(x)
#else
@@ -130,10 +136,10 @@
#endif
/* get index of swap page at address 'addr' */
-#define SWAP_NR(addr) (((unsigned long)(addr)-swap_start) >> PAGE_SHIFT)
+#define SWAP_NR(addr) (((addr) - swap_start) >> PAGE_SHIFT)
/* get address of swap page #'nr' */
-#define SWAP_ADDR(nr) ((void *)(swap_start + ((nr)<<PAGE_SHIFT)))
+#define SWAP_ADDR(nr) (swap_start + ((nr) << PAGE_SHIFT))
/* get number of pages for 'n' bytes (already page-aligned) */
#define N_PAGES(n) ((n) >> PAGE_SHIFT)
@@ -144,11 +150,8 @@
#define MAX_STRAM_FRACTION_NOM 1
#define MAX_STRAM_FRACTION_DENOM 3
-/* Start and end of the (pre-mem_init) reserved ST-RAM region */
-static unsigned long rsvd_stram_beg, rsvd_stram_end;
-
/* Start and end (virtual) of ST-RAM */
-static unsigned long stram_start, stram_end;
+static void *stram_start, *stram_end;
/* set after memory_init() executed and allocations via start_mem aren't
* possible anymore */
@@ -159,7 +162,7 @@ static int kernel_in_stram;
typedef struct stram_block {
struct stram_block *next;
- unsigned long start;
+ void *start;
unsigned long size;
unsigned flags;
const char *owner;
@@ -168,7 +171,6 @@ typedef struct stram_block {
/* values for flags field */
#define BLOCK_FREE 0x01 /* free structure in the BLOCKs pool */
#define BLOCK_KMALLOCED 0x02 /* structure allocated by kmalloc() */
-#define BLOCK_STATIC 0x04 /* pre-mem_init() allocated block */
#define BLOCK_GFP 0x08 /* block allocated with __get_dma_pages() */
#define BLOCK_INSWAP 0x10 /* block allocated in swap space */
@@ -191,7 +193,7 @@ static BLOCK static_blocks[N_STATIC_BLOCKS];
static int max_swap_size = -1;
/* start and end of swapping area */
-static unsigned long swap_start, swap_end;
+static void *swap_start, *swap_end;
/* The ST-RAM's swap info structure */
static struct swap_info_struct *stram_swap_info;
@@ -215,7 +217,6 @@ static DECLARE_MUTEX(stram_swap_sem);
#ifdef DO_PROC
static unsigned stat_swap_read = 0;
static unsigned stat_swap_write = 0;
-static unsigned stat_swap_move = 0;
static unsigned stat_swap_force = 0;
#endif /* DO_PROC */
@@ -224,21 +225,19 @@ static unsigned stat_swap_force = 0;
/***************************** Prototypes *****************************/
#ifdef CONFIG_STRAM_SWAP
-static int swap_init( unsigned long start_mem, unsigned long swap_data );
+static int swap_init(void *start_mem, void *swap_data);
static void *get_stram_region( unsigned long n_pages );
static void free_stram_region( unsigned long offset, unsigned long n_pages
);
-static int in_some_region( unsigned long addr );
+static int in_some_region(void *addr);
static unsigned long find_free_region( unsigned long n_pages, unsigned long
*total_free, unsigned long
*region_free );
-static void do_stram_request( void );
+static void do_stram_request(request_queue_t *);
static int stram_open( struct inode *inode, struct file *filp );
static int stram_release( struct inode *inode, struct file *filp );
-static void do_z2_request( void );
#endif
-static int get_gfp_order( unsigned long size );
-static void reserve_region( unsigned long addr, unsigned long end );
+static void reserve_region(void *start, void *end);
static BLOCK *add_region( void *addr, unsigned long size );
static BLOCK *find_region( void *addr );
static int remove_region( BLOCK *block );
@@ -264,14 +263,12 @@ void __init atari_stram_init(void)
/* determine whether kernel code resides in ST-RAM (then ST-RAM is the
* first memory block at virtual 0x0) */
- stram_start = (unsigned long)phys_to_virt(0);
+ stram_start = phys_to_virt(0);
kernel_in_stram = (stram_start == 0);
for( i = 0; i < m68k_num_memory; ++i ) {
if (m68k_memory[i].addr == 0) {
/* skip first 2kB or page (supervisor-only!) */
- rsvd_stram_beg = stram_start + ALIGN_IF_SWAP(0x800);
- rsvd_stram_end = rsvd_stram_beg;
stram_end = stram_start + m68k_memory[i].size;
return;
}
@@ -282,10 +279,10 @@ void __init atari_stram_init(void)
/*
- * This function is called from mem_init() to reserve the pages needed for
+ * This function is called from setup_arch() to reserve the pages needed for
* ST-RAM management.
*/
-void __init atari_stram_reserve_pages(unsigned long start_mem)
+void __init atari_stram_reserve_pages(void *start_mem)
{
#ifdef CONFIG_STRAM_SWAP
/* if max_swap_size is negative (i.e. no stram_swap= option given),
@@ -299,42 +296,24 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
max_swap_size =
(!MACH_IS_HADES &&
(N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <=
- max_mapnr*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
+ (high_memory>>PAGE_SHIFT)*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size );
#endif
/* always reserve first page of ST-RAM, the first 2 kB are
* supervisor-only! */
- set_bit( PG_reserved, &virt_to_page(stram_start)->flags );
+ if (!kernel_in_stram)
+ reserve_bootmem (0, PAGE_SIZE);
#ifdef CONFIG_STRAM_SWAP
- if (!max_swap_size) {
- fallback:
-#endif
- DPRINTK( "atari_stram_reserve_pages: swapping disabled\n" );
- if (!kernel_in_stram) {
- /* Reserve all pages that have been marked by pre-mem_init
- * stram_alloc() (e.g. for the screen memory). */
- reserve_region( rsvd_stram_beg, rsvd_stram_end );
- DPRINTK( "atari_stram_reserve_pages: reseverved %08lx-%08lx\n",
- rsvd_stram_beg, rsvd_stram_end );
- }
- /* else (kernel in ST-RAM): nothing to do, ST-RAM buffers are
- * kernel data */
-#ifdef CONFIG_STRAM_SWAP
- }
- else {
- unsigned long swap_data;
- BLOCK *p;
-
- /* determine first page to use as swap:
- * if the kernel is in TT-RAM, this is the first page of (usable)
- * ST-RAM; else if there were already some allocations (probable...),
- * use the lowest address of these (the list is sorted by address!);
- * otherwise just use the end of kernel data (= start_mem) */
- swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE :
- alloc_list ? alloc_list->start :
- start_mem;
+ {
+ void *swap_data;
+
+ start_mem = (void *) PAGE_ALIGN ((unsigned long) start_mem);
+ /* determine first page to use as swap: if the kernel is
+ in TT-RAM, this is the first page of (usable) ST-RAM;
+ otherwise just use the end of kernel data (= start_mem) */
+ swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : start_mem;
/* decrement by one page, rest of kernel assumes that first swap page
* is always reserved and maybe doesn't handle SWP_ENTRY == 0
* correctly */
@@ -343,7 +322,7 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
if (swap_end-swap_start > max_swap_size)
swap_end = swap_start + max_swap_size;
DPRINTK( "atari_stram_reserve_pages: swapping enabled; "
- "swap=%08lx-%08lx\n", swap_start, swap_end );
+ "swap=%p-%p\n", swap_start, swap_end);
/* reserve some amount of memory for maintainance of
* swapping itself: one page for each 2048 (PAGE_SIZE/2)
@@ -352,24 +331,18 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
>> (PAGE_SHIFT-1)) << PAGE_SHIFT;
/* correct swap_start if necessary */
- if (swap_start == swap_data)
- swap_start = start_mem;
+ if (swap_start + PAGE_SIZE == swap_data)
+ swap_start = start_mem - PAGE_SIZE;
if (!swap_init( start_mem, swap_data )) {
printk( KERN_ERR "ST-RAM swap space initialization failed\n" );
max_swap_size = 0;
- goto fallback;
+ return;
}
/* reserve region for swapping meta-data */
- reserve_region( swap_data, start_mem );
+ reserve_region(swap_data, start_mem);
/* reserve swapping area itself */
- reserve_region( swap_start+PAGE_SIZE, swap_end );
-
- /* Formerly static areas have been included in the swap area. */
- for( p = alloc_list; p; p = p->next ) {
- if (p->flags & BLOCK_STATIC)
- p->flags = (p->flags & ~BLOCK_STATIC) | BLOCK_INSWAP;
- }
+ reserve_region(swap_start + PAGE_SIZE, swap_end);
/*
* If the whole ST-RAM is used for swapping, there are no allocatable
@@ -387,15 +360,12 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
* You just will get non-DMA-able memory...
*/
mach_max_dma_address = 0xffffffff;
-
- /*
- * Ok, num_physpages needs not be really exact, but it's better to
- * subtract the pages set aside for swapping.
- */
- num_physpages -= SWAP_NR(swap_end)-1;
}
#endif
-
+}
+
+void atari_stram_mem_init_hook (void)
+{
mem_init_done = 1;
}
@@ -420,68 +390,33 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
* likely to fail :-(
*
*/
-void *atari_stram_alloc( long size, unsigned long *start_mem,
- const char *owner )
+void *atari_stram_alloc(long size, const char *owner)
{
void *addr = NULL;
BLOCK *block;
int flags;
- DPRINTK( "atari_stram_alloc(size=%08lx,*start_mem=%08lx,owner=%s)\n",
- size, start_mem ? *start_mem : 0xffffffff, owner );
-
- if (start_mem && mem_init_done) {
- printk( KERN_ERR "atari_stram_alloc called with start_mem!=NULL "
- "after mem_init() from %p\n", __builtin_return_address(0) );
- return( NULL );
- }
- if (!start_mem && !mem_init_done) {
- printk( KERN_ERR "atari_stram_alloc called with start_mem==NULL "
- "before mem_init() from %p\n", __builtin_return_address(0) );
- return( NULL );
- }
+ DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
size = ALIGN_IF_SWAP(size);
DPRINTK( "atari_stram_alloc: rounded size = %08lx\n", size );
- if (!mem_init_done) {
- /* before mem_init(): allocate "statically", i.e. either in the kernel
- * data space (current end in *start_mem), or at the end of currently
- * reserved ST-RAM. */
- if (kernel_in_stram) {
- /* Get memory from kernel data space */
- *start_mem = ALIGN_IF_SWAP(*start_mem);
- addr = (void *)*start_mem;
- *start_mem += size;
- DPRINTK( "atari_stram_alloc: pre-mem_init and k/ST: "
- "shifted start_mem to %08lx, addr=%p\n",
- *start_mem, addr );
- }
- else {
- /* Get memory from rsvd_stram_beg */
- if (rsvd_stram_end + size < stram_end) {
- addr = (void *) rsvd_stram_end;
- rsvd_stram_end += size;
- DPRINTK( "atari_stram_alloc: pre-mem_init and k/TT: "
- "shifted rsvd_stram_end to %08lx, addr=%p\n",
- rsvd_stram_end, addr );
- }
- }
- flags = BLOCK_STATIC;
- }
#ifdef CONFIG_STRAM_SWAP
- else if (max_swap_size) {
- /* If swapping is active (can only be the case after mem_init()!):
- * make some free space in the swap "device". */
+ if (max_swap_size) {
+ /* If swapping is active: make some free space in the swap
+ "device". */
DPRINTK( "atari_stram_alloc: after mem_init, swapping ok, "
"calling get_region\n" );
addr = get_stram_region( N_PAGES(size) );
flags = BLOCK_INSWAP;
}
+ else
#endif
+ if (!mem_init_done)
+ return alloc_bootmem_low(size);
else {
/* After mem_init() and no swapping: can only resort to
* __get_dma_pages() */
- addr = (void *)__get_dma_pages(GFP_KERNEL, get_gfp_order(size));
+ addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
flags = BLOCK_GFP;
DPRINTK( "atari_stram_alloc: after mem_init, swapping off, "
"get_pages=%p\n", addr );
@@ -492,14 +427,12 @@ void *atari_stram_alloc( long size, unsigned long *start_mem,
/* out of memory for BLOCK structure :-( */
DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
"freeing again\n" );
- if (flags == BLOCK_STATIC)
- rsvd_stram_end -= size;
#ifdef CONFIG_STRAM_SWAP
- else if (flags == BLOCK_INSWAP)
+ if (flags == BLOCK_INSWAP)
free_stram_region( SWAP_NR(addr), N_PAGES(size) );
-#endif
else
- free_pages( (unsigned long)addr, get_gfp_order(size));
+#endif
+ free_pages((unsigned long)addr, get_order(size));
return( NULL );
}
block->owner = owner;
@@ -527,15 +460,15 @@ void atari_stram_free( void *addr )
if (!max_swap_size) {
#endif
if (block->flags & BLOCK_GFP) {
- DPRINTK( "atari_stram_free: is kmalloced, order_size=%d\n",
- get_gfp_order(block->size) );
- free_pages( (unsigned long)addr, get_gfp_order(block->size) );
+ DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
+ get_order(block->size));
+ free_pages((unsigned long)addr, get_order(block->size));
}
else
goto fail;
#ifdef CONFIG_STRAM_SWAP
}
- else if (block->flags & (BLOCK_INSWAP|BLOCK_STATIC)) {
+ else if (block->flags & BLOCK_INSWAP) {
DPRINTK( "atari_stram_free: is swap-alloced\n" );
free_stram_region( SWAP_NR(block->start), N_PAGES(block->size) );
}
@@ -563,17 +496,18 @@ void atari_stram_free( void *addr )
* Initialize ST-RAM swap device
* (lots copied and modified from sys_swapon() in mm/swapfile.c)
*/
-static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
+static int __init swap_init(void *start_mem, void *swap_data)
{
- static struct dentry fake_dentry[3];
+ static struct dentry fake_dentry;
+ static struct vfsmount fake_vfsmnt;
struct swap_info_struct *p;
struct inode swap_inode;
unsigned int type;
- unsigned long addr;
+ void *addr;
int i, j, k, prev;
- DPRINTK( "swap_init(start_mem=%08lx, swap_data=%08lx)\n",
- start_mem, swap_data );
+ DPRINTK("swap_init(start_mem=%p, swap_data=%p)\n",
+ start_mem, swap_data);
/* need at least one page for swapping to (and this also isn't very
* much... :-) */
@@ -598,18 +532,16 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
stram_swap_type = type;
/* fake some dir cache entries to give us some name in /dev/swaps */
- fake_dentry[0].d_covers = &fake_dentry[1];
- fake_dentry[0].d_parent = &fake_dentry[0];
- fake_dentry[1].d_parent = &fake_dentry[2];
- fake_dentry[1].d_name.name = "stram (internal)";
- fake_dentry[1].d_name.len = 16;
- fake_dentry[2].d_covers = &fake_dentry[2];
- fake_dentry[2].d_parent = &fake_dentry[2];
+ fake_dentry.d_parent = &fake_dentry;
+ fake_dentry.d_name.name = "stram (internal)";
+ fake_dentry.d_name.len = 16;
+ fake_vfsmnt.mnt_parent = &fake_vfsmnt;
p->flags = SWP_USED;
- p->swap_file = &fake_dentry[0];
+ p->swap_file = &fake_dentry;
+ p->swap_vfsmnt = &fake_vfsmnt;
p->swap_device = 0;
- p->swap_map = (unsigned short *)swap_data;
+ p->swap_map = swap_data;
p->cluster_nr = 0;
p->next = -1;
p->prio = 0x7ff0; /* a rather high priority, but not the higest
@@ -628,7 +560,7 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
k = 0; /* # of already allocated pages (from pre-mem_init stram_alloc()) */
p->lowest_bit = 0;
p->highest_bit = 0;
- for( i = 1, addr = (unsigned long)SWAP_ADDR(1); i < p->max;
+ for( i = 1, addr = SWAP_ADDR(1); i < p->max;
i++, addr += PAGE_SIZE ) {
if (in_some_region( addr )) {
p->swap_map[i] = SWAP_MAP_BAD;
@@ -685,8 +617,8 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
* what to do if a write is requested later.
*/
static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
- address, pte_t *dir, unsigned long entry,
- unsigned long page /*, int isswap */)
+ address, pte_t *dir, swp_entry_t entry,
+ struct page *page)
{
pte_t pte = *dir;
@@ -698,34 +630,25 @@ static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
memory */
if (pte_page(pte) != page)
return;
- if (0 /* isswap */)
- virt_to_page(pte_page(pte))->offset = page;
- else
- /* We will be removing the swap cache in a moment, so... */
- set_pte(dir, pte_mkdirty(pte));
+ /* We will be removing the swap cache in a moment, so... */
+ set_pte(dir, pte_mkdirty(pte));
return;
}
- if (pte_val(pte) != entry)
+ if (pte_val(pte) != entry.val)
return;
- if (0 /* isswap */) {
- DPRINTK( "unswap_pte: replacing entry %08lx by %08lx", entry, page );
- set_pte(dir, __pte(page));
- }
- else {
- DPRINTK( "unswap_pte: replacing entry %08lx by new page %08lx",
- entry, page );
- set_pte(dir, pte_mkdirty(__mk_pte(page,vma->vm_page_prot)));
- atomic_inc(&virt_to_page(page)->count);
- ++vma->vm_mm->rss;
- }
+ DPRINTK("unswap_pte: replacing entry %08lx by new page %p",
+ entry.val, page);
+ set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
swap_free(entry);
+ get_page(page);
+ ++vma->vm_mm->rss;
}
static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
unsigned long address, unsigned long size,
- unsigned long offset, unsigned long entry,
- unsigned long page /* , int isswap */)
+ unsigned long offset, swp_entry_t entry,
+ struct page *page)
{
pte_t * pte;
unsigned long end;
@@ -733,7 +656,7 @@ static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
if (pmd_none(*dir))
return;
if (pmd_bad(*dir)) {
- printk("unswap_pmd: bad pmd (%08lx)\n", pmd_val(*dir));
+ pmd_ERROR(*dir);
pmd_clear(dir);
return;
}
@@ -744,8 +667,7 @@ static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
if (end > PMD_SIZE)
end = PMD_SIZE;
do {
- unswap_pte(vma, offset+address-vma->vm_start, pte, entry,
- page /* , isswap */);
+ unswap_pte(vma, offset+address-vma->vm_start, pte, entry, page);
address += PAGE_SIZE;
pte++;
} while (address < end);
@@ -753,8 +675,7 @@ static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
unsigned long address, unsigned long size,
- unsigned long entry, unsigned long page
- /* , int isswap */)
+ swp_entry_t entry, struct page *page)
{
pmd_t * pmd;
unsigned long offset, end;
@@ -762,7 +683,7 @@ static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
if (pgd_none(*dir))
return;
if (pgd_bad(*dir)) {
- printk("unswap_pgd: bad pgd (%08lx)\n", pgd_val(*dir));
+ pgd_ERROR(*dir);
pgd_clear(dir);
return;
}
@@ -774,28 +695,26 @@ static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
end = PGDIR_SIZE;
do {
unswap_pmd(vma, pmd, address, end - address, offset, entry,
- page /* , isswap */);
+ page);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
}
static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir,
- unsigned long entry, unsigned long page
- /* , int isswap */)
+ swp_entry_t entry, struct page *page)
{
unsigned long start = vma->vm_start, end = vma->vm_end;
- while (start < end) {
- unswap_pgd(vma, pgdir, start, end - start, entry, page
- /* , isswap */);
+ do {
+ unswap_pgd(vma, pgdir, start, end - start, entry, page);
start = (start + PGDIR_SIZE) & PGDIR_MASK;
pgdir++;
- }
+ } while (start < end);
}
-static void unswap_process(struct mm_struct * mm, unsigned long entry,
- unsigned long page /* , int isswap */)
+static void unswap_process(struct mm_struct * mm, swp_entry_t entry,
+ struct page *page)
{
struct vm_area_struct* vma;
@@ -806,110 +725,18 @@ static void unswap_process(struct mm_struct * mm, unsigned long entry,
return;
for (vma = mm->mmap; vma; vma = vma->vm_next) {
pgd_t * pgd = pgd_offset(mm, vma->vm_start);
- unswap_vma(vma, pgd, entry, page /* , isswap */);
+ unswap_vma(vma, pgd, entry, page);
}
}
-#if 0
-static int unswap_by_move(unsigned short *map, unsigned long max,
- unsigned long start, unsigned long n_pages)
-{
- struct task_struct *p;
- unsigned long entry, rover = (start == 1) ? n_pages+1 : 1;
- unsigned long i, j;
-
- DPRINTK( "unswapping %lu..%lu by moving in swap\n",
- start, start+n_pages-1 );
-
- /* can free the allocated pages by moving them to other swap pages */
- for( i = start; i < start+n_pages; ++i ) {
- if (!map[i]) {
- map[i] = SWAP_MAP_BAD;
- DPRINTK( "unswap: page %lu was free\n", i );
- continue;
- }
- else if (map[i] == SWAP_MAP_BAD) {
- printk( KERN_ERR "get_stram_region: page %lu already "
- "reserved??\n", i );
- }
- DPRINTK( "unswap: page %lu is alloced, count=%u\n", i, map[i] );
-
- /* find a free page not in our region */
- for( j = rover; j != rover-1; j = (j == max-1) ? 1 : j+1 ) {
- if (j >= start && j < start+n_pages)
- continue;
- if (!map[j]) {
- rover = j+1;
- break;
- }
- }
- if (j == rover-1) {
- printk( KERN_ERR "get_stram_region: not enough free swap "
- "pages now??\n" );
- return( -ENOMEM );
- }
- DPRINTK( "unswap: map[i=%lu]=%u map[j=%lu]=%u nr_swap=%u\n",
- i, map[i], j, map[j], nr_swap_pages );
-
- --nr_swap_pages;
- entry = SWP_ENTRY( stram_swap_type, j );
- if (stram_swap_info->lowest_bit == j)
- stram_swap_info->lowest_bit++;
- if (stram_swap_info->highest_bit == j)
- stram_swap_info->highest_bit--;
-
- memcpy( SWAP_ADDR(j), SWAP_ADDR(i), PAGE_SIZE );
-#ifdef DO_PROC
- stat_swap_move++;
-#endif
-
- while( map[i] ) {
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (unswap_process( p->mm, SWP_ENTRY( stram_swap_type, i ),
- entry, 1 )) {
- read_unlock(&tasklist_lock);
- map[j]++;
- goto repeat;
- }
- }
- read_unlock(&tasklist_lock);
- if (map[i] && map[i] != SWAP_MAP_MAX) {
- printk( KERN_ERR "get_stram_region: ST-RAM swap page %lu "
- "not used by any process\n", i );
- /* quit while loop and overwrite bad map entry */
- break;
- }
- else if (!map[i]) {
- /* somebody else must have swapped in that page, so free the
- * new one (we're moving to) */
- DPRINTK( "unswap: map[i] became 0, also clearing map[j]\n" );
- map[j] = 0;
- }
- repeat:
- }
-
- DPRINTK( "unswap: map[i=%lu]=%u map[j=%lu]=%u nr_swap=%u\n",
- i, map[i], j, map[j], nr_swap_pages );
- map[i] = SWAP_MAP_BAD;
- if (stram_swap_info->lowest_bit == i)
- stram_swap_info->lowest_bit++;
- if (stram_swap_info->highest_bit == i)
- stram_swap_info->highest_bit--;
- --nr_swap_pages;
- }
- return( 0 );
-}
-#endif
-
static int unswap_by_read(unsigned short *map, unsigned long max,
unsigned long start, unsigned long n_pages)
{
struct task_struct *p;
- unsigned long entry, page;
+ struct page *page;
+ swp_entry_t entry;
unsigned long i;
- struct page *page_map;
DPRINTK( "unswapping %lu..%lu by reading in\n",
start, start+n_pages-1 );
@@ -932,28 +759,24 @@ static int unswap_by_read(unsigned short *map, unsigned long max,
/* Get a page for the entry, using the existing
swap cache page if there is one. Otherwise,
get a clean page and read the swap into it. */
- page_map = read_swap_cache(entry);
- if (page_map) {
- page = (unsigned long) page_address(page_map);
- read_lock(&tasklist_lock);
- for_each_task(p)
- unswap_process(p->mm, entry, page
- /* , 0 */);
- read_unlock(&tasklist_lock);
- shm_unuse(entry, page);
- /* Now get rid of the extra reference to
- the temporary page we've been using. */
- if (PageSwapCache(page_map))
- delete_from_swap_cache(page_map);
- __free_page(page_map);
- #ifdef DO_PROC
- stat_swap_force++;
- #endif
- }
- else {
+ page = read_swap_cache(entry);
+ if (!page) {
swap_free(entry);
return -ENOMEM;
}
+ read_lock(&tasklist_lock);
+ for_each_task(p)
+ unswap_process(p->mm, entry, page);
+ read_unlock(&tasklist_lock);
+ shm_unuse(entry, page);
+ /* Now get rid of the extra reference to the
+ temporary page we've been using. */
+ if (PageSwapCache(page))
+ delete_from_swap_cache(page);
+ __free_page(page);
+ #ifdef DO_PROC
+ stat_swap_force++;
+ #endif
}
DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n",
@@ -998,14 +821,7 @@ static void *get_stram_region( unsigned long n_pages )
DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n",
start, region_free );
-#if 0
- err = ((total_free-region_free >= n_pages-region_free) ?
- unswap_by_move( map, max, start, n_pages ) :
- unswap_by_read( map, max, start, n_pages ));
-#else
err = unswap_by_read(map, max, start, n_pages);
-#endif
-
if (err)
goto end;
@@ -1062,7 +878,7 @@ static void free_stram_region( unsigned long offset, unsigned long n_pages )
/* is addr in some of the allocated regions? */
-static int in_some_region( unsigned long addr )
+static int in_some_region(void *addr)
{
BLOCK *p;
@@ -1164,17 +980,13 @@ static int stram_sizes[14] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static int refcnt = 0;
-static void do_stram_request( void )
+static void do_stram_request(request_queue_t *q)
{
- unsigned long start, len;
-
- while( !QUEUE_EMPTY ) {
- if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
- panic("stram: request list destroyed");
- if (CURRENT->bh) {
- if (!buffer_locked(CURRENT->bh))
- panic("stram: block not locked");
- }
+ void *start;
+ unsigned long len;
+
+ while (1) {
+ INIT_REQUEST;
start = swap_start + (CURRENT->sector << 9);
len = CURRENT->current_nr_sectors << 9;
@@ -1188,13 +1000,13 @@ static void do_stram_request( void )
}
if (CURRENT->cmd == READ) {
- memcpy( CURRENT->buffer, (char *)start, len );
+ memcpy(CURRENT->buffer, start, len);
#ifdef DO_PROC
stat_swap_read += N_PAGES(len);
#endif
}
else {
- memcpy( (char *)start, CURRENT->buffer, len );
+ memcpy(start, CURRENT->buffer, len);
#ifdef DO_PROC
stat_swap_write += N_PAGES(len);
#endif
@@ -1251,19 +1063,15 @@ int __init stram_device_init(void)
return( -ENXIO );
}
- blk_dev[STRAM_MAJOR].request_fn = do_stram_request;
+ blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request);
blksize_size[STRAM_MAJOR] = stram_blocksizes;
stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024;
blk_size[STRAM_MAJOR] = stram_sizes;
register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops,
(swap_end-swap_start)>>9);
- do_z2_request(); /* to avoid warning */
return( 0 );
}
-/* to avoid warning */
-static void do_z2_request( void ) { }
-
#endif /* CONFIG_STRAM_SWAP */
@@ -1271,30 +1079,10 @@ static void do_z2_request( void ) { }
/* Misc Utility Functions */
/* ------------------------------------------------------------------------ */
-
-/* return log2 of #pages for size */
-static int get_gfp_order( unsigned long size )
+/* reserve a range of pages */
+static void reserve_region(void *start, void *end)
{
- int order;
-
- size = N_PAGES( size + PAGE_SIZE -1 );
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
-
- return( order );
-}
-
-
-/* reserve a range of pages in mem_map[] */
-static void reserve_region( unsigned long addr, unsigned long end )
-{
- mem_map_t *mapp = virt_to_page(addr);
-
- for( ; addr < end; addr += PAGE_SIZE, ++mapp )
- set_bit( PG_reserved, &mapp->flags );
+ reserve_bootmem (virt_to_phys(start), end - start);
}
@@ -1328,11 +1116,11 @@ static BLOCK *add_region( void *addr, unsigned long size )
printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" );
return( NULL );
}
- n->start = (unsigned long)addr;
+ n->start = addr;
n->size = size;
for( p = &alloc_list; *p; p = &((*p)->next) )
- if ((*p)->start > (unsigned long)addr) break;
+ if ((*p)->start > addr) break;
n->next = *p;
*p = n;
@@ -1346,9 +1134,9 @@ static BLOCK *find_region( void *addr )
BLOCK *p;
for( p = alloc_list; p; p = p->next ) {
- if (p->start == (unsigned long)addr)
+ if (p->start == addr)
return( p );
- if (p->start > (unsigned long)addr)
+ if (p->start > addr)
break;
}
return( NULL );
@@ -1405,14 +1193,13 @@ int get_stram_list( char *buf )
++used;
}
PRINT_PROC(
- "Total ST-RAM: %8lu kB\n"
+ "Total ST-RAM: %8u kB\n"
"Total ST-RAM swap: %8lu kB\n"
"Free swap: %8u kB\n"
"Used swap: %8u kB\n"
"Allocated swap: %8u kB\n"
"Swap Reads: %8u\n"
"Swap Writes: %8u\n"
- "Swap Moves: %8u\n"
"Swap Forced Reads: %8u\n",
(stram_end - stram_start) >> 10,
(max-1) << (PAGE_SHIFT-10),
@@ -1421,17 +1208,13 @@ int get_stram_list( char *buf )
rsvd << (PAGE_SHIFT-10),
stat_swap_read,
stat_swap_write,
- stat_swap_move,
stat_swap_force );
}
else {
#endif
PRINT_PROC( "ST-RAM swapping disabled\n" );
- PRINT_PROC(
- "Total ST-RAM: %8lu kB\n"
- "Reserved ST-RAM: %8lu kB\n",
- (stram_end - stram_start) >> 10,
- (rsvd_stram_end - rsvd_stram_beg) >> 10 );
+ PRINT_PROC("Total ST-RAM: %8u kB\n",
+ (stram_end - stram_start) >> 10);
#ifdef CONFIG_STRAM_SWAP
}
#endif
@@ -1441,12 +1224,10 @@ int get_stram_list( char *buf )
if (len + 50 >= PAGE_SIZE)
break;
PRINT_PROC("0x%08lx-0x%08lx: %s (",
- virt_to_phys((void *)p->start),
- virt_to_phys((void *)p->start+p->size-1),
+ virt_to_phys(p->start),
+ virt_to_phys(p->start+p->size-1),
p->owner);
- if (p->flags & BLOCK_STATIC)
- PRINT_PROC( "static)\n" );
- else if (p->flags & BLOCK_GFP)
+ if (p->flags & BLOCK_GFP)
PRINT_PROC( "page-alloced)\n" );
else if (p->flags & BLOCK_INSWAP)
PRINT_PROC( "in swap)\n" );
diff --git a/arch/m68k/fpsp040/bindec.S b/arch/m68k/fpsp040/bindec.S
index ef3a627bf..9fb65e320 100644
--- a/arch/m68k/fpsp040/bindec.S
+++ b/arch/m68k/fpsp040/bindec.S
@@ -484,7 +484,7 @@ A9_str:
fmovex (%a0),%fp0 |load X from memory
fabsx %fp0 |use abs(X)
tstw %d5 |LAMBDA is in lower word of d5
- bnes sc_mul |if neg (LAMBDA = 1), scale by mul
+ bne sc_mul |if neg (LAMBDA = 1), scale by mul
fdivx %fp1,%fp0 |calculate X / SCALE -> Y to fp0
bras A10_st |branch to A10
diff --git a/arch/m68k/fpsp040/decbin.S b/arch/m68k/fpsp040/decbin.S
index af1279a4a..d2bf1b641 100644
--- a/arch/m68k/fpsp040/decbin.S
+++ b/arch/m68k/fpsp040/decbin.S
@@ -230,7 +230,7 @@ nextlw:
|
m_sign:
btst #31,(%a0) |test sign of the mantissa
- beqs ap_st_z |if clear, go to append/strip zeros
+ beq ap_st_z |if clear, go to append/strip zeros
fnegx %fp0 |if set, negate fp0
|
@@ -288,7 +288,7 @@ ap_st_z:
cmpl #27,%d1 |test is with 27
ble pwrten |if abs(expA) <28, skip ap/st zeros
btst #30,(%a0) |check sign of exp
- bnes ap_st_n |if neg, go to neg side
+ bne ap_st_n |if neg, go to neg side
clrl %d1 |zero count reg
movel (%a0),%d4 |load lword 1 to d4
bfextu %d4{#28:#4},%d0 |get M16 in d0
@@ -336,7 +336,7 @@ ap_p_en:
tstl %d0 |check if d0 is zero
bnes ap_p_el |if not, get next bit
fmulx %fp1,%fp0 |mul mantissa by 10**(no_bits_shifted)
- bras pwrten |go calc pwrten
+ bra pwrten |go calc pwrten
|
| This section handles a negative adjusted exponent.
|
diff --git a/arch/m68k/fpsp040/do_func.S b/arch/m68k/fpsp040/do_func.S
index 2df0c3700..0a9c776f0 100644
--- a/arch/m68k/fpsp040/do_func.S
+++ b/arch/m68k/fpsp040/do_func.S
@@ -77,7 +77,7 @@ not_fmovecr:
movew CMDREG1B(%a6),%d0
andl #0x7F,%d0
cmpil #0x38,%d0 |if the extension is >= $38,
- bges serror |it is illegal
+ bge serror |it is illegal
bfextu STAG(%a6){#0:#3},%d1
lsll #3,%d0 |make room for STAG
addl %d1,%d0 |combine for final index into table
diff --git a/arch/m68k/fpsp040/get_op.S b/arch/m68k/fpsp040/get_op.S
index 2bd236d45..480405d4f 100644
--- a/arch/m68k/fpsp040/get_op.S
+++ b/arch/m68k/fpsp040/get_op.S
@@ -171,7 +171,7 @@ PTENRP:
get_op:
clrb DY_MO_FLG(%a6)
tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
- beqs uni_getop
+ beq uni_getop
uns_getop:
btstb #direction_bit,CMDREG1B(%a6)
diff --git a/arch/m68k/fpsp040/util.S b/arch/m68k/fpsp040/util.S
index e59b352ab..cc9ae013b 100644
--- a/arch/m68k/fpsp040/util.S
+++ b/arch/m68k/fpsp040/util.S
@@ -138,20 +138,20 @@ ovf_e1_exc:
|
ovf_fsgl:
clrl %d0
- bras ovf_res
+ bra ovf_res
ovff_sgl:
movel #0x00000001,%d0 |set single
- bras ovf_res
+ bra ovf_res
ovff_dbl:
movel #0x00000002,%d0 |set double
- bras ovf_res
+ bra ovf_res
|
| The precision is in the fpcr.
|
ovf_fpcr:
bfextu FPCR_MODE(%a6){#0:#2},%d0 |set round precision
- bras ovf_res
+ bra ovf_res
|
|
diff --git a/arch/m68k/fpsp040/x_store.S b/arch/m68k/fpsp040/x_store.S
index a3468f338..b3357fd65 100644
--- a/arch/m68k/fpsp040/x_store.S
+++ b/arch/m68k/fpsp040/x_store.S
@@ -92,7 +92,7 @@ opc011:
cmpil #0,%d0 |if dest format is extended
beq dest_ext |then branch
cmpil #1,%d0 |if dest format is single
- beqs dest_sgl |then branch
+ beq dest_sgl |then branch
|
| fall through to dest_dbl
|
diff --git a/arch/m68k/ifpsp060/os.S b/arch/m68k/ifpsp060/os.S
index 4bbf86f96..037aa6c00 100644
--- a/arch/m68k/ifpsp060/os.S
+++ b/arch/m68k/ifpsp060/os.S
@@ -85,21 +85,20 @@
|
.global _060_dmem_write
_060_dmem_write:
+ subq.l #1,%d0
btst #0x5,0x4(%a6) | check for supervisor state
beqs user_write
super_write:
move.b (%a0)+,(%a1)+ | copy 1 byte
- subq.l #0x1,%d0 | decr byte counter
- bnes super_write | quit if ctr = 0
+ dbra %d0,super_write | quit if --ctr < 0
clr.l %d1 | return success
rts
user_write:
- move.l %d0,-(%sp) | pass: counter
- move.l %a1,-(%sp) | pass: user dst
- move.l %a0,-(%sp) | pass: supervisor src
- bsr.l _copyout | write byte to user mem
- move.l %d0,%d1 | return success
- add.l #0xc, %sp | clear 3 lw params
+ move.b (%a0)+,%d1 | copy 1 byte
+copyoutae:
+ movs.b %d1,(%a1)+
+ dbra %d0,user_write | quit if --ctr < 0
+ clr.l %d1 | return success
rts
|
@@ -119,21 +118,20 @@ user_write:
.global _060_dmem_read
_060_imem_read:
_060_dmem_read:
+ subq.l #1,%d0
btst #0x5,0x4(%a6) | check for supervisor state
beqs user_read
super_read:
move.b (%a0)+,(%a1)+ | copy 1 byte
- subq.l #0x1,%d0 | decr byte counter
- bnes super_read | quit if ctr = 0
+ dbra %d0,super_read | quit if --ctr < 0
clr.l %d1 | return success
rts
user_read:
- move.l %d0,-(%sp) | pass: counter
- move.l %a1,-(%sp) | pass: super dst
- move.l %a0,-(%sp) | pass: user src
- bsr.l _copyin | read byte from user mem
- move.l %d0,%d1 | return success
- add.l #0xc,%sp | clear 3 lw params
+copyinae:
+ movs.b (%a0)+,%d1
+ move.b %d1,(%a1)+ | copy 1 byte
+ dbra %d0,user_read | quit if --ctr < 0
+ clr.l %d1 | return success
rts
|
@@ -150,14 +148,13 @@ user_read:
|
.global _060_dmem_read_byte
_060_dmem_read_byte:
+ clr.l %d0 | clear whole longword
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrbs | supervisor
-dmrbu: clr.l %d0 | clear whole longword
dmrbuae:movs.b (%a0),%d0 | fetch user byte
- bras dmrbr
-dmrbs: clr.l %d0 | clear whole longword
- move.b (%a0),%d0 | fetch super byte
-dmrbr: clr.l %d1 | return success
+ rts
+dmrbs: move.b (%a0),%d0 | fetch super byte
rts
|
@@ -187,14 +184,13 @@ dmrbr: clr.l %d1 | return success
.global _060_imem_read_word
_060_dmem_read_word:
_060_imem_read_word:
+ clr.l %d1 | assume success
+ clr.l %d0 | clear whole longword
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrws | supervisor
-dmrwu: clr.l %d0 | clear whole longword
dmrwuae:movs.w (%a0), %d0 | fetch user word
- bras dmrwr
-dmrws: clr.l %d0 | clear whole longword
- move.w (%a0), %d0 | fetch super word
-dmrwr: clr.l %d1 | return success
+ rts
+dmrws: move.w (%a0), %d0 | fetch super word
rts
|
@@ -224,13 +220,12 @@ dmrwr: clr.l %d1 | return success
.global _060_imem_read_long
_060_dmem_read_long:
_060_imem_read_long:
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrls | supervisor
-dmrlu:
dmrluae:movs.l (%a0),%d0 | fetch user longword
- bras dmrlr
+ rts
dmrls: move.l (%a0),%d0 | fetch super longword
-dmrlr: clr.l %d1 | return success
rts
|
@@ -247,13 +242,12 @@ dmrlr: clr.l %d1 | return success
|
.global _060_dmem_write_byte
_060_dmem_write_byte:
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwbs | supervisor
-dmwbu:
dmwbuae:movs.b %d0,(%a0) | store user byte
- bras dmwbr
+ rts
dmwbs: move.b %d0,(%a0) | store super byte
-dmwbr: clr.l %d1 | return success
rts
|
@@ -270,6 +264,7 @@ dmwbr: clr.l %d1 | return success
|
.global _060_dmem_write_word
_060_dmem_write_word:
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwws | supervisor
dmwwu:
@@ -293,16 +288,16 @@ dmwwr: clr.l %d1 | return success
|
.global _060_dmem_write_long
_060_dmem_write_long:
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwls | supervisor
-dmwlu:
dmwluae:movs.l %d0,(%a0) | store user longword
- bra dmwlr
+ rts
dmwls: move.l %d0,(%a0) | store super longword
-dmwlr: clr.l %d1 | return success
rts
+#if 0
|###############################################
|
@@ -323,7 +318,7 @@ _copyout:
move.l 4(%sp),%a0 | source
move.l 8(%sp),%a1 | destination
move.l 12(%sp),%d0 | count
- subq.l #1,%d0
+ subq.l #1,%d0
moreout:
move.b (%a0)+,%d1 | fetch supervisor byte
copyoutae:
@@ -348,6 +343,7 @@ copyinae:
dbra %d0,morein | are we through yet?
moveq #0,%d0 | return success
rts
+#endif
|###########################################################################
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 165809c56..3e62e6fe1 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -28,6 +28,9 @@
* 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
* all pointers that used to be 'current' are now entry
* number 0 in the 'current_set' list.
+ *
+ * 6/05/00 RZ: addedd writeback completion after return from sighandler
+ * for 68040
*/
#include <linux/sys.h>
@@ -104,8 +107,18 @@ do_trace:
jbsr SYMBOL_NAME(syscall_trace)
SYMBOL_NAME_LABEL(ret_from_signal)
- RESTORE_SWITCH_STACK
+ RESTORE_SWITCH_STACK
addql #4,%sp
+/* on 68040 complete pending writebacks if any */
+#ifdef CONFIG_M68040
+ bfextu %sp@(PT_VECTOR){#0,#4},%d0
+ subql #7,%d0 | bus error frame ?
+ jbne 1f
+ movel %sp,%sp@-
+ jbsr SYMBOL_NAME(berr_040cleanup)
+ addql #4,%sp
+1:
+#endif
jra SYMBOL_NAME(ret_from_exception)
ENTRY(system_call)
@@ -115,7 +128,7 @@ ENTRY(system_call)
| save top of frame
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
- btst #PF_TRACESYS_BIT,%curptr@(TASK_FLAGS+PF_TRACESYS_OFF)
+ btst #PT_TRACESYS_BIT,%curptr@(TASK_PTRACE+PT_TRACESYS_OFF)
jne do_trace
cmpl #NR_syscalls,%d0
jcc badsys
@@ -136,7 +149,7 @@ SYMBOL_NAME_LABEL(ret_from_exception)
jeq 2f
#endif
| check for delayed trace
- bclr #PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF)
+ bclr #PT_DTRACE_BIT,%curptr@(TASK_PTRACE+PT_DTRACE_OFF)
jne do_delayed_trace
5:
tstl %curptr@(TASK_STATE) | state
@@ -578,7 +591,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_mremap)
.long SYMBOL_NAME(sys_setresuid16)
.long SYMBOL_NAME(sys_getresuid16) /* 165 */
- .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */
+ .long SYMBOL_NAME(sys_getpagesize)
.long SYMBOL_NAME(sys_query_module)
.long SYMBOL_NAME(sys_poll)
.long SYMBOL_NAME(sys_nfsservctl)
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 74e1e4c1e..805ce9b83 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -71,6 +71,8 @@ int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
unsigned long, const char *, void *) = dummy_request_irq;
void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
+void init_irq_proc(void);
+
/*
* void init_IRQ(void)
*
@@ -257,3 +259,9 @@ int get_irq_list(char *buf)
len += mach_get_irq_list(buf+len);
return len;
}
+
+void init_irq_proc(void)
+{
+ /* Insert /proc/irq driver here */
+}
+
diff --git a/arch/m68k/kernel/m68k_defs.c b/arch/m68k/kernel/m68k_defs.c
index 47cffcfa9..817583a7d 100644
--- a/arch/m68k/kernel/m68k_defs.c
+++ b/arch/m68k/kernel/m68k_defs.c
@@ -24,6 +24,7 @@ int main(void)
/* offsets into the task struct */
DEFINE(TASK_STATE, offsetof(struct task_struct, state));
DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, sigpending));
DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, need_resched));
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 7bf46149f..35d194623 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -21,6 +21,7 @@
asmlinkage long long __ashrdi3 (long long, int);
asmlinkage long long __lshrdi3 (long long, int);
+asmlinkage long long __muldi3 (long long, long long);
extern char m68k_debug_device[];
extern void dump_thread(struct pt_regs *, struct user *);
@@ -72,6 +73,7 @@ EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL_NOVERS(__muldi3);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 0dd5870f2..6b1f5f386 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -97,10 +97,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
- if (current->flags & PF_PTRACED)
+ if (current->ptrace & PT_PTRACED)
goto out;
/* set the ptrace bit in the process flags. */
- current->flags |= PF_PTRACED;
+ current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
@@ -126,9 +126,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED)
+ if (child->ptrace & PT_PTRACED)
goto out;
- child->flags |= PF_PTRACED;
+ child->ptrace |= PT_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
if (child->p_pptr != current) {
@@ -143,7 +143,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
}
ret = -ESRCH;
- if (!(child->flags & PF_PTRACED))
+ if (!(child->ptrace & PT_PTRACED))
goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
@@ -250,9 +250,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if ((unsigned long) data > _NSIG)
goto out;
if (request == PTRACE_SYSCALL)
- child->flags |= PF_TRACESYS;
+ child->ptrace |= PT_TRACESYS;
else
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
child->exit_code = data;
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
@@ -287,7 +287,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
goto out;
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
@@ -304,7 +304,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
goto out;
- child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
child->exit_code = data;
write_lock_irqsave(&tasklist_lock, flags);
REMOVE_LINKS(child);
@@ -384,8 +384,8 @@ out:
asmlinkage void syscall_trace(void)
{
lock_kernel();
- if ((current->flags & (PF_PTRACED|PF_TRACESYS))
- != (PF_PTRACED|PF_TRACESYS))
+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+ != (PT_PTRACED|PT_TRACESYS))
goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index a2e3f47f1..040f96d97 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -73,6 +73,8 @@ void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initd
int (*mach_keyb_init) (void) __initdata = NULL;
int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
void (*mach_kbd_leds) (unsigned int) = NULL;
+int (*mach_kbd_translate)(unsigned char scancode, unsigned char *keycode, char raw_mode) = NULL;
+unsigned int SYSRQ_KEY;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void) __initdata = NULL;
void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index fa13dc390..9d754f9b8 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -1043,7 +1043,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!signr)
break;
- if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
regs->sr &= ~PS_T;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 86637d4d6..f7386cbc6 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -24,6 +24,7 @@
#include <asm/cachectl.h>
#include <asm/traps.h>
#include <asm/ipc.h>
+#include <asm/page.h>
/*
* sys_pipe() is the normal C calling standard for creating
@@ -661,6 +662,11 @@ out:
return ret;
}
+asmlinkage int sys_getpagesize(void)
+{
+ return PAGE_SIZE;
+}
+
/*
* Old cruft
*/
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 5fd9dc0a7..d5d6753cb 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -5,6 +5,7 @@
*
* 68040 fixes by Michael Rausch
* 68040 fixes by Martin Apel
+ * 68040 fixes and writeback by Richard Zidlicky
* 68060 fixes by Roman Hodek
* 68060 fixes by Jesper Skov
*
@@ -34,7 +35,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/traps.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/machdep.h>
#include <asm/siginfo.h>
@@ -195,6 +196,7 @@ static char *space_names[] = {
void die_if_kernel(char *,struct pt_regs *,int);
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
+int send_fault_sig(struct pt_regs *regs);
asmlinkage void trap_c(struct frame *fp);
@@ -214,26 +216,33 @@ static inline void access_error060 (struct frame *fp)
"movec %/d0,%/cacr"
: : : "d0" );
/* return if there's no other error */
- if ((!(fslw & MMU060_ERR_BITS)) && !(fslw & MMU060_SEE))
+ if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
return;
}
if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
unsigned long errorcode;
unsigned long addr = fp->un.fmt4.effaddr;
- errorcode = ((fslw & MMU060_WP) ? 1 : 0) |
- ((fslw & MMU060_W) ? 2 : 0);
+
+ if (fslw & MMU060_MA)
+ addr = (addr + 7) & -8;
+
+ errorcode = 1;
+ if (fslw & MMU060_DESC_ERR) {
+ __flush_tlb040_one(addr);
+ errorcode = 0;
+ }
+ if (fslw & MMU060_W)
+ errorcode |= 2;
#ifdef DEBUG
printk("errorcode = %d\n", errorcode );
#endif
- if (fslw & MMU060_MA)
- addr = PAGE_ALIGN(addr);
do_page_fault(&fp->ptregs, addr, errorcode);
} else if (fslw & (MMU060_SEE)){
- /* Software Emulation Error. Probably an instruction
- * using an unsupported addressing mode
+ /* Software Emulation Error.
+ * fault during mem_read/mem_write in ifpsp060/os.S
*/
- send_sig (SIGSEGV, current, 1);
+ send_fault_sig(&fp->ptregs);
} else {
printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
printk( "68060 access error, fslw=%lx\n", fslw );
@@ -243,74 +252,113 @@ static inline void access_error060 (struct frame *fp)
#endif /* CONFIG_M68060 */
#if defined (CONFIG_M68040)
-static inline unsigned long probe040 (int iswrite, int fc, unsigned long addr)
+static inline unsigned long probe040(int iswrite, unsigned long addr)
{
unsigned long mmusr;
- mm_segment_t fs = get_fs();
- set_fs (MAKE_MM_SEG(fc));
+ asm volatile (".chip 68040");
if (iswrite)
- /* write */
- asm volatile (".chip 68040\n\t"
- "ptestw (%1)\n\t"
- "movec %%mmusr,%0\n\t"
- ".chip 68k"
- : "=r" (mmusr)
- : "a" (addr));
+ asm volatile ("ptestw (%0)" : : "a" (addr));
else
- asm volatile (".chip 68040\n\t"
- "ptestr (%1)\n\t"
- "movec %%mmusr,%0\n\t"
- ".chip 68k"
- : "=r" (mmusr)
- : "a" (addr));
+ asm volatile ("ptestr (%0)" : : "a" (addr));
+
+ asm volatile ("movec %%mmusr,%0" : "=r" (mmusr));
- set_fs (fs);
+ asm volatile (".chip 68k");
return mmusr;
}
-static inline void do_040writeback (unsigned short ssw,
- unsigned short wbs,
- unsigned long wba,
- unsigned long wbd,
- struct frame *fp)
+static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
+ unsigned long wbd)
{
- mm_segment_t fs = get_fs ();
- unsigned long mmusr;
- unsigned long errorcode;
+ int res = 0;
- /*
- * No special handling for the second writeback anymore.
- * It misinterpreted the misaligned status sometimes.
- * This way an extra page-fault may be caused (Martin Apel).
- */
-
- mmusr = probe040 (1, wbs & WBTM_040, wba);
- errorcode = (mmusr & MMU_R_040) ? 3 : 2;
- if (do_page_fault (&fp->ptregs, wba, errorcode))
- /* just return if we can't perform the writeback */
- return;
+ set_fs(MAKE_MM_SEG(wbs));
- set_fs (MAKE_MM_SEG(wbs & WBTM_040));
switch (wbs & WBSIZ_040) {
- case BA_SIZE_BYTE:
- put_user (wbd & 0xff, (char *)wba);
+ case BA_SIZE_BYTE:
+ res = put_user(wbd & 0xff, (char *)wba);
break;
- case BA_SIZE_WORD:
- put_user (wbd & 0xffff, (short *)wba);
+ case BA_SIZE_WORD:
+ res = put_user(wbd & 0xffff, (short *)wba);
break;
- case BA_SIZE_LONG:
- put_user (wbd, (int *)wba);
+ case BA_SIZE_LONG:
+ res = put_user(wbd, (int *)wba);
break;
}
- set_fs (fs);
+
+#ifdef DEBUG
+ printk("do_040writeback1, res=%d\n",res);
+#endif
+
+ return res;
+}
+
+/* after an exception in a writeback the stack frame coresponding
+ * to that exception is discarded, set a few bits in the old frame
+ * to simulate what it should look like
+ */
+static inline void fix_xframe040(struct frame *fp, unsigned short wbs)
+{
+ fp->un.fmt7.faddr = current->thread.faddr;
+ fp->un.fmt7.ssw = wbs & 0xff;
+}
+
+static inline void do_040writebacks(struct frame *fp)
+{
+ int res = 0;
+#if 0
+ if (fp->un.fmt7.wb1s & WBV_040)
+ printk("access_error040: cannot handle 1st writeback. oops.\n");
+#endif
+
+ if ((fp->un.fmt7.wb2s & WBV_040) &&
+ !(fp->un.fmt7.wb2s & WBTT_040)) {
+ res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
+ fp->un.fmt7.wb2d);
+ if (res)
+ fix_xframe040(fp, fp->un.fmt7.wb2s);
+ else
+ fp->un.fmt7.wb2s = 0;
+ }
+
+ /* do the 2nd wb only if the first one was succesful (except for a kernel wb) */
+ if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
+ res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
+ fp->un.fmt7.wb3d);
+ if (res)
+ fix_xframe040(fp, fp->un.fmt7.wb3s);
+ else
+ fp->un.fmt7.wb3s = 0;
+ }
+
+ if (res)
+ send_fault_sig(&fp->ptregs);
+}
+
+/*
+ * called from sigreturn(), must ensure userspace code didn't
+ * manipulate exception frame to circumvent protection, then complete
+ * pending writebacks
+ * we just clear TM2 to turn it into an userspace access
+ */
+asmlinkage void berr_040cleanup(struct frame *fp)
+{
+ mm_segment_t old_fs = get_fs();
+
+ fp->un.fmt7.wb2s &= ~4;
+ fp->un.fmt7.wb3s &= ~4;
+
+ do_040writebacks(fp);
+ set_fs(old_fs);
}
-static inline void access_error040 (struct frame *fp)
+static inline void access_error040(struct frame *fp)
{
unsigned short ssw = fp->un.fmt7.ssw;
+ mm_segment_t old_fs = get_fs();
unsigned long mmusr;
#ifdef DEBUG
@@ -322,7 +370,6 @@ static inline void access_error040 (struct frame *fp)
fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
#endif
-
if (ssw & ATC_040) {
unsigned long addr = fp->un.fmt7.faddr;
unsigned long errorcode;
@@ -332,56 +379,50 @@ static inline void access_error040 (struct frame *fp)
* has been corrected if there was a misaligned access (MA).
*/
if (ssw & MA_040)
- addr = PAGE_ALIGN (addr);
+ addr = (addr + 7) & -8;
+ set_fs(MAKE_MM_SEG(ssw));
/* MMU error, get the MMUSR info for this access */
- mmusr = probe040 (!(ssw & RW_040), ssw & TM_040, addr);
+ mmusr = probe040(!(ssw & RW_040), addr);
#ifdef DEBUG
printk("mmusr = %lx\n", mmusr);
#endif
- errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
- ((ssw & RW_040) ? 0 : 2);
-#ifdef CONFIG_FTRACE
- {
- unsigned long flags;
-
- save_flags(flags);
- cli();
- do_ftrace(0xfa000000 | errorcode);
- do_ftrace(mmusr);
- restore_flags(flags);
+ errorcode = 1;
+ if (!(mmusr & MMU_R_040)) {
+ /* clear the invalid atc entry */
+ __flush_tlb040_one(addr);
+ errorcode = 0;
}
+ if (!(ssw & RW_040))
+ errorcode |= 2;
+ if (do_page_fault(&fp->ptregs, addr, errorcode)) {
+#ifdef DEBUG
+ printk("do_page_fault() !=0 \n");
#endif
- do_page_fault (&fp->ptregs, addr, errorcode);
+ if (user_mode(&fp->ptregs)){
+ /* delay writebacks after signal delivery */
+#ifdef DEBUG
+ printk(".. was usermode - return\n");
+#endif
+ return;
+ }
+ /* disable writeback into user space from kernel
+ * (if do_page_fault didn't fix the mapping,
+ * the writeback won't do good)
+ */
+#ifdef DEBUG
+ printk(".. disabling wb2\n");
+#endif
+ if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
+ fp->un.fmt7.wb2s &= ~WBV_040;
+ }
} else {
- printk ("68040 access error, ssw=%x\n", ssw);
- trap_c (fp);
+ printk("68040 access error, ssw=%x\n", ssw);
+ trap_c(fp);
}
-#if 0
- if (fp->un.fmt7.wb1s & WBV_040)
- printk("access_error040: cannot handle 1st writeback. oops.\n");
-#endif
-
-/*
- * We may have to do a couple of writebacks here.
- *
- * MR: we can speed up the thing a little bit and let do_040writeback()
- * not produce another page fault as wb2 corresponds to the address that
- * caused the fault. on write faults no second fault is generated, but
- * on read faults for security reasons (although per definitionem impossible)
- */
-
- if (fp->un.fmt7.wb2s & WBV_040 && (fp->un.fmt7.wb2s &
- WBTT_040) != BA_TT_MOVE16)
- do_040writeback (ssw,
- fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
- fp->un.fmt7.wb2d, fp);
-
- if (fp->un.fmt7.wb3s & WBV_040)
- do_040writeback (ssw, fp->un.fmt7.wb3s,
- fp->un.fmt7.wb3a, fp->un.fmt7.wb3d,
- fp);
+ do_040writebacks(fp);
+ set_fs(old_fs);
}
#endif /* CONFIG_M68040 */
@@ -470,12 +511,14 @@ extern inline void bus_error030 (struct frame *fp)
else if (buserr_type & SUN3_BUSERR_INVALID)
errorcode = 0x00;
else {
+#ifdef DEBUG
printk ("*** unexpected busfault type=%#04x\n", buserr_type);
printk ("invalid %s access at %#lx from pc %#lx\n",
!(ssw & RW) ? "write" : "read", addr,
fp->ptregs.pc);
+#endif
die_if_kernel ("Oops", &fp->ptregs, buserr_type);
- force_sig (SIGSEGV, current);
+ force_sig (SIGBUS, current);
return;
}
@@ -596,7 +639,7 @@ static inline void bus_error030 (struct frame *fp)
printk ("mmusr is %#x for addr %#lx in task %p\n",
mmusr, addr, current);
printk ("descriptor address is %#lx, contents %#lx\n",
- mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
+ __va(desc), *(unsigned long *)__va(desc));
#endif
errorcode = (mmusr & MMU_I) ? 0 : 1;
@@ -694,7 +737,7 @@ static inline void bus_error030 (struct frame *fp)
printk ("mmusr is %#x for addr %#lx in task %p\n",
mmusr, addr, current);
printk ("descriptor address is %#lx, contents %#lx\n",
- mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
+ __va(desc), *(unsigned long *)__va(desc));
#endif
if (mmusr & MMU_I)
@@ -904,7 +947,7 @@ asmlinkage void trap_c(struct frame *fp)
if (fp->ptregs.sr & PS_S) {
if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
/* traced a trapping instruction */
- current->flags |= PF_DTRACE;
+ current->ptrace |= PT_DTRACE;
} else
bad_super_trap(fp);
return;
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index b9480aeb6..a230bad9e 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -6,6 +6,6 @@
$(CC) $(AFLAGS) -traditional -c $< -o $@
L_TARGET = lib.a
-L_OBJS = ashrdi3.o lshrdi3.o checksum.o memcpy.o memcmp.o memset.o semaphore.o
+L_OBJS = ashrdi3.o lshrdi3.o checksum.o memcpy.o memcmp.o memset.o semaphore.o muldi3.o
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
new file mode 100644
index 000000000..9ea8812fc
--- /dev/null
+++ b/arch/m68k/lib/muldi3.c
@@ -0,0 +1,63 @@
+/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
+ gcc-2.7.2.3/longlong.h which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define BITS_PER_UNIT 8
+
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mulu%.l %3,%1:%0" \
+ : "=d" ((USItype)(w0)), \
+ "=d" ((USItype)(w1)) \
+ : "%0" ((USItype)(u)), \
+ "dmi" ((USItype)(v)))
+
+#define __umulsidi3(u, v) \
+ ({DIunion __w; \
+ umul_ppmm (__w.s.high, __w.s.low, u, v); \
+ __w.ll; })
+
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef int word_type __attribute__ ((mode (__word__)));
+
+struct DIstruct {SItype high, low;};
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
+DItype
+__muldi3 (DItype u, DItype v)
+{
+ DIunion w;
+ DIunion uu, vv;
+
+ uu.ll = u,
+ vv.ll = v;
+
+ w.ll = __umulsidi3 (uu.s.low, vv.s.low);
+ w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+ + (USItype) uu.s.high * (USItype) vv.s.low);
+
+ return w.ll;
+}
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
index 445a99780..9b9bab2bd 100644
--- a/arch/m68k/mac/baboon.c
+++ b/arch/m68k/mac/baboon.c
@@ -27,8 +27,6 @@ volatile struct baboon *baboon;
void baboon_irq(int, void *, struct pt_regs *);
-extern int console_loglevel;
-
extern int macide_ack_intr(ide_hwif_t *);
/*
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index a0486cf95..1a1a38e60 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -61,10 +61,6 @@ void *mac_env; /* Loaded by the boot asm */
/* The phys. video addr. - might be bogus on some machines */
unsigned long mac_orig_videoaddr;
-/* Mac specific keyboard functions */
-extern int mackbd_init_hw(void);
-extern void mackbd_leds(unsigned int leds);
-
/* Mac specific timer functions */
extern void mac_gettod (int *, int *, int *, int *, int *, int *);
extern unsigned long mac_gettimeoffset (void);
@@ -91,20 +87,21 @@ extern void nubus_sweep_video(void);
extern void mac_debug_init(void);
extern void mac_debugging_long(int, long);
-#ifdef CONFIG_MAGIC_SYSRQ
-static char mac_sysrq_xlate[128] =
- "\000sdfghzxcv\000bqwer" /* 0x00 - 0x0f */
- "yt123465=97-80)o" /* 0x10 - 0x1f */
- "u(ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
- "\t `\000\033\000\000\000\000\000\000\000\000\000\000\000" /* 0x30 - 0x3f */
- "\000.\000*\000+\000\000\000\000\000/\r\000-\000" /* 0x40 - 0x4f */
- "\000\00001234567a89\000\000\000" /* 0x50 - 0x5f */
- "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x60 - 0x6f */
- "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */
-#endif
-
extern void (*kd_mksound)(unsigned int, unsigned int);
+extern int mackbd_init_hw(void);
+extern void mackbd_leds(unsigned int leds);
+extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode);
+
+extern void mac_hid_init_hw(void);
+extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode);
+
+#ifdef CONFIG_MAGIC_SYSRQ
+extern unsigned char mac_hid_kbd_sysrq_xlate[128];
+extern unsigned char pckbd_sysrq_xlate[128];
+extern unsigned char mackbd_sysrq_xlate[128];
+#endif /* CONFIG_MAGIC_SYSRQ */
+
static void mac_get_model(char *str);
void mac_bang(int irq, void *vector, struct pt_regs *p)
@@ -118,8 +115,6 @@ static void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
via_init_clock(vector);
}
-extern int console_loglevel;
-
#if 0
void mac_waitbut (void)
{
@@ -213,76 +208,93 @@ static void mac_cache_card_flush(int writeback)
void __init config_mac(void)
{
-
- if (!MACH_IS_MAC) {
- printk("ERROR: no Mac, but config_mac() called!! \n");
- }
-
- mach_sched_init = mac_sched_init;
- mach_keyb_init = mackbd_init_hw;
- mach_kbd_leds = mackbd_leds;
- mach_init_IRQ = mac_init_IRQ;
- mach_request_irq = mac_request_irq;
- mach_free_irq = mac_free_irq;
- enable_irq = mac_enable_irq;
- disable_irq = mac_disable_irq;
- mach_get_model = mac_get_model;
- mach_default_handler = &mac_handlers;
- mach_get_irq_list = mac_get_irq_list;
- mach_gettimeoffset = mac_gettimeoffset;
- mach_gettod = mac_gettod;
- mach_hwclk = mac_hwclk;
- mach_set_clock_mmss = mac_set_clock_mmss;
+ if (!MACH_IS_MAC) {
+ printk("ERROR: no Mac, but config_mac() called!! \n");
+ }
+
+#ifdef CONFIG_VT
+#ifdef CONFIG_INPUT_ADBHID
+ mach_keyb_init = mac_hid_init_hw;
+ mach_kbd_translate = mac_hid_kbd_translate;
+#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_MAC_ADBKEYCODES
+ if (!keyboard_sends_linux_keycodes) {
+ mach_sysrq_xlate = mac_hid_kbd_sysrq_xlate;
+ SYSRQ_KEY = 0x69;
+ } else
+#endif /* CONFIG_MAC_ADBKEYCODES */
+ {
+ mach_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x54;
+ }
+#endif /* CONFIG_MAGIC_SYSRQ */
+#elif defined(CONFIG_ADB_KEYBOARD)
+ mach_keyb_init = mackbd_init_hw;
+ mach_kbd_leds = mackbd_leds;
+ mach_kbd_translate = mackbd_translate;
+ mach_sysrq_xlate = mackbd_sysrq_xlate;
+ SYSRQ_KEY = 0x69;
+#endif /* CONFIG_INPUT_ADBHID */
+#endif /* CONFIG_VT */
+
+ mach_sched_init = mac_sched_init;
+ mach_init_IRQ = mac_init_IRQ;
+ mach_request_irq = mac_request_irq;
+ mach_free_irq = mac_free_irq;
+ enable_irq = mac_enable_irq;
+ disable_irq = mac_disable_irq;
+ mach_get_model = mac_get_model;
+ mach_default_handler = &mac_handlers;
+ mach_get_irq_list = mac_get_irq_list;
+ mach_gettimeoffset = mac_gettimeoffset;
+ mach_gettod = mac_gettod;
+ mach_hwclk = mac_hwclk;
+ mach_set_clock_mmss = mac_set_clock_mmss;
#if 0
- mach_mksound = mac_mksound;
+ mach_mksound = mac_mksound;
#endif
- mach_reset = mac_reset;
- mach_halt = mac_poweroff;
- mach_power_off = mac_poweroff;
- conswitchp = &dummy_con;
- mach_max_dma_address = 0xffffffff;
+ mach_reset = mac_reset;
+ mach_halt = mac_poweroff;
+ mach_power_off = mac_poweroff;
+ conswitchp = &dummy_con;
+ mach_max_dma_address = 0xffffffff;
#if 0
- mach_debug_init = mac_debug_init;
-#endif
- kd_mksound = mac_mksound;
-#ifdef CONFIG_MAGIC_SYSRQ
- mach_sysrq_key = 114; /* HELP */
- mach_sysrq_shift_state = 8; /* Alt */
- mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */
- mach_sysrq_xlate = mac_sysrq_xlate;
+ mach_debug_init = mac_debug_init;
#endif
+ kd_mksound = mac_mksound;
#ifdef CONFIG_HEARTBEAT
#if 0
- mach_heartbeat = mac_heartbeat;
- mach_heartbeat_irq = IRQ_MAC_TIMER;
+ mach_heartbeat = mac_heartbeat;
+ mach_heartbeat_irq = IRQ_MAC_TIMER;
#endif
#endif
- /*
- * Determine hardware present
- */
+ /*
+ * Determine hardware present
+ */
- mac_identify();
- mac_report_hardware();
+ mac_identify();
+ mac_report_hardware();
- /* AFAIK only the IIci takes a cache card. The IIfx has onboard
- cache ... someone needs to figure out how to tell if it's on or
- not. */
- if (macintosh_config->ident == MAC_MODEL_IICI
- || macintosh_config->ident == MAC_MODEL_IIFX) {
- mach_l2_flush = mac_cache_card_flush;
- }
+ /* AFAIK only the IIci takes a cache card. The IIfx has onboard
+ cache ... someone needs to figure out how to tell if it's on or
+ not. */
+
+ if (macintosh_config->ident == MAC_MODEL_IICI
+ || macintosh_config->ident == MAC_MODEL_IIFX) {
+ mach_l2_flush = mac_cache_card_flush;
+ }
#ifdef MAC_DEBUG_SOUND
- /* goes on forever if timers broken */
- mac_mksound(1000,10);
+ /* goes on forever if timers broken */
+ mac_mksound(1000,10);
#endif
- /*
- * Check for machine specific fixups.
- */
+ /*
+ * Check for machine specific fixups.
+ */
#ifdef OLD_NUBUS_CODE
- nubus_sweep_video();
+ nubus_sweep_video();
#endif
}
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index febba1982..061b01bd8 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -211,8 +211,6 @@ static void scc_irq_disable(int);
* console_loglevel determines NMI handler function
*/
-extern int console_loglevel;
-
extern void mac_bang(int, void *, struct pt_regs *);
void mac_nmi_handler(int, void *, struct pt_regs *);
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index c405fc0da..87d155ee0 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -35,7 +35,6 @@ void oss_nubus_irq(int, void *, struct pt_regs *);
extern void via1_irq(int, void *, struct pt_regs *);
extern void mac_scc_dispatch(int, void *, struct pt_regs *);
-extern int console_loglevel;
/*
* Initialize the OSS
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index 86bbf72cc..d792ef987 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -32,8 +32,6 @@ volatile __u8 *psc;
void psc_irq(int, void *, struct pt_regs *);
-extern int console_loglevel;
-
/*
* Debugging dump, used in various places to see what's going on.
*/
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index af001907d..ec0b2ce19 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -74,7 +74,6 @@ void via_irq_clear(int irq);
extern void mac_bang(int, void *, struct pt_regs *);
extern void mac_scc_dispatch(int, void *, struct pt_regs *);
-extern int console_loglevel;
extern int oss_present;
/*
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index 3eba3d13b..8dc87ebc1 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -19,6 +19,55 @@
extern void die_if_kernel(char *, struct pt_regs *, long);
extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
+int send_fault_sig(struct pt_regs *regs)
+{
+ siginfo_t siginfo = { 0, 0, 0, };
+
+ siginfo.si_signo = current->thread.signo;
+ siginfo.si_code = current->thread.code;
+ siginfo.si_addr = (void *)current->thread.faddr;
+ printk("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, siginfo.si_signo, siginfo.si_code);
+
+ if (user_mode(regs)) {
+ force_sig_info(siginfo.si_signo,
+ &siginfo, current);
+ } else {
+ unsigned long fixup;
+
+ /* Are we prepared to handle this kernel fault? */
+ if ((fixup = search_exception_table(regs->pc))) {
+ struct pt_regs *tregs;
+ /* Create a new four word stack frame, discarding the old
+ one. */
+ regs->stkadj = frame_extra_sizes[regs->format];
+ tregs = (struct pt_regs *)((ulong)regs + regs->stkadj);
+ tregs->vector = regs->vector;
+ tregs->format = 0;
+ tregs->pc = fixup;
+ tregs->sr = regs->sr;
+ return -1;
+ }
+
+ //if (siginfo.si_signo == SIGBUS)
+ // force_sig_info(siginfo.si_signo,
+ // &siginfo, current);
+
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+ if ((unsigned long)siginfo.si_addr < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel access");
+ printk(" at virtual address %p\n", siginfo.si_addr);
+ die_if_kernel("Oops", regs, 0 /*error_code*/);
+ do_exit(SIGKILL);
+ }
+
+ return 1;
+}
+
/*
* This routine handles page faults. It determines the problem, and
* then passes it off to one of the appropriate routines.
@@ -30,16 +79,15 @@ extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
* If this routine detects a bad access, it returns 1, otherwise it
* returns 0.
*/
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
+int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct * vma;
- unsigned long fixup;
int write, fault;
#ifdef DEBUG
- printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
+ printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
regs->sr, regs->pc, address, error_code,
current->mm->pgd);
#endif
@@ -55,43 +103,46 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
vma = find_vma(mm, address);
if (!vma)
- goto bad_area;
+ goto map_err;
if (vma->vm_flags & VM_IO)
- goto bad_area;
+ goto acc_err;
if (vma->vm_start <= address)
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
+ goto map_err;
if (user_mode(regs)) {
/* Accessing the stack below usp is always a bug. The
"+ 256" is there due to some instructions doing
pre-decrement on the stack and that doesn't show up
until later. */
if (address + 256 < rdusp())
- goto bad_area;
+ goto map_err;
}
if (expand_stack(vma, address))
- goto bad_area;
+ goto map_err;
/*
* Ok, we have a good vm_area for this memory access, so
* we can handle it..
*/
good_area:
+#ifdef DEBUG
+ printk("do_page_fault: good_area\n");
+#endif
write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
/* fall through */
case 2: /* write, not present */
if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
+ goto acc_err;
write++;
break;
case 1: /* read, present */
- goto bad_area;
+ goto acc_err;
case 0: /* read, not present */
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
- goto bad_area;
+ goto acc_err;
}
/*
@@ -100,87 +151,56 @@ good_area:
* the fault.
*/
fault = handle_mm_fault(mm, vma, address, write);
+#ifdef DEBUG
+ printk("handle_mm_fault returns %d\n",fault);
+#endif
if (fault < 0)
goto out_of_memory;
if (!fault)
- goto do_sigbus;
+ goto bus_err;
/* There seems to be a missing invalidate somewhere in do_no_page.
* Until I found it, this one cures the problem and makes
* 1.2 run on the 68040 (Martin Apel).
*/
+ #warning should be obsolete now...
if (CPU_IS_040_OR_060)
flush_tlb_page(vma, address);
up(&mm->mmap_sem);
return 0;
/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
- up(&mm->mmap_sem);
-
- /* User mode accesses just cause a SIGSEGV */
- if (user_mode(regs)) {
- siginfo_t info;
- info.si_signo = SIGSEGV;
- info.si_code = SEGV_MAPERR;
- info.si_addr = (void *)address;
- force_sig_info(SIGSEGV, &info, current);
- return 1;
- }
-
-no_context:
- /* Are we prepared to handle this kernel fault? */
- if ((fixup = search_exception_table(regs->pc)) != 0) {
- struct pt_regs *tregs;
- /* Create a new four word stack frame, discarding the old
- one. */
- regs->stkadj = frame_extra_sizes[regs->format];
- tregs = (struct pt_regs *)((ulong)regs + regs->stkadj);
- tregs->vector = regs->vector;
- tregs->format = 0;
- tregs->pc = fixup;
- tregs->sr = regs->sr;
- return -1;
- }
-
-/*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
- if ((unsigned long) address < PAGE_SIZE) {
- printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- } else
- printk(KERN_ALERT "Unable to handle kernel access");
- printk(" at virtual address %08lx\n",address);
- die_if_kernel("Oops", regs, error_code);
- do_exit(SIGKILL);
-
-/*
* We ran out of memory, or some other thing happened to us that made
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- up(&mm->mmap_sem);
printk("VM: killing process %s\n", current->comm);
- if (error_code & 4)
+ if (user_mode(regs))
do_exit(SIGKILL);
- goto no_context;
-do_sigbus:
+no_context:
+ current->thread.signo = SIGBUS;
+ current->thread.faddr = address;
+ return send_fault_sig(regs);
+
+bus_err:
+ current->thread.signo = SIGBUS;
+ current->thread.code = BUS_ADRERR;
+ current->thread.faddr = address;
+ goto send_sig;
+
+map_err:
+ current->thread.signo = SIGSEGV;
+ current->thread.code = SEGV_MAPERR;
+ current->thread.faddr = address;
+ goto send_sig;
+
+acc_err:
+ current->thread.signo = SIGSEGV;
+ current->thread.code = SEGV_ACCERR;
+ current->thread.faddr = address;
+
+send_sig:
up(&mm->mmap_sem);
-
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- force_sig(SIGBUS, current);
-
- /* Kernel mode? Handle exceptions or die */
- if (!user_mode(regs))
- goto no_context;
-
- return 1;
+ return send_fault_sig(regs);
}
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index d48a0201b..06ffa5692 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -201,15 +201,6 @@ int mvme147_keyb_init (void)
/*------------------- Serial console stuff ------------------------*/
-void m147_scc_write(struct console *co, const char *str, unsigned cnt);
-
-
-void mvme147_init_console_port (struct console *co, int cflag)
-{
- co->write = m147_scc_write;
-}
-
-
static void scc_delay (void)
{
int n;
@@ -250,3 +241,31 @@ 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/README b/arch/m68k/q40/README
index 60134d9de..b61ee9c6a 100644
--- a/arch/m68k/q40/README
+++ b/arch/m68k/q40/README
@@ -56,8 +56,7 @@ SRAM can also be used as additional console device, use debug=mem.
This will save kernel startup msgs into SRAM, the screen will display
only the penguin - and shell prompt if it gets that far..
-Serial console works and can also be used for debugging, provided serial
-initialisation works.
+Serial console works and can also be used for debugging, see loader_txt
Most problems seem to be caused by fawlty or badly configured io-cards or
harddrives anyway..there are so many things that can go wrong here.
@@ -82,8 +81,9 @@ The main interrupt register IIRQ_REG will indicate whether an IRQ was internal
or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs.
The Q40 custom chip is programmable to provide 2 periodic timers:
- - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!!
- - 10 or 20 KHz - level 4 (and possibly 6 - hardware decoding..)
+ - 50 or 200 Hz - level 2,
+ - 10 or 20 KHz - level 4
+ !!THIS CANT BE DISABLED!!
Linux uses the 200 Hz interrupt for timer and beep by default.
@@ -92,9 +92,6 @@ Interrupts
==========
q40 master chip handles only level triggered interrupts :-((
-further limitation is no disabling etc. There is NO WAY to remove
-an ISA irq request other than serve the HW specific control register,
-the ISA irq lines are connected straight to the CPU ipl1 pin..
IRQ sharing is not yet implemented but this should be only a minor
problem..
@@ -102,12 +99,17 @@ problem..
Linux has some requirements wrt interrupt architecture, these are
to my knowledge:
(a) interrupt handler must not be reentered even when sti() is called
+ from within handler
(b) working enable/disable_irq
Luckily these requirements are only important for drivers shared
with other architectures - ide,serial,parallel, ethernet..
-q40ints.c now contains a trivial hack for (a), however (b) could
-be only solved by driver-specific code
+q40ints.c now contains a trivial hack for (a), (b) is more difficult
+because only irq's 4-15 can be disabled - and only all o them at once.
+Thus disable_irq() can effectively block the machine if the driver goes
+asleep.
+One thing to keep in minde when hacking around the interrupt code is
+that there is no way to find out which IRQ caused a request.
Keyboard
========
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 2496aa9ba..294765dd2 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -13,6 +13,7 @@
*/
#include <linux/config.h>
+#include <stdarg.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -22,6 +23,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/major.h>
+#include <linux/serial_reg.h>
#include <asm/rtc.h>
#include <asm/bootinfo.h>
@@ -34,8 +36,8 @@
#include <asm/q40_master.h>
#include <asm/keyboard.h>
-extern void fd_floppy_eject(void);
-extern void fd_floppy_setup(char *str, int *ints);
+extern void floppy_eject(void);
+extern void floppy_setup(char *str, int *ints);
extern void q40_process_int (int level, struct pt_regs *regs);
extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
@@ -65,9 +67,12 @@ extern char *saved_command_line;
extern char m68k_debug_device[];
static void q40_mem_console_write(struct console *co, const char *b,
unsigned int count);
+#if 0
+extern int ql_ticks=0;
+extern int sound_ticks=0;
+#endif
-static int ql_ticks=0;
-static int sound_ticks=0;
+extern int ql_ticks;
static unsigned char bcd2bin (unsigned char b);
static unsigned char bin2bcd (unsigned char b);
@@ -81,16 +86,16 @@ static struct console q40_console_driver = {
};
-/* Save tick handler routine pointer, will point to do_timer() in
- * kernel/sched.c */
-
-/* static void (*tick_handler)(int, void *, struct pt_regs *); */
-
-
/* early debugging function:*/
extern char *q40_mem_cptr; /*=(char *)0xff020000;*/
static int _cpleft;
+int q40_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
+{
+ *keycodep = keycode;
+ return 1;
+}
+
static void q40_mem_console_write(struct console *co, const char *s,
unsigned int count)
{
@@ -140,6 +145,41 @@ static void q40_get_model(char *model)
sprintf(model, "Q40");
}
+/* pasted code to make parport_pc happy */
+extern __inline__ int __get_order(unsigned long size)
+{
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+void *pci_alloc_consistent(void *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ void *ret;
+ int gfp = GFP_ATOMIC;
+
+ ret = (void *)__get_free_pages(gfp, __get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_bus(ret);
+ }
+ return ret;
+}
+
+void pci_free_consistent(void *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, __get_order(size));
+}
+/* end pasted code */
+
/* No hardware options on Q40? */
@@ -149,12 +189,23 @@ static int q40_get_hardware_list(char *buffer)
return 0;
}
+static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0};
+void q40_disable_irqs(void)
+{
+ unsigned i,j;
+
+ j=0;
+ while((i=serports[j++])) outb(0,i+UART_IER);
+ master_outb(0,EXT_ENABLE_REG);
+ master_outb(0,KEY_IRQ_ENABLE_REG);
+}
void __init config_q40(void)
{
mach_sched_init = q40_sched_init; /* ok */
/*mach_kbdrate = q40_kbdrate;*/ /* unneeded ?*/
mach_keyb_init = q40_keyb_init; /* OK */
+ mach_kbd_translate = q40_kbd_translate;
mach_init_IRQ = q40_init_IRQ;
mach_gettimeoffset = q40_gettimeoffset;
mach_gettod = q40_gettod;
@@ -177,13 +228,14 @@ void __init config_q40(void)
mach_sysrq_key = 0x54;
#endif
conswitchp = &dummy_con;
-#ifdef CONFIG_BLK_DEV_FD
- mach_floppy_setup = fd_floppy_setup;
- mach_floppy_eject = fd_floppy_eject;
+#if 0 /*def CONFIG_BLK_DEV_FD*/
+ mach_floppy_setup = floppy_setup;
+ mach_floppy_eject = floppy_eject;
/**/
#endif
- mach_max_dma_address = 0; /* no DMA at all */
+ q40_disable_irqs();
+ mach_max_dma_address = 32*1024*1024; /* no DMA at all, but ide-scsi requires it.. */
/* userfull for early debuging stages writes kernel messages into SRAM */
@@ -203,6 +255,7 @@ int q40_parse_bootinfo(const struct bi_record *rec)
return 1; /* unknown */
}
+#if 0
#define DAC_LEFT ((unsigned char *)0xff008000)
#define DAC_RIGHT ((unsigned char *)0xff008004)
void q40_mksound(unsigned int hz, unsigned int ticks)
@@ -258,7 +311,11 @@ static void q40_timer_int (int irq, void *dev_id, struct pt_regs *fp)
#endif
q40_timer_routine(irq, dev_id, fp);
}
+#endif
+#if 0
+extern void (*q40_timer_routine)(int, void *, struct pt_regs *);
+extern void q40_timer_int();
void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
{
@@ -289,7 +346,7 @@ void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
#endif
#endif
}
-
+#endif
unsigned long q40_gettimeoffset (void)
{
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index c6625aad8..96d9414d3 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -7,18 +7,22 @@
* License. See the file COPYING in the main directory of this archive
* for more details.
*
- * losely based on bvme6000ints.c
+ * .. used to be losely based on bvme6000ints.c
*
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/sched.h>
+#include <asm/rtc.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/irq.h>
+#include <asm/hardirq.h>
#include <asm/traps.h>
#include <asm/q40_master.h>
@@ -71,13 +75,16 @@ short unsigned q40_ablecount[Q40_IRQ_MAX+1];
* the q40 IRQ handling routines.
*/
+static int disabled=0;
+
void q40_init_IRQ (void)
{
int i;
+ disabled=0;
for (i = 0; i <= Q40_IRQ_MAX; i++) {
irq_tab[i].handler = q40_defhand;
- irq_tab[i].flags = IRQ_FLG_STD;
+ irq_tab[i].flags = 0;
irq_tab[i].dev_id = NULL;
/* irq_tab[i].next = NULL;*/
irq_tab[i].devname[0] = 0;
@@ -87,14 +94,10 @@ void q40_init_IRQ (void)
}
/* setup handler for ISA ints */
- sys_request_irq(IRQ2,q40_irq2_handler, IRQ_FLG_LOCK, "q40 ISA and master chip", NULL);
+ sys_request_irq(IRQ2,q40_irq2_handler, 0, "q40 ISA and master chip", NULL);
/* now enable some ints.. */
-
-#if 0 /* has been abandoned */
- master_outb(1,SER_ENABLE_REG);
-#endif
- master_outb(1,EXT_ENABLE_REG);
+ master_outb(1,EXT_ENABLE_REG); /* hm, aint that too early? */
/* would be spurious ints by now, q40kbd_init_hw() does that */
master_outb(0,KEY_IRQ_ENABLE_REG);
@@ -124,24 +127,20 @@ int q40_request_irq(unsigned int irq,
default:
}
- if (irq<Q40_IRQ_TIMER)
+ if (irq<Q40_IRQ_SAMPLE)
{
- if (!(irq_tab[irq].flags & IRQ_FLG_STD))
- {
- if (irq_tab[irq].flags & IRQ_FLG_LOCK)
+ if (irq_tab[irq].dev_id != NULL)
{
printk("%s: IRQ %d from %s is not replaceable\n",
__FUNCTION__, irq, irq_tab[irq].devname);
return -EBUSY;
}
- if (flags & IRQ_FLG_REPLACE)
+ /*printk("IRQ %d set to handler %p\n",irq,handler);*/
+ if (dev_id==NULL)
{
- printk("%s: %s can't replace IRQ %d from %s\n",
- __FUNCTION__, devname, irq, irq_tab[irq].devname);
- return -EBUSY;
- }
+ printk("WARNING: dev_id == NULL in request_irq\n");
+ dev_id=1;
}
- /*printk("IRQ %d set to handler %p\n",irq,handler);*/
irq_tab[irq].handler = handler;
irq_tab[irq].flags = flags;
irq_tab[irq].dev_id = dev_id;
@@ -150,7 +149,7 @@ int q40_request_irq(unsigned int irq,
return 0;
}
else {
- /* Q40_IRQ_TIMER :somewhat special actions required here ..*/
+ /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/
sys_request_irq(4,handler,flags,devname,dev_id);
sys_request_irq(6,handler,flags,devname,dev_id);
return 0;
@@ -175,31 +174,120 @@ void q40_free_irq(unsigned int irq, void *dev_id)
default:
}
- if (irq<Q40_IRQ_TIMER)
+ if (irq<Q40_IRQ_SAMPLE)
{
if (irq_tab[irq].dev_id != dev_id)
printk("%s: Removing probably wrong IRQ %d from %s\n",
__FUNCTION__, irq, irq_tab[irq].devname);
irq_tab[irq].handler = q40_defhand;
- irq_tab[irq].flags = IRQ_FLG_STD;
+ irq_tab[irq].flags = 0;
irq_tab[irq].dev_id = NULL;
/* irq_tab[irq].devname = NULL; */
/* do not reset state !! */
}
else
- { /* == Q40_IRQ_TIMER */
+ { /* == Q40_IRQ_SAMPLE */
sys_free_irq(4,dev_id);
sys_free_irq(6,dev_id);
}
}
-#if 1
+
void q40_process_int (int level, struct pt_regs *fp)
{
printk("unexpected interrupt %x\n",level);
}
+
+/*
+ * this stuff doesn't really belong here..
+*/
+int ql_ticks=0;
+static int sound_ticks=0;
+
+#define SVOL 45
+
+void q40_mksound(unsigned int hz, unsigned int ticks)
+{
+ /* for now ignore hz, except that hz==0 switches off sound */
+ /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
+ if (hz==0)
+ {
+ if (sound_ticks)
+ sound_ticks=1; /* atomic - no irq spinlock used */
+
+ *DAC_LEFT=128;
+ *DAC_RIGHT=128;
+
+ return;
+ }
+ /* sound itself is done in q40_timer_int */
+ if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
+ sound_ticks=ticks<<1;
+}
+
+static void (*q40_timer_routine)(int, void *, struct pt_regs *);
+static short rtc_oldsecs=0;
+unsigned rtc_irq_flags=0;
+unsigned rtc_irq_ctrl=0;
+
+static void q40_timer_int (int irq, void * dev, struct pt_regs * regs)
+{
+
+
+#if (HZ==100)
+ ql_ticks = ql_ticks ? 0 : 1;
+ if (sound_ticks)
+ {
+ unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
+ sound_ticks--;
+ *DAC_LEFT=sval;
+ *DAC_RIGHT=sval;
+ }
+#ifdef CONFIG_Q40RTC
+ if (rtc_irq_ctrl && (rtc_oldsecs != RTC_SECS))
+ {
+ rtc_oldsecs = RTC_SECS;
+ rtc_irq_flags = RTC_UIE;
+ rtc_interrupt();
+ }
#endif
+ if (ql_ticks) return;
+#endif
+ q40_timer_routine(irq, dev, regs);
+}
+
+void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+{
+ int timer_irq;
+
+ q40_timer_routine = timer_routine;
+
+#if (HZ==10000)
+ timer_irq=Q40_IRQ_SAMPLE;
+#else
+ timer_irq=Q40_IRQ_FRAME;
+#endif
+
+ /*printk("registering sched/timer IRQ %d, handler %p\n", timer_irq,q40_timer_int);*/
+ /*printk("timer routine %p\n",q40_timer_routine);*/
+
+ if (request_irq(timer_irq, q40_timer_int, 0,
+ "timer", q40_timer_int))
+ panic ("Couldn't register timer int");
+
+#if (HZ==10000)
+ master_outb(SAMPLE_LOW,SAMPLE_RATE_REG);
+ master_outb(-1,SAMPLE_CLEAR_REG);
+ master_outb(1,SAMPLE_ENABLE_REG);
+#else
+ master_outb(-1,FRAME_CLEAR_REG); /* not necessary ? */
+#if (HZ==100)
+ master_outb( 1,FRAME_RATE_REG);
+#endif
+#endif
+}
+
/*
* tables to translate bits into IRQ numbers
@@ -208,11 +296,12 @@ void q40_process_int (int level, struct pt_regs *fp)
*/
struct IRQ_TABLE{ unsigned mask; int irq ;};
-
+#if 0
static struct IRQ_TABLE iirqs[]={
{IRQ_FRAME_MASK,Q40_IRQ_FRAME},
{IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
{0,0}};
+#endif
static struct IRQ_TABLE eirqs[]={
{IRQ3_MASK,3}, /* ser 1 */
{IRQ4_MASK,4}, /* ser 2 */
@@ -231,103 +320,124 @@ static struct IRQ_TABLE eirqs[]={
/* complain only this many times about spurious ints : */
static int ccleirq=60; /* ISA dev IRQ's*/
-static int cclirq=60; /* internal */
+/*static int cclirq=60;*/ /* internal */
/* FIX: add shared ints,mask,unmask,probing.... */
-/* this is an awfull hack.. */
+
#define IRQ_INPROGRESS 1
-static int disabled=0;
/*static unsigned short saved_mask;*/
+static int do_tint=0;
+
+#define DEBUG_Q40INT
+#define IP_USE_DISABLE /* would be nice, but crashes ???? */
+/*static int dd_count=0;*/
+static int mext_disabled=0; /* ext irq disabled by master chip? */
+static int aliased_irq=0; /* how many times inside handler ?*/
+
+
+/* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */
void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
{
- /* got level 2 interrupt, dispatch to ISA or keyboard IRQs */
-
- unsigned mir=master_inb(IIRQ_REG);
+ unsigned mir;
unsigned mer;
int irq,i;
+ repeat:
+ mir=master_inb(IIRQ_REG);
+ if (mir&IRQ_FRAME_MASK)
+ { /* dont loose ticks */
+ do_tint++;
+ master_outb(-1,FRAME_CLEAR_REG);
+ }
if ((mir&IRQ_SER_MASK) || (mir&IRQ_EXT_MASK))
{
-
/* some ISA dev caused the int */
-
mer=master_inb(EIRQ_REG);
-
for (i=0; eirqs[i].mask; i++)
{
if (mer&(eirqs[i].mask))
{
irq=eirqs[i].irq;
- irq_tab[irq].count++;
+/*
+ * There is a little mess wrt which IRQ really caused this irq request. The
+ * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they
+ * are read - which is long after the request came in. In theory IRQs should
+ * not just go away but they occassionally do
+ */
+ if (irq>4 && irq<=15 && mext_disabled)
+ {
+ /*aliased_irq++;*/
+ goto iirq;
+ }
if (irq_tab[irq].handler == q40_defhand )
{
printk("handler for IRQ %d not defined\n",irq);
continue; /* ignore uninited INTs :-( */
}
-
if ( irq_tab[irq].state & IRQ_INPROGRESS )
{
+ /* some handlers do sti() for irq latency reasons, */
+ /* however reentering an active irq handler is not permitted */
+#ifdef IP_USE_DISABLE
+ /* in theory this is the better way to do it because it still */
+ /* lets through eg the serial irqs, unfortunately it crashes */
+ disable_irq(irq);
+ disabled=1;
+#else
/*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */
-
- /*saved_mask = fp->sr;*/
- fp->sr = (fp->sr & (~0x700))+0x200;
+ fp->sr = (((fp->sr) & (~0x700))+0x200);
disabled=1;
- return;
+#endif
+ goto iirq;
}
+ irq_tab[irq].count++;
irq_tab[irq].state |= IRQ_INPROGRESS;
irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+ irq_tab[irq].state &= ~IRQ_INPROGRESS;
/* naively enable everything, if that fails than */
/* this function will be reentered immediately thus */
/* getting another chance to disable the IRQ */
- irq_tab[irq].state &= ~IRQ_INPROGRESS;
if ( disabled )
{
+#ifdef IP_USE_DISABLE
+ if (irq>4){
+ disabled=0;
+ /*dd_count--;*/
+ enable_irq(irq);}
+#else
+ disabled=0;
/*printk("reenabling irq %d\n",irq); */
- fp->sr = (fp->sr & (~0x700)); /*saved_mask; */
- disabled=0;
+#if 0
+ fp->sr = ((fp->sr) & (~0x700)); /* unneeded ?! */
+#endif
+#endif
}
- else if ( fp->sr &0x200 )
- printk("exiting irq handler: fp->sr &0x200 !!\n");
-
- return;
+ goto repeat; /* return; */
}
}
- if (ccleirq>0)
+ if (mer && ccleirq>0 && !aliased_irq)
printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
}
- else
+ iirq:
+ mir=master_inb(IIRQ_REG);
+ if (mir&IRQ_FRAME_MASK)
{
- /* internal */
-
- for (i=0; iirqs[i].mask; i++)
+ do_tint++;
+ master_outb(-1,FRAME_CLEAR_REG);
+ }
+ for(;do_tint>0;do_tint--)
{
- if (mir&(iirqs[i].mask))
- {
- irq=iirqs[i].irq;
- irq_tab[irq].count++;
- if (irq_tab[irq].handler == q40_defhand )
- continue; /* ignore uninited INTs :-( */
-
- /* the INPROGRESS stuff should be completely useless*/
- /* for internal ints, nevertheless test it..*/
- if ( irq_tab[irq].state & IRQ_INPROGRESS )
+ irq_tab[Q40_IRQ_FRAME].count++;
+ irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);
+ }
+ if (mir&IRQ_KEYB_MASK) /* may handle it even if actually disabled*/
{
- /*disable_irq(irq);
- return;*/
- printk("rentering handler for IRQ %d !!\n",irq);
- }
- irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
- irq_tab[irq].state &= ~IRQ_INPROGRESS;
- /*enable_irq(irq);*/ /* better not try luck !*/
- return;
- }
- }
- if (cclirq>0)
- printk("internal level 2 interrupt from unknown source ? IIRQ_REG=%x\n",mir),cclirq--;
+ irq_tab[Q40_IRQ_KEYBOARD].count++;
+ irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
}
}
@@ -335,9 +445,11 @@ int q40_get_irq_list (char *buf)
{
int i, len = 0;
- for (i = 0; i <= Q40_IRQ_MAX; i++) {
+ for (i = 0; i <= Q40_IRQ_MAX; i++)
+ {
if (irq_tab[i].count)
- len += sprintf (buf+len, "Vec 0x%02x: %8d %s%s\n",
+ len += sprintf (buf+len, "%sIRQ %02d: %8d %s%s\n",
+ (i<=15) ? "ISA-" : " " ,
i, irq_tab[i].count,
irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
irq_tab[i].handler == q40_defhand ?
@@ -370,30 +482,17 @@ static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs)
sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler
};
-int irq_disabled=0;
+
void q40_enable_irq (unsigned int irq)
{
- /* enable ISA iqs */
- if ( irq>=0 && irq<=15 ) /* the moderately bad case */
+ if ( irq>=5 && irq<=15 )
+ {
+ mext_disabled--;
+ if (mext_disabled>0)
+ printk("q40_enable_irq : nested disable/enable\n");
+ if (mext_disabled==0)
master_outb(1,EXT_ENABLE_REG);
-#if 0
- unsigned long flags;
- int i;
-
- if (irq>=10 && irq <= 15)
- {
- if ( !(--q40_ablecount[irq]))
- for (i=10,irq_disabled=0; i<=15; i++)
- {
- irq_disabled |= (q40_ablecount[irq] !=0);
- }
- if ( !irq_disabled )
- {
- save_flags(flags);
- restore_flags(flags & (~0x700));
- }
}
-#endif
}
@@ -404,19 +503,12 @@ void q40_disable_irq (unsigned int irq)
* Any driver should not attempt to sleep accross disable_irq !!
*/
- if ( irq>=10 && irq<=15 ) /* the moderately bad case */
- master_outb(0,EXT_ENABLE_REG);
-#if 0
- unsigned long flags;
-
- if (irq>=10 && irq <= 15)
+ if ( irq>=5 && irq<=15 )
{
- save_flags(flags);
- restore_flags(flags | 0x200 );
- irq_disabled=1;
- q40_ablecount[irq]++;
+ master_outb(0,EXT_ENABLE_REG);
+ mext_disabled++;
+ if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled);
}
-#endif
}
unsigned long q40_probe_irq_on (void)
@@ -428,3 +520,7 @@ int q40_probe_irq_off (unsigned long irqs)
{
return -1;
}
+/*
+ * Local variables:
+ * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040 -c -o q40ints.o q40ints.c"
+ */
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6a8cfe187..3ea928267 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -151,7 +151,8 @@ LOADADDR += 0x80080000
endif
ifdef CONFIG_SGI_IP22
-LIBS += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a
+CORE_FILES += arch/mips/sgi/kernel/ip22-kern.o
+LIBS += arch/mips/arc/arclib.a
SUBDIRS += arch/mips/sgi/kernel arch/mips/arc
#
# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
@@ -273,7 +274,6 @@ zdisk: vmlinux
archclean:
@$(MAKEBOOT) clean
rm -f arch/$(ARCH)/ld.script
- $(MAKE) -C arch/$(ARCH)/kernel clean
$(MAKE) -C arch/$(ARCH)/tools clean
$(MAKE) -C arch/mips/baget clean
diff --git a/arch/mips/arc/Makefile b/arch/mips/arc/Makefile
index e37207b33..8af31d353 100644
--- a/arch/mips/arc/Makefile
+++ b/arch/mips/arc/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
#
# Makefile for the SGI arcs prom monitor library routines
# under Linux.
@@ -10,11 +9,12 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
L_TARGET = arclib.a
-L_OBJS = console.o init.o memory.o tree.o env.o cmdline.o misc.o time.o \
- file.o identify.o
-ifdef CONFIG_ARC_CONSOLE
-L_OBJS += arc_con.o
-endif
+obj-y += console.o init.o memory.o tree.o env.o cmdline.o misc.o \
+ time.o file.o identify.o
+
+obj-$(CONFIG_ARC_CONSOLE) += arc_con.o
+
+L_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 6f64e8a9a..b75e37c6b 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -301,8 +301,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-atlas b/arch/mips/defconfig-atlas
index 4b0740fe9..e622a3f9a 100644
--- a/arch/mips/defconfig-atlas
+++ b/arch/mips/defconfig-atlas
@@ -28,7 +28,7 @@ CONFIG_MIPS_ATLAS=y
# CONFIG_MCA is not set
# CONFIG_SBUS is not set
CONFIG_PCI=y
-# CONFIG_ISA is not set
+CONFIG_SWAP_IO_SPACE=y
# CONFIG_ISA is not set
# CONFIG_EISA is not set
# CONFIG_I8259 is not set
@@ -429,8 +429,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-cp7000 b/arch/mips/defconfig-cp7000
index d67e287ba..1d98bca31 100644
--- a/arch/mips/defconfig-cp7000
+++ b/arch/mips/defconfig-cp7000
@@ -405,8 +405,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-ddb5476 b/arch/mips/defconfig-ddb5476
index 21f540a76..9c74cad89 100644
--- a/arch/mips/defconfig-ddb5476
+++ b/arch/mips/defconfig-ddb5476
@@ -468,8 +468,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-decstation b/arch/mips/defconfig-decstation
index dece17abb..72ac15128 100644
--- a/arch/mips/defconfig-decstation
+++ b/arch/mips/defconfig-decstation
@@ -295,8 +295,6 @@ CONFIG_EXT2_FS=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-ev64120 b/arch/mips/defconfig-ev64120
index 38dd7bbfb..004f6083f 100644
--- a/arch/mips/defconfig-ev64120
+++ b/arch/mips/defconfig-ev64120
@@ -404,8 +404,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-ev96100 b/arch/mips/defconfig-ev96100
index 262fd226a..eae29f655 100644
--- a/arch/mips/defconfig-ev96100
+++ b/arch/mips/defconfig-ev96100
@@ -395,8 +395,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22
index 6f64e8a9a..b75e37c6b 100644
--- a/arch/mips/defconfig-ip22
+++ b/arch/mips/defconfig-ip22
@@ -301,8 +301,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-malta b/arch/mips/defconfig-malta
index 826c3f871..7f83eba55 100644
--- a/arch/mips/defconfig-malta
+++ b/arch/mips/defconfig-malta
@@ -29,7 +29,8 @@ CONFIG_MIPS_MALTA=y
# CONFIG_SBUS is not set
CONFIG_I8259=y
CONFIG_PCI=y
-# CONFIG_ISA is not set
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+CONFIG_SWAP_IO_SPACE=y
# CONFIG_ISA is not set
# CONFIG_EISA is not set
@@ -427,8 +428,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-rm200 b/arch/mips/defconfig-rm200
index 8fced9009..fefe5f65d 100644
--- a/arch/mips/defconfig-rm200
+++ b/arch/mips/defconfig-rm200
@@ -319,8 +319,6 @@ CONFIG_EXT2_FS=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 9be8406e4..6bec68661 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -11,97 +11,60 @@
.S.o:
$(CC) $(AFLAGS) -c $< -o $@
-all: kernel.o head.o init_task.o
EXTRA_ASFLAGS = -mips3 -mcpu=r4000
+
+all: kernel.o head.o init_task.o
+
O_TARGET := kernel.o
-O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
- ioport.o reset.o semaphore.o setup.o syscall.o sysmips.o ipc.o \
- scall_o32.o unaligned.o
-OX_OBJS := mips_ksyms.o
+
+obj-y += branch.o process.o signal.o entry.o \
+ traps.o ptrace.o vm86.o ioport.o reset.o \
+ semaphore.o setup.o syscall.o sysmips.o \
+ ipc.o scall_o32.o unaligned.o
+obj-$(CONFIG_MODULES) += mips_ksyms.o
ifdef CONFIG_CPU_R3000
-O_OBJS += r2300_misc.o r2300_fpu.o r2300_switch.o
+obj-y += r2300_misc.o r2300_fpu.o r2300_switch.o
else
-O_OBJS += r4k_misc.o r4k_switch.o
+obj-y += r4k_misc.o r4k_switch.o
ifdef CONFIG_CPU_R6000
-O_OBJS += r6000_fpu.o
+obj-y += r6000_fpu.o
else
-O_OBJS += r4k_fpu.o
-endif
+obj-y += r4k_fpu.o
endif
-
-ifdef CONFIG_MIPS_FPE_MODULE
-M_OBJS += fpe.o
endif
-ifndef CONFIG_MIPS_FPU_EMULATOR
-O_OBJS += softfp.o
-endif
+obj-$(CONFIG_MIPS_FPE_MODULE) += fpe.o
+obj-$(CONFIG_MIPS_FPU_EMULATOR) += softfp.o
-ifdef CONFIG_ROTTEN_IRQ
- OX_OBJS += old-irq.o
-endif
+# Old style irq support, going to die in 2.5.
+export-objs += old-irq.o
+obj-$(CONFIG_ROTTEN_IRQ) += old-irq.o
ifndef CONFIG_DECSTATION
ifndef CONFIG_BAGET_MIPS
ifndef CONFIG_MIPS_ATLAS
ifndef CONFIG_MIPS_MALTA
ifndef CONFIG_MIPS_EV96100
- O_OBJS += time.o
+ obj-y += time.o
endif
endif
endif
endif
endif
-#
-# Do we want to be able to execute IRIX elf binaries?
-#
-ifdef CONFIG_BINFMT_IRIX
-O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o irixinv.o
-endif
-
-#
-# Kernel debugging
-#
-ifdef CONFIG_REMOTE_DEBUG
-O_OBJS += gdb-low.o gdb-stub.o
-endif
-
-ifdef CONFIG_PCI
-O_OBJS += pci-dma.o
-endif
-
-ifdef CONFIG_PROC_FS
-O_OBJS += proc.o
-endif
-
-#
-# Since we add the same object files to O_OBJS for different configurations.
-# O_OBJS might contain duplicate files. We correct this by filtering out
-# duplicate files. Just to avoid users having to know about all the
-# compatibility stuff between various boards and boards.
-#
-O_OBJS := $(sort $(O_OBJS))
+obj-$(CONFIG_BINFMT_IRIX) += irixelf.o irixioctl.o irixsig.o sysirix.o \
+ irixinv.o
+obj-$(CONFIG_REMOTE_DEBUG) += gdb-low.o gdb-stub.o
+obj-$(CONFIG_PCI) += pci-dma.o
+obj-$(CONFIG_PROC_FS) += proc.o
entry.o: entry.S
-
head.o: head.S
-#r4k_switch.o: r4k_switch.S
-#
-#r4k_misc.o: r4k_misc.S
-#
-#r4k_fpu.o: r4k_fpu.S
-#
-#r2300_switch.o: r2300_switch.S
-#
-#r2300_misc.o: r2300_misc.S
-#
-#r2300_fpu.o: r2300_fpu.S
-#
-#r6000_fpu.o: r6000_fpu.S
-
-clean:
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS := $(filter $(export-objs), $(obj-y))
+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 6f6556da4..022bb1f77 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -716,7 +716,7 @@ repeat:
SET_LINKS(p);
notify_parent(p, SIGCHLD);
} else
- release(p);
+ release_task(p);
goto end_waitsys;
default:
continue;
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index d3ea588f0..f2a1d7032 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -36,19 +36,6 @@
#include <asm/inst.h>
#endif
-extern int console_loglevel;
-
-static inline void console_silent(void)
-{
- console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
- if (console_loglevel)
- console_loglevel = 15;
-}
-
/*
* Machine specific interrupt handlers
*/
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 52331d233..a5c870b73 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -9,26 +9,21 @@
L_TARGET = lib.a
-L_OBJS = csum_partial.o csum_partial_copy.o \
- rtc-std.o rtc-no.o memcpy.o memset.o watch.o\
- strlen_user.o strncpy_user.o strnlen_user.o
+obj-y += csum_partial.o csum_partial_copy.o \
+ rtc-std.o rtc-no.o memcpy.o memset.o \
+ watch.o strlen_user.o strncpy_user.o \
+ strnlen_user.o
ifdef CONFIG_CPU_R3000
- L_OBJS += r3k_dump_tlb.o
+ obj-y += r3k_dump_tlb.o
else
- L_OBJS += dump_tlb.o
+ obj-y += dump_tlb.o
endif
-ifdef CONFIG_BLK_DEV_FD
- L_OBJS += floppy-no.o floppy-std.o
-endif
-
-ifdef CONFIG_IDE
- L_OBJS += ide-std.o ide-no.o
-endif
+obj-$(CONFIG_BLK_DEV_FD) += floppy-no.o floppy-std.o
+obj-$(CONFIG_IDE) += ide-std.o ide-no.o
+obj-$(CONFIG_PC_KEYB) += kbd-std.o kbd-no.o
-ifdef CONFIG_PC_KEYB
- L_OBJS += kbd-std.o kbd-no.o
-endif
+L_OBJS := $(filter-out $(export-objs), $(obj-y))
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 4febbefd2..67a987693 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -8,46 +8,20 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := mm.o
-O_OBJS := extable.o init.o fault.o loadmmu.o
-ifdef CONFIG_CPU_R3000
-O_OBJS += r2300.o
-endif
+obj-y += extable.o init.o fault.o loadmmu.o
-ifdef CONFIG_CPU_R4300
-O_OBJS += r4xx0.o
-endif
+obj-$(CONFIG_CPU_R3000) += r2300.o
+obj-$(CONFIG_CPU_R4300) += r4xx0.o
+obj-$(CONFIG_CPU_R4X00) += r4xx0.o
+obj-$(CONFIG_CPU_R5000) += r4xx0.o
+obj-$(CONFIG_CPU_NEVADA) += r4xx0.o
+obj-$(CONFIG_CPU_R5432) += r5432.o
+obj-$(CONFIG_CPU_RM7000) += rm7k.o
+obj-$(CONFIG_CPU_MIPS32) += mips32.o
+obj-$(CONFIG_SGI_IP22) += umap.o
+obj-$(CONFIG_BAGET_MIPS) += umap.o
-ifdef CONFIG_CPU_R4X00
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R5000
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R5432
-O_OBJS += r5432.o
-endif
-
-ifdef CONFIG_CPU_RM7000
-O_OBJS += rm7k.o
-endif
-
-ifdef CONFIG_CPU_NEVADA
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_MIPS32
-O_OBJS += mips32.o
-endif
-
-ifdef CONFIG_SGI_IP22
-O_OBJS += umap.o
-endif
-
-ifdef CONFIG_BAGET_MIPS
-O_OBJS += umap.o
-endif
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/sgi/kernel/Makefile b/arch/mips/sgi/kernel/Makefile
index f016cd12f..62fd01001 100644
--- a/arch/mips/sgi/kernel/Makefile
+++ b/arch/mips/sgi/kernel/Makefile
@@ -13,18 +13,15 @@
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
-OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \
- system.o indyIRQ.o reset.o setup.o time.o
+O_TARGET := ip22-kern.o
-all: sgikern.a
+all: ip22-kern.o indyIRQ.o
-sgikern.a: $(OBJS)
- $(AR) rcs sgikern.a $(OBJS)
- sync
+obj-y += indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \
+ indyIRQ.o reset.o setup.o time.o
indyIRQ.o: indyIRQ.S
-dep:
- $(CPP) $(CPPFLAGS) -M *.c > .depend
+O_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/arc/Makefile b/arch/mips64/arc/Makefile
index 141093f78..eb805e260 100644
--- a/arch/mips64/arc/Makefile
+++ b/arch/mips64/arc/Makefile
@@ -3,15 +3,15 @@
#
L_TARGET = arclib.a
-L_OBJS = init.o printf.o tree.o env.o cmdline.o misc.o time.o \
- file.o identify.o
+obj-y := init.o printf.o tree.o env.o cmdline.o misc.o time.o file.o \
+ identify.o
ifndef CONFIG_SGI_IP27
-L_OBJS += console.o
+ obj-y += console.o
endif
-ifdef CONFIG_ARC_MEMORY
-L_OBJS += memory.o
-endif
+obj-$(CONFIG_ARC_MEMORY) += memory.o
+
+L_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig
index 72f0b52bc..580ecb084 100644
--- a/arch/mips64/defconfig
+++ b/arch/mips64/defconfig
@@ -405,8 +405,6 @@ CONFIG_LOCKD_V4=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips64/defconfig-ip22 b/arch/mips64/defconfig-ip22
index 3848c0c96..8a747d636 100644
--- a/arch/mips64/defconfig-ip22
+++ b/arch/mips64/defconfig-ip22
@@ -321,8 +321,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips64/defconfig-ip27 b/arch/mips64/defconfig-ip27
index 72f0b52bc..580ecb084 100644
--- a/arch/mips64/defconfig-ip27
+++ b/arch/mips64/defconfig-ip27
@@ -405,8 +405,6 @@ CONFIG_LOCKD_V4=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips64/kernel/traps.c b/arch/mips64/kernel/traps.c
index 997aee0c7..c6777f938 100644
--- a/arch/mips64/kernel/traps.c
+++ b/arch/mips64/kernel/traps.c
@@ -27,19 +27,6 @@
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
-extern int console_loglevel;
-
-static inline void console_silent(void)
-{
- console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
- if (console_loglevel)
- console_loglevel = 15;
-}
-
extern asmlinkage void __xtlb_mod(void);
extern asmlinkage void __xtlb_tlbl(void);
extern asmlinkage void __xtlb_tlbs(void);
diff --git a/arch/mips64/lib/Makefile b/arch/mips64/lib/Makefile
index b8392d527..9ce5f0bd7 100644
--- a/arch/mips64/lib/Makefile
+++ b/arch/mips64/lib/Makefile
@@ -8,9 +8,12 @@
$(CC) $(CFLAGS) -c $< -o $*.o
L_TARGET = lib.a
-L_OBJS = csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \
+
+obj-y += csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \
floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \
rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o \
strnlen_user.o watch.o
+L_OBJS := $(obj-y)
+
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/mm/Makefile b/arch/mips64/mm/Makefile
index fe95aff18..2505f05bd 100644
--- a/arch/mips64/mm/Makefile
+++ b/arch/mips64/mm/Makefile
@@ -1,33 +1,18 @@
-# $Id: Makefile,v 1.4 2000/01/17 23:32:46 ralf Exp $
#
# Makefile for the Linux/MIPS-specific parts of the memory manager.
#
O_TARGET := mm.o
-O_OBJS := extable.o init.o fault.o loadmmu.o
-ifdef CONFIG_CPU_R4300
-O_OBJS += r4xx0.o
-endif
-ifdef CONFIG_CPU_R4X00
-O_OBJS += r4xx0.o
-endif
-ifdef CONFIG_CPU_R5000
-O_OBJS += r4xx0.o
-endif
-ifdef CONFIG_CPU_NEVADA
-O_OBJS += r4xx0.o
-endif
-ifdef CONFIG_CPU_R10000
-O_OBJS += andes.o
-endif
+obj-y := extable.o init.o fault.o loadmmu.o
-ifdef CONFIG_SGI_IP22
-O_OBJS += umap.o
-endif
+obj-$(CONFIG_CPU_R4300) += r4xx0.o
+obj-$(CONFIG_CPU_R4X00) += r4xx0.o
+obj-$(CONFIG_CPU_R5000) += r4xx0.o
+obj-$(CONFIG_CPU_NEVADA) += r4xx0.o
+obj-$(CONFIG_CPU_R10000) += andes.o
+obj-$(CONFIG_SGI_IP22) += umap.o
-ifdef CONFIG_BAGET_MIPS
-O_OBJS += umap.o
-endif
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/sgi-ip22/Makefile b/arch/mips64/sgi-ip22/Makefile
index f303d90da..641fcbddf 100644
--- a/arch/mips64/sgi-ip22/Makefile
+++ b/arch/mips64/sgi-ip22/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1999/08/20 21:13:33 ralf Exp $
#
# Makefile for the SGI specific kernel interface routines
# under Linux.
@@ -10,7 +9,10 @@
$(CC) $(CFLAGS) -c $< -o $*.o
L_TARGET = ip22.a
-L_OBJS = ip22-berr.o ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \
- ip22-setup.o system.o ip22-timer.o ip22-irq.o ip22-reset.o time.o
+
+obj-y += ip22-berr.o ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \
+ ip22-setup.o system.o ip22-timer.o ip22-irq.o ip22-reset.o time.o
+
+L_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/sgi-ip27/Makefile b/arch/mips64/sgi-ip27/Makefile
index cab7e6be5..49dd85cb4 100644
--- a/arch/mips64/sgi-ip27/Makefile
+++ b/arch/mips64/sgi-ip27/Makefile
@@ -8,8 +8,11 @@
$(CC) $(CFLAGS) -c $< -o $*.o
O_TARGET = ip27.a
-O_OBJS = ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
- ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \
- ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o
+
+obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+ ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \
+ ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o
+
+O_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/tools/Makefile b/arch/mips64/tools/Makefile
index 3218bfe5f..33d0c17b1 100644
--- a/arch/mips64/tools/Makefile
+++ b/arch/mips64/tools/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1999/08/18 21:46:53 ralf Exp $
#
# Makefile for MIPS kernel build tools.
#
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
new file mode 100644
index 000000000..ec27df6b0
--- /dev/null
+++ b/arch/parisc/Makefile
@@ -0,0 +1,91 @@
+#
+# parisc/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Portions Copyright (C) 1999 The Puffin Group
+#
+# Modified for PA-RISC Linux by Paul Lahaie, Alex deVries,
+# Mike Shaver, Helge Deller and Martin K. Petersen
+#
+
+FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align
+
+CPP=$(CC) -E
+OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
+LDFLAGS =
+LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux.lds $(LDFLAGS)
+
+CFLAGS_PIPE := -pipe
+CFLAGS_NSR := -fno-strength-reduce
+CFLAGS := $(CFLAGS) -D__linux__ $(CFLAGS_PIPE) $(CFLAGS_NSR)
+
+# These should be on for older toolchains or SOM toolchains that don't
+# enable them by default.
+CFLAGS += -mno-space-regs -mfast-indirect-calls
+
+# If we become able to compile for specific platforms, this should be
+# conditional on that.
+CFLAGS += -mschedule=7200
+
+# No fixed-point multiply
+CFLAGS += -mdisable-fpregs
+
+HEAD = arch/parisc/kernel/head.o
+
+SUBDIRS := $(SUBDIRS) $(addprefix arch/parisc/, tools kernel mm lib hpux)
+CORE_FILES := $(addprefix arch/parisc/, kernel/pdc_cons.o kernel/process.o \
+ lib/lib.a mm/mm.o kernel/kernel.o hpux/hpux.o) \
+ $(CORE_FILES) arch/parisc/kernel/init_task.o
+LIBS := `$(CC) -print-libgcc-file-name` $(TOPDIR)/arch/parisc/lib/lib.a $(LIBS)
+
+ifdef CONFIG_MATH_EMULATION
+SUBDIRS := $(SUBDIRS) arch/parisc/math-emu
+DRIVERS := $(DRIVERS) arch/parisc/math-emu/math.a
+endif
+
+ifdef CONFIG_KWDB
+SUBDIRS := $(SUBDIRS) arch/parisc/kdb
+DRIVERS := $(DRIVERS) arch/parisc/kdb/kdb.o
+
+arch/parisc/kdb: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/kdb
+endif
+
+arch/parisc/kernel: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/kernel
+
+arch/parisc/mm: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/mm
+
+palo: vmlinux
+ export TOPDIR=`pwd`; export CONFIG_STI_CONSOLE=$(CONFIG_STI_CONSOLE); \
+ unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage
+
+Image: palo
+
+Image-clean:
+
+ramdisk.o:
+
+zImage: palo
+
+bzImage: palo
+
+compressed: zImage
+
+install:
+
+archclean:
+
+archmrproper:
+
+archdep:
diff --git a/arch/parisc/config.in b/arch/parisc/config.in
new file mode 100644
index 000000000..eed80181e
--- /dev/null
+++ b/arch/parisc/config.in
@@ -0,0 +1,208 @@
+#
+# For a description of the syntax of this configuration file,
+# see the Configure script.
+#
+
+mainmenu_name "Linux Kernel Configuration"
+
+define_bool CONFIG_PARISC y
+define_bool CONFIG_UID16 n
+
+mainmenu_option next_comment
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
+
+mainmenu_option next_comment
+comment 'General options'
+
+# bool 'Symmetric multi-processing support' CONFIG_SMP
+define_bool CONFIG_SMP n
+
+bool 'Kernel Debugger support' CONFIG_KWDB
+# define_bool CONFIG_KWDB n
+
+# bool 'GSC/Gecko bus support' CONFIG_GSC y
+define_bool CONFIG_GSC y
+
+bool 'U2/Uturn I/O MMU' CONFIG_IOMMU_CCIO y
+bool 'LASI I/O support' CONFIG_GSC_LASI y
+
+bool 'PCI bus support' CONFIG_PCI y
+
+if [ "$CONFIG_PCI" = "y" ]; then
+ bool 'GSCtoPCI/DINO PCI support' CONFIG_GSC_DINO y
+ bool 'LBA/Elroy PCI support' CONFIG_PCI_LBA n
+fi
+
+if [ "$CONFIG_PCI_LBA" = "y" ]; then
+ define_bool CONFIG_IOSAPIC y
+ define_bool CONFIG_IOMMU_SBA y
+fi
+
+#
+# if [ "$CONFIG_PCI_EPIC" = "y" ]; then...
+#
+
+endmenu
+
+mainmenu_option next_comment
+comment 'Loadable module support'
+bool 'Enable loadable module support' CONFIG_MODULES
+if [ "$CONFIG_MODULES" = "y" ]; then
+ bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+ bool 'Kernel module loader' CONFIG_KMOD
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'General setup'
+
+bool 'Networking support' CONFIG_NET
+
+bool 'System V IPC' CONFIG_SYSVIPC
+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
+bool 'Sysctl support' CONFIG_SYSCTL
+tristate 'Kernel support for SOM binaries' CONFIG_BINFMT_SOM
+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA
+fi
+
+endmenu
+
+##source drivers/parport/Config.in
+mainmenu_option next_comment
+comment 'Parallel port support'
+
+tristate 'Parallel port support' CONFIG_PARPORT
+if [ "$CONFIG_PARPORT" != "n" ]; then
+ if [ "$CONFIG_PCI" = "y" ]; then
+ dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT_PC" != "n" ]; then
+ bool ' Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool ' SuperIO chipset support (EXPERIMENTAL)' CONFIG_PARPORT_PC_SUPERIO
+ fi
+ fi
+ fi
+ if [ "$CONFIG_GSC_LASI" = "y" ]; then
+ dep_tristate ' LASI/ASP builtin parallel-port' CONFIG_PARPORT_GSC $CONFIG_PARPORT
+ else
+ define_tristate CONFIG_PARPORT_GSC n
+ fi
+
+ # If exactly one hardware type is selected then parport will optimise away
+ # support for loading any others. Defeat this if the user is keen.
+ bool ' Support foreign hardware' CONFIG_PARPORT_OTHER
+
+ bool ' IEEE 1284 transfer modes' CONFIG_PARPORT_1284
+fi
+endmenu
+
+
+source drivers/block/Config.in
+
+if [ "$CONFIG_NET" = "y" ]; then
+ source net/Config.in
+fi
+
+mainmenu_option next_comment
+comment 'SCSI support'
+
+tristate 'SCSI support' CONFIG_SCSI
+
+if [ "$CONFIG_SCSI" != "n" ]; then
+ comment 'SCSI support type (disk, tape, CDrom)'
+
+ dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+ if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+ fi
+
+ dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+ dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+ if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
+ bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
+ fi
+ dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
+
+ comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
+ bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
+ bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
+
+ mainmenu_option next_comment
+ comment 'SCSI low-level drivers'
+ if [ "$CONFIG_GSC_LASI" = "y" ]; then
+ dep_tristate 'Lasi SCSI support' CONFIG_SCSI_LASI $CONFIG_SCSI
+ dep_tristate 'Zalon SCSI support' CONFIG_SCSI_ZALON $CONFIG_SCSI
+ fi
+ if [ "$CONFIG_PCI" = "y" ]; then
+ dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI
+ fi
+ if [ "$CONFIG_SCSI_ZALON" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then
+ int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8
+ int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32
+ int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 20
+ bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE
+ bool ' use normal IO' CONFIG_SCSI_NCR53C8XX_IOMAPPED
+ fi
+ endmenu
+fi
+endmenu
+
+if [ "$CONFIG_NET" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Network device support'
+
+ bool 'Network device support' CONFIG_NETDEVICES
+
+ if [ "$CONFIG_NETDEVICES" = "y" ]; then
+ if [ "$CONFIG_GSC_LASI" = "y" ]; then
+ tristate 'Lasi ethernet' CONFIG_LASI_82596
+ fi
+ source drivers/net/Config.in
+ fi
+ endmenu
+fi
+
+source drivers/char/Config.in
+
+source fs/Config.in
+
+mainmenu_option next_comment
+comment 'Sound Drivers'
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+ source drivers/sound/Config.in
+fi
+endmenu
+
+if [ "$CONFIG_VT" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Console drivers'
+ source drivers/video/Config.in
+
+# bool 'IODC console' CONFIG_IODC_CONSOLE
+ bool 'STI console' CONFIG_STI_CONSOLE
+ if [ "$CONFIG_IODC_CONSOLE" = "n" ]; then
+ if [ "$CONFIG_GSC_PS2" = "y" ]; then
+ define_bool CONFIG_DUMMY_CONSOLE y
+ fi
+ fi
+ if [ "$CONFIG_STI_CONSOLE" = "y" ]; then
+ define_bool CONFIG_DUMMY_CONSOLE y
+ fi
+ endmenu
+fi
+# endmenu
+
+mainmenu_option next_comment
+comment 'Kernel hacking'
+
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+endmenu
+
diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig
new file mode 100644
index 000000000..352fa78c0
--- /dev/null
+++ b/arch/parisc/defconfig
@@ -0,0 +1,363 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_PARISC=y
+# CONFIG_UID16 is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General options
+#
+# CONFIG_SMP is not set
+# CONFIG_KWDB is not set
+CONFIG_GSC=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_PCI=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_IOSAPIC=y
+CONFIG_IOMMU_SBA=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_BINFMT_SOM=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_BINFMT_JAVA is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+# CONFIG_PARPORT_PC is not set
+CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 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=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# 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=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=y
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SCSI_LASI=y
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_LASI_82596=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_NET_SB1000 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=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DE4X5 is not set
+CONFIG_TULIP=y
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_LNE390 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_RTL8129 is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC 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
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_GSC_PS2=y
+CONFIG_HIL=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_SERIAL_GSC=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_GENRTC=y
+# 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
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS 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_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_CRAMFS is not set
+# CONFIG_RAMFS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_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 is not set
+# 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_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 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_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Sound Drivers
+#
+# CONFIG_SOUND is not set
+
+#
+# Console drivers
+#
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+# CONFIG_STI_CONSOLE is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/parisc/hpux/Makefile b/arch/parisc/hpux/Makefile
new file mode 100644
index 000000000..d946959be
--- /dev/null
+++ b/arch/parisc/hpux/Makefile
@@ -0,0 +1,16 @@
+#
+# 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).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+all: hpux.o
+O_TARGET = hpux.o
+O_OBJS = entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o
+
+.o.S: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/hpux/entry_hpux.S b/arch/parisc/hpux/entry_hpux.S
new file mode 100644
index 000000000..165aeb6af
--- /dev/null
+++ b/arch/parisc/hpux/entry_hpux.S
@@ -0,0 +1,537 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ *
+ * modified by Matthew Wilcox <willy@bofh.ai> 1999-07-26
+ */
+
+
+#define ASSEMBLY
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+
+ .text
+
+#define ENTRY_NAME(_name_) .word _name_
+
+ .align 4
+ .export hpux_call_table
+hpux_call_table:
+ ENTRY_NAME(sys_ni_syscall) /* 0 */
+ ENTRY_NAME(sys_exit)
+ ENTRY_NAME(hpux_fork_wrapper)
+ ENTRY_NAME(sys_read)
+ ENTRY_NAME(sys_write)
+ ENTRY_NAME(sys_open) /* 5 */
+ ENTRY_NAME(sys_close)
+ ENTRY_NAME(hpux_wait)
+ ENTRY_NAME(sys_creat)
+ ENTRY_NAME(sys_link)
+ ENTRY_NAME(sys_unlink) /* 10 */
+ ENTRY_NAME(hpux_execv_wrapper)
+ ENTRY_NAME(sys_chdir)
+ ENTRY_NAME(sys_time)
+ ENTRY_NAME(sys_mknod)
+ ENTRY_NAME(sys_chmod) /* 15 */
+ ENTRY_NAME(sys_chown)
+ ENTRY_NAME(hpux_brk)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_lseek)
+ ENTRY_NAME(sys_getpid) /* 20 */
+ ENTRY_NAME(hpux_mount)
+ ENTRY_NAME(sys_oldumount)
+ ENTRY_NAME(sys_setuid)
+ ENTRY_NAME(sys_getuid)
+ ENTRY_NAME(sys_stime) /* 25 */
+ ENTRY_NAME(hpux_ptrace)
+ ENTRY_NAME(sys_alarm)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_pause)
+ ENTRY_NAME(sys_utime) /* 30 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_access)
+ ENTRY_NAME(hpux_nice)
+ ENTRY_NAME(sys_ni_syscall) /* 35 */
+ ENTRY_NAME(sys_sync)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_newstat)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_newlstat) /* 40 */
+ ENTRY_NAME(sys_dup)
+ ENTRY_NAME(hpux_pipe_wrapper)
+ ENTRY_NAME(sys_times)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 45 */
+ ENTRY_NAME(sys_setgid)
+ ENTRY_NAME(sys_getgid)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 50 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_ioctl)
+ ENTRY_NAME(sys_ni_syscall) /* 55 */
+ ENTRY_NAME(sys_symlink)
+ ENTRY_NAME(hpux_utssys)
+ ENTRY_NAME(sys_readlink)
+ ENTRY_NAME(hpux_execve_wrapper)
+ ENTRY_NAME(sys_umask) /* 60 */
+ ENTRY_NAME(sys_chroot)
+ ENTRY_NAME(sys_fcntl)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 65 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_sbrk)
+ ENTRY_NAME(sys_ni_syscall) /* 70 */
+ ENTRY_NAME(sys_mmap)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 75 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 80 */
+ ENTRY_NAME(sys_getpgid)
+ ENTRY_NAME(sys_setpgid)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 85 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_dup2) /* 90 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_newfstat)
+ ENTRY_NAME(sys_select)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 95 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 100 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 105 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 110 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 115 */
+ ENTRY_NAME(sys_gettimeofday)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 120 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_fchown)
+ ENTRY_NAME(sys_fchmod)
+ ENTRY_NAME(sys_ni_syscall) /* 125 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_rename)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 130 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_sysconf)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 135 */
+ ENTRY_NAME(sys_mkdir)
+ ENTRY_NAME(sys_rmdir)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 140 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 145 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 150 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 155 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 160 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 165 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 170 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 175 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 180 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 185 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 190 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_getdomainname)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 195 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_waitpid) /* 200 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 205 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 210 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 215 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 220 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 225 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 230 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 235 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 240 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 245 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 250 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 255 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 260 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 265 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 270 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_fchdir)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_accept) /* 275 */
+ ENTRY_NAME(sys_bind)
+ ENTRY_NAME(sys_connect)
+ ENTRY_NAME(sys_getpeername)
+ ENTRY_NAME(sys_getsockname)
+ ENTRY_NAME(sys_getsockopt) /* 280 */
+ ENTRY_NAME(sys_listen)
+ ENTRY_NAME(sys_recv)
+ ENTRY_NAME(sys_recvfrom)
+ ENTRY_NAME(sys_recvmsg)
+ ENTRY_NAME(sys_send) /* 285 */
+ ENTRY_NAME(sys_sendmsg)
+ ENTRY_NAME(sys_sendto)
+ ENTRY_NAME(sys_setsockopt)
+ ENTRY_NAME(sys_shutdown)
+ ENTRY_NAME(sys_socket) /* 290 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 295 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 300 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 305 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 310 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 315 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 320 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 325 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 330 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_lchown)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 335 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 340 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 345 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 350 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_nanosleep)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 355 */
+ ENTRY_NAME(hpux_getdents)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 360 */
+ ENTRY_NAME(hpux_fstat64)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 365 */
+ ENTRY_NAME(hpux_lstat64)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_stat64)
+ ENTRY_NAME(sys_ni_syscall) /* 370 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 375 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 380 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 385 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 390 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 395 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 400 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 405 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 410 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 415 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 420 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 425 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 430 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 435 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 440 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 445 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 450 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 455 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 460 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 465 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 470 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 475 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 480 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 485 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 490 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 495 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 500 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 505 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 510 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+.end
+
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
new file mode 100644
index 000000000..4957a05f8
--- /dev/null
+++ b/arch/parisc/hpux/fs.c
@@ -0,0 +1,250 @@
+/*
+ * linux/arch/parisc/kernel/sys_hpux.c
+ *
+ * implements HPUX syscalls.
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+int hpux_execve(struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname((char *) regs->gr[26]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+
+ error = do_execve(filename, (char **) regs->gr[25],
+ (char **)regs->gr[24], regs);
+
+ if (error == 0)
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+
+out:
+ return error;
+}
+
+struct hpux_dirent {
+ long d_off_pad; /* we only have a 32-bit off_t */
+ long d_off;
+ ino_t d_ino;
+ short d_reclen;
+ short d_namlen;
+ char d_name[1];
+};
+
+struct getdents_callback {
+ struct hpux_dirent *current_dir;
+ struct hpux_dirent *previous;
+ int count;
+ int error;
+};
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+
+static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
+{
+ struct hpux_dirent * dirent;
+ struct getdents_callback * buf = (struct getdents_callback *) __buf;
+ int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
+ dirent = buf->previous;
+ if (dirent)
+ put_user(offset, &dirent->d_off);
+ dirent = buf->current_dir;
+ buf->previous = dirent;
+ put_user(ino, &dirent->d_ino);
+ put_user(reclen, &dirent->d_reclen);
+ put_user(namlen, &dirent->d_namlen);
+ copy_to_user(dirent->d_name, name, namlen);
+ put_user(0, dirent->d_name + namlen);
+ ((char *) dirent) += reclen;
+ buf->current_dir = dirent;
+ buf->count -= reclen;
+ return 0;
+}
+
+#undef NAME_OFFSET
+#undef ROUND_UP
+
+int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count)
+{
+ struct file * file;
+ struct dentry * dentry;
+ struct inode * inode;
+ struct hpux_dirent * lastdirent;
+ struct getdents_callback buf;
+ int error;
+
+ lock_kernel();
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out_putf;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out_putf;
+
+ buf.current_dir = dirent;
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
+
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out_putf;
+
+ /*
+ * Get the inode's semaphore to prevent changes
+ * to the directory while we read it.
+ */
+ down(&inode->i_sem);
+ error = file->f_op->readdir(file, &buf, filldir);
+ up(&inode->i_sem);
+ if (error < 0)
+ goto out_putf;
+ error = buf.error;
+ lastdirent = buf.previous;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
+ }
+
+out_putf:
+ fput(file);
+out:
+ unlock_kernel();
+ return error;
+}
+
+int hpux_mount(const char *fs, const char *path, int mflag,
+ const char *fstype, const char *dataptr, int datalen)
+{
+ return -ENOSYS;
+}
+
+static int cp_hpux_stat(struct inode * inode, struct hpux_stat64 * statbuf)
+{
+ struct hpux_stat64 tmp;
+ unsigned int blocks, indirect;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.st_dev = kdev_t_to_nr(inode->i_dev);
+ tmp.st_ino = inode->i_ino;
+ tmp.st_mode = inode->i_mode;
+ tmp.st_nlink = inode->i_nlink;
+ tmp.st_uid = inode->i_uid;
+ tmp.st_gid = inode->i_gid;
+ tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
+ tmp.st_size = inode->i_size;
+ tmp.st_atime = inode->i_atime;
+ tmp.st_mtime = inode->i_mtime;
+ tmp.st_ctime = inode->i_ctime;
+
+#define D_B 7
+#define I_B (BLOCK_SIZE / sizeof(unsigned short))
+
+ if (!inode->i_blksize) {
+ blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ if (blocks > D_B) {
+ indirect = (blocks - D_B + I_B - 1) / I_B;
+ blocks += indirect;
+ if (indirect > 1) {
+ indirect = (indirect - 1 + I_B - 1) / I_B;
+ blocks += indirect;
+ if (indirect > 1)
+ blocks++;
+ }
+ }
+ tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
+ tmp.st_blksize = BLOCK_SIZE;
+ } else {
+ tmp.st_blocks = inode->i_blocks;
+ tmp.st_blksize = inode->i_blksize;
+ }
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+/*
+ * Revalidate the inode. This is required for proper NFS attribute caching.
+ * Blatently copied wholesale from fs/stat.c
+ */
+static __inline__ int
+do_revalidate(struct dentry *dentry)
+{
+ struct inode * inode = dentry->d_inode;
+ if (inode->i_op && inode->i_op->revalidate)
+ return inode->i_op->revalidate(dentry);
+ return 0;
+}
+
+long hpux_stat64(const char *path, struct hpux_stat64 *buf)
+{
+ struct nameidata nd;
+ int error;
+
+ lock_kernel();
+ error = user_path_walk(path, &nd);
+ if (!error) {
+ error = do_revalidate(nd.dentry);
+ if (!error)
+ error = cp_hpux_stat(nd.dentry->d_inode, buf);
+ path_release(&nd);
+ }
+ unlock_kernel();
+ return error;
+}
+
+long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
+{
+ struct file * f;
+ int err = -EBADF;
+
+ lock_kernel();
+ f = fget(fd);
+ if (f) {
+ struct dentry * dentry = f->f_dentry;
+
+ err = do_revalidate(dentry);
+ if (!err)
+ err = cp_hpux_stat(dentry->d_inode, statbuf);
+ fput(f);
+ }
+ unlock_kernel();
+ return err;
+}
+
+long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf)
+{
+ struct nameidata nd;
+ int error;
+
+ lock_kernel();
+ error = user_path_walk_link(filename, &nd);
+ if (!error) {
+ error = do_revalidate(nd.dentry);
+ if (!error)
+ error = cp_hpux_stat(nd.dentry->d_inode, statbuf);
+ path_release(&nd);
+ }
+ unlock_kernel();
+ return error;
+}
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S
new file mode 100644
index 000000000..0b8976386
--- /dev/null
+++ b/arch/parisc/hpux/gate.S
@@ -0,0 +1,72 @@
+/* ------------------------------------------------------------------------------
+ *
+ * Linux/PARISC Project (http://www.thepuffingroup.com/parisc)
+ *
+ * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
+ * Licensed under the GNU GPL.
+ * thanks to Philipp Rumpf, Mike Shaver and various others
+ * sorry about the wall, puffin..
+ */
+
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/offset.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+ .text
+
+ .import hpux_call_table
+ .import hpux_syscall_exit,code
+ .export hpux_gateway_page
+
+ .align 4096
+hpux_gateway_page:
+ nop
+ mfsp %sr7,%r1 ;! we must set sr3 to the space
+ mtsp %r1,%sr3 ;! of the user before the gate
+#ifdef __LP64__
+#warning NEEDS WORK for 64-bit
+#endif
+ ldw -64(%r30), %r28 ;! 8th argument
+ ldw -60(%r30), %r19 ;! 7th argument
+ ldw -56(%r30), %r20 ;! 6th argument
+ ldw -52(%r30), %r21 ;! 5th argument
+ gate .+8, %r0 ;! become privileged
+ mtsp %r0,%sr4 ;! get kernel space into sr4
+ mtsp %r0,%sr5 ;! get kernel space into sr5
+ mtsp %r0,%sr6 ;! get kernel space into sr6
+ mtsp %r0,%sr7 ;! get kernel space into sr7
+ mfctl %cr30,%r1 ;! get the kernel task ptr
+ mtctl %r0,%cr30 ;! zero it (flag)
+ STREG %r30,TASK_PT_GR30(%r1) ;! preserve userspace sp
+ STREG %r2,TASK_PT_GR2(%r1) ;! preserve rp
+ STREG %r27,TASK_PT_GR27(%r1) ;! user dp
+ STREG %r31,TASK_PT_GR31(%r1) ;! preserve syscall return ptr
+
+ loadgp ;! setup kernel dp
+
+ ldo TASK_SZ_ALGN+64(%r1),%r30 ;! set up kernel stack
+
+ stw %r21, -52(%r30) ;! 5th argument
+ stw %r20, -56(%r30) ;! 6th argument
+ stw %r19, -60(%r30) ;! 7th argument
+ stw %r28, -64(%r30) ;! 8th argument
+
+ ldil L%hpux_call_table, %r21
+ ldo R%hpux_call_table(%r21), %r21
+ comiclr,>>= __NR_HPUX_syscalls, %r22, %r0
+ b,n syscall_nosys
+ ldwx,s %r22(%r21), %r21
+ ldil L%hpux_syscall_exit,%r2
+ be 0(%sr7,%r21)
+ ldo R%hpux_syscall_exit(%r2),%r2
+
+syscall_nosys:
+ ldil L%hpux_syscall_exit,%r1
+ be R%hpux_syscall_exit(%sr7,%r1)
+ ldo -ENOSYS(%r0),%r28
+
+ .align 4096
+ .export end_hpux_gateway_page
+end_hpux_gateway_page:
diff --git a/arch/parisc/hpux/ioctl.c b/arch/parisc/hpux/ioctl.c
new file mode 100644
index 000000000..9087123e1
--- /dev/null
+++ b/arch/parisc/hpux/ioctl.c
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/parisc/hpux/ioctl.c
+ *
+ * implements some necessary HPUX ioctls.
+ */
+
+/*
+ * Supported ioctls:
+ * TCGETA
+ * TCSETA
+ * TCSETAW
+ * TCSETAF
+ * TCSBRK
+ * TCXONC
+ * TCFLSH
+ * TIOCGWINSZ
+ * TIOCSWINSZ
+ * TIOCGPGRP
+ * TIOCSPGRP
+ */
+
+#include <linux/smp_lock.h>
+#include <asm/errno.h>
+#include <asm/ioctl.h>
+#include <asm/termios.h>
+#include <asm/uaccess.h>
+
+int sys_ioctl(unsigned int, unsigned int, unsigned long);
+
+static int hpux_ioctl_t(int fd, unsigned long cmd, unsigned long arg)
+{
+ int result = -EOPNOTSUPP;
+ int nr = _IOC_NR(cmd);
+ switch (nr) {
+ case 106:
+ result = sys_ioctl(fd, TIOCSWINSZ, arg);
+ break;
+ case 107:
+ result = sys_ioctl(fd, TIOCGWINSZ, arg);
+ break;
+ }
+ return result;
+}
+
+int hpux_ioctl(int fd, unsigned long cmd, unsigned long arg)
+{
+ int result = -EOPNOTSUPP;
+ int type = _IOC_TYPE(cmd);
+ switch (type) {
+ case 'T':
+ /* Our structures are now compatible with HPUX's */
+ result = sys_ioctl(fd, cmd, arg);
+ break;
+ case 't':
+ result = hpux_ioctl_t(fd, cmd, arg);
+ break;
+ default:
+ /* If my mother ever sees this, I hope she disowns me.
+ * Take this out after NYLWE. */
+ result = sys_ioctl(fd, cmd, arg);
+ }
+ return result;
+}
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
new file mode 100644
index 000000000..e0c832e76
--- /dev/null
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -0,0 +1,334 @@
+/*
+ * linux/arch/parisc/kernel/sys_hpux.c
+ *
+ * implements HPUX syscalls.
+ */
+
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/utsname.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+unsigned long sys_brk(unsigned long addr);
+
+unsigned long hpux_brk(unsigned long addr)
+{
+ /* Sigh. Looks like HP/UX libc relies on kernel bugs. */
+ return sys_brk(addr + PAGE_SIZE);
+}
+
+int hpux_sbrk(void)
+{
+ return -ENOSYS;
+}
+
+/* Random other syscalls */
+
+int hpux_nice(int priority_change)
+{
+ return -ENOSYS;
+}
+
+int hpux_ptrace(void)
+{
+ return -ENOSYS;
+}
+
+int hpux_wait(int *stat_loc)
+{
+ extern int sys_waitpid(int, int *, int);
+ return sys_waitpid(-1, stat_loc, 0);
+}
+
+#define _SC_CPU_VERSION 10001
+#define _SC_OPEN_MAX 4
+#define CPU_PA_RISC1_1 0x210
+
+int hpux_sysconf(int which)
+{
+ switch (which) {
+ case _SC_CPU_VERSION:
+ return CPU_PA_RISC1_1;
+ case _SC_OPEN_MAX:
+ return INT_MAX;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*****************************************************************************/
+
+#define HPUX_UTSLEN 9
+#define HPUX_SNLEN 15
+
+struct hpux_utsname {
+ char sysname[HPUX_UTSLEN];
+ char nodename[HPUX_UTSLEN];
+ char release[HPUX_UTSLEN];
+ char version[HPUX_UTSLEN];
+ char machine[HPUX_UTSLEN];
+ char idnumber[HPUX_SNLEN];
+} ;
+
+struct hpux_ustat {
+ int32_t f_tfree; /* total free (daddr_t) */
+ u_int32_t f_tinode; /* total inodes free (ino_t) */
+ char f_fname[6]; /* filsys name */
+ char f_fpack[6]; /* filsys pack name */
+ u_int32_t f_blksize; /* filsys block size (int) */
+};
+
+/*
+ * HPUX's utssys() call. It's a collection of miscellaneous functions,
+ * alas, so there's no nice way of splitting them up.
+ */
+
+/* This function is called from hpux_utssys(); HP-UX implements
+ * ustat() as an option to utssys().
+ *
+ * Now, struct ustat on HP-UX is exactly the same as on Linux, except
+ * that it contains one addition field on the end, int32_t f_blksize.
+ * So, we could have written this function to just call the Linux
+ * sys_ustat(), (defined in linux/fs/super.c), and then just
+ * added this additional field to the user's structure. But I figure
+ * if we're gonna be digging through filesystem structures to get
+ * this, we might as well just do the whole enchilada all in one go.
+ *
+ * So, most of this function is almost identical to sys_ustat().
+ * I have placed comments at the few lines changed or added, to
+ * aid in porting forward if and when sys_ustat() is changed from
+ * its form in kernel 2.2.5.
+ */
+static int hpux_ustat(dev_t dev, struct hpux_ustat *ubuf)
+{
+ struct super_block *s;
+ struct hpux_ustat tmp; /* Changed to hpux_ustat */
+ struct statfs sbuf;
+ int err = -EINVAL;
+
+ lock_kernel();
+ s = get_super(to_kdev_t(dev));
+ if (s == NULL)
+ goto out;
+ err = vfs_statfs(s, &sbuf);
+ if (err)
+ goto out;
+
+ memset(&tmp,0,sizeof(struct hpux_ustat)); /* Changed to hpux_ustat */
+
+ tmp.f_tfree = (int32_t)sbuf.f_bfree;
+ tmp.f_tinode = (u_int32_t)sbuf.f_ffree;
+ tmp.f_blksize = (u_int32_t)sbuf.f_bsize; /* Added this line */
+
+ /* Changed to hpux_ustat: */
+ err = copy_to_user(ubuf,&tmp,sizeof(struct hpux_ustat)) ? -EFAULT : 0;
+out:
+ unlock_kernel();
+ return err;
+}
+
+
+/* This function is called from hpux_utssys(); HP-UX implements
+ * uname() as an option to utssys().
+ *
+ * The form of this function is pretty much copied from sys_olduname(),
+ * defined in linux/arch/i386/kernel/sys_i386.c.
+ */
+/* TODO: Are these put_user calls OK? Should they pass an int?
+ * (I copied it from sys_i386.c like this.)
+ */
+static int hpux_uname(struct hpux_utsname *name)
+{
+ int error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct hpux_utsname)))
+ return -EFAULT;
+
+ down_read(&uts_sem);
+
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->sysname+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->nodename+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->release,&system_utsname.release,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->release+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->version,&system_utsname.version,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->version+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->machine,&system_utsname.machine,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->machine+HPUX_UTSLEN-1);
+
+ up_read(&uts_sem);
+
+ /* HP-UX utsname has no domainname field. */
+
+ /* TODO: Implement idnumber!!! */
+#if 0
+ error |= __put_user(0,name->idnumber);
+ error |= __put_user(0,name->idnumber+HPUX_SNLEN-1);
+#endif
+
+ error = error ? -EFAULT : 0;
+
+ return error;
+}
+
+int sys_sethostname(char *, int);
+int sys_gethostname(char *, int);
+
+/* Note: HP-UX just uses the old suser() function to check perms
+ * in this system call. We'll use capable(CAP_SYS_ADMIN).
+ */
+int hpux_utssys(char *ubuf, int n, int type)
+{
+ int len;
+ int error;
+ switch( type ) {
+ case 0:
+ /* uname(): */
+ return( hpux_uname( (struct hpux_utsname *)ubuf ) );
+ break ;
+ case 1:
+ /* Obsolete (used to be umask().) */
+ return -EFAULT ;
+ break ;
+ case 2:
+ /* ustat(): */
+ return( hpux_ustat((dev_t)n, (struct hpux_ustat *)ubuf) );
+ break ;
+ case 3:
+ /* setuname():
+ *
+ * On linux (unlike HP-UX), utsname.nodename
+ * is the same as the hostname.
+ *
+ * sys_sethostname() is defined in linux/kernel/sys.c.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ return( sys_sethostname(ubuf, len) );
+ break ;
+ case 4:
+ /* sethostname():
+ *
+ * sys_sethostname() is defined in linux/kernel/sys.c.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ return( sys_sethostname(ubuf, len) );
+ break ;
+ case 5:
+ /* gethostname():
+ *
+ * sys_gethostname() is defined in linux/kernel/sys.c.
+ */
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ return( sys_gethostname(ubuf, n) );
+ break ;
+ case 6:
+ /* Supposedly called from setuname() in libc.
+ * TODO: When and why is this called?
+ * Is it ever even called?
+ *
+ * This code should look a lot like sys_sethostname(),
+ * defined in linux/kernel/sys.c. If that gets updated,
+ * update this code similarly.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ /**/
+ /* TODO: print a warning about using this? */
+ down_write(&uts_sem);
+ error = -EFAULT;
+ if (!copy_from_user(system_utsname.sysname, ubuf, len)) {
+ system_utsname.sysname[len] = 0;
+ error = 0;
+ }
+ up_write(&uts_sem);
+ return error;
+ break ;
+ case 7:
+ /* Sets utsname.release, if you're allowed.
+ * Undocumented. Used by swinstall to change the
+ * OS version, during OS updates. Yuck!!!
+ *
+ * This code should look a lot like sys_sethostname()
+ * in linux/kernel/sys.c. If that gets updated, update
+ * this code similarly.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ /**/
+ /* TODO: print a warning about this? */
+ down_write(&uts_sem);
+ error = -EFAULT;
+ if (!copy_from_user(system_utsname.release, ubuf, len)) {
+ system_utsname.release[len] = 0;
+ error = 0;
+ }
+ up_write(&uts_sem);
+ return error;
+ break ;
+ default:
+ /* This system call returns -EFAULT if given an unknown type.
+ * Why not -EINVAL? I don't know, it's just not what they did.
+ */
+ return -EFAULT ;
+ }
+}
+
+int hpux_getdomainname(char *name, int len)
+{
+ int nlen;
+ int err = -EFAULT;
+
+ down_read(&uts_sem);
+
+ nlen = strlen(system_utsname.domainname) + 1;
+
+ if (nlen < len)
+ len = nlen;
+ if(len > __NEW_UTS_LEN)
+ goto done;
+ if(copy_to_user(name, system_utsname.domainname, len))
+ goto done;
+ err = 0;
+done:
+ up_read(&uts_sem);
+ return err;
+
+}
+
+int hpux_pipe(int *kstack_fildes)
+{
+ int error;
+
+ lock_kernel();
+ error = do_pipe(kstack_fildes);
+ unlock_kernel();
+ return error;
+}
diff --git a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S
new file mode 100644
index 000000000..c150783d9
--- /dev/null
+++ b/arch/parisc/hpux/wrappers.S
@@ -0,0 +1,244 @@
+/*------------------------------------------------------------------------------
+ * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ *
+ * HP-UX System Call Wrapper routines and System Call Return Path
+ *
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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.
+ */
+
+#ifdef __LP64__
+#warning Must be changed for PA64
+#endif
+
+#include <asm/offset.h>
+
+ .level 1.1
+ .text
+
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/signal.h>
+
+ /* These should probably go in a header file somewhere.
+ * They are duplicated in kernel/wrappers.S
+ * Possibly we should consider consolidating these
+ * register save/restore macros.
+ */
+ .macro reg_save regs
+#ifdef __LP64__
+#warning NEEDS WORK for 64-bit
+#endif
+ stw %r3, PT_GR3(\regs)
+ stw %r4, PT_GR4(\regs)
+ stw %r5, PT_GR5(\regs)
+ stw %r6, PT_GR6(\regs)
+ stw %r7, PT_GR7(\regs)
+ stw %r8, PT_GR8(\regs)
+ stw %r9, PT_GR9(\regs)
+ stw %r10,PT_GR10(\regs)
+ stw %r11,PT_GR11(\regs)
+ stw %r12,PT_GR12(\regs)
+ stw %r13,PT_GR13(\regs)
+ stw %r14,PT_GR14(\regs)
+ stw %r15,PT_GR15(\regs)
+ stw %r16,PT_GR16(\regs)
+ stw %r17,PT_GR17(\regs)
+ stw %r18,PT_GR18(\regs)
+ .endm
+
+ .macro reg_restore regs
+ ldw PT_GR3(\regs), %r3
+ ldw PT_GR4(\regs), %r4
+ ldw PT_GR5(\regs), %r5
+ ldw PT_GR6(\regs), %r6
+ ldw PT_GR7(\regs), %r7
+ ldw PT_GR8(\regs), %r8
+ ldw PT_GR9(\regs), %r9
+ ldw PT_GR10(\regs),%r10
+ ldw PT_GR11(\regs),%r11
+ ldw PT_GR12(\regs),%r12
+ ldw PT_GR13(\regs),%r13
+ ldw PT_GR14(\regs),%r14
+ ldw PT_GR15(\regs),%r15
+ ldw PT_GR16(\regs),%r16
+ ldw PT_GR17(\regs),%r17
+ ldw PT_GR18(\regs),%r18
+ .endm
+
+
+ .export hpux_fork_wrapper
+ .import sys_fork
+
+hpux_fork_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+ ;! pointer in task
+ reg_save %r1
+
+ stw %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ stw %r2,PT_GR19(%r1) ;! save for child
+ stw %r30,PT_GR20(%r1) ;! save for child
+ ldil L%child_return,%r3
+ ldo R%child_return(%r3),%r3
+ stw %r3,PT_GR21(%r1) ;! save for child
+
+ ldw TASK_PT_GR30(%r1),%r25
+ copy %r1,%r24
+ bl sys_clone,%r2
+ ldi SIGCHLD,%r26
+
+ ldw -84(%r30),%r2
+fork_return:
+ ldo -64(%r30),%r30
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+
+ reg_restore %r1
+
+ /*
+ * HP-UX wants pid (child gets parent pid, parent gets child pid)
+ * in r28 and a flag in r29 (r29 == 1 for child, 0 for parent).
+ * Linux fork returns 0 for child, pid for parent. Since HP-UX
+ * libc stub throws away parent pid and returns 0 for child,
+ * we'll just return 0 for parent pid now. Only applications
+ * that jump directly to the gateway page (not supported) will
+ * know the difference. We can fix this later if necessary.
+ */
+
+ ldo -1024(%r0),%r1
+ comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */
+ or,= %r28,%r0,%r0
+ or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */
+ ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */
+
+fork_exit:
+ bv %r0(%r2)
+ nop
+
+ /* Set the return value for the child */
+
+child_return:
+ ldw TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
+ b fork_return
+ copy %r0,%r28
+
+ .export hpux_execve_wrapper
+ .export hpux_execv_wrapper
+ .import hpux_execve
+
+hpux_execv_wrapper:
+ copy %r0,%r24 /* NULL environment */
+
+hpux_execve_wrapper:
+
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+
+ /*
+ * Do we need to save/restore r3-r18 here?
+ * I don't think so. why would new thread need old
+ * threads registers?
+ */
+
+ /* Store arg0, arg1 and arg2 so that hpux_execve will find them */
+
+ stw %r26,PT_GR26(%r1)
+ stw %r25,PT_GR25(%r1)
+ stw %r24,PT_GR24(%r1)
+
+ stw %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ bl hpux_execve,%r2
+ copy %r1,%arg0
+
+ ldo -64(%r30),%r30
+ ldw -20(%r30),%r2
+
+ /* If exec succeeded we need to load the args */
+
+ ldo -1024(%r0),%r1
+ comb,>>= %r28,%r1,exec_error
+ copy %r2,%r19
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr
+ ldw TASK_PT_GR26(%r1),%r26
+ ldw TASK_PT_GR25(%r1),%r25
+ ldw TASK_PT_GR24(%r1),%r24
+ ldw TASK_PT_GR23(%r1),%r23
+ copy %r0,%r2 /* Flag to syscall_exit not to clear args */
+
+exec_error:
+ bv %r0(%r19)
+ nop
+
+ .export hpux_pipe_wrapper
+ .import hpux_pipe
+
+ /* HP-UX expects pipefd's returned in r28 & r29 */
+
+hpux_pipe_wrapper:
+ stw %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ bl hpux_pipe,%r2
+ ldo -56(%r30),%r26 /* pass local array to hpux_pipe */
+
+
+ ldo -1024(%r0),%r1
+ comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */
+ ldw -84(%r30),%r2
+
+ /* if success, load fd's from stack array */
+
+ ldw -56(%r30),%r28
+ ldw -52(%r30),%r29
+
+pipe_exit:
+ bv %r0(%r2)
+ ldo -64(%r30),%r30
+
+ .export hpux_syscall_exit
+ .import syscall_exit
+
+hpux_syscall_exit:
+
+ /*
+ *
+ * HP-UX call return conventions:
+ *
+ * if error:
+ * r22 = 1
+ * r28 = errno value
+ * r29 = secondary return value
+ * else
+ * r22 = 0
+ * r28 = return value
+ * r29 = secondary return value
+ *
+ * For now, we'll just check to see if r28 is < (unsigned long)-1024
+ * (to handle addresses > 2 Gb) and if so set r22 to zero. If not,
+ * we'll complement r28 and set r22 to 1. Wrappers will be
+ * needed for syscalls that care about the secondary return value.
+ * The wrapper may also need a way of avoiding the following code,
+ * but we'll deal with that when it becomes necessary.
+ */
+
+ ldo -1024(%r0),%r1
+ comb,<< %r28,%r1,no_error
+ copy %r0,%r22
+ subi 0,%r28,%r28
+ ldo 1(%r0),%r22
+
+no_error:
+ b syscall_exit
+ nop
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
new file mode 100644
index 000000000..03ce8e58b
--- /dev/null
+++ b/arch/parisc/kernel/Makefile
@@ -0,0 +1,52 @@
+#
+# 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).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+all: kernel.o init_task.o pdc_cons.o process.o head.o
+O_TARGET = kernel.o
+O_OBJS =
+
+# Object file lists.
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-y += cache.o setup.o traps.o time.o irq.o \
+ syscall.o entry.o sys_parisc.o pdc.o ptrace.o hardware.o \
+ inventory.o drivers.o semaphore.o pa7300lc.o pci-dma.o \
+ signal.o hpmc.o \
+ real1.o real2.o led.o parisc_ksyms.o
+
+export-objs := parisc_ksyms.o
+
+
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_VT) += keyboard.o
+obj-$(CONFIG_PCI_LBA) += lba_pci.o
+# I/O SAPIC is also on IA64 platforms.
+# The two could be merged into a common source some day.
+obj-$(CONFIG_IOSAPIC) += iosapic.o
+obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o
+# Only use one of them: ccio-rm-dma is for PCX-W systems *only*
+# obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o
+obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o
+
+.o.S: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
+
+# Translate to Rules.make lists.
+
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS := $(filter $(export-objs), $(obj-y))
+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
+MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
+MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
new file mode 100644
index 000000000..713a8b39a
--- /dev/null
+++ b/arch/parisc/kernel/cache.c
@@ -0,0 +1,253 @@
+/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 Helge Deller (07-13-1999)
+ * Copyright (C) 1999 SuSE GmbH Nuernberg
+ * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
+ *
+ * Cache and TLB management
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/pdc.h>
+#include <asm/cache.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+
+struct pdc_cache_info cache_info;
+#ifndef __LP64__
+static struct pdc_btlb_info btlb_info;
+#endif
+
+
+void __flush_page_to_ram(unsigned long address)
+{
+ __flush_dcache_range(address, PAGE_SIZE);
+ __flush_icache_range(address, PAGE_SIZE);
+}
+
+
+
+void flush_data_cache(void)
+{
+ register unsigned long base = cache_info.dc_base;
+ register unsigned long count = cache_info.dc_count;
+ register unsigned long loop = cache_info.dc_loop;
+ register unsigned long stride = cache_info.dc_stride;
+ register unsigned long addr;
+ register long i, j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ fdce(addr);
+}
+
+static inline void flush_data_tlb_space(void)
+{
+ unsigned long base = cache_info.dt_off_base;
+ unsigned long count = cache_info.dt_off_count;
+ unsigned long stride = cache_info.dt_off_stride;
+ unsigned long loop = cache_info.dt_loop;
+
+ unsigned long addr;
+ long i,j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ pdtlbe(addr);
+}
+
+
+
+void flush_data_tlb(void)
+{
+ unsigned long base = cache_info.dt_sp_base;
+ unsigned long count = cache_info.dt_sp_count;
+ unsigned long stride = cache_info.dt_sp_stride;
+ unsigned long space;
+ unsigned long old_sr1;
+ long i;
+
+ old_sr1 = mfsp(1);
+
+ for(i=0,space=base; i<count; i++, space+=stride) {
+ mtsp(space,1);
+ flush_data_tlb_space();
+ }
+
+ mtsp(old_sr1, 1);
+}
+
+static inline void flush_instruction_tlb_space(void)
+{
+ unsigned long base = cache_info.it_off_base;
+ unsigned long count = cache_info.it_off_count;
+ unsigned long stride = cache_info.it_off_stride;
+ unsigned long loop = cache_info.it_loop;
+
+ unsigned long addr;
+ long i,j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ pitlbe(addr);
+}
+
+void flush_instruction_tlb(void)
+{
+ unsigned long base = cache_info.it_sp_base;
+ unsigned long count = cache_info.it_sp_count;
+ unsigned long stride = cache_info.it_sp_stride;
+ unsigned long space;
+ unsigned long old_sr1;
+ unsigned int i;
+
+ old_sr1 = mfsp(1);
+
+ for(i=0,space=base; i<count; i++, space+=stride) {
+ mtsp(space,1);
+ flush_instruction_tlb_space();
+ }
+
+ mtsp(old_sr1, 1);
+}
+
+
+void __flush_tlb_space(unsigned long space)
+{
+ unsigned long old_sr1;
+
+ old_sr1 = mfsp(1);
+ mtsp(space, 1);
+
+ flush_data_tlb_space();
+ flush_instruction_tlb_space();
+
+ mtsp(old_sr1, 1);
+}
+
+
+void flush_instruction_cache(void)
+{
+ register unsigned long base = cache_info.ic_base;
+ register unsigned long count = cache_info.ic_count;
+ register unsigned long loop = cache_info.ic_loop;
+ register unsigned long stride = cache_info.ic_stride;
+ register unsigned long addr;
+ register long i, j;
+ unsigned long old_sr1;
+
+ old_sr1 = mfsp(1);
+ mtsp(0,1);
+
+ /*
+ * Note: fice instruction has 3 bit space field, so one must
+ * be specified (otherwise you are justing using whatever
+ * happens to be in sr0).
+ */
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ fice(addr);
+
+ mtsp(old_sr1, 1);
+}
+
+/* not yet ... fdc() needs to be implemented in cache.h !
+void flush_datacache_range( unsigned int base, unsigned int end )
+{
+ register long offset,offset_add;
+ offset_add = ( (1<<(cache_info.dc_conf.cc_block-1)) *
+ cache_info.dc_conf.cc_line ) << 4;
+ for (offset=base; offset<=end; offset+=offset_add)
+ fdc(space,offset);
+ fdc(space,end);
+}
+*/
+
+/* flushes code and data-cache */
+void flush_all_caches(void)
+{
+ flush_instruction_cache();
+ flush_data_cache();
+
+ flush_instruction_tlb();
+ flush_data_tlb();
+
+ asm volatile("sync");
+ asm volatile("syncdma");
+ asm volatile("sync");
+}
+
+int get_cache_info(char *buffer)
+{
+ char *p = buffer;
+
+ p += sprintf(p, "I-cache\t\t: %ld KB\n",
+ cache_info.ic_size/1024 );
+ p += sprintf(p, "D-cache\t\t: %ld KB (%s)%s\n",
+ cache_info.dc_size/1024,
+ (cache_info.dc_conf.cc_wt ? "WT":"WB"),
+ (cache_info.dc_conf.cc_sh ? " - shared I/D":"")
+ );
+
+ p += sprintf(p, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
+ cache_info.it_size,
+ cache_info.dt_size,
+ cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
+ );
+
+#ifndef __LP64__
+ /* BTLB - Block TLB */
+ if (btlb_info.max_size==0) {
+ p += sprintf(p, "BTLB\t\t: not supported\n" );
+ } else {
+ p += sprintf(p,
+ "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
+ "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
+ "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
+ btlb_info.max_size, (int)4096,
+ btlb_info.max_size>>8,
+ btlb_info.fixed_range_info.num_i,
+ btlb_info.fixed_range_info.num_d,
+ btlb_info.fixed_range_info.num_comb,
+ btlb_info.variable_range_info.num_i,
+ btlb_info.variable_range_info.num_d,
+ btlb_info.variable_range_info.num_comb
+ );
+ }
+#endif
+
+ return p - buffer;
+}
+
+
+void __init
+cache_init(void)
+{
+ if(pdc_cache_info(&cache_info)<0)
+ panic("cache_init: pdc_cache_info failed");
+
+#if 0
+ printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n",
+ cache_info.ic_size,
+ cache_info.dc_size,
+ cache_info.it_size,
+ sizeof (struct pdc_cache_info) / sizeof (long),
+ sizeof (struct pdc_cache_cf)
+ );
+#endif
+#ifndef __LP64__
+ if(pdc_btlb_info(&btlb_info)<0) {
+ memset(&btlb_info, 0, sizeof btlb_info);
+ }
+#endif
+}
diff --git a/arch/parisc/kernel/ccio-dma.c b/arch/parisc/kernel/ccio-dma.c
new file mode 100644
index 000000000..c8f72c813
--- /dev/null
+++ b/arch/parisc/kernel/ccio-dma.c
@@ -0,0 +1,1209 @@
+/*
+** ccio-dma.c:
+** DMA management routines for first generation cache-coherent machines.
+** Program U2/Uturn in "Virtual Mode" and use the I/O MMU.
+**
+** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2000 Ryan Bradetich
+** (c) Copyright 2000 Hewlett-Packard Company
+**
+** 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.
+**
+**
+** "Real Mode" operation refers to U2/Uturn chip operation.
+** U2/Uturn were designed to perform coherency checks w/o using
+** the I/O MMU - basically what x86 does.
+**
+** Philipp Rumpf has a "Real Mode" driver for PCX-W machines at:
+** CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc
+** cvs -z3 co linux/arch/parisc/kernel/dma-rm.c
+**
+** I've rewritten his code to work under TPG's tree. See ccio-rm-dma.c.
+**
+** Drawbacks of using Real Mode are:
+** o outbound DMA is slower - U2 won't prefetch data (GSC+ XQL signal).
+** o Inbound DMA less efficient - U2 can't use DMA_FAST attribute.
+** o Ability to do scatter/gather in HW is lost.
+** o Doesn't work under PCX-U/U+ machines since they didn't follow
+** the coherency design originally worked out. Only PCX-W does.
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/cache.h> /* for L1_CACHE_BYTES */
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/page.h>
+
+#include <asm/io.h>
+#include <asm/gsc.h> /* for gsc_writeN()... */
+
+/*
+** Choose "ccio" since that's what HP-UX calls it.
+** Make it easier for folks to migrate from one to the other :^)
+*/
+#define MODULE_NAME "ccio"
+
+/*
+#define DEBUG_CCIO_RES
+#define DEBUG_CCIO_RUN
+#define DEBUG_CCIO_INIT
+#define DUMP_RESMAP
+*/
+
+#include <linux/proc_fs.h>
+#include <asm/runway.h> /* for proc_runway_root */
+
+#ifdef DEBUG_CCIO_INIT
+#define DBG_INIT(x...) printk(x)
+#else
+#define DBG_INIT(x...)
+#endif
+
+#ifdef DEBUG_CCIO_RUN
+#define DBG_RUN(x...) printk(x)
+#else
+#define DBG_RUN(x...)
+#endif
+
+#ifdef DEBUG_CCIO_RES
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+#define CCIO_INLINE /* inline */
+#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
+
+#define U2_IOA_RUNWAY 0x580
+#define U2_BC_GSC 0x501
+#define UTURN_IOA_RUNWAY 0x581
+#define UTURN_BC_GSC 0x502
+/* We *can't* support JAVA (T600). Venture there at your own risk. */
+
+static void dump_resmap(void);
+
+static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+static struct pa_iodc_driver ccio_drivers_for[] = {
+
+ {HPHW_IOA, U2_IOA_RUNWAY, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback},
+
+ {HPHW_IOA, UTURN_IOA_RUNWAY, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback},
+
+/*
+** FIXME: The following claims the GSC bus port, not the IOA.
+** And there are two busses below a single I/O TLB.
+**
+** These should go away once we have a real PA bus walk.
+** Firmware wants to tell the PA bus walk code about the GSC ports
+** since they are not "architected" PA I/O devices. Ie a PA bus walk
+** wouldn't discover them. But the PA bus walk code could check
+** the "fixed module table" to add such devices to an I/O Tree
+** and proceed with the recursive, depth first bus walk.
+*/
+ {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xc, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "U2 GSC+ BC", (void *) ccio_driver_callback},
+
+ {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xc, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "Uturn GSC+ BC", (void *) ccio_driver_callback},
+
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL }
+};
+
+
+#define IS_U2(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \
+)
+
+#define IS_UTURN(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \
+)
+
+
+#define IOA_NORMAL_MODE 0x00020080 /* IO_CONTROL to turn on CCIO */
+#define CMD_TLB_DIRECT_WRITE 35 /* IO_COMMAND for I/O TLB Writes */
+#define CMD_TLB_PURGE 33 /* IO_COMMAND to Purge I/O TLB entry */
+
+struct ioa_registers {
+ /* Runway Supervisory Set */
+ volatile int32_t unused1[12];
+ volatile uint32_t io_command; /* Offset 12 */
+ volatile uint32_t io_status; /* Offset 13 */
+ volatile uint32_t io_control; /* Offset 14 */
+ volatile int32_t unused2[1];
+
+ /* Runway Auxiliary Register Set */
+ volatile uint32_t io_err_resp; /* Offset 0 */
+ volatile uint32_t io_err_info; /* Offset 1 */
+ volatile uint32_t io_err_req; /* Offset 2 */
+ volatile uint32_t io_err_resp_hi; /* Offset 3 */
+ volatile uint32_t io_tlb_entry_m; /* Offset 4 */
+ volatile uint32_t io_tlb_entry_l; /* Offset 5 */
+ volatile uint32_t unused3[1];
+ volatile uint32_t io_pdir_base; /* Offset 7 */
+ volatile uint32_t io_io_low_hv; /* Offset 8 */
+ volatile uint32_t io_io_high_hv; /* Offset 9 */
+ volatile uint32_t unused4[1];
+ volatile uint32_t io_chain_id_mask; /* Offset 11 */
+ volatile uint32_t unused5[2];
+ volatile uint32_t io_io_low; /* Offset 14 */
+ volatile uint32_t io_io_high; /* Offset 15 */
+};
+
+
+struct ccio_device {
+ struct ccio_device *next; /* list of LBA's in system */
+ struct hp_device *iodc; /* data about dev from firmware */
+ spinlock_t ccio_lock;
+
+ struct ioa_registers *ccio_hpa; /* base address */
+ u64 *pdir_base; /* physical base address */
+ char *res_map; /* resource map, bit == pdir entry */
+
+ int res_hint; /* next available IOVP - circular search */
+ int res_size; /* size of resource map in bytes */
+ int chainid_shift; /* specify bit location of chain_id */
+ int flags; /* state/functionality enabled */
+#ifdef DELAYED_RESOURCE_CNT
+ dma_addr_t res_delay[DELAYED_RESOURCE_CNT];
+#endif
+
+ /* STUFF We don't need in performance path */
+ int pdir_size; /* in bytes, determined by IOV Space size */
+ int hw_rev; /* HW revision of chip */
+};
+
+
+/* Ratio of Host MEM to IOV Space size */
+static unsigned long ccio_mem_ratio = 4;
+static struct ccio_device *ccio_list = NULL;
+
+static int ccio_proc_info(char *buffer, char **start, off_t offset, int length);
+static unsigned long ccio_used_bytes = 0;
+static unsigned long ccio_used_pages = 0;
+static int ccio_cujo_bug = 0;
+
+static unsigned long ccio_alloc_size = 0;
+static unsigned long ccio_free_size = 0;
+
+/**************************************************************
+*
+* I/O Pdir Resource Management
+*
+* Bits set in the resource map are in use.
+* Each bit can represent a number of pages.
+* LSbs represent lower addresses (IOVA's).
+*
+* This was was copied from sba_iommu.c. Don't try to unify
+* the two resource managers unless a way to have different
+* allocation policies is also adjusted. We'd like to avoid
+* I/O TLB thrashing by having resource allocation policy
+* match the I/O TLB replacement policy.
+*
+***************************************************************/
+#define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */
+#define IOVP_SIZE PAGE_SIZE
+#define IOVP_SHIFT PAGE_SHIFT
+#define IOVP_MASK PAGE_MASK
+
+/* Convert from IOVP to IOVA and vice versa. */
+#define CCIO_IOVA(iovp,offset) ((iovp) | (offset))
+#define CCIO_IOVP(iova) ((iova) & ~(IOVP_SIZE-1) )
+
+#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT)
+#define MKIOVP(pdir_idx) ((long)(pdir_idx) << IOVP_SHIFT)
+#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
+
+/* CUJO20 KLUDGE start */
+#define CUJO_20_BITMASK 0x0ffff000 /* upper nibble is a don't care */
+#define CUJO_20_STEP 0x10000000 /* inc upper nibble */
+#define CUJO_20_BADPAGE1 0x01003000 /* pages that hpmc on raven U+ */
+#define CUJO_20_BADPAGE2 0x01607000 /* pages that hpmc on firehawk U+ */
+#define CUJO_20_BADHVERS 0x6821 /* low nibble 1 is cujo rev 2.0 */
+#define CUJO_RAVEN_LOC 0xf1000000UL /* cujo location on raven U+ */
+#define CUJO_FIREHAWK_LOC 0xf1604000UL /* cujo location on firehawk U+ */
+/* CUJO20 KLUDGE end */
+
+/*
+** Don't worry about the 150% average search length on a miss.
+** If the search wraps around, and passes the res_hint, it will
+** cause the kernel to panic anyhow.
+*/
+
+/* ioa->res_hint = idx + (size >> 3); \ */
+
+#define CCIO_SEARCH_LOOP(ioa, idx, mask, size) \
+ for(; res_ptr < res_end; ++res_ptr) \
+ { \
+ if(0 == ((*res_ptr) & mask)) { \
+ *res_ptr |= mask; \
+ idx = (int)((unsigned long)res_ptr - (unsigned long)ioa->res_map); \
+ ioa->res_hint = 0;\
+ goto resource_found; \
+ } \
+ }
+
+#define CCIO_FIND_FREE_MAPPING(ioa, idx, mask, size) { \
+ u##size *res_ptr = (u##size *)&((ioa)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \
+ u##size *res_end = (u##size *)&(ioa)->res_map[ioa->res_size]; \
+ CCIO_SEARCH_LOOP(ioa, idx, mask, size); \
+ res_ptr = (u##size *)&(ioa)->res_map[0]; \
+ CCIO_SEARCH_LOOP(ioa, idx, mask, size); \
+}
+
+/*
+** Find available bit in this ioa's resource map.
+** Use a "circular" search:
+** o Most IOVA's are "temporary" - avg search time should be small.
+** o keep a history of what happened for debugging
+** o KISS.
+**
+** Perf optimizations:
+** o search for log2(size) bits at a time.
+** o search for available resource bits using byte/word/whatever.
+** o use different search for "large" (eg > 4 pages) or "very large"
+** (eg > 16 pages) mappings.
+*/
+static int
+ccio_alloc_range(struct ccio_device *ioa, size_t size)
+{
+ int res_idx;
+ unsigned long mask, flags;
+ unsigned int pages_needed = size >> PAGE_SHIFT;
+
+ ASSERT(pages_needed);
+ ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT));
+
+ mask = (unsigned long) -1L;
+ mask >>= BITS_PER_LONG - pages_needed;
+
+ DBG_RES(__FUNCTION__ " size: %d pages_needed %d pages_mask 0x%08lx\n",
+ size, pages_needed, mask);
+
+ spin_lock_irqsave(&ioa->ccio_lock, flags);
+
+ /*
+ ** "seek and ye shall find"...praying never hurts either...
+ ** ggg sacrafices another 710 to the computer gods.
+ */
+
+ if(pages_needed <= 8) {
+ CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 8);
+ } else if(pages_needed <= 16) {
+ CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 16);
+ } else if(pages_needed <= 32) {
+ CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 32);
+#ifdef __LP64__
+ } else if(pages_needed <= 64) {
+ CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 64)
+#endif
+ } else {
+ panic(__FILE__ ":" __FUNCTION__ "() Too many pages to map.\n");
+ }
+
+#ifdef DUMP_RESMAP
+ dump_resmap();
+#endif
+ panic(__FILE__ ":" __FUNCTION__ "() I/O MMU is out of mapping resources\n");
+
+resource_found:
+
+ DBG_RES(__FUNCTION__ " res_idx %d mask 0x%08lx res_hint: %d\n",
+ res_idx, mask, ioa->res_hint);
+
+ ccio_used_pages += pages_needed;
+ ccio_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1);
+
+ spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+
+#ifdef DUMP_RESMAP
+ dump_resmap();
+#endif
+
+ /*
+ ** return the bit address (convert from byte to bit).
+ */
+ return (res_idx << 3);
+}
+
+
+#define CCIO_FREE_MAPPINGS(ioa, idx, mask, size) \
+ u##size *res_ptr = (u##size *)&((ioa)->res_map[idx + (((size >> 3) - 1) & ~((size >> 3) - 1))]); \
+ ASSERT((*res_ptr & mask) == mask); \
+ *res_ptr &= ~mask;
+
+/*
+** clear bits in the ioa's resource map
+*/
+static void
+ccio_free_range(struct ccio_device *ioa, dma_addr_t iova, size_t size)
+{
+ unsigned long mask, flags;
+ unsigned long iovp = CCIO_IOVP(iova);
+ unsigned int res_idx = PDIR_INDEX(iovp)>>3;
+ unsigned int pages_mapped = (size >> IOVP_SHIFT) + !!(size & ~IOVP_MASK);
+
+ ASSERT(pages_needed);
+ ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT));
+
+ mask = (unsigned long) -1L;
+ mask >>= BITS_PER_LONG - pages_mapped;
+
+ DBG_RES(__FUNCTION__ " res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n",
+ res_idx, size, pages_mapped, mask);
+
+ spin_lock_irqsave(&ioa->ccio_lock, flags);
+
+ if(pages_mapped <= 8) {
+ CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 8);
+ } else if(pages_mapped <= 16) {
+ CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 16);
+ } else if(pages_mapped <= 32) {
+ CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 32);
+#ifdef __LP64__
+ } else if(pages_mapped <= 64) {
+ CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 64);
+#endif
+ } else {
+ panic(__FILE__ ":" __FUNCTION__ "() Too many pages to unmap.\n");
+ }
+
+ ccio_used_pages -= (pages_mapped ? pages_mapped : 1);
+ ccio_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1);
+
+ spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+
+#ifdef DUMP_RESMAP
+ dump_resmap();
+#endif
+}
+
+
+/****************************************************************
+**
+** CCIO dma_ops support routines
+**
+*****************************************************************/
+
+typedef unsigned long space_t;
+#define KERNEL_SPACE 0
+
+
+/*
+** DMA "Page Type" and Hints
+** o if SAFE_DMA isn't set, mapping is for FAST_DMA. SAFE_DMA should be
+** set for subcacheline DMA transfers since we don't want to damage the
+** other part of a cacheline.
+** o SAFE_DMA must be set for "memory" allocated via pci_alloc_consistent().
+** This bit tells U2 to do R/M/W for partial cachelines. "Streaming"
+** data can avoid this if the mapping covers full cache lines.
+** o STOP_MOST is needed for atomicity across cachelines.
+** Apperently only "some EISA devices" need this.
+** Using CONFIG_ISA is hack. Only the IOA with EISA under it needs
+** to use this hint iff the EISA devices needs this feature.
+** According to the U2 ERS, STOP_MOST enabled pages hurt performance.
+** o PREFETCH should *not* be set for cases like Multiple PCI devices
+** behind GSCtoPCI (dino) bus converter. Only one cacheline per GSC
+** device can be fetched and multiply DMA streams will thrash the
+** prefetch buffer and burn memory bandwidth. See 6.7.3 "Prefetch Rules
+** and Invalidation of Prefetch Entries".
+**
+** FIXME: the default hints need to be per GSC device - not global.
+**
+** HP-UX dorks: linux device driver programming model is totally different
+** than HP-UX's. HP-UX always sets HINT_PREFETCH since it's drivers
+** do special things to work on non-coherent platforms...linux has to
+** be much more careful with this.
+*/
+#define IOPDIR_VALID 0x01UL
+#define HINT_SAFE_DMA 0x02UL /* used for pci_alloc_consistent() pages */
+#ifdef CONFIG_ISA /* EISA support really */
+#define HINT_STOP_MOST 0x04UL /* LSL support */
+#else
+#define HINT_STOP_MOST 0x00UL /* only needed for "some EISA devices" */
+#endif
+#define HINT_UDPATE_ENB 0x08UL /* not used/supported by U2 */
+#define HINT_PREFETCH 0x10UL /* for outbound pages which are not SAFE */
+
+
+/*
+** Use direction (ie PCI_DMA_TODEVICE) to pick hint.
+** ccio_alloc_consistent() depends on this to get SAFE_DMA
+** when it passes in BIDIRECTIONAL flag.
+*/
+static u32 hint_lookup[] = {
+ [PCI_DMA_BIDIRECTIONAL] HINT_STOP_MOST | HINT_SAFE_DMA | IOPDIR_VALID,
+ [PCI_DMA_TODEVICE] HINT_STOP_MOST | HINT_PREFETCH | IOPDIR_VALID,
+ [PCI_DMA_FROMDEVICE] HINT_STOP_MOST | IOPDIR_VALID,
+ [PCI_DMA_NONE] 0, /* not valid */
+};
+
+/*
+** Initialize an I/O Pdir entry
+**
+** Given a virtual address (vba, arg2) and space id, (sid, arg1),
+** load the I/O PDIR entry pointed to by pdir_ptr (arg0). Each IO Pdir
+** entry consists of 8 bytes as shown below (MSB == bit 0):
+**
+**
+** WORD 0:
+** +------+----------------+-----------------------------------------------+
+** | Phys | Virtual Index | Phys |
+** | 0:3 | 0:11 | 4:19 |
+** |4 bits| 12 bits | 16 bits |
+** +------+----------------+-----------------------------------------------+
+** WORD 1:
+** +-----------------------+-----------------------------------------------+
+** | Phys | Rsvd | Prefetch |Update |Rsvd |Lock |Safe |Valid |
+** | 20:39 | | Enable |Enable | |Enable|DMA | |
+** | 20 bits | 5 bits | 1 bit |1 bit |2 bits|1 bit |1 bit |1 bit |
+** +-----------------------+-----------------------------------------------+
+**
+** The virtual index field is filled with the results of the LCI
+** (Load Coherence Index) instruction. The 8 bits used for the virtual
+** index are bits 12:19 of the value returned by LCI.
+*/
+
+void CCIO_INLINE
+ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, void * vba, unsigned long hints)
+{
+ register unsigned long pa = (volatile unsigned long) vba;
+ register unsigned long ci; /* coherent index */
+
+ /* We currently only support kernel addresses */
+ ASSERT(sid == 0);
+ ASSERT(((unsigned long) vba & 0xf0000000UL) == 0xc0000000UL);
+
+ mtsp(sid,1);
+
+ /*
+ ** WORD 1 - low order word
+ ** "hints" parm includes the VALID bit!
+ ** "dep" clobbers the physical address offset bits as well.
+ */
+ pa = virt_to_phys(vba);
+ asm volatile("depw %1,31,12,%0" : "+r" (pa) : "r" (hints));
+ ((u32 *)pdir_ptr)[1] = (u32) pa;
+
+ /*
+ ** WORD 0 - high order word
+ */
+
+#ifdef __LP64__
+ /*
+ ** get bits 12:15 of physical address
+ ** shift bits 16:31 of physical address
+ ** and deposit them
+ */
+ asm volatile ("extrd,u %1,15,4,%0" : "=r" (ci) : "r" (pa));
+ asm volatile ("extrd,u %1,31,16,%0" : "+r" (ci) : "r" (ci));
+ asm volatile ("depd %1,35,4,%0" : "+r" (pa) : "r" (ci));
+#else
+ pa = 0;
+#endif
+ /*
+ ** get CPU coherency index bits
+ ** Grab virtual index [0:11]
+ ** Deposit virt_idx bits into I/O PDIR word
+ */
+ asm volatile ("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+ asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
+ asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci));
+
+ ((u32 *)pdir_ptr)[0] = (u32) pa;
+
+
+ /* FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360)
+ ** PCX-U/U+ do. (eg C200/C240)
+ ** PCX-T'? Don't know. (eg C110 or similar K-class)
+ **
+ ** See PDC_MODEL/option 0/SW_CAP word for "Non-coherent IO-PDIR bit".
+ ** Hopefully we can patch (NOP) these out at boot time somehow.
+ **
+ ** "Since PCX-U employs an offset hash that is incompatible with
+ ** the real mode coherence index generation of U2, the PDIR entry
+ ** must be flushed to memory to retain coherence."
+ */
+ asm volatile("fdc 0(%0)" : : "r" (pdir_ptr));
+ asm volatile("sync");
+}
+
+
+/*
+** Remove stale entries from the I/O TLB.
+** Need to do this whenever an entry in the PDIR is marked invalid.
+*/
+static CCIO_INLINE void
+ccio_clear_io_tlb( struct ccio_device *d, dma_addr_t iovp, size_t byte_cnt)
+{
+ u32 chain_size = 1 << d->chainid_shift;
+
+ iovp &= ~(IOVP_SIZE-1); /* clear offset bits, just want pagenum */
+ byte_cnt += chain_size;
+
+ while (byte_cnt > chain_size) {
+ WRITE_U32(CMD_TLB_PURGE | iovp, &d->ccio_hpa->io_command);
+ iovp += chain_size;
+ byte_cnt -= chain_size;
+ }
+}
+
+
+/***********************************************************
+ *
+ * Mark the I/O Pdir entries invalid and blow away the
+ * corresponding I/O TLB entries.
+ *
+ * FIXME: at some threshhold it might be "cheaper" to just blow
+ * away the entire I/O TLB instead of individual entries.
+ *
+ * FIXME: Uturn has 256 TLB entries. We don't need to purge every
+ * PDIR entry - just once for each possible TLB entry.
+ * (We do need to maker I/O PDIR entries invalid regardless).
+ ***********************************************************/
+static CCIO_INLINE void
+ccio_mark_invalid(struct ccio_device *d, dma_addr_t iova, size_t byte_cnt)
+{
+ u32 iovp = (u32) CCIO_IOVP(iova);
+ size_t saved_byte_cnt;
+
+ /* round up to nearest page size */
+ saved_byte_cnt = byte_cnt = (byte_cnt + IOVP_SIZE - 1) & IOVP_MASK;
+
+ while (byte_cnt > 0) {
+ /* invalidate one page at a time */
+ unsigned int idx = PDIR_INDEX(iovp);
+ char *pdir_ptr = (char *) &(d->pdir_base[idx]);
+
+ ASSERT( idx < (d->pdir_size/sizeof(u64)));
+
+ pdir_ptr[7] = 0; /* clear only VALID bit */
+
+ /*
+ ** FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360)
+ ** PCX-U/U+ do. (eg C200/C240)
+ ** See PDC_MODEL/option 0/SW_CAP for "Non-coherent IO-PDIR bit".
+ **
+ ** Hopefully someone figures out how to patch (NOP) the
+ ** FDC/SYNC out at boot time.
+ */
+ asm volatile("fdc 0(%0)" : : "r" (pdir_ptr[7]));
+
+ iovp += IOVP_SIZE;
+ byte_cnt -= IOVP_SIZE;
+ }
+
+ asm volatile("sync");
+ ccio_clear_io_tlb(d, CCIO_IOVP(iova), saved_byte_cnt);
+}
+
+
+/****************************************************************
+**
+** CCIO dma_ops
+**
+*****************************************************************/
+
+void __init ccio_init(void)
+{
+ register_driver(ccio_drivers_for);
+}
+
+
+static int ccio_dma_supported( struct pci_dev *dev, dma_addr_t mask)
+{
+ if (dev == NULL) {
+ printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+ BUG();
+ return(0);
+ }
+
+ dev->dma_mask = mask; /* save it */
+
+ /* only support 32-bit devices (ie PCI/GSC) */
+ return((int) (mask >= 0xffffffffUL));
+}
+
+/*
+** Dump a hex representation of the resource map.
+*/
+
+#ifdef DUMP_RESMAP
+static
+void dump_resmap()
+{
+ struct ccio_device *ioa = ccio_list;
+ unsigned long *res_ptr = (unsigned long *)ioa->res_map;
+ unsigned long i = 0;
+
+ printk("res_map: ");
+ for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr)
+ printk("%08lx ", *res_ptr);
+
+ printk("\n");
+}
+#endif
+
+/*
+** map_single returns a fully formed IOVA
+*/
+static dma_addr_t ccio_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+{
+ struct ccio_device *ioa = ccio_list; /* FIXME : see Multi-IOC below */
+ dma_addr_t iovp;
+ dma_addr_t offset;
+ u64 *pdir_start;
+ unsigned long hint = hint_lookup[direction];
+ int idx;
+
+ ASSERT(size > 0);
+
+ /* save offset bits */
+ offset = ((dma_addr_t) addr) & ~IOVP_MASK;
+
+ /* round up to nearest IOVP_SIZE */
+ size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK;
+
+ idx = ccio_alloc_range(ioa, size);
+ iovp = (dma_addr_t) MKIOVP(idx);
+
+ DBG_RUN(__FUNCTION__ " 0x%p -> 0x%lx", addr, (long) iovp | offset);
+
+ pdir_start = &(ioa->pdir_base[idx]);
+
+ /* If not cacheline aligned, force SAFE_DMA on the whole mess */
+ if ((size % L1_CACHE_BYTES) || ((unsigned long) addr % L1_CACHE_BYTES))
+ hint |= HINT_SAFE_DMA;
+
+ /* round up to nearest IOVP_SIZE */
+ size = (size + IOVP_SIZE - 1) & IOVP_MASK;
+
+ while (size > 0) {
+
+ ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, addr, hint);
+
+ DBG_RUN(" pdir %p %08x%08x\n",
+ pdir_start,
+ (u32) (((u32 *) pdir_start)[0]),
+ (u32) (((u32 *) pdir_start)[1])
+ );
+ addr += IOVP_SIZE;
+ size -= IOVP_SIZE;
+ pdir_start++;
+ }
+ /* form complete address */
+ return CCIO_IOVA(iovp, offset);
+}
+
+
+static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction)
+{
+#ifdef FIXME
+/* Multi-IOC (ie N-class) : need to lookup IOC from dev
+** o If we can't know about lba PCI data structs, that eliminates ->sysdata.
+** o walking up pcidev->parent dead ends at elroy too
+** o leaves hashing dev->bus->number into some lookup.
+** (may only work for N-class)
+*/
+ struct ccio_device *ioa = dev->sysdata
+#else
+ struct ccio_device *ioa = ccio_list;
+#endif
+ dma_addr_t offset;
+
+ offset = iova & ~IOVP_MASK;
+
+ /* round up to nearest IOVP_SIZE */
+ size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK;
+
+ /* Mask off offset */
+ iova &= IOVP_MASK;
+
+ DBG_RUN(__FUNCTION__ " iovp 0x%lx\n", (long) iova);
+
+#ifdef DELAYED_RESOURCE_CNT
+ if (ioa->saved_cnt < DELAYED_RESOURCE_CNT) {
+ ioa->saved_iova[ioa->saved_cnt] = iova;
+ ioa->saved_size[ioa->saved_cnt] = size;
+ ccio_saved_cnt++;
+ } else {
+ do {
+#endif
+ ccio_mark_invalid(ioa, iova, size);
+ ccio_free_range(ioa, iova, size);
+
+#ifdef DELAYED_RESOURCE_CNT
+ d->saved_cnt--;
+ iova = ioa->saved_iova[ioa->saved_cnt];
+ size = ioa->saved_size[ioa->saved_cnt];
+ } while (ioa->saved_cnt)
+ }
+#endif
+}
+
+
+static void * ccio_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+{
+ void *ret;
+ unsigned long flags;
+ struct ccio_device *ioa = ccio_list;
+
+ DBG_RUN(__FUNCTION__ " size 0x%x\n", size);
+
+#if 0
+/* GRANT Need to establish hierarchy for non-PCI devs as well
+** and then provide matching gsc_map_xxx() functions for them as well.
+*/
+ if (!hwdev) {
+ /* only support PCI */
+ *dma_handle = 0;
+ return 0;
+ }
+#endif
+ spin_lock_irqsave(&ioa->ccio_lock, flags);
+ ccio_alloc_size += get_order(size);
+ spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+
+ ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size));
+
+ if (ret) {
+ memset(ret, 0, size);
+ *dma_handle = ccio_map_single(hwdev, ret, size, PCI_DMA_BIDIRECTIONAL);
+ }
+ DBG_RUN(__FUNCTION__ " ret %p\n", ret);
+
+ return ret;
+}
+
+
+static void ccio_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ unsigned long flags;
+ struct ccio_device *ioa = ccio_list;
+
+ spin_lock_irqsave(&ioa->ccio_lock, flags);
+ ccio_free_size += get_order(size);
+ spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+
+ ccio_unmap_single(hwdev, dma_handle, size, 0);
+ free_pages((unsigned long) vaddr, get_order(size));
+}
+
+
+static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int tmp = nents;
+
+ DBG_RUN(KERN_WARNING __FUNCTION__ " START\n");
+
+ /* KISS: map each buffer seperately. */
+ while (nents) {
+ sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction);
+ sg_dma_len(sglist) = sglist->length;
+ nents--;
+ sglist++;
+ }
+
+ DBG_RUN(KERN_WARNING __FUNCTION__ " DONE\n");
+ return tmp;
+}
+
+
+static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ DBG_RUN(KERN_WARNING __FUNCTION__ " : unmapping %d entries\n", nents);
+ while (nents) {
+ ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
+ nents--;
+ sglist++;
+ }
+ return;
+}
+
+
+static struct pci_dma_ops ccio_ops = {
+ ccio_dma_supported,
+ ccio_alloc_consistent,
+ ccio_free_consistent,
+ ccio_map_single,
+ ccio_unmap_single,
+ ccio_map_sg,
+ ccio_unmap_sg,
+ NULL, /* dma_sync_single : NOP for U2/Uturn */
+ NULL, /* dma_sync_sg : ditto */
+};
+
+#if 0
+/* GRANT - is this needed for U2 or not? */
+
+/*
+** Get the size of the I/O TLB for this I/O MMU.
+**
+** If spa_shift is non-zero (ie probably U2),
+** then calculate the I/O TLB size using spa_shift.
+**
+** Otherwise we are supposed to get the IODC entry point ENTRY TLB
+** and execute it. However, both U2 and Uturn firmware supplies spa_shift.
+** I think only Java (K/D/R-class too?) systems don't do this.
+*/
+static int
+ccio_get_iotlb_size(struct hp_device *d)
+{
+ if(d->spa_shift == 0) {
+ panic(__FUNCTION__ ": Can't determine I/O TLB size.\n");
+ }
+ return(1 << d->spa_shift);
+}
+#else
+
+/* Uturn supports 256 TLB entries */
+#define CCIO_CHAINID_SHIFT 8
+#define CCIO_CHAINID_MASK 0xff
+
+#endif /* 0 */
+
+
+/*
+** Figure out how big the I/O PDIR should be and alloc it.
+** Also sets variables which depend on pdir size.
+*/
+static void
+ccio_alloc_pdir(struct ccio_device *ioa)
+{
+ extern unsigned long mem_max; /* arch.../setup.c */
+
+ u32 iova_space_size = 0;
+ void * pdir_base;
+ int pdir_size, iov_order;
+
+ /*
+ ** Determine IOVA Space size from memory size.
+ ** Using "mem_max" is a kluge.
+ **
+ ** Ideally, PCI drivers would register the maximum number
+ ** of DMA they can have outstanding for each device they
+ ** own. Next best thing would be to guess how much DMA
+ ** can be outstanding based on PCI Class/sub-class. Both
+ ** methods still require some "extra" to support PCI
+ ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
+ */
+ /* limit IOVA space size to 1MB-1GB */
+ if (mem_max < (ccio_mem_ratio*1024*1024)) {
+ iova_space_size = 1024*1024;
+#ifdef __LP64__
+ } else if (mem_max > (ccio_mem_ratio*512*1024*1024)) {
+ iova_space_size = 512*1024*1024;
+#endif
+ } else {
+ iova_space_size = (u32) (mem_max/ccio_mem_ratio);
+ }
+
+ /*
+ ** iova space must be log2() in size.
+ ** thus, pdir/res_map will also be log2().
+ */
+
+ /* We could use larger page sizes in order to *decrease* the number
+ ** of mappings needed. (ie 8k pages means 1/2 the mappings).
+ **
+ ** Note: Grant Grunder says "Using 8k I/O pages isn't trivial either
+ ** since the pages must also be physically contiguous - typically
+ ** this is the case under linux."
+ */
+
+ iov_order = get_order(iova_space_size);
+ ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */
+ ASSERT(iov_order >= (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */
+ iova_space_size = 1 << (iov_order + IOVP_SHIFT);
+
+ ioa->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
+
+ ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */
+
+ /* Verify it's a power of two */
+ ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
+
+ DBG_INIT(__FUNCTION__ " hpa 0x%p mem %dMB IOV %dMB (%d bits)\n PDIR size 0x%0x",
+ ioa->ccio_hpa, (int) (mem_max>>20), iova_space_size>>20,
+ iov_order + PAGE_SHIFT, pdir_size);
+
+ ioa->pdir_base =
+ pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
+ if (NULL == pdir_base)
+ {
+ panic(__FILE__ ":" __FUNCTION__ "() could not allocate I/O Page Table\n");
+ }
+ memset(pdir_base, 0, pdir_size);
+
+ ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base);
+
+ DBG_INIT(" base %p", pdir_base);
+
+ /*
+ ** Chainid is the upper most bits of an IOVP used to determine
+ ** which TLB entry an IOVP will use.
+ */
+ ioa->chainid_shift = get_order(iova_space_size)+PAGE_SHIFT-CCIO_CHAINID_SHIFT;
+
+ DBG_INIT(" chainid_shift 0x%x\n", ioa->chainid_shift);
+}
+
+
+static void
+ccio_hw_init(struct ccio_device *ioa)
+{
+ int i;
+
+ /*
+ ** Initialize IOA hardware
+ */
+ WRITE_U32(CCIO_CHAINID_MASK << ioa->chainid_shift, &ioa->ccio_hpa->io_chain_id_mask);
+ WRITE_U32(virt_to_phys(ioa->pdir_base), &ioa->ccio_hpa->io_pdir_base);
+
+
+ /*
+ ** Go to "Virtual Mode"
+ */
+ WRITE_U32(IOA_NORMAL_MODE, &ioa->ccio_hpa->io_control);
+
+ /*
+ ** Initialize all I/O TLB entries to 0 (Valid bit off).
+ */
+ WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_m);
+ WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_l);
+
+ for (i = 1 << CCIO_CHAINID_SHIFT; i ; i--) {
+ WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioa->chainid_shift)),
+ &ioa->ccio_hpa->io_command);
+ }
+
+}
+
+
+static void
+ccio_resmap_init(struct ccio_device *ioa)
+{
+ u32 res_size;
+
+ /*
+ ** Ok...we do more than just init resource map
+ */
+ ioa->ccio_lock = SPIN_LOCK_UNLOCKED;
+
+ ioa->res_hint = 16; /* next available IOVP - circular search */
+
+ /* resource map size dictated by pdir_size */
+ res_size = ioa->pdir_size/sizeof(u64); /* entries */
+ res_size >>= 3; /* convert bit count to byte count */
+ DBG_INIT(__FUNCTION__ "() res_size 0x%x\n", res_size);
+
+ ioa->res_size = res_size;
+ ioa->res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size));
+ if (NULL == ioa->res_map)
+ {
+ panic(__FILE__ ":" __FUNCTION__ "() could not allocate resource map\n");
+ }
+ memset(ioa->res_map, 0, res_size);
+}
+
+/* CUJO20 KLUDGE start */
+static struct {
+ u16 hversion;
+ u8 spa;
+ u8 type;
+ u32 foo[3]; /* 16 bytes total */
+} cujo_iodc __attribute__ ((aligned (64)));
+static unsigned long cujo_result[32] __attribute__ ((aligned (16))) = {0,0,0,0};
+
+/*
+** CUJO 2.0 incorrectly decodes a memory access for specific
+** pages (every page at specific iotlb locations dependent
+** upon where the cujo is flexed - diff on raven/firehawk.
+** resulting in an hpmc and/or silent data corruption.
+** Workaround is to prevent use of those I/O TLB entries
+** by marking the suspect bitmap range entries as busy.
+*/
+static void
+ccio_cujo20_hack(struct ccio_device *ioa)
+{
+ unsigned long status;
+ unsigned int idx;
+ u8 *res_ptr = ioa->res_map;
+ u32 iovp=0x0;
+ unsigned long mask;
+
+ status = pdc_iodc_read( &cujo_result, (void *) CUJO_RAVEN_LOC, 0, &cujo_iodc, 16);
+ if (status == 0) {
+ if (cujo_iodc.hversion==CUJO_20_BADHVERS)
+ iovp = CUJO_20_BADPAGE1;
+ } else {
+ status = pdc_iodc_read( &cujo_result, (void *) CUJO_FIREHAWK_LOC, 0, &cujo_iodc, 16);
+ if (status == 0) {
+ if (cujo_iodc.hversion==CUJO_20_BADHVERS)
+ iovp = CUJO_20_BADPAGE2;
+ } else {
+ /* not a defective system */
+ return;
+ }
+ }
+
+ printk(MODULE_NAME ": Cujo 2.0 bug needs a work around\n");
+ ccio_cujo_bug = 1;
+
+ /*
+ ** mark bit entries that match "bad page"
+ */
+ idx = PDIR_INDEX(iovp)>>3;
+ mask = 0xff;
+
+ while(idx * sizeof(u8) < ioa->res_size) {
+ res_ptr[idx] |= mask;
+ idx += (PDIR_INDEX(CUJO_20_STEP)>>3);
+ ccio_used_pages += 8;
+ ccio_used_bytes += 1;
+ }
+}
+/* CUJO20 KLUDGE end */
+
+#ifdef CONFIG_PROC_FS
+static int ccio_proc_info(char *buf, char **start, off_t offset, int len)
+{
+ unsigned long i = 0;
+ struct ccio_device *ioa = ccio_list;
+ unsigned long *res_ptr = (unsigned long *)ioa->res_map;
+ unsigned long total_pages = ioa->res_size << 3; /* 8 bits per byte */
+
+ sprintf(buf, "%s\nCujo 2.0 bug : %s\n",
+ parisc_getHWdescription(ioa->iodc->hw_type, ioa->iodc->hversion,
+ ioa->iodc->sversion),
+ (ccio_cujo_bug ? "yes" : "no"));
+
+ sprintf(buf, "%sIO pdir size : %d bytes (%d entries)\n",
+ buf, ((ioa->res_size << 3) * sizeof(u64)), /* 8 bits per byte */
+ ioa->res_size << 3); /* 8 bits per byte */
+
+ sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
+ buf, ioa->res_size, ioa->res_size << 3); /* 8 bits per byte */
+
+ strcat(buf, " total: free: used: % used:\n");
+ sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, ioa->res_size,
+ ioa->res_size - ccio_used_bytes, ccio_used_bytes,
+ (ccio_used_bytes * 100) / ioa->res_size);
+
+ sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
+ total_pages - ccio_used_pages, ccio_used_pages,
+ (ccio_used_pages * 100 / total_pages));
+
+ sprintf(buf, "%sconsistent %8ld %8ld\n", buf,
+ ccio_alloc_size, ccio_free_size);
+
+ strcat(buf, "\nResource bitmap:\n");
+
+ for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr)
+ len += sprintf(buf, "%s%08lx ", buf, *res_ptr);
+
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+#endif
+
+/*
+** Determine if ccio should claim this chip (return 0) or not (return 1).
+** If so, initialize the chip and tell other partners in crime they
+** have work to do.
+*/
+static int
+ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ struct ccio_device *ioa;
+
+ printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+
+ if (ccio_list) {
+ printk(MODULE_NAME ": already initialized one device\n");
+ return(0);
+ }
+
+ ioa = kmalloc(sizeof(struct ccio_device), GFP_KERNEL);
+ if (NULL == ioa)
+ {
+ printk(MODULE_NAME " - couldn't alloc ccio_device\n");
+ return(1);
+ }
+ memset(ioa, 0, sizeof(struct ccio_device));
+
+ /*
+ ** ccio list is used mainly as a kluge to support a single instance.
+ ** Eventually, with core dumps, it'll be useful for debugging.
+ */
+ ccio_list = ioa;
+ ioa->iodc = d;
+
+#if 1
+/* KLUGE: determine IOA hpa based on GSC port value.
+** Needed until we have a PA bus walk. Can only discover IOA via
+** walking the architected PA MMIO space as described by the I/O ACD.
+** "Legacy" PA Firmware only tells us about unarchitected devices
+** that can't be detected by PA/EISA/PCI bus walks.
+*/
+ switch((long) d->hpa) {
+ case 0xf3fbf000L: /* C110 IOA0 LBC (aka GSC port) */
+ /* ccio_hpa same as C200 IOA0 */
+ case 0xf203f000L: /* C180/C200/240/C360 IOA0 LBC (aka GSC port) */
+ ioa->ccio_hpa = (struct ioa_registers *) 0xfff88000L;
+ break;
+ case 0xf103f000L: /* C180/C200/240/C360 IOA1 LBC (aka GSC port) */
+ ioa->ccio_hpa = (struct ioa_registers *) 0xfff8A000L;
+ break;
+ default:
+ panic("ccio-dma.c doesn't know this GSC port Address!\n");
+ break;
+ };
+#else
+ ioa->ccio_hpa = d->hpa;
+#endif
+
+ ccio_alloc_pdir(ioa);
+ ccio_hw_init(ioa);
+ ccio_resmap_init(ioa);
+
+ /* CUJO20 KLUDGE start */
+ ccio_cujo20_hack(ioa);
+ /* CUJO20 KLUDGE end */
+
+ hppa_dma_ops = &ccio_ops;
+
+ create_proc_info_entry(MODULE_NAME, 0, proc_runway_root, ccio_proc_info);
+ return(0);
+}
+
+
+
diff --git a/arch/parisc/kernel/ccio-rm-dma.c b/arch/parisc/kernel/ccio-rm-dma.c
new file mode 100644
index 000000000..25ec90c1b
--- /dev/null
+++ b/arch/parisc/kernel/ccio-rm-dma.c
@@ -0,0 +1,212 @@
+/*
+ * ccio-rm-dma.c:
+ * DMA management routines for first generation cache-coherent machines.
+ * "Real Mode" operation refers to U2/Uturn chip operation. The chip
+ * can perform coherency checks w/o using the I/O MMU. That's all we
+ * need until support for more than 4GB phys mem is needed.
+ *
+ * This is the trivial case - basically what x86 does.
+ *
+ * Drawbacks of using Real Mode are:
+ * o outbound DMA is slower since one isn't using the prefetching
+ * U2 can do for outbound DMA.
+ * o Ability to do scatter/gather in HW is also lost.
+ * o only known to work with PCX-W processor. (eg C360)
+ * (PCX-U/U+ are not coherent with U2 in real mode.)
+ *
+ *
+ * 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.
+ *
+ *
+ * Original version/author:
+ * CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc
+ * cvs -z3 co linux/arch/parisc/kernel/dma-rm.c
+ *
+ * (C) Copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ *
+ * Adopted for The Puffin Group's parisc-linux port by Grant Grundler.
+ * (C) Copyright 2000 Grant Grundler <grundler@puffin.external.hp.com>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+
+/* Only chose "ccio" since that's what HP-UX calls it....
+** Make it easier for folks to migrate from one to the other :^)
+*/
+#define MODULE_NAME "ccio"
+
+#define U2_IOA_RUNWAY 0x580
+#define U2_BC_GSC 0x501
+#define UTURN_IOA_RUNWAY 0x581
+#define UTURN_BC_GSC 0x502
+
+static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+static struct pa_iodc_driver ccio_drivers_for[] = {
+
+ {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback},
+
+ {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback},
+
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL }
+};
+
+
+#define IS_U2(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \
+)
+
+#define IS_UTURN(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \
+)
+
+
+void __init ccio_init(void)
+{
+ register_driver(ccio_drivers_for);
+}
+
+
+static int ccio_dma_supported( struct pci_dev *dev, dma_addr_t mask)
+{
+ if (dev == NULL) {
+ printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+ BUG();
+ return(0);
+ }
+
+ dev->dma_mask = mask; /* save it */
+
+ /* only support 32-bit devices (ie PCI/GSC) */
+ return((int) (mask >= 0xffffffffUL));
+}
+
+
+static void *ccio_alloc_consistent(struct pci_dev *dev, size_t size,
+ dma_addr_t *handle)
+{
+ void *ret;
+
+ ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *handle = virt_to_phys(ret);
+ }
+ return ret;
+}
+
+static void ccio_free_consistent(struct pci_dev *dev, size_t size,
+ void *vaddr, dma_addr_t handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+
+static dma_addr_t ccio_map_single(struct pci_dev *dev, void *ptr, size_t size,
+ int direction)
+{
+ return virt_to_phys(ptr);
+}
+
+static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+ /* Nothing to do */
+}
+
+
+static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int tmp = nents;
+
+ /* KISS: map each buffer seperately. */
+ while (nents) {
+ sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction);
+ sg_dma_len(sglist) = sglist->length;
+ nents--;
+ sglist++;
+ }
+
+ return tmp;
+}
+
+
+static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+#if 0
+ while (nents) {
+ ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
+ nents--;
+ sglist++;
+ }
+ return;
+#else
+ /* Do nothing (copied from current ccio_unmap_single() :^) */
+#endif
+}
+
+
+static struct pci_dma_ops ccio_ops = {
+ ccio_dma_supported,
+ ccio_alloc_consistent,
+ ccio_free_consistent,
+ ccio_map_single,
+ ccio_unmap_single,
+ ccio_map_sg,
+ ccio_unmap_sg,
+ NULL, /* dma_sync_single : NOP for U2 */
+ NULL, /* dma_sync_sg : ditto */
+
+
+};
+
+
+/*
+** Determine if u2 should claim this chip (return 0) or not (return 1).
+** If so, initialize the chip and tell other partners in crime they
+** have work to do.
+*/
+static int
+ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+
+/*
+** FIXME - should check U2 registers to verify it's really running
+** in "Real Mode".
+*/
+
+#if 0
+/* will need this for "Virtual Mode" operation */
+ ccio_hw_init(ccio_dev);
+ ccio_common_init(ccio_dev);
+#endif
+ hppa_dma_ops = &ccio_ops;
+ return 0;
+}
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
new file mode 100644
index 000000000..ba93bbda0
--- /dev/null
+++ b/arch/parisc/kernel/drivers.c
@@ -0,0 +1,134 @@
+/*
+
+drivers.c
+
+Copyright (c) 1999 The Puffin Group
+
+This is a collection of routines intended to register all the devices
+in a system, and register device drivers.
+
+*/
+
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/pdc.h>
+
+
+extern struct hp_hardware *parisc_get_reference(
+ unsigned short hw_type, unsigned long hversion,
+ unsigned long sversion );
+
+
+/* I'm assuming there'll never be 64 devices. We should probably make
+ this more flexible. */
+
+#define MAX_DEVICES 64
+
+unsigned int num_devices = 0;
+
+struct hp_device devices[MAX_DEVICES];
+
+static unsigned long pdc_result[32] __attribute__ ((aligned (16))) = {0,0,0,0};
+static u8 iodc_data[32] __attribute__ ((aligned (64)));
+
+/*
+ * XXX should we be using a locked array ?
+ */
+
+int register_driver(struct pa_iodc_driver *driver)
+{
+ unsigned int i;
+ struct hp_device * device;
+
+ for (;driver->check;driver++) {
+
+ for (i=0;i<num_devices;i++) {
+ device = &devices[i];
+
+ if (device->managed) continue;
+
+ if ((driver->check & DRIVER_CHECK_HWTYPE) &&
+ (driver->hw_type != device->hw_type))
+ continue;
+ if ((driver->check & DRIVER_CHECK_HVERSION) &&
+ (driver->hversion != device->hversion))
+ continue;
+ if ((driver->check & DRIVER_CHECK_HVERSION_REV) &&
+ (driver->hversion_rev != device->hversion_rev))
+ continue;
+ if ((driver->check & DRIVER_CHECK_SVERSION) &&
+ (driver->sversion != device->sversion))
+ continue;
+ if ((driver->check & DRIVER_CHECK_SVERSION_REV) &&
+ (driver->sversion_rev != device->sversion_rev))
+ continue;
+ if ((driver->check & DRIVER_CHECK_OPT) &&
+ (driver->opt != device->opt))
+ continue;
+ if ( (*driver->callback)(device,driver) ==0) {
+ device->managed=1;
+ } else {
+ printk("Warning : device (%d, 0x%x, 0x%x, 0x%x, 0x%x) NOT claimed by %s %s\n",
+ device->hw_type,
+ device->hversion, device->hversion_rev,
+ device->sversion, device->sversion_rev,
+ driver->name, driver->version);
+ }
+ }
+ }
+ return 0;
+}
+
+
+struct hp_device * register_module(void *hpa)
+{
+
+ struct hp_device * d;
+ int status;
+
+ d = &devices[num_devices];
+ status = pdc_iodc_read(&pdc_result,hpa,0,&iodc_data,32 );
+ if (status !=PDC_RET_OK) {
+ /* There is no device here, so we'll skip it */
+ return 0;
+ }
+
+ d->hw_type = iodc_data[3]&0x1f;
+ d->hversion = (iodc_data[0]<<4)|((iodc_data[1]&0xf0)>>4);
+ d->sversion =
+ ((iodc_data[4]&0x0f)<<16)|(iodc_data[5]<<8)|(iodc_data[6]);
+ d->hversion_rev = iodc_data[1]&0x0f;
+ d->sversion_rev = iodc_data[4]>>4;
+ d->opt = iodc_data[7];
+ d->hpa = hpa;
+ d->managed=0;
+ d->reference = parisc_get_reference(d->hw_type, d->hversion,
+ d->sversion);
+
+ num_devices++;
+
+ return d;
+}
+
+void print_devices(char * buf) {
+
+ int i;
+ struct hp_device *d;
+ printk("Found devices:\n");
+ for (i=0;i<num_devices;i++) {
+ d = &devices[i];
+ printk(KERN_INFO
+ "%d. %s (%d) at 0x%p, versions 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
+ i+1,
+ (d->reference) ? d->reference->name : "Unknown device",
+ d->hw_type,d->hpa, d->hversion, d->hversion_rev,
+ d->sversion, d->sversion_rev, d->opt);
+
+ }
+ printk("That's a total of %d devices.\n",num_devices);
+}
+
+
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
new file mode 100644
index 000000000..0839e0bbb
--- /dev/null
+++ b/arch/parisc/kernel/entry.S
@@ -0,0 +1,1867 @@
+/*------------------------------------------------------------------------------
+ * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ *
+ * kernel entry points (interruptions, system call wrappers)
+ * Copyright (C) 1999,2000 Philipp Rumpf
+ * Copyright (C) 1999 SuSE GmbH Nuernberg
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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 <asm/offset.h>
+
+/* the following is the setup i think we should follow:
+ * whenever the CPU is interruptible, the following has to be true:
+ * CR30 is the kernel sp or 0 if we currently use the kernel stack
+ * CR31 is the kernel gp */
+
+/* we have the following possibilities to act on an interruption:
+ * - handle in assembly and use shadowed registers only
+ * - save registers to kernel stack and handle in assembly or C */
+
+ .text
+
+#ifdef __LP64__
+ .level 2.0w
+#endif
+
+#define __ASSEMBLY__
+#include <asm/assembly.h> /* for LDREG/STREG defines */
+#include <asm/pgtable.h>
+#include <asm/psw.h>
+#include <asm/signal.h>
+
+#ifdef __LP64__
+#define FRAME_SIZE 64
+#else
+#define FRAME_SIZE 64
+#endif
+
+ /* Switch to virtual mapping, trashing only %r1 */
+ .macro virt_map rfi_type
+ mtsm %r0
+ tovirt %r29
+ tovirt %r30
+ mfsp %sr7, %r1
+ mtsp %r1, %sr3
+ mtsp %r0, %sr4
+ mtsp %r0, %sr5
+ mtsp %r0, %sr6
+ mtsp %r0, %sr7
+ ldil L%KERNEL_PSW, %r1
+ ldo R%KERNEL_PSW(%r1), %r1
+ LDIL_FIXUP(%r1)
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17
+ mtctl %r0, %cr17
+ ldil L%.+28, %r1
+ ldo R%.+24(%r1), %r1
+ LDIL_FIXUP(%r1)
+ mtctl %r1, %cr18
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18
+ \rfi_type
+ nop
+ .endm
+
+ .macro get_stack
+ mfctl %cr30, %r1
+ comib,=,n 0, %r1, 0f /* forward so predicted not taken */
+
+ /* we save the registers in the task struct */
+ ldo TASK_REGS(%r1), %r29
+ tophys %r29
+ STREG %r30, PT_GR30(%r29)
+ STREG %r1, PT_CR30(%r29)
+ ldo TASK_SZ_ALGN(%r1), %r30
+ b 1f /* unconditional so predicted taken */
+ mtctl %r0,%cr30
+0:
+ /* we put a struct pt_regs on the stack and save the registers there */
+ copy %r30,%r29
+ ldo PT_SZ_ALGN(%r30),%r30
+ tophys %r29
+ STREG %r30,PT_GR30(%r29)
+ STREG %r0,PT_CR30(%r29)
+1:
+ .endm
+
+ .macro rest_stack regs
+ LDREG PT_CR30(\regs), %r1
+ comib,=,n 0, %r1, 2f/* forward so predicted not taken */
+
+ /* we restore the registers out of the task struct */
+ mtctl %r1, %cr30
+ LDREG PT_GR1(\regs), %r1
+ LDREG PT_GR30(\regs),%r30
+ b 3f
+ LDREG PT_GR29(\regs),%r29
+2:
+ /* we take a struct pt_regs off the stack */
+ LDREG PT_GR1(\regs), %r1
+ LDREG PT_GR29(\regs), %r29
+ ldo -PT_SZ_ALGN(%r30), %r30
+3:
+ .endm
+
+#ifdef OLD
+ /* fixme interruption handler */
+ .macro def code
+ /* WARNING!!! THIS IS DEBUG CODE ONLY!!! */
+ b unimplemented_64bitirq
+ ldi \code, %r1
+ .align 32
+ .endm
+
+ /* Use def to enable break - KWDB wants em
+ * (calls traps.c:handle_interruption) */
+ .macro pass_break code
+
+#else
+ /* default interruption handler
+ * (calls traps.c:handle_interruption) */
+ .macro def code
+#endif
+ mtctl %r29, %cr31
+ mtctl %r1, %cr28
+ ldi \code, %r1
+ b intr_save
+ mtctl %r1, %cr29
+ .align 32
+ .endm
+
+ /* Interrupt interruption handler
+ * (calls irq.c:do_irq_mask) */
+ .macro extint code
+ mtctl %r29, %cr31
+ mtctl %r1, %cr28
+ mfctl %cr23, %r1
+ mtctl %r1, %cr23
+ b intr_extint
+ mtctl %r1, %cr29
+ .align 32
+ .endm
+
+ .import os_hpmc, code
+
+ /* HPMC handler */
+ .macro hpmc code
+ nop /* must be a NOP, will be patched later */
+ ldil L%PA(os_hpmc), %r3
+ ldo R%PA(os_hpmc)(%r3), %r3
+ bv,n 0(%r3)
+ nop
+ .word 0 /* checksum (will be patched) */
+ .word PA(os_hpmc) /* address of handler */
+ .word 0 /* length of handler */
+ .endm
+
+ /*
+ * Performance Note: Instructions will be moved up into
+ * this part of the code later on, once we are sure
+ * that the tlb miss handlers are close to final form.
+ */
+
+ /* Register definitions for tlb miss handler macros */
+
+ va = r8 /* virtual address for which the trap occured */
+ spc = r24 /* space for which the trap occured */
+
+#ifndef __LP64__
+
+ /*
+ * itlb miss interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro itlb_11 code
+
+ mfctl %pcsq, spc
+ b itlb_miss_11
+ mfctl %pcoq, va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * itlb miss interruption handler (parisc 2.0)
+ */
+
+ .macro itlb_20 code
+
+ mfctl %pcsq, spc
+#ifdef __LP64__
+ b itlb_miss_20w
+#else
+ b itlb_miss_20
+#endif
+ mfctl %pcoq, va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * naitlb miss interruption handler (parisc 1.1 - 32 bit)
+ *
+ * Note: naitlb misses will be treated
+ * as an ordinary itlb miss for now.
+ * However, note that naitlb misses
+ * have the faulting address in the
+ * IOR/ISR.
+ */
+
+ .macro naitlb_11 code
+
+ mfctl %isr,spc
+ b itlb_miss_11
+ mfctl %ior,va
+ /* FIXME: If user causes a naitlb miss, the priv level may not be in
+ * lower bits of va, where the itlb miss handler is expecting them
+ */
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * naitlb miss interruption handler (parisc 2.0)
+ *
+ * Note: naitlb misses will be treated
+ * as an ordinary itlb miss for now.
+ * However, note that naitlb misses
+ * have the faulting address in the
+ * IOR/ISR.
+ */
+
+ .macro naitlb_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b itlb_miss_20w
+#else
+ b itlb_miss_20
+#endif
+ mfctl %ior,va
+ /* FIXME: If user causes a naitlb miss, the priv level may not be in
+ * lower bits of va, where the itlb miss handler is expecting them
+ */
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * dtlb miss interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro dtlb_11 code
+
+ mfctl %isr, spc
+ b dtlb_miss_11
+ mfctl %ior, va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * dtlb miss interruption handler (parisc 2.0)
+ */
+
+ .macro dtlb_20 code
+
+ mfctl %isr, spc
+#ifdef __LP64__
+ b dtlb_miss_20w
+#else
+ b dtlb_miss_20
+#endif
+ mfctl %ior, va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /* nadtlb miss interruption handler (parisc 1.1 - 32 bit)
+ *
+ * Note: nadtlb misses will be treated
+ * as an ordinary dtlb miss for now.
+ *
+ */
+
+ .macro nadtlb_11 code
+
+ mfctl %isr,spc
+ b dtlb_miss_11
+ mfctl %ior,va
+
+ .align 32
+ .endm
+#endif
+
+ /* nadtlb miss interruption handler (parisc 2.0)
+ *
+ * Note: nadtlb misses will be treated
+ * as an ordinary dtlb miss for now.
+ *
+ */
+
+ .macro nadtlb_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b dtlb_miss_20w
+#else
+ b dtlb_miss_20
+#endif
+ mfctl %ior,va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * dirty bit trap interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro dbit_11 code
+
+ mfctl %isr,spc
+ b dbit_trap_11
+ mfctl %ior,va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * dirty bit trap interruption handler (parisc 2.0)
+ */
+
+ .macro dbit_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b dbit_trap_20w
+#else
+ b dbit_trap_20
+#endif
+ mfctl %ior,va
+
+ .align 32
+ .endm
+
+ /*
+ * Align fault_vector_20 on 4K boundary so that both
+ * fault_vector_11 and fault_vector_20 are on the
+ * same page. This is only necessary as long as we
+ * write protect the kernel text, which we may stop
+ * doing once we use large parge translations to cover
+ * the static part of the kernel address space.
+ */
+
+
+ .export fault_vector_20
+
+ .align 4096
+
+fault_vector_20:
+ /* First vector is invalid (0) */
+ .ascii "cows can fly"
+ .byte 0
+ .align 32
+
+ hpmc 1
+ def 2
+ def 3
+ extint 4
+ def 5
+ itlb_20 6
+ def 7
+ def 8
+ def 9
+ def 10
+ def 11
+ def 12
+ def 13
+ def 14
+ dtlb_20 15
+ naitlb_20 16
+ nadtlb_20 17
+ def 18
+ def 19
+ dbit_20 20
+ def 21
+ def 22
+ def 23
+ def 24
+ def 25
+ def 26
+ def 27
+ def 28
+ def 29
+ def 30
+ def 31
+
+#ifndef __LP64__
+
+ .export fault_vector_11
+
+ .align 2048
+
+fault_vector_11:
+ /* First vector is invalid (0) */
+ .ascii "cows can fly"
+ .byte 0
+ .align 32
+
+ hpmc 1
+ def 2
+ def 3
+ extint 4
+ def 5
+ itlb_11 6
+ def 7
+ def 8
+ def 9
+ def 10
+ def 11
+ def 12
+ def 13
+ def 14
+ dtlb_11 15
+ naitlb_11 16
+ nadtlb_11 17
+ def 18
+ def 19
+ dbit_11 20
+ def 21
+ def 22
+ def 23
+ def 24
+ def 25
+ def 26
+ def 27
+ def 28
+ def 29
+ def 30
+ def 31
+
+#endif
+
+ .import handle_interruption,code
+ .import handle_real_interruption,code
+ .import do_irq_mask,code
+ .import parisc_stopkernel,code
+ .import cpu_irq_region,data
+
+ /*
+ * r26 = function to be called
+ * r25 = argument to pass in
+ * r24 = flags for do_fork()
+ *
+ * Kernel threads don't ever return, so they don't need
+ * a true register context. We just save away the arguments
+ * for copy_thread/ret_ to properly set up the child.
+ */
+
+#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
+
+ .export __kernel_thread, code
+ .import do_fork
+__kernel_thread:
+ STREG %r2, -RP_OFFSET(%r30)
+
+ copy %r30, %r1
+ ldo PT_SZ_ALGN(%r30),%r30
+#ifdef __LP64__
+ /* Yo, function pointers in wide mode are little structs... -PB */
+ /* XXX FIXME do we need to honor the fptr's %dp value too? */
+ ldd 16(%r26), %r26
+#endif
+ STREG %r26, PT_GR26(%r1) /* Store function & argument for child */
+ STREG %r25, PT_GR25(%r1)
+ ldo CLONE_VM(%r0), %r26 /* Force CLONE_VM since only init_mm */
+ or %r26, %r24, %r26 /* will have kernel mappings. */
+ copy %r0, %r25
+ bl do_fork, %r2
+ copy %r1, %r24
+
+ /* Parent Returns here */
+
+ ldo -PT_SZ_ALGN(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ nop
+
+ /*
+ * Child Returns here
+ *
+ * copy_thread moved args from temp save area set up above
+ * into task save area.
+ */
+
+ .export ret_from_kernel_thread
+ret_from_kernel_thread:
+
+ LDREG TASK_PT_GR26-TASK_SZ_ALGN(%r30), %r1
+ LDREG TASK_PT_GR25-TASK_SZ_ALGN(%r30), %r26
+ ble 0(%sr7, %r1)
+ copy %r31, %r2
+
+ b sys_exit
+ ldi 0, %r26
+
+ .import sys_execve, code
+ .export __execve, code
+__execve:
+ copy %r2, %r15
+ copy %r23, %r17
+ copy %r30, %r16
+ ldo PT_SZ_ALGN(%r30), %r30
+ STREG %r26, PT_GR26(%r16)
+ STREG %r25, PT_GR25(%r16)
+ STREG %r24, PT_GR24(%r16)
+ bl sys_execve, %r2
+ copy %r16, %r26
+
+ comib,<>,n 0,%r28,__execve_failed
+
+ b intr_return
+ STREG %r17, PT_CR30(%r16)
+
+__execve_failed:
+ /* yes, this will trap and die. */
+ copy %r15, %r2
+ bv %r0(%r2)
+ nop
+
+ .align 4
+
+ /*
+ * struct task_struct *_switch_to(struct task_struct *prev,
+ * struct task_struct *next)
+ *
+ * switch kernel stacks and return prev */
+ .export _switch_to, code
+_switch_to:
+ STREG %r2, -RP_OFFSET(%r30)
+
+ callee_save
+
+ ldil L%_switch_to_ret, %r2
+ ldo R%_switch_to_ret(%r2), %r2
+ LDIL_FIXUP(%r2)
+
+ STREG %r2, TASK_PT_KPC(%r26)
+ LDREG TASK_PT_KPC(%r25), %r2
+
+ STREG %r30, TASK_PT_KSP(%r26)
+ LDREG TASK_PT_KSP(%r25), %r30
+
+ bv %r0(%r2)
+ nop
+
+_switch_to_ret:
+ mtctl %r0, %cr0 /* Needed for single stepping */
+ callee_rest
+
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ copy %r26, %r28
+
+ /*
+ * Common rfi return path for interruptions, kernel execve, and some
+ * syscalls. The sys_rt_sigreturn syscall will return via this path
+ * if the signal was received when the process was running; if the
+ * process was blocked on a syscall then the normal syscall_exit
+ * path is used. All syscalls for traced proceses exit via
+ * intr_restore.
+ * Note that the following code uses a "relied upon translation". See
+ * the parisc ACD for details. The ssm is necessary due to a PCXT bug.
+ */
+
+ .align 4096
+
+ .export syscall_exit_rfi
+syscall_exit_rfi:
+ copy %r30,%r16
+ /* FIXME! depi below has hardcoded dependency on kernel stack size */
+ depi 0,31,14,%r16 /* get task pointer */
+ ldo TASK_REGS(%r16),%r16
+ /* Force iaoq to userspace, as the user has had access to our current
+ * context via sigcontext.
+ * XXX do we need any other protection here?
+ */
+ LDREG PT_IAOQ0(%r16),%r19
+ depi 3,31,2,%r19
+ STREG %r19,PT_IAOQ0(%r16)
+ LDREG PT_IAOQ1(%r16),%r19
+ depi 3,31,2,%r19
+ STREG %r19,PT_IAOQ1(%r16)
+
+intr_return:
+
+ /* Check for software interrupts */
+
+ .import irq_stat,data
+
+ ldil L%irq_stat,%r19
+ ldo R%irq_stat(%r19),%r19
+ LDIL_FIXUP(%r19)
+
+#ifdef CONFIG_SMP
+ copy %r30,%r1
+ /* FIXME! depi below has hardcoded dependency on kernel stack size */
+ depi 0,31,14,%r1 /* get task pointer */
+ ldw TASK_PROCESSOR(%r1),%r20 /* get cpu # - int */
+#if (IRQSTAT_SZ == 32)
+ dep %r20,26,27,%r20 /* shift left 5 bits */
+#else
+#error IRQSTAT_SZ changed, fix dep
+#endif /* IRQSTAT_SZ */
+ add %r19,%r20,%r19
+#endif /* CONFIG_SMP */
+
+ ldw IRQSTAT_SI_ACTIVE(%r19),%r20 /* hardirq.h: unsigned int */
+ ldw IRQSTAT_SI_MASK(%r19),%r19 /* hardirq.h: unsigned int */
+ and %r19,%r20,%r20
+ comib,<>,n 0,%r20,intr_do_softirq /* forward */
+
+intr_check_resched:
+
+ /* check for reschedule */
+ copy %r30,%r1
+ /* FIXME! depi below has hardcoded dependency on kernel stack size */
+ depi 0,31,14,%r1 /* get task pointer */
+ LDREG TASK_NEED_RESCHED(%r1),%r19 /* sched.h: long need_resched */
+ comib,<>,n 0,%r19,intr_do_resched /* forward */
+
+intr_check_sig:
+ /* As above */
+ copy %r30,%r1
+ depi 0,31,14,%r1 /* get task pointer */
+ ldw TASK_SIGPENDING(%r1),%r19 /* sched.h: int sigpending */
+ comib,<>,n 0,%r19,intr_do_signal /* forward */
+
+intr_restore:
+ copy %r16, %r29
+ ldo PT_FR31(%r29), %r29
+ rest_fp %r29
+ copy %r16, %r29
+ rest_general %r29
+ ssm 0,%r0
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ tophys %r29
+ mtsm %r0
+ rest_specials %r29
+ rest_stack %r29
+ rfi
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ .import do_softirq,code
+intr_do_softirq:
+ bl do_softirq,%r2
+ nop
+ b intr_check_resched
+ nop
+
+ .import schedule,code
+intr_do_resched:
+ /* Only do reschedule if we are returning to user space */
+ LDREG PT_SR7(%r16), %r20
+ comib,= 0,%r20,intr_restore /* backward */
+ nop
+
+ bl schedule,%r2
+ ssm PSW_SM_I, %r0
+
+ /* It's OK to leave I bit on */
+ b intr_return /* start over if we got a resched */
+ nop
+
+ .import do_signal,code
+intr_do_signal:
+ /* Only do signals if we are returning to user space */
+ LDREG PT_SR7(%r16), %r20
+ comib,= 0,%r20,intr_restore /* backward */
+ nop
+
+ copy %r0, %r24 /* unsigned long in_syscall */
+ copy %r16, %r25 /* struct pt_regs *regs */
+ ssm PSW_SM_I, %r0
+ bl do_signal,%r2
+ copy %r0, %r26 /* sigset_t *oldset = NULL */
+
+ b intr_restore
+ nop
+
+ /* CR28 - saved GR1
+ * CR29 - argument for do_irq_mask */
+
+ /* External interrupts */
+intr_extint:
+ get_stack
+ save_specials %r29
+ virt_map rfi
+ save_general %r29
+
+ ldo PT_FR0(%r29), %r24
+ save_fp %r24
+
+ loadgp
+
+ copy %r29, %r24 /* arg2 is pt_regs */
+ copy %r29, %r16 /* save pt_regs */
+#ifdef CONFIG_KWDB
+ copy %r29, %r3 /* KWDB - update frame pointer (gr3) */
+#endif
+
+ /* sorry to put this cruft in the interrupt path */
+ ldil L%cpu_irq_region, %r25
+ ldo R%cpu_irq_region(%r25), %r25
+ bl do_irq_mask,%r2
+#ifdef __LP64__
+ LDIL_FIXUP(%r25)
+#else
+ nop
+#endif
+
+ b intr_return
+ nop
+
+ /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
+
+ .export intr_save, code /* for os_hpmc */
+
+intr_save:
+ get_stack
+ save_specials %r29
+
+ mfctl %cr20, %r1
+ STREG %r1, PT_ISR(%r29)
+ mfctl %cr21, %r1
+ STREG %r1, PT_IOR(%r29)
+
+ virt_map rfi
+ save_general %r29
+
+ ldo PT_FR0(%r29), %r25
+ save_fp %r25
+
+ loadgp
+
+ copy %r29, %r25 /* arg1 is pt_regs */
+#ifdef CONFIG_KWDB
+ copy %r29, %r3 /* KWDB - update frame pointer (gr3) */
+#endif
+
+ bl handle_interruption,%r2
+ copy %r29, %r16 /* save pt_regs */
+
+ b intr_return
+ nop
+
+ /*
+ * Note for all tlb miss handlers:
+ *
+ * cr24 contains a pointer to the kernel address space
+ * page directory.
+ *
+ * cr25 contains a pointer to the current user address
+ * space page directory.
+ *
+ * sr3 will contain the space id of the user address space
+ * of the current running thread while that thread is
+ * running in the kernel.
+ */
+
+ /*
+ * register number allocations. Note that these are all
+ * in the shadowed registers
+ */
+
+ t0 = r1 /* temporary register 0 */
+ va = r8 /* virtual address for which the trap occured */
+ t1 = r9 /* temporary register 1 */
+ pte = r16 /* pte/phys page # */
+ prot = r17 /* prot bits */
+ spc = r24 /* space for which the trap occured */
+ ptp = r25 /* page directory/page table pointer */
+
+#ifdef __LP64__
+
+dtlb_miss_20w:
+
+ extrd,u spc,31,7,t1 /* adjust va */
+ depd t1,31,7,va /* adjust va */
+ depdi 0,31,7,spc /* adjust space */
+ mfctl %cr25,ptp /* Assume user space miss */
+ or,*<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extrd,u va,33,9,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,*= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dtlb_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldd,s t1(ptp),ptp
+ extrd,u va,42,9,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ ldd,s t0(ptp),ptp
+ extrd,u va,51,9,t0 /* get third-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Third level page table lookup */
+
+ shladd t0,3,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldd 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,*<> t1,pte,%r0 /* test and nullify if already set */
+ std t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,32,pte
+ idtlbt %r16,%r17
+
+ rfir
+ nop
+#else
+
+dtlb_miss_11:
+ mfctl %cr25,ptp /* Assume user space miss */
+ or,<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dtlb_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,<> t1,pte,%r0 /* test and nullify if already set */
+ stw t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+ dep pte,8,7,prot
+
+ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0
+ depi 1,12,1,prot
+ extru,= pte,_PAGE_USER_BIT,1,r0
+ depi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extru,= pte,_PAGE_GATEWAY_BIT,1,r0
+ depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlba */
+
+ depi 0,31,12,pte
+ extru pte,24,25,pte
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ idtlba pte,(%sr1,va)
+ idtlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+dtlb_miss_20:
+ .level 2.0
+
+ mfctl %cr25,ptp /* Assume user space miss */
+ or,<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dtlb_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,<> t1,pte,%r0 /* test and nullify if already set */
+ stw t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,25,pte
+ idtlbt %r16,%r17
+
+ .level 1.1
+
+ rfir
+ nop
+#endif
+
+#ifdef __LP64__
+itlb_miss_20w:
+
+ /*
+ * I miss is a little different, since we allow users to fault
+ * on the gateway page which is in the kernel address space.
+ */
+
+ extrd,u spc,31,7,t1 /* adjust va */
+ depd t1,31,7,va /* adjust va */
+ depdi 0,31,7,spc /* adjust space */
+ cmpib,*= 0,spc,itlb_miss_kernel_20w
+ extrd,u va,33,9,t1 /* Get pgd index */
+
+ mfctl %cr25,ptp /* load user pgd */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,*= %r0,t0,%r0 /* If kernel, nullify following test */
+ cmpb,*<>,n t0,spc,itlb_fault /* forward */
+
+ /* First level page table lookup */
+
+itlb_miss_common_20w:
+ ldd,s t1(ptp),ptp
+ extrd,u va,42,9,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ ldd,s t0(ptp),ptp
+ extrd,u va,51,9,t0 /* get third-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Third level page table lookup */
+
+ shladd t0,3,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldd 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,*<> t1,pte,%r0 /* test and nullify if already set */
+ std t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for iitlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,32,pte
+ iitlbt %r16,%r17
+
+ rfir
+ nop
+
+itlb_miss_kernel_20w:
+ b itlb_miss_common_20w
+ mfctl %cr24,ptp /* Load kernel pgd */
+#else
+
+itlb_miss_11:
+
+ /*
+ * I miss is a little different, since we allow users to fault
+ * on the gateway page which is in the kernel address space.
+ */
+
+ comib,= 0,spc,itlb_miss_kernel_11
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfctl %cr25,ptp /* load user pgd */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,itlb_fault /* forward */
+
+ /* First level page table lookup */
+
+itlb_miss_common_11:
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,<> t1,pte,%r0 /* test and nullify if already set */
+ stw t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+ dep pte,8,7,prot
+
+ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0
+ depi 1,12,1,prot
+ extru,= pte,_PAGE_USER_BIT,1,r0
+ depi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extru,= pte,_PAGE_GATEWAY_BIT,1,r0
+ depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for iitlba */
+
+ depi 0,31,12,pte
+ extru pte,24,25,pte
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ iitlba pte,(%sr1,va)
+ iitlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+itlb_miss_kernel_11:
+ b itlb_miss_common_11
+ mfctl %cr24,ptp /* Load kernel pgd */
+
+itlb_miss_20:
+
+ /*
+ * I miss is a little different, since we allow users to fault
+ * on the gateway page which is in the kernel address space.
+ */
+
+ comib,= 0,spc,itlb_miss_kernel_20
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfctl %cr25,ptp /* load user pgd */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,itlb_fault /* forward */
+
+ /* First level page table lookup */
+
+itlb_miss_common_20:
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,<> t1,pte,%r0 /* test and nullify if already set */
+ stw t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ .level 2.0
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for iitlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,25,pte
+ iitlbt %r16,%r17
+ .level 1.1
+
+ rfir
+ nop
+
+
+itlb_miss_kernel_20:
+ b itlb_miss_common_20
+ mfctl %cr24,ptp /* Load kernel pgd */
+#endif
+
+#ifdef __LP64__
+
+dbit_trap_20w:
+
+ extrd,u spc,31,7,t1 /* adjust va */
+ depd t1,31,7,va /* adjust va */
+ depdi 0,1,2,va /* adjust va */
+ depdi 0,31,7,spc /* adjust space */
+ mfctl %cr25,ptp /* Assume user space miss */
+ or,*<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extrd,u va,33,9,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,*= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dbit_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldd,s t1(ptp),ptp
+ extrd,u va,42,9,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ ldd,s t0(ptp),ptp
+ extrd,u va,51,9,t0 /* get third-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Third level page table lookup */
+
+ shladd t0,3,ptp,ptp
+ ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1
+ ldd 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault
+
+ /* Set Accessed and Dirty bits in the pte */
+
+ or t1,pte,pte
+ std pte,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,32,pte
+ idtlbt %r16,%r17
+
+ rfir
+ nop
+#else
+
+dbit_trap_11:
+ mfctl %cr25,ptp /* Assume user space trap */
+ or,<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dbit_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault
+
+ /* Set Accessed and Dirty bits in the pte */
+
+ or t1,pte,pte
+ stw pte,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+ dep pte,8,7,prot
+
+ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0
+ depi 1,12,1,prot
+ extru,= pte,_PAGE_USER_BIT,1,r0
+ depi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extru,= pte,_PAGE_GATEWAY_BIT,1,r0
+ depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlba */
+
+ depi 0,31,12,pte
+ extru pte,24,25,pte
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ idtlba pte,(%sr1,va)
+ idtlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+dbit_trap_20:
+ mfctl %cr25,ptp /* Assume user space trap */
+ or,<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dbit_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault
+
+ /* Set Accessed and Dirty bits in the pte */
+
+ or t1,pte,pte
+ stw pte,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ .level 2.0
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,25,pte
+ idtlbt %r16,%r17
+
+ .level 1.1
+
+ rfir
+ nop
+#endif
+
+ .import handle_interruption,code
+
+kernel_bad_space:
+ b tlb_fault
+ ldi 31,%r1 /* Use an unused code */
+
+dbit_fault:
+ b tlb_fault
+ ldi 20,%r1
+
+itlb_fault:
+ b tlb_fault
+ ldi 6,%r1
+
+dtlb_fault:
+ ldi 15,%r1
+
+ /* Fall Through */
+
+tlb_fault:
+ mtctl %r1,%cr29
+ mtctl %r29,%cr31
+
+ get_stack
+ save_specials %r29 /* Note this saves a trashed r1 */
+
+ SAVE_CR (%cr20, PT_ISR(%r29))
+ SAVE_CR (%cr21, PT_IOR(%r29))
+
+ virt_map rfir
+
+ STREG %r1,PT_GR1(%r29) /* save good value after rfir */
+
+ save_general %r29
+
+ ldo PT_FR0(%r29), %r25
+ save_fp %r25
+
+ loadgp
+
+ copy %r29, %r25
+
+ bl handle_interruption, %r2
+ copy %r29, %r16
+
+ b intr_return
+ nop
+
+ /* Register saving semantics for system calls:
+
+ %r1 clobbered by system call macro in userspace
+ %r2 saved in PT_REGS by gateway page
+ %r3 - %r18 preserved by C code (saved by signal code)
+ %r19 - %r20 saved in PT_REGS by gateway page
+ %r21 - %r22 non-standard syscall args
+ stored in kernel stack by gateway page
+ %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page
+ %r27 - %r30 saved in PT_REGS by gateway page
+ %r31 syscall return pointer
+ */
+
+ /* Floating point registers (FIXME: what do we do with these?)
+
+ %fr0 - %fr3 status/exception, not preserved
+ %fr4 - %fr7 arguments
+ %fr8 - %fr11 not preserved by C code
+ %fr12 - %fr21 preserved by C code
+ %fr22 - %fr31 not preserved by C code
+ */
+
+ .macro reg_save regs
+ STREG %r3, PT_GR3(\regs)
+ STREG %r4, PT_GR4(\regs)
+ STREG %r5, PT_GR5(\regs)
+ STREG %r6, PT_GR6(\regs)
+ STREG %r7, PT_GR7(\regs)
+ STREG %r8, PT_GR8(\regs)
+ STREG %r9, PT_GR9(\regs)
+ STREG %r10,PT_GR10(\regs)
+ STREG %r11,PT_GR11(\regs)
+ STREG %r12,PT_GR12(\regs)
+ STREG %r13,PT_GR13(\regs)
+ STREG %r14,PT_GR14(\regs)
+ STREG %r15,PT_GR15(\regs)
+ STREG %r16,PT_GR16(\regs)
+ STREG %r17,PT_GR17(\regs)
+ STREG %r18,PT_GR18(\regs)
+ .endm
+
+ .macro reg_restore regs
+ LDREG PT_GR3(\regs), %r3
+ LDREG PT_GR4(\regs), %r4
+ LDREG PT_GR5(\regs), %r5
+ LDREG PT_GR6(\regs), %r6
+ LDREG PT_GR7(\regs), %r7
+ LDREG PT_GR8(\regs), %r8
+ LDREG PT_GR9(\regs), %r9
+ LDREG PT_GR10(\regs),%r10
+ LDREG PT_GR11(\regs),%r11
+ LDREG PT_GR12(\regs),%r12
+ LDREG PT_GR13(\regs),%r13
+ LDREG PT_GR14(\regs),%r14
+ LDREG PT_GR15(\regs),%r15
+ LDREG PT_GR16(\regs),%r16
+ LDREG PT_GR17(\regs),%r17
+ LDREG PT_GR18(\regs),%r18
+ .endm
+
+ .export sys_fork_wrapper
+sys_fork_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+ reg_save %r1
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+
+ /* These are call-clobbered registers and therefore
+ also syscall-clobbered (we hope). */
+ STREG %r2,PT_GR19(%r1) /* save for child */
+ STREG %r30,PT_GR20(%r1)
+ ldil L%child_return, %r3
+ ldo R%child_return(%r3), %r3
+ LDIL_FIXUP(%r3)
+ STREG %r3,PT_GR21(%r1) /* save for child */
+
+ LDREG PT_GR30(%r1),%r25
+ copy %r1,%r24
+ bl sys_clone,%r2
+ ldi SIGCHLD,%r26
+
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+wrapper_exit:
+ ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+
+ reg_restore %r1
+
+ bv %r0(%r2)
+ nop
+
+ /* Set the return value for the child */
+child_return:
+ LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
+ b wrapper_exit
+ copy %r0,%r28
+
+
+ .export sys_clone_wrapper
+sys_clone_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+ reg_save %r1
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+
+ STREG %r30,PT_GR20(%r1)
+ ldil L%child_return,%r3
+ ldo R%child_return(%r3),%r3
+ LDIL_FIXUP(%r3)
+
+ bl sys_clone,%r2
+ STREG %r3,PT_GR21(%r1) /* save for child */
+
+ b wrapper_exit
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+
+
+ .export sys_vfork_wrapper
+sys_vfork_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+ reg_save %r1
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+
+ STREG %r30,PT_GR20(%r1)
+ ldil L%child_return,%r3
+ ldo R%child_return(%r3),%r3
+ LDIL_FIXUP(%r3)
+ STREG %r3,PT_GR21(%r1) /* save for child */
+
+ bl sys_vfork,%r2
+ copy %r1,%r26
+
+ b wrapper_exit
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+
+
+ .macro execve_wrapper execve
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+
+ /*
+ * Do we need to save/restore r3-r18 here?
+ * I don't think so. why would new thread need old
+ * threads registers?
+ */
+
+ /* %arg0 - %arg3 are already saved for us. */
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+ bl \execve,%r2
+ copy %r1,%arg0
+
+ ldo -FRAME_SIZE(%r30),%r30
+ LDREG -RP_OFFSET(%r30),%r2
+
+ /* If exec succeeded we need to load the args */
+
+ ldo -1024(%r0),%r1
+ comb,>>= %r28,%r1,error_\execve
+ copy %r2,%r19
+
+error_\execve:
+ bv %r0(%r19)
+ nop
+ .endm
+
+ .export sys_execve_wrapper
+ .import sys_execve
+
+sys_execve_wrapper:
+ execve_wrapper sys_execve
+
+#ifdef __LP64__
+ .export sys32_execve_wrapper
+ .import sys32_execve
+
+sys32_execve_wrapper:
+ execve_wrapper sys32_execve
+#endif
+
+ .export sys_rt_sigreturn_wrapper
+sys_rt_sigreturn_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r26
+ /* Don't save regs, we are going to restore them from sigcontext. */
+ STREG %r2, -RP_OFFSET(%r30)
+ bl sys_rt_sigreturn,%r2
+ ldo FRAME_SIZE(%r30), %r30
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+
+ /* FIXME: I think we need to restore a few more things here. */
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+ reg_restore %r1
+
+ /* If the signal was received while the process was blocked on a
+ * syscall, then r2 will take us to syscall_exit; otherwise r2 will
+ * take us to syscall_exit_rfi and on to intr_return.
+ */
+ bv %r0(%r2)
+ LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
+
+ .export sys_sigaltstack_wrapper
+sys_sigaltstack_wrapper:
+ /* Get the user stack pointer */
+ LDREG -TASK_SZ_ALGN-FRAME_SIZE+TASK_PT_GR30(%r30), %r24
+ STREG %r2, -RP_OFFSET(%r30)
+ bl do_sigaltstack,%r2
+ ldo FRAME_SIZE(%r30), %r30
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ nop
+
+ .export sys_rt_sigsuspend_wrapper
+sys_rt_sigsuspend_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r24
+ reg_save %r24
+
+ STREG %r2, -RP_OFFSET(%r30)
+ bl sys_rt_sigsuspend,%r2
+ ldo FRAME_SIZE(%r30), %r30
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ reg_restore %r1
+
+ bv %r0(%r2)
+ nop
+
+ .export syscall_exit
+syscall_exit:
+ /* NOTE: HP-UX syscalls also come through here
+ after hpux_syscall_exit fixes up return
+ values. */
+ /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
+ * via syscall_exit_rfi if the signal was received while the process
+ * was running. All traced processes will probably exit via
+ * syscall_exit_rfi in the future.
+ */
+
+ /* save return value now */
+
+ STREG %r28,TASK_PT_GR28-TASK_SZ_ALGN-FRAME_SIZE(%r30)
+
+syscall_check_bh:
+
+/* #ifdef NOTNOW */
+ /* Check for software interrupts */
+
+ .import irq_stat,data
+
+ ldil L%irq_stat,%r19
+ ldo R%irq_stat(%r19),%r19
+ LDIL_FIXUP(%r19)
+
+#ifdef CONFIG_SMP
+ /* sched.h: int processor */
+ ldw TASK_PROCESSOR-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r20 /* get cpu # */
+#if (IRQSTAT_SZ == 32)
+ dep %r20,26,27,%r20 /* shift left 5 bits */
+#else
+#error IRQSTAT_SZ changed, fix dep
+#endif /* IRQSTAT_SZ */
+ add %r19,%r20,%r19
+#endif /* CONFIG_SMP */
+
+ ldw IRQSTAT_SI_ACTIVE(%r19),%r20 /* hardirq.h: unsigned int */
+ ldw IRQSTAT_SI_MASK(%r19),%r19 /* hardirq.h: unsigned int */
+ and %r19,%r20,%r20
+ comib,<>,n 0,%r20,syscall_do_softirq /* forward */
+/* #endif */
+
+
+syscall_check_resched:
+
+ /* check for reschedule */
+
+ LDREG TASK_NEED_RESCHED-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */
+ comib,<>,n 0,%r19,syscall_do_resched /* forward */
+
+syscall_check_sig:
+ ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
+ /* check for pending signals */
+ ldw TASK_SIGPENDING(%r1),%r19
+ comib,<>,n 0,%r19,syscall_do_signal /* forward */
+
+syscall_restore:
+ /* disable interrupts while dicking with the kernel stack, */
+ /* or life can become unpleasant */
+ rsm PSW_SM_I, %r20
+ LDREG TASK_PTRACE(%r1), %r19 /* Are we being ptraced? */
+ bb,<,n %r19,31,syscall_restore_rfi
+ LDREG TASK_PT_GR20(%r1),%r19
+ mtctl %r19, %cr27
+
+ LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */
+ LDREG TASK_PT_GR21(%r1),%r21
+ LDREG TASK_PT_GR22(%r1),%r22
+ LDREG TASK_PT_GR23(%r1),%r23
+ LDREG TASK_PT_GR24(%r1),%r24
+ LDREG TASK_PT_GR25(%r1),%r25
+ LDREG TASK_PT_GR26(%r1),%r26
+ LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */
+ LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */
+ LDREG TASK_PT_GR29(%r1),%r29
+ LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */
+ LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */
+ ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */
+ rest_fp %r19
+ LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */
+ mtsar %r19
+ LDREG TASK_PT_GR19(%r1),%r19
+
+ mtctl %r1,%cr30 /* intrhandler okay. */
+ mfsp %sr3,%r1 /* Get users space id */
+ mtsp %r1,%sr4 /* Restore sr4 */
+ mtsp %r1,%sr5 /* Restore sr5 */
+ mtsp %r1,%sr6 /* Restore sr6 */
+
+ depi 3,31,2,%r31 /* ensure return to user mode. */
+
+ mtsm %r20 /* restore irq state */
+ mfctl %cr27,%r20
+
+ /*
+ * Due to a dependency in the tlb miss handlers on sr7, it
+ * is essential that sr7 get set in the delay slot.
+ */
+
+#ifdef __LP64__
+
+ /* Note the be (and mtsp) is executed in narrow mode. This is OK
+ * for 32 bit processes, but won't work once we support 64 bit
+ * processes.
+ */
+
+ rsm PSW_SM_W, %r0
+ be 0(%sr3,%r31) /* return to user space */
+ mtsp %r1,%sr7 /* Restore sr7 */
+#else
+ be 0(%sr3,%r31) /* return to user space */
+ mtsp %r1,%sr7 /* Restore sr7 */
+#endif
+
+ /* We have to return via an RFI, so that PSW T and R bits can be set
+ * appropriately.
+ * This sets up pt_regs so we can return via intr_restore, which is not
+ * the most efficient way of doing things, but it works.
+ */
+syscall_restore_rfi:
+ ldo -1(%r0),%r2 /* Set recovery cntr to -1 */
+ mtctl %r2,%cr0 /* for immediate trap */
+ copy %r0,%r2 /* Create a reasonable PSW */
+ /* XXX W bit??? */
+ depi -1,13,1,%r2
+ depi -1,28,1,%r2
+ depi -1,30,1,%r2
+ depi -1,31,1,%r2
+ bb,<,n %r19,15,set_rbit /* PT_SINGLESTEP */
+ bb,>=,n %r19,14,set_nobit /* PT_BLOCKSTEP, see ptrace.c */
+set_tbit:
+ depi -1,7,1,%r2
+ b,n set_nobit
+set_rbit:
+ depi -1,27,1,%r2
+set_nobit:
+ STREG %r2,TASK_PT_PSW(%r1)
+ STREG %r1,TASK_PT_CR30(%r1)
+ mfsp %sr0,%r2
+ STREG %r2,TASK_PT_SR0(%r1)
+ mfsp %sr1,%r2
+ STREG %r2,TASK_PT_SR1(%r1)
+ mfsp %sr2,%r2
+ STREG %r2,TASK_PT_SR2(%r1)
+ mfsp %sr3,%r2
+ STREG %r2,TASK_PT_SR3(%r1)
+ STREG %r2,TASK_PT_SR4(%r1)
+ STREG %r2,TASK_PT_SR5(%r1)
+ STREG %r2,TASK_PT_SR6(%r1)
+ STREG %r2,TASK_PT_SR7(%r1)
+ STREG %r2,TASK_PT_IASQ0(%r1)
+ STREG %r2,TASK_PT_IASQ1(%r1)
+ LDREG TASK_PT_GR31(%r1),%r2
+ depi 3,31,2,%r2 /* ensure return to user mode. */
+ STREG %r2,TASK_PT_IAOQ0(%r1)
+ ldo 4(%r2),%r2
+ STREG %r2,TASK_PT_IAOQ1(%r1)
+ ldo TASK_REGS(%r1),%r25
+ reg_save %r25 /* Save r3 to r18 */
+ copy %r25,%r16
+ b intr_restore
+ nop
+
+ .import do_softirq,code
+syscall_do_softirq:
+ bl do_softirq,%r2
+ nop
+ b syscall_check_resched
+ ssm PSW_SM_I, %r0 /* do_softirq returns with I bit off */
+
+ .import schedule,code
+syscall_do_resched:
+ bl schedule,%r2
+ nop
+ b syscall_check_bh /* if resched, we start over again */
+ nop
+
+ .import do_signal,code
+syscall_do_signal:
+ /* Save callee-save registers (for sigcontext).
+ FIXME: After this point the process structure should be
+ consistent with all the relevant state of the process
+ before the syscall. We need to verify this. */
+ ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */
+ reg_save %r25
+
+ ldi 1, %r24 /* unsigned long in_syscall */
+
+ bl do_signal,%r2
+ copy %r0, %r26 /* sigset_t *oldset = NULL */
+
+ ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30), %r1 /* reload task ptr */
+ ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
+ reg_restore %r20
+
+ b,n syscall_restore
+
+#ifdef __LP64__
+unimplemented_64bitirq:
+ ssm PSW_SM_Q+PSW_SM_I, %r0
+ /* indicate that we had an interrupt */
+ ldi 0x77, %r28
+ ldi 0x77, %r29
+ /* save interrupt registers in GRs for diagnosis */
+ mfctl %cr17, %r17
+ mfctl %cr18, %r18
+ mfctl %cr19, %r19
+ mfctl %cr20, %r20
+ mfctl %cr21, %r21
+ mfctl %cr22, %r22
+ b,n .
+ nop
+#endif
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
new file mode 100644
index 000000000..75d5c6695
--- /dev/null
+++ b/arch/parisc/kernel/hardware.c
@@ -0,0 +1,1446 @@
+/*
+ * Hardware descriptions for HP 9000 based hardware, including
+ * system types, SCSI controllers, DMA controllers, HPPB controllers
+ * and lots more.
+ *
+ * Based on the document "PA-RISC 1.1 I/O Firmware Architecture
+ * Reference Specification", March 7, 1999, version 0.96. This
+ * is available at ?.
+ *
+ * Copyright 1999 by Alex deVries <adevries@thepuffingroup.com>
+ * and copyright 1999 The Puffin Group Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * 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 <asm/hardware.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+
+#define HPHW_NUM_TYPES 3431
+
+static char * hw_type_name[16] = {
+ "Processor",
+ "Memory",
+ "B DMA",
+ "Obsolete",
+ "A DMA",
+ "A Direct",
+ "Obsolete",
+ "Bus Converter Port",
+ "HP CIO Adapter",
+ "Console",
+ "Foreign I/O Module",
+ "Bus Adapter",
+ "IOA (?)",
+ "Bus Bridge to Foreign Bus",
+ "HP Clothing: Fabric Component"
+};
+
+/*
+ * XXX Could this be __init ??
+ */
+
+static struct hp_hardware hp_hardware_list[] = {
+ {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
+ {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
+ {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
+ {HPHW_NPROC,0xB,0x4,0x01,"Technical Shogun (845, 645)"},
+ {HPHW_NPROC,0xF,0x4,0x01,"Commercial Shogun (949)"},
+ {HPHW_NPROC,0xC,0x4,0x01,"Cheetah (850, 950)"},
+ {HPHW_NPROC,0x80,0x4,0x01,"Cheetah (950S)"},
+ {HPHW_NPROC,0x81,0x4,0x01,"Jaguar (855, 955)"},
+ {HPHW_NPROC,0x82,0x4,0x01,"Cougar (860, 960)"},
+ {HPHW_NPROC,0x83,0x4,0x13,"Panther (865, 870, 980)"},
+ {HPHW_NPROC,0x100,0x4,0x01,"Burgundy (810)"},
+ {HPHW_NPROC,0x101,0x4,0x01,"SilverFox Low (822, 922)"},
+ {HPHW_NPROC,0x102,0x4,0x01,"SilverFox High (832, 932)"},
+ {HPHW_NPROC,0x103,0x4,0x01,"Lego, SilverLite (815, 808, 920)"},
+ {HPHW_NPROC,0x104,0x4,0x03,"SilverBullet Low (842, 948)"},
+ {HPHW_NPROC,0x105,0x4,0x03,"SilverBullet High (852, 958)"},
+ {HPHW_NPROC,0x106,0x4,0x81,"Oboe"},
+ {HPHW_NPROC,0x180,0x4,0x12,"Dragon"},
+ {HPHW_NPROC,0x181,0x4,0x13,"Chimera (890, 990, 992)"},
+ {HPHW_NPROC,0x182,0x4,0x91,"TNT 100 (891,T500)"},
+ {HPHW_NPROC,0x183,0x4,0x91,"TNT 120 (892,T520)"},
+ {HPHW_NPROC,0x184,0x4,0x91,"Jade 180 U (893,T540)"},
+ {HPHW_NPROC,0x1FF,0x4,0x91,"Hitachi X Processor"},
+ {HPHW_NPROC,0x200,0x4,0x81,"Cobra (720)"},
+ {HPHW_NPROC,0x201,0x4,0x81,"Coral (750)"},
+ {HPHW_NPROC,0x202,0x4,0x81,"King Cobra (730)"},
+ {HPHW_NPROC,0x203,0x4,0x81,"Hardball (735/99)"},
+ {HPHW_NPROC,0x204,0x4,0x81,"Coral II (755/99)"},
+ {HPHW_NPROC,0x205,0x4,0x81,"Coral II (755/125)"},
+ {HPHW_NPROC,0x205,0x4,0x91,"Snake Eagle "},
+ {HPHW_NPROC,0x206,0x4,0x81,"Snake Cheetah (735/130)"},
+ {HPHW_NPROC,0x280,0x4,0x81,"Nova Low (817, 827, 957, 957LX)"},
+ {HPHW_NPROC,0x281,0x4,0x81,"Nova High (837, 847, 857, 967, 967LX)"},
+ {HPHW_NPROC,0x282,0x4,0x81,"Nova8 (807, 917, 917LX, 927,927LX, 937, 937LX, 947,947LX)"},
+ {HPHW_NPROC,0x283,0x4,0x81,"Nova64 (867, 877, 977)"},
+ {HPHW_NPROC,0x284,0x4,0x81,"TNova (887, 897, 987)"},
+ {HPHW_NPROC,0x285,0x4,0x81,"TNova64"},
+ {HPHW_NPROC,0x286,0x4,0x91,"Hydra64 (Nova)"},
+ {HPHW_NPROC,0x287,0x4,0x91,"Hydra96 (Nova)"},
+ {HPHW_NPROC,0x288,0x4,0x81,"TNova96"},
+ {HPHW_NPROC,0x300,0x4,0x81,"Bushmaster (710)"},
+ {HPHW_NPROC,0x302,0x4,0x81,"Flounder (705)"},
+ {HPHW_NPROC,0x310,0x4,0x81,"Scorpio (715/50)"},
+ {HPHW_NPROC,0x311,0x4,0x81,"Scorpio Jr.(715/33)"},
+ {HPHW_NPROC,0x312,0x4,0x81,"Strider-50 (715S/50)"},
+ {HPHW_NPROC,0x313,0x4,0x81,"Strider-33 (715S/33)"},
+ {HPHW_NPROC,0x314,0x4,0x81,"Trailways-50 (715T/50)"},
+ {HPHW_NPROC,0x315,0x4,0x81,"Trailways-33 (715T/33)"},
+ {HPHW_NPROC,0x316,0x4,0x81,"Scorpio Sr.(715/75)"},
+ {HPHW_NPROC,0x317,0x4,0x81,"Scorpio 100 (715/100)"},
+ {HPHW_NPROC,0x318,0x4,0x81,"Spectra (725/50)"},
+ {HPHW_NPROC,0x319,0x4,0x81,"Spectra (725/75)"},
+ {HPHW_NPROC,0x320,0x4,0x81,"Spectra (725/100)"},
+ {HPHW_NPROC,0x401,0x4,0x81,"Pace (745i, 747i)"},
+ {HPHW_NPROC,0x402,0x4,0x81,"Sidewinder (742i)"},
+ {HPHW_NPROC,0x403,0x4,0x81,"Fast Pace"},
+ {HPHW_NPROC,0x480,0x4,0x81,"Orville (E23)"},
+ {HPHW_NPROC,0x481,0x4,0x81,"Wilbur (E25)"},
+ {HPHW_NPROC,0x482,0x4,0x81,"WB-80 (E35)"},
+ {HPHW_NPROC,0x483,0x4,0x81,"WB-96 (E45)"},
+ {HPHW_NPROC,0x48,0x4,0x81,"UL Proc L-100 (811/D210,D310)"},
+ {HPHW_NPROC,0x48,0x4,0x81,"UL Proc L-75 (801/D200)"},
+ {HPHW_NPROC,0x501,0x4,0x81,"Merlin L2 132 (9000/778/B132L)"},
+ {HPHW_NPROC,0x502,0x4,0x81,"Merlin L2 160 (9000/778/B160L)"},
+ {HPHW_NPROC,0x503,0x4,0x81,"Merlin L2+ 132 (9000/778/B132L)"},
+ {HPHW_NPROC,0x504,0x4,0x81,"Merlin L2+ 180 (9000/778/B180L)"},
+ {HPHW_NPROC,0x505,0x4,0x81,"Raven L2 132 (9000/778/C132L)"},
+ {HPHW_NPROC,0x506,0x4,0x81,"Raven L2 160 (9000/779/C160L)"},
+ {HPHW_NPROC,0x507,0x4,0x81,"Raven L2 180 (9000/779/C180L)"},
+ {HPHW_NPROC,0x508,0x4,0x81,"Raven L2 160 (9000/779/C160L)"},
+ {HPHW_NPROC,0x509,0x4,0x81,"712/132 L2 Upgrade"},
+ {HPHW_NPROC,0x50A,0x4,0x81,"712/160 L2 Upgrade"},
+ {HPHW_NPROC,0x50B,0x4,0x81,"715/132 L2 Upgrade"},
+ {HPHW_NPROC,0x50C,0x4,0x81,"715/160 L2 Upgrade"},
+ {HPHW_NPROC,0x50D,0x4,0x81,"Rocky2 L2 120"},
+ {HPHW_NPROC,0x50E,0x4,0x81,"Rocky2 L2 150"},
+ {HPHW_NPROC,0x50F,0x4,0x81,"Anole L2 132 (744)"},
+ {HPHW_NPROC,0x510,0x4,0x81,"Anole L2 165 (744)"},
+ {HPHW_NPROC,0x511,0x4,0x81,"Kiji L2 132"},
+ {HPHW_NPROC,0x512,0x4,0x81,"UL L2 132 (803/D220,D320)"},
+ {HPHW_NPROC,0x513,0x4,0x81,"UL L2 160 (813/D220,D320)"},
+ {HPHW_NPROC,0x514,0x4,0x81,"Merlin Jr L2 132"},
+ {HPHW_NPROC,0x515,0x4,0x81,"Staccato L2 132"},
+ {HPHW_NPROC,0x516,0x4,0x81,"Staccato L2 180 (A Class 180)"},
+ {HPHW_NPROC,0x580,0x4,0x81,"KittyHawk DC2-100 (K100)"},
+ {HPHW_NPROC,0x581,0x4,0x91,"KittyHawk DC3-120 (K210)"},
+ {HPHW_NPROC,0x582,0x4,0x91,"KittyHawk DC3 100 (K400)"},
+ {HPHW_NPROC,0x583,0x4,0x91,"KittyHawk DC3 120 (K410)"},
+ {HPHW_NPROC,0x584,0x4,0x91,"LighteningHawk T120"},
+ {HPHW_NPROC,0x585,0x4,0x91,"SkyHawk 100"},
+ {HPHW_NPROC,0x586,0x4,0x91,"SkyHawk 120"},
+ {HPHW_NPROC,0x587,0x4,0x81,"UL Proc 1-way T'120"},
+ {HPHW_NPROC,0x588,0x4,0x91,"UL Proc 2-way T'120"},
+ {HPHW_NPROC,0x589,0x4,0x81,"UL Proc 1-way T'100 (821/D250,D350)"},
+ {HPHW_NPROC,0x58A,0x4,0x91,"UL Proc 2-way T'100 (831/D250,D350)"},
+ {HPHW_NPROC,0x58B,0x4,0x91,"KittyHawk DC2 100 (K200)"},
+ {HPHW_NPROC,0x58C,0x4,0x91,"ThunderHawk DC3- 120 1M (K220)"},
+ {HPHW_NPROC,0x58D,0x4,0x91,"ThunderHawk DC3 120 1M (K420)"},
+ {HPHW_NPROC,0x58E,0x4,0x81,"Raven 120 T'"},
+ {HPHW_NPROC,0x58F,0x4,0x91,"Mohawk 160 U 1M DC3 (K450)"},
+ {HPHW_NPROC,0x590,0x4,0x91,"Mohawk 180 U 1M DC3 (K460)"},
+ {HPHW_NPROC,0x591,0x4,0x91,"Mohawk 200 U 1M DC3"},
+ {HPHW_NPROC,0x592,0x4,0x81,"Raven 100 T'"},
+ {HPHW_NPROC,0x593,0x4,0x91,"FireHawk 160 U"},
+ {HPHW_NPROC,0x594,0x4,0x91,"FireHawk 180 U"},
+ {HPHW_NPROC,0x595,0x4,0x91,"FireHawk 220 U"},
+ {HPHW_NPROC,0x596,0x4,0x91,"FireHawk 240 U"},
+ {HPHW_NPROC,0x597,0x4,0x91,"SPP2000 processor"},
+ {HPHW_NPROC,0x598,0x4,0x81,"Raven U 230 (9000/780/C230)"},
+ {HPHW_NPROC,0x599,0x4,0x81,"Raven U 240 (9000/780/C240)"},
+ {HPHW_NPROC,0x59A,0x4,0x91,"Unlisted but reserved"},
+ {HPHW_NPROC,0x59A,0x4,0x81,"Unlisted but reserved"},
+ {HPHW_NPROC,0x59B,0x4,0x81,"Raven U 160 (9000/780/C160)"},
+ {HPHW_NPROC,0x59D,0x4,0x81,"Raven U 200 (9000/780/C200)"},
+ {HPHW_NPROC,0x59E,0x4,0x91,"ThunderHawk T' 120"},
+ {HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780/\?\?\?\?)"},
+ {HPHW_NPROC,0x5A0,0x4,0x81,"UL 1w T120 1MB/1MB (841/D260,D360)"},
+ {HPHW_NPROC,0x5A1,0x4,0x91,"UL 2w T120 1MB/1MB (851/D260,D360)"},
+ {HPHW_NPROC,0x5A2,0x4,0x81,"UL 1w U160 512K/512K (861/D270,D370)"},
+ {HPHW_NPROC,0x5A3,0x4,0x91,"UL 2w U160 512K/512K (871/D270,D370)"},
+ {HPHW_NPROC,0x5A4,0x4,0x91,"Mohawk 160 U 1M DC3- (K250)"},
+ {HPHW_NPROC,0x5A5,0x4,0x91,"Mohawk 180 U 1M DC3- (K260)"},
+ {HPHW_NPROC,0x5A6,0x4,0x91,"Mohawk 200 U 1M DC3-"},
+ {HPHW_NPROC,0x5A7,0x4,0x81,"UL proc 1-way U160 1M/1M"},
+ {HPHW_NPROC,0x5A8,0x4,0x91,"UL proc 2-way U160 1M/1M"},
+ {HPHW_NPROC,0x5A9,0x4,0x81,"UL proc 1-way U180 1M/1M"},
+ {HPHW_NPROC,0x5AA,0x4,0x91,"UL proc 2-way U180 1M/1M"},
+ {HPHW_NPROC,0x5AB,0x4,0x91,"Obsolete"},
+ {HPHW_NPROC,0x5AB,0x4,0x81,"Obsolete"},
+ {HPHW_NPROC,0x5AC,0x4,0x91,"Obsolete"},
+ {HPHW_NPROC,0x5AC,0x4,0x81,"Obsolete"},
+ {HPHW_NPROC,0x5AD,0x4,0x91,"BraveHawk 180MHz DC3-"},
+ {HPHW_NPROC,0x5AE,0x4,0x91,"BraveHawk 200MHz DC3- (898/K370)"},
+ {HPHW_NPROC,0x5AF,0x4,0x91,"BraveHawk 220MHz DC3-"},
+ {HPHW_NPROC,0x5B0,0x4,0x91,"BraveHawk 180MHz DC3"},
+ {HPHW_NPROC,0x5B1,0x4,0x91,"BraveHawk 200MHz DC3 (899/K570)"},
+ {HPHW_NPROC,0x5B2,0x4,0x91,"BraveHawk 220MHz DC3"},
+ {HPHW_NPROC,0x5B3,0x4,0x91,"FireHawk 200"},
+ {HPHW_NPROC,0x5B4,0x4,0x91,"SPP2500"},
+ {HPHW_NPROC,0x5B5,0x4,0x91,"SummitHawk U+"},
+ {HPHW_NPROC,0x5B6,0x4,0x91,"DragonHawk U+ 240 DC3"},
+ {HPHW_NPROC,0x5B7,0x4,0x91,"DragonHawk U+ 240 DC3-"},
+ {HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"},
+ {HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"},
+ {HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"},
+ {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W "},
+ {HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"},
+ {HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"},
+ {HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"},
+ {HPHW_NPROC,0x5BF,0x4,0x91,"Forte W 4-way"},
+ {HPHW_NPROC,0x5C0,0x4,0x91,"M2250"},
+ {HPHW_NPROC,0x5C1,0x4,0x91,"M2500"},
+ {HPHW_NPROC,0x5C2,0x4,0x91,"Sonata 440"},
+ {HPHW_NPROC,0x5C3,0x4,0x91,"Sonata 360"},
+ {HPHW_NPROC,0x5C4,0x4,0x91,"Rhapsody 440"},
+ {HPHW_NPROC,0x5C5,0x4,0x91,"Rhapsody 360"},
+ {HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780/\?\?\?\?)"},
+ {HPHW_NPROC,0x5C7,0x4,0x91,"Halfdome W 440"},
+ {HPHW_NPROC,0x5C8,0x4,0x81,"Lego 360 processor"},
+ {HPHW_NPROC,0x5C9,0x4,0x91,"Rhapsody DC- 440"},
+ {HPHW_NPROC,0x5CA,0x4,0x91,"Rhapsody DC- 360"},
+ {HPHW_NPROC,0x5CB,0x4,0x91,"Crescendo 440"},
+ {HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"},
+ {HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"},
+ {HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"},
+ {HPHW_NPROC,0x602,0x4,0x81,"Gecko 100 (712/100)"},
+ {HPHW_NPROC,0x603,0x4,0x81,"Anole 64 (743/64)"},
+ {HPHW_NPROC,0x604,0x4,0x81,"Anole 100 (743/100)"},
+ {HPHW_NPROC,0x605,0x4,0x81,"Gecko 120 (712/120)"},
+ {HPHW_NPROC,0x606,0x4,0x81,"Gila 80"},
+ {HPHW_NPROC,0x607,0x4,0x81,"Gila 100"},
+ {HPHW_NPROC,0x608,0x4,0x81,"Gila 120"},
+ {HPHW_NPROC,0x609,0x4,0x81,"Scorpio-L 80"},
+ {HPHW_NPROC,0x60A,0x4,0x81,"Mirage Jr (715/64)"},
+ {HPHW_NPROC,0x60B,0x4,0x81,"Mirage 100"},
+ {HPHW_NPROC,0x60C,0x4,0x81,"Mirage 100+"},
+ {HPHW_NPROC,0x60D,0x4,0x81,"Electra 100"},
+ {HPHW_NPROC,0x60E,0x4,0x81,"Electra 120"},
+ {HPHW_NPROC,0x610,0x4,0x81,"Scorpio-L 100"},
+ {HPHW_NPROC,0x611,0x4,0x81,"Scorpio-L 120"},
+ {HPHW_NPROC,0x612,0x4,0x81,"Spectra-L 80"},
+ {HPHW_NPROC,0x613,0x4,0x81,"Spectra-L 100"},
+ {HPHW_NPROC,0x614,0x4,0x81,"Spectra-L 120"},
+ {HPHW_NPROC,0x615,0x4,0x81,"Piranha 100"},
+ {HPHW_NPROC,0x616,0x4,0x81,"Piranha 120"},
+ {HPHW_NPROC,0x617,0x4,0x81,"Jason 50"},
+ {HPHW_NPROC,0x618,0x4,0x81,"Jason 100"},
+ {HPHW_NPROC,0x619,0x4,0x81,"Mirage 80 "},
+ {HPHW_NPROC,0x61A,0x4,0x81,"SAIC L-80"},
+ {HPHW_NPROC,0x61B,0x4,0x81,"Rocky1 L-60"},
+ {HPHW_NPROC,0x61C,0x4,0x81,"Anole T (743/T)"},
+ {HPHW_NPROC,0x67E,0x4,0x81,"Hitachi Tiny 80"},
+ {HPHW_NPROC,0x67F,0x4,0x81,"Hitachi Tiny 64"},
+ {HPHW_NPROC,0x700,0x4,0x91,"NEC Aska Processor"},
+ {HPHW_A_DIRECT, 0x004, 0x0000D, 0x00, "Arrakis MUX"},
+ {HPHW_A_DIRECT, 0x005, 0x0000D, 0x00, "Dyun Kiuh MUX"},
+ {HPHW_A_DIRECT, 0x006, 0x0000D, 0x00, "Baat Kiuh AP/MUX (40299B)"},
+ {HPHW_A_DIRECT, 0x007, 0x0000D, 0x00, "Dino AP"},
+ {HPHW_A_DIRECT, 0x009, 0x0000D, 0x00, "Solaris Direct Connect MUX (J2092A)"},
+ {HPHW_A_DIRECT, 0x00A, 0x0000D, 0x00, "Solaris RS-422/423 MUX (J2093A)"},
+ {HPHW_A_DIRECT, 0x00B, 0x0000D, 0x00, "Solaris RS-422/423 Quadriloops MUX"},
+ {HPHW_A_DIRECT, 0x00C, 0x0000D, 0x00, "Solaris Modem MUX (J2094A)"},
+ {HPHW_A_DIRECT, 0x00D, 0x0000D, 0x00, "Twins Direct Connect MUX"},
+ {HPHW_A_DIRECT, 0x00E, 0x0000D, 0x00, "Twins Modem MUX"},
+ {HPHW_A_DIRECT, 0x00F, 0x0000D, 0x00, "Nautilus RS-485"},
+ {HPHW_A_DIRECT, 0x010, 0x0000D, 0x00, "UltraLight CAP/MUX"},
+ {HPHW_A_DIRECT, 0x015, 0x0000D, 0x00, "Eole CAP/MUX"},
+ {HPHW_A_DIRECT, 0x024, 0x0000D, 0x00, "Sahp Kiuh AP/MUX"},
+ {HPHW_A_DIRECT, 0x034, 0x0000D, 0x00, "Sahp Kiuh Low AP/MUX"},
+ {HPHW_A_DIRECT, 0x044, 0x0000D, 0x00, "Sahp Baat Kiuh AP/MUX"},
+ {HPHW_A_DIRECT, 0x004, 0x0000E, 0x80, "Burgundy RS-232"},
+ {HPHW_A_DIRECT, 0x005, 0x0000E, 0x80, "Silverfox RS-232"},
+ {HPHW_A_DIRECT, 0x006, 0x0000E, 0x80, "Lego RS-232"},
+ {HPHW_A_DIRECT, 0x004, 0x0000F, 0x00, "Peacock Graphics"},
+ {HPHW_A_DIRECT, 0x004, 0x00014, 0x80, "Burgundy HIL"},
+ {HPHW_A_DIRECT, 0x005, 0x00014, 0x80, "Peacock HIL"},
+ {HPHW_A_DIRECT, 0x004, 0x00015, 0x80, "Leonardo"},
+ {HPHW_A_DIRECT, 0x004, 0x00016, 0x80, "HP-PB HRM"},
+ {HPHW_A_DIRECT, 0x004, 0x00017, 0x80, "HP-PB HRC"},
+ {HPHW_A_DIRECT, 0x004, 0x0003A, 0x80, "Skunk Centronics (28655A)"},
+ {HPHW_A_DIRECT, 0x024, 0x0003A, 0x80, "Sahp Kiuh Centronics"},
+ {HPHW_A_DIRECT, 0x044, 0x0003A, 0x80, "Sahp Baat Kiuh Centronics"},
+ {HPHW_A_DIRECT, 0x004, 0x0004E, 0x80, "AT&T DataKit (AMSO)"},
+ {HPHW_A_DIRECT, 0x004, 0x0009B, 0x80, "Test&Meas GSC HPIB"},
+ {HPHW_A_DIRECT, 0x004, 0x000A8, 0x00, "Rocky2-120 Front Keyboard"},
+ {HPHW_A_DIRECT, 0x005, 0x000A8, 0x00, "Rocky2-150 Front Keyboard"},
+ {HPHW_A_DIRECT, 0x004, 0x00101, 0x80, "Hitachi Console Module"},
+ {HPHW_A_DIRECT, 0x004, 0x00102, 0x80, "Hitachi Boot Module"},
+ {HPHW_A_DIRECT, 0x004, 0x00203, 0x80, "MELCO HBMLA MLAIT"},
+ {HPHW_A_DIRECT, 0x004, 0x00208, 0x80, "MELCO HBDPC"},
+ {HPHW_A_DIRECT, 0x004, 0x00300, 0x00, "DCI TWINAX TERM IO MUX"},
+ {HPHW_A_DMA, 0x004, 0x00039, 0x80, "Skunk SCSI (28655A)"},
+ {HPHW_A_DMA, 0x005, 0x00039, 0x80, "KittyHawk CSY Core SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00039, 0x80, "Diablo SCSI"},
+ {HPHW_A_DMA, 0x024, 0x00039, 0x80, "Sahp Kiuh SCSI"},
+ {HPHW_A_DMA, 0x034, 0x00039, 0x80, "Sahp Kiuh Low SCSI"},
+ {HPHW_A_DMA, 0x044, 0x00039, 0x80, "Sahp Baat Kiuh SCSI"},
+ {HPHW_A_DMA, 0x004, 0x0003B, 0x80, "Wizard SCSI"},
+ {HPHW_A_DMA, 0x005, 0x0003B, 0x80, "KittyHawk CSY Core FW-SCSI"},
+ {HPHW_A_DMA, 0x006, 0x0003B, 0x80, "Symbios EPIC FW-SCSI"},
+ {HPHW_A_DMA, 0x004, 0x00040, 0x80, "HP-PB Shazam HPIB (28650A)"},
+ {HPHW_A_DMA, 0x005, 0x00040, 0x80, "Burgundy HPIB"},
+ {HPHW_A_DMA, 0x004, 0x00041, 0x80, "HP-PB HP-FL"},
+ {HPHW_A_DMA, 0x004, 0x00042, 0x80, "HP-PB LoQuix HPIB (28650B)"},
+ {HPHW_A_DMA, 0x004, 0x00043, 0x80, "HP-PB Crypt LoQuix"},
+ {HPHW_A_DMA, 0x004, 0x00044, 0x80, "HP-PB Shazam GPIO (28651A)"},
+ {HPHW_A_DMA, 0x004, 0x00045, 0x80, "HP-PB LoQuix GPIO"},
+ {HPHW_A_DMA, 0x004, 0x00046, 0x80, "2-Port X.25 NIO_ACC (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x00047, 0x80, "4-Port X.25 NIO_ACC (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x0004B, 0x80, "LGB Control"},
+ {HPHW_A_DMA, 0x004, 0x0004C, 0x80, "Martian RTI (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x0004D, 0x80, "ACC Mux (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x00050, 0x80, "Lanbrusca 802.3 (36967A)"},
+ {HPHW_A_DMA, 0x004, 0x00056, 0x80, "HP-PB LoQuix FDDI"},
+ {HPHW_A_DMA, 0x004, 0x00057, 0x80, "HP-PB LoQuix FDDI (28670A)"},
+ {HPHW_A_DMA, 0x012, 0x00089, 0x80, "Barracuda Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x013, 0x00089, 0x80, "Bluefish Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00089, 0x80, "Shrike Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x015, 0x00089, 0x80, "KittyHawk GSY Core FW-SCSI"},
+ {HPHW_A_DMA, 0x017, 0x00089, 0x80, "Shrike Jade Add-on FW-SCSI (A3644A)"},
+ {HPHW_A_DMA, 0x01F, 0x00089, 0x80, "SkyHawk 100/120 FW-SCSI"},
+ {HPHW_A_DMA, 0x027, 0x00089, 0x80, "Piranha 100 FW-SCSI"},
+ {HPHW_A_DMA, 0x032, 0x00089, 0x80, "Raven T' Core FW-SCSI"},
+ {HPHW_A_DMA, 0x03d, 0x00089, 0x80, "Merlin 160 Core FW-SCSI"},
+ {HPHW_A_DMA, 0x044, 0x00089, 0x80, "Mohawk Core FW-SCSI"},
+ {HPHW_A_DMA, 0x051, 0x00089, 0x80, "Firehawk FW-SCSI"},
+ {HPHW_A_DMA, 0x058, 0x00089, 0x80, "FireHawk 200 FW-SCSI"},
+ {HPHW_A_DMA, 0x05C, 0x00089, 0x80, "SummitHawk 230 Ultra-SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00091, 0x80, "Baby Hugo Add-on Net FC (A3406A)"},
+ {HPHW_A_DMA, 0x020, 0x00091, 0x80, "Baby Jade Add-on Net FC (A3638A)"},
+ {HPHW_A_DMA, 0x004, 0x00092, 0x80, "GSC+ YLIASTER ATM"},
+ {HPHW_A_DMA, 0x004, 0x00095, 0x80, "Hamlyn GSC+ Network Card"},
+ {HPHW_A_DMA, 0x004, 0x00098, 0x80, "Lo-fat Emulator"},
+ {HPHW_A_DMA, 0x004, 0x0009A, 0x80, "GSC+ Venus ATM"},
+ {HPHW_A_DMA, 0x005, 0x0009A, 0x80, "GSC+ Samorobrive ATM"},
+ {HPHW_A_DMA, 0x004, 0x0009D, 0x80, "HP HSC-PCI Cards"},
+ {HPHW_A_DMA, 0x004, 0x0009E, 0x80, "Alaxis GSC+ 155Mb ATM"},
+ {HPHW_A_DMA, 0x005, 0x0009E, 0x80, "Alaxis GSC+ 622Mb ATM"},
+ {HPHW_A_DMA, 0x05C, 0x0009F, 0x80, "SummitHawk 230 USB"},
+ {HPHW_A_DMA, 0x05C, 0x000A0, 0x80, "SummitHawk 230 100BaseT"},
+ {HPHW_A_DMA, 0x015, 0x000A7, 0x80, "Baby Hugo Add-on mass FC (A3404A)"},
+ {HPHW_A_DMA, 0x018, 0x000A7, 0x80, "Mombasa GS Add-on mass FC (A3591)"},
+ {HPHW_A_DMA, 0x021, 0x000A7, 0x80, "Baby Jade Add-on mass FC (A3636A)"},
+ {HPHW_A_DMA, 0x004, 0x00201, 0x80, "MELCO HCMAP"},
+ {HPHW_A_DMA, 0x004, 0x00202, 0x80, "MELCO HBMLA MLAMA"},
+ {HPHW_A_DMA, 0x004, 0x00205, 0x80, "MELCO HBRFU"},
+ {HPHW_A_DMA, 0x004, 0x00380, 0x80, "Interphase NIO-FC"},
+ {HPHW_A_DMA, 0x004, 0x00381, 0x80, "Interphase NIO-ATM"},
+ {HPHW_A_DMA, 0x004, 0x00382, 0x80, "Interphase NIO-100BaseTX"},
+ {HPHW_BA, 0x004, 0x00070, 0x0, "Cobra Core BA"},
+ {HPHW_BA, 0x005, 0x00070, 0x0, "Coral Core BA"},
+ {HPHW_BA, 0x006, 0x00070, 0x0, "Bushmaster Core BA"},
+ {HPHW_BA, 0x007, 0x00070, 0x0, "Scorpio Core BA"},
+ {HPHW_BA, 0x008, 0x00070, 0x0, "Flounder Core BA"},
+ {HPHW_BA, 0x009, 0x00070, 0x0, "Outfield Core BA"},
+ {HPHW_BA, 0x00A, 0x00070, 0x0, "CoralII Core BA"},
+ {HPHW_BA, 0x00B, 0x00070, 0x0, "Scorpio Jr. Core BA"},
+ {HPHW_BA, 0x00C, 0x00070, 0x0, "Strider-50 Core BA"},
+ {HPHW_BA, 0x00D, 0x00070, 0x0, "Strider-33 Core BA"},
+ {HPHW_BA, 0x00E, 0x00070, 0x0, "Trailways-50 Core BA"},
+ {HPHW_BA, 0x00F, 0x00070, 0x0, "Trailways-33 Core BA"},
+ {HPHW_BA, 0x010, 0x00070, 0x0, "Pace Core BA"},
+ {HPHW_BA, 0x011, 0x00070, 0x0, "Sidewinder Core BA"},
+ {HPHW_BA, 0x019, 0x00070, 0x0, "Scorpio Sr. Core BA"},
+ {HPHW_BA, 0x020, 0x00070, 0x0, "Scorpio 100 Core BA"},
+ {HPHW_BA, 0x021, 0x00070, 0x0, "Spectra 50 Core BA"},
+ {HPHW_BA, 0x022, 0x00070, 0x0, "Spectra 75 Core BA"},
+ {HPHW_BA, 0x023, 0x00070, 0x0, "Spectra 100 Core BA"},
+ {HPHW_BA, 0x024, 0x00070, 0x0, "Fast Pace Core BA"},
+ {HPHW_BA, 0x026, 0x00070, 0x0, "CoralII Jaguar Core BA"},
+ {HPHW_BA, 0x004, 0x00076, 0x0, "Cobra EISA BA"},
+ {HPHW_BA, 0x005, 0x00076, 0x0, "Coral EISA BA"},
+ {HPHW_BA, 0x007, 0x00076, 0x0, "Scorpio EISA BA"},
+ {HPHW_BA, 0x00A, 0x00076, 0x0, "CoralII EISA BA"},
+ {HPHW_BA, 0x00B, 0x00076, 0x0, "Scorpio Jr. EISA BA"},
+ {HPHW_BA, 0x00C, 0x00076, 0x0, "Strider-50 Core EISA"},
+ {HPHW_BA, 0x00D, 0x00076, 0x0, "Strider-33 Core EISA"},
+ {HPHW_BA, 0x00E, 0x00076, 0x0, "Trailways-50 Core EISA"},
+ {HPHW_BA, 0x00F, 0x00076, 0x0, "Trailways-33 Core EISA"},
+ {HPHW_BA, 0x010, 0x00076, 0x0, "Pace Core EISA"},
+ {HPHW_BA, 0x019, 0x00076, 0x0, "Scorpio Sr. EISA BA"},
+ {HPHW_BA, 0x020, 0x00076, 0x0, "Scorpio 100 EISA BA"},
+ {HPHW_BA, 0x021, 0x00076, 0x0, "Spectra 50 EISA BA"},
+ {HPHW_BA, 0x022, 0x00076, 0x0, "Spectra 75 EISA BA"},
+ {HPHW_BA, 0x023, 0x00076, 0x0, "Spectra 100 EISA BA"},
+ {HPHW_BA, 0x026, 0x00076, 0x0, "CoralII Jaguar EISA BA"},
+ {HPHW_BA, 0x010, 0x00078, 0x0, "Pace VME BA"},
+ {HPHW_BA, 0x011, 0x00078, 0x0, "Sidewinder VME BA"},
+ {HPHW_BA, 0x01A, 0x00078, 0x0, "Anole 64 VME BA"},
+ {HPHW_BA, 0x01B, 0x00078, 0x0, "Anole 100 VME BA"},
+ {HPHW_BA, 0x024, 0x00078, 0x0, "Fast Pace VME BA"},
+ {HPHW_BA, 0x034, 0x00078, 0x0, "Anole T VME BA"},
+ {HPHW_BA, 0x04A, 0x00078, 0x0, "Anole L2 132 BME BA"},
+ {HPHW_BA, 0x04C, 0x00078, 0x0, "Anole L2 165 VME BA"},
+ {HPHW_BA, 0x011, 0x00081, 0x0, "WB-96 Core BA"},
+ {HPHW_BA, 0x012, 0x00081, 0x0, "Orville UX Core BA"},
+ {HPHW_BA, 0x013, 0x00081, 0x0, "Wilbur UX Core BA"},
+ {HPHW_BA, 0x014, 0x00081, 0x0, "WB-80 Core BA"},
+ {HPHW_BA, 0x015, 0x00081, 0x0, "KittyHawk GSY Core BA"},
+ {HPHW_BA, 0x016, 0x00081, 0x0, "Gecko Core BA"},
+ {HPHW_BA, 0x018, 0x00081, 0x0, "Gecko Optional BA"},
+ {HPHW_BA, 0x01A, 0x00081, 0x0, "Anole 64 Core BA"},
+ {HPHW_BA, 0x01B, 0x00081, 0x0, "Anole 100 Core BA"},
+ {HPHW_BA, 0x01C, 0x00081, 0x0, "Gecko 80 Core BA"},
+ {HPHW_BA, 0x01D, 0x00081, 0x0, "Gecko 100 Core BA"},
+ {HPHW_BA, 0x01F, 0x00081, 0x0, "SkyHawk 100/120 Core BA"},
+ {HPHW_BA, 0x027, 0x00081, 0x0, "Piranha 100 Core BA"},
+ {HPHW_BA, 0x028, 0x00081, 0x0, "Mirage Jr Core BA"},
+ {HPHW_BA, 0x029, 0x00081, 0x0, "Mirage Core BA"},
+ {HPHW_BA, 0x02A, 0x00081, 0x0, "Electra Core BA"},
+ {HPHW_BA, 0x02B, 0x00081, 0x0, "Mirage 80 Core BA"},
+ {HPHW_BA, 0x02C, 0x00081, 0x0, "Mirage 100+ Core BA"},
+ {HPHW_BA, 0x02E, 0x00081, 0x0, "UL 350 Lasi Core BA"},
+ {HPHW_BA, 0x02F, 0x00081, 0x0, "UL 550 Lasi Core BA"},
+ {HPHW_BA, 0x032, 0x00081, 0x0, "Raven T' Core BA"},
+ {HPHW_BA, 0x033, 0x00081, 0x0, "Anole T Core BA"},
+ {HPHW_BA, 0x034, 0x00081, 0x0, "SAIC L-80 Core BA"},
+ {HPHW_BA, 0x035, 0x00081, 0x0, "PCX-L2 712/132 Core BA"},
+ {HPHW_BA, 0x036, 0x00081, 0x0, "PCX-L2 712/160 Core BA"},
+ {HPHW_BA, 0x03B, 0x00081, 0x0, "Raven U/L2 Core BA"},
+ {HPHW_BA, 0x03C, 0x00081, 0x0, "Merlin 132 Core BA"},
+ {HPHW_BA, 0x03D, 0x00081, 0x0, "Merlin 160 Core BA"},
+ {HPHW_BA, 0x03E, 0x00081, 0x0, "Merlin+ 132 Core BA"},
+ {HPHW_BA, 0x03F, 0x00081, 0x0, "Merlin+ 180 Core BA"},
+ {HPHW_BA, 0x044, 0x00081, 0x0, "Mohawk Core BA"},
+ {HPHW_BA, 0x045, 0x00081, 0x0, "Rocky1 Core BA"},
+ {HPHW_BA, 0x046, 0x00081, 0x0, "Rocky2 120 Core BA"},
+ {HPHW_BA, 0x047, 0x00081, 0x0, "Rocky2 150 Core BA"},
+ {HPHW_BA, 0x04B, 0x00081, 0x0, "Anole L2 132 Core BA"},
+ {HPHW_BA, 0x04D, 0x00081, 0x0, "Anole L2 165 Core BA"},
+ {HPHW_BA, 0x04E, 0x00081, 0x0, "Kiji L2 132 Core BA"},
+ {HPHW_BA, 0x050, 0x00081, 0x0, "Merlin Jr 132 Core BA"},
+ {HPHW_BA, 0x051, 0x00081, 0x0, "Firehawk Core BA"},
+ {HPHW_BA, 0x056, 0x00081, 0x0, "Raven+ w SE FWSCSI Core BA"},
+ {HPHW_BA, 0x057, 0x00081, 0x0, "Raven+ w Diff FWSCSI Core BA"},
+ {HPHW_BA, 0x058, 0x00081, 0x0, "FireHawk 200 Core BA"},
+ {HPHW_BA, 0x05C, 0x00081, 0x0, "SummitHawk 230 Core BA"},
+ {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 132 Core BA"},
+ {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 180 Core BA"},
+ {HPHW_BA, 0x05F, 0x00081, 0x0, "Staccato 180 Lasi"},
+ {HPHW_BA, 0x800, 0x00081, 0x0, "Hitachi Tiny 64 Core BA"},
+ {HPHW_BA, 0x801, 0x00081, 0x0, "Hitachi Tiny 80 Core BA"},
+ {HPHW_BA, 0x004, 0x0008B, 0x0, "Anole Optional PCMCIA BA"},
+ {HPHW_BA, 0x004, 0x0008E, 0x0, "GSC ITR Wax BA"},
+ {HPHW_BA, 0x011, 0x0008E, 0x0, "SuperPace Wax BA"},
+ {HPHW_BA, 0x012, 0x0008E, 0x0, "Mirage Jr Wax BA"},
+ {HPHW_BA, 0x013, 0x0008E, 0x0, "Mirage Wax BA"},
+ {HPHW_BA, 0x014, 0x0008E, 0x0, "Electra Wax BA"},
+ {HPHW_BA, 0x017, 0x0008E, 0x0, "Raven Backplane Wax BA"},
+ {HPHW_BA, 0x01E, 0x0008E, 0x0, "Raven T' Wax BA"},
+ {HPHW_BA, 0x01F, 0x0008E, 0x0, "SkyHawk Wax BA"},
+ {HPHW_BA, 0x023, 0x0008E, 0x0, "Rocky1 Wax BA"},
+ {HPHW_BA, 0x02B, 0x0008E, 0x0, "Mirage 80 Wax BA"},
+ {HPHW_BA, 0x02C, 0x0008E, 0x0, "Mirage 100+ Wax BA"},
+ {HPHW_BA, 0x030, 0x0008E, 0x0, "UL 350 Core Wax BA"},
+ {HPHW_BA, 0x031, 0x0008E, 0x0, "UL 550 Core Wax BA"},
+ {HPHW_BA, 0x034, 0x0008E, 0x0, "SAIC L-80 Wax BA"},
+ {HPHW_BA, 0x03A, 0x0008E, 0x0, "Merlin+ Wax BA"},
+ {HPHW_BA, 0x040, 0x0008E, 0x0, "Merlin 132 Wax BA"},
+ {HPHW_BA, 0x041, 0x0008E, 0x0, "Merlin 160 Wax BA"},
+ {HPHW_BA, 0x043, 0x0008E, 0x0, "Merlin 132/160 Wax BA"},
+ {HPHW_BA, 0x052, 0x0008E, 0x0, "Raven+ Hi Power Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x054, 0x0008E, 0x0, "Raven+ Lo Power Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x059, 0x0008E, 0x0, "FireHawk 200 Wax BA"},
+ {HPHW_BA, 0x05A, 0x0008E, 0x0, "Raven+ L2 Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x05D, 0x0008E, 0x0, "SummitHawk Wax BA"},
+ {HPHW_BA, 0x800, 0x0008E, 0x0, "Hitachi Tiny 64 Wax BA"},
+ {HPHW_BA, 0x801, 0x0008E, 0x0, "Hitachi Tiny 80 Wax BA"},
+ {HPHW_BA, 0x011, 0x00090, 0x0, "SuperPace Wax EISA BA"},
+ {HPHW_BA, 0x017, 0x00090, 0x0, "Raven Backplane Wax EISA BA"},
+ {HPHW_BA, 0x01E, 0x00090, 0x0, "Raven T' Wax EISA BA"},
+ {HPHW_BA, 0x01F, 0x00090, 0x0, "SkyHawk 100/120 Wax EISA BA"},
+ {HPHW_BA, 0x027, 0x00090, 0x0, "Piranha 100 Wax EISA BA"},
+ {HPHW_BA, 0x028, 0x00090, 0x0, "Mirage Jr Wax EISA BA"},
+ {HPHW_BA, 0x029, 0x00090, 0x0, "Mirage Wax EISA BA"},
+ {HPHW_BA, 0x02A, 0x00090, 0x0, "Electra Wax EISA BA"},
+ {HPHW_BA, 0x02B, 0x00090, 0x0, "Mirage 80 Wax EISA BA"},
+ {HPHW_BA, 0x02C, 0x00090, 0x0, "Mirage 100+ Wax EISA BA"},
+ {HPHW_BA, 0x030, 0x00090, 0x0, "UL 350 Wax EISA BA"},
+ {HPHW_BA, 0x031, 0x00090, 0x0, "UL 550 Wax EISA BA"},
+ {HPHW_BA, 0x034, 0x00090, 0x0, "SAIC L-80 Wax EISA BA"},
+ {HPHW_BA, 0x03A, 0x00090, 0x0, "Merlin+ Wax EISA BA"},
+ {HPHW_BA, 0x040, 0x00090, 0x0, "Merlin 132 Wax EISA BA"},
+ {HPHW_BA, 0x041, 0x00090, 0x0, "Merlin 160 Wax EISA BA"},
+ {HPHW_BA, 0x043, 0x00090, 0x0, "Merlin 132/160 Wax EISA BA"},
+ {HPHW_BA, 0x052, 0x00090, 0x0, "Raven Hi Power Backplane Wax EISA BA"},
+ {HPHW_BA, 0x054, 0x00090, 0x0, "Raven Lo Power Backplane Wax EISA BA"},
+ {HPHW_BA, 0x059, 0x00090, 0x0, "FireHawk 200 Wax EISA BA"},
+ {HPHW_BA, 0x05A, 0x00090, 0x0, "Raven L2 Backplane Wax EISA BA"},
+ {HPHW_BA, 0x05D, 0x00090, 0x0, "SummitHawk Wax EISA BA"},
+ {HPHW_BA, 0x800, 0x00090, 0x0, "Hitachi Tiny 64 Wax EISA BA"},
+ {HPHW_BA, 0x801, 0x00090, 0x0, "Hitachi Tiny 80 Wax EISA BA"},
+ {HPHW_BA, 0x01A, 0x00093, 0x0, "Anole 64 TIMI BA"},
+ {HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 64 TIMI BA"},
+ {HPHW_BA, 0x034, 0x00093, 0x0, "Anole T TIMI BA"},
+ {HPHW_BA, 0x04A, 0x00093, 0x0, "Anole L2 132 TIMI BA"},
+ {HPHW_BA, 0x04C, 0x00093, 0x0, "Anole L2 165 TIMI BA"},
+ {HPHW_BA, 0x582, 0x000A5, 0x00, "Epic PCI Bridge"},
+ {HPHW_BCPORT, 0x504, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"},
+ {HPHW_BCPORT, 0x505, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"},
+ {HPHW_BCPORT, 0x503, 0x0000C, 0x00, "Java BC GSC+ Port"},
+ {HPHW_BCPORT, 0x57F, 0x0000C, 0x00, "Hitachi Ghostview GSC+ Port"},
+ {HPHW_BCPORT, 0x501, 0x0000C, 0x00, "U2-IOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x502, 0x0000C, 0x00, "Uturn-IOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x780, 0x0000C, 0x00, "Astro BC Ropes Port"},
+ {HPHW_BCPORT, 0x506, 0x0000C, 0x00, "NEC-IOS BC HSC Port"},
+ {HPHW_BCPORT, 0x004, 0x0000C, 0x00, "Cheetah BC SMB Port"},
+ {HPHW_BCPORT, 0x006, 0x0000C, 0x00, "Cheetah BC MID_BUS Port"},
+ {HPHW_BCPORT, 0x005, 0x0000C, 0x00, "Condor BC MID_BUS Port"},
+ {HPHW_BCPORT, 0x100, 0x0000C, 0x00, "Condor BC HP-PB Port"},
+ {HPHW_BCPORT, 0x184, 0x0000C, 0x00, "Summit BC Port"},
+ {HPHW_BCPORT, 0x101, 0x0000C, 0x00, "Summit BC HP-PB Port"},
+ {HPHW_BCPORT, 0x102, 0x0000C, 0x00, "HP-PB Port (prefetch)"},
+ {HPHW_BCPORT, 0x500, 0x0000C, 0x00, "Gecko BOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x103, 0x0000C, 0x00, "Gecko BOA BC HP-PB Port"},
+ {HPHW_BCPORT, 0x507, 0x0000C, 0x00, "Keyaki BC GSC+ Port"},
+ {HPHW_BCPORT, 0x508, 0x0000C, 0x00, "Keyaki-DX BC GSC+ Port"},
+ {HPHW_BCPORT, 0x584, 0x0000C, 0x10, "DEW BC Runway Port"},
+ {HPHW_BCPORT, 0x800, 0x0000C, 0x10, "DEW BC Merced Port"},
+ {HPHW_BCPORT, 0x801, 0x0000C, 0x10, "SMC Bus Interface Merced Bus0"},
+ {HPHW_BCPORT, 0x802, 0x0000C, 0x10, "SMC Bus INterface Merced Bus1"},
+ {HPHW_BCPORT, 0x803, 0x0000C, 0x10, "IKE I/O Bus Converter Merced Port"},
+ {HPHW_BCPORT, 0x781, 0x0000C, 0x00, "IKE I/O Bus Converter Ropes Port"},
+ {HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O Bus Converter Merced Port"},
+ {HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O Bus Converter Ropes Port"},
+ {HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"},
+ {HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"},
+ {HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"},
+ {HPHW_BRIDGE, 0x583, 0x000A5, 0x00, "Saga PCI Bridge"},
+ {HPHW_B_DMA, 0x004, 0x00018, 0x00, "Parallel I/O"},
+ {HPHW_B_DMA, 0x004, 0x00019, 0x00, "Parallel RDB"},
+ {HPHW_B_DMA, 0x004, 0x00020, 0x80, "MID_BUS PSI"},
+ {HPHW_B_DMA, 0x004, 0x0002F, 0x80, "HP-PB Transit PSI (36960A)"},
+ {HPHW_B_DMA, 0x008, 0x00051, 0x80, "HP-PB Transit 802.3"},
+ {HPHW_B_DMA, 0x004, 0x00052, 0x80, "Miura LAN/Console (J2146A)"},
+ {HPHW_B_DMA, 0x008, 0x00058, 0x80, "HP-PB Transit 802.4"},
+ {HPHW_B_DMA, 0x005, 0x00060, 0x80, "KittyHawk CSY Core LAN/Console"},
+ {HPHW_B_DMA, 0x014, 0x00060, 0x80, "Diablo LAN/Console"},
+ {HPHW_B_DMA, 0x054, 0x00060, 0x80, "Countach LAN/Console"},
+ {HPHW_B_DMA, 0x004, 0x00094, 0x80, "KittyHawk GSC+ Exerciser"},
+ {HPHW_B_DMA, 0x004, 0x00100, 0x80, "HP-PB HF Interface"},
+ {HPHW_B_DMA, 0x000, 0x00206, 0x80, "MELCO HMPHA"},
+ {HPHW_B_DMA, 0x005, 0x00206, 0x80, "MELCO HMPHA_10"},
+ {HPHW_B_DMA, 0x006, 0x00206, 0x80, "MELCO HMQHA"},
+ {HPHW_B_DMA, 0x007, 0x00206, 0x80, "MELCO HMQHA_10"},
+ {HPHW_B_DMA, 0x004, 0x207, 0x80, "MELCO HNDWA MDWS-70"},
+ {HPHW_CIO, 0x004, 0x00010, 0x00, "VLSI CIO"},
+ {HPHW_CIO, 0x005, 0x00010, 0x00, "Silverfox CIO"},
+ {HPHW_CIO, 0x006, 0x00010, 0x00, "Emerald CIO"},
+ {HPHW_CIO, 0x008, 0x00010, 0x00, "Discrete CIO"},
+ {HPHW_CONSOLE, 0x004, 0x0001C, 0x00, "Cheetah console"},
+ {HPHW_CONSOLE, 0x005, 0x0001C, 0x00, "Emerald console"},
+ {HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"},
+ {HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"},
+ {HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"},
+ {HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"},
+ {HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"},
+ {HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"},
+ {HPHW_FIO, 0x004, 0x0004F, 0x0, "8-Port X.25 EISA-ACC (AMSO)"},
+ {HPHW_FIO, 0x004, 0x00071, 0x0, "Cobra Core SCSI"},
+ {HPHW_FIO, 0x005, 0x00071, 0x0, "Coral Core SCSI"},
+ {HPHW_FIO, 0x006, 0x00071, 0x0, "Bushmaster Core SCSI"},
+ {HPHW_FIO, 0x007, 0x00071, 0x0, "Scorpio Core SCSI"},
+ {HPHW_FIO, 0x008, 0x00071, 0x0, "Flounder Core SCSI"},
+ {HPHW_FIO, 0x009, 0x00071, 0x0, "Outfield Core SCSI"},
+ {HPHW_FIO, 0x00A, 0x00071, 0x0, "CoralII Core SCSI"},
+ {HPHW_FIO, 0x00B, 0x00071, 0x0, "Scorpio Jr. Core SCSI"},
+ {HPHW_FIO, 0x00C, 0x00071, 0x0, "Strider-50 Core SCSI"},
+ {HPHW_FIO, 0x00D, 0x00071, 0x0, "Strider-33 Core SCSI"},
+ {HPHW_FIO, 0x00E, 0x00071, 0x0, "Trailways-50 Core SCSI"},
+ {HPHW_FIO, 0x00F, 0x00071, 0x0, "Trailways-33 Core SCSI"},
+ {HPHW_FIO, 0x010, 0x00071, 0x0, "Pace Core SCSI"},
+ {HPHW_FIO, 0x011, 0x00071, 0x0, "Sidewinder Core SCSI"},
+ {HPHW_FIO, 0x019, 0x00071, 0x0, "Scorpio Sr. Core SCSI"},
+ {HPHW_FIO, 0x020, 0x00071, 0x0, "Scorpio 100 Core SCSI"},
+ {HPHW_FIO, 0x021, 0x00071, 0x0, "Spectra 50 Core SCSI"},
+ {HPHW_FIO, 0x022, 0x00071, 0x0, "Spectra 75 Core SCSI"},
+ {HPHW_FIO, 0x023, 0x00071, 0x0, "Spectra 100 Core SCSI"},
+ {HPHW_FIO, 0x024, 0x00071, 0x0, "Fast Pace Core SCSI"},
+ {HPHW_FIO, 0x026, 0x00071, 0x0, "CoralII Jaguar Core SCSI"},
+ {HPHW_FIO, 0x004, 0x00072, 0x0, "Cobra Core LAN (802.3)"},
+ {HPHW_FIO, 0x005, 0x00072, 0x0, "Coral Core LAN (802.3)"},
+ {HPHW_FIO, 0x006, 0x00072, 0x0, "Bushmaster Core LAN (802.3)"},
+ {HPHW_FIO, 0x007, 0x00072, 0x0, "Scorpio Core LAN (802.3)"},
+ {HPHW_FIO, 0x008, 0x00072, 0x0, "Flounder Core LAN (802.3)"},
+ {HPHW_FIO, 0x009, 0x00072, 0x0, "Outfield Core LAN (802.3)"},
+ {HPHW_FIO, 0x00A, 0x00072, 0x0, "CoralII Core LAN (802.3)"},
+ {HPHW_FIO, 0x00B, 0x00072, 0x0, "Scorpio Jr. Core LAN (802.3)"},
+ {HPHW_FIO, 0x00C, 0x00072, 0x0, "Strider-50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00D, 0x00072, 0x0, "Strider-33 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00E, 0x00072, 0x0, "Trailways-50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00F, 0x00072, 0x0, "Trailways-33 Core LAN (802.3)"},
+ {HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core Lan (802.3)"},
+ {HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core Lan (802.3)"},
+ {HPHW_FIO, 0x019, 0x00072, 0x0, "Scorpio Sr. Core LAN (802.3)"},
+ {HPHW_FIO, 0x020, 0x00072, 0x0, "Scorpio 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x021, 0x00072, 0x0, "Spectra 50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x022, 0x00072, 0x0, "Spectra 75 Core LAN (802.3)"},
+ {HPHW_FIO, 0x023, 0x00072, 0x0, "Spectra 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core Lan (802.3)"},
+ {HPHW_FIO, 0x026, 0x00072, 0x0, "CoralII Jaguar Core LAN (802.3)"},
+ {HPHW_FIO, 0x004, 0x00073, 0x0, "Cobra Core HIL"},
+ {HPHW_FIO, 0x005, 0x00073, 0x0, "Coral Core HIL"},
+ {HPHW_FIO, 0x006, 0x00073, 0x0, "Bushmaster Core HIL"},
+ {HPHW_FIO, 0x007, 0x00073, 0x0, "Scorpio Core HIL"},
+ {HPHW_FIO, 0x008, 0x00073, 0x0, "Flounder Core HIL"},
+ {HPHW_FIO, 0x009, 0x00073, 0x0, "Outfield Core HIL"},
+ {HPHW_FIO, 0x00A, 0x00073, 0x0, "CoralII Core HIL"},
+ {HPHW_FIO, 0x00B, 0x00073, 0x0, "Scorpio Jr. Core HIL"},
+ {HPHW_FIO, 0x00C, 0x00073, 0x0, "Strider-50 Core HIL"},
+ {HPHW_FIO, 0x00D, 0x00073, 0x0, "Strider-33 Core HIL"},
+ {HPHW_FIO, 0x00E, 0x00073, 0x0, "Trailways-50 Core HIL"},
+ {HPHW_FIO, 0x00F, 0x00073, 0x0, "Trailways-33 Core HIL"},
+ {HPHW_FIO, 0x010, 0x00073, 0x0, "Pace Core HIL"},
+ {HPHW_FIO, 0x011, 0x00073, 0xcc, "SuperPace Wax HIL"},
+ {HPHW_FIO, 0x012, 0x00073, 0x0, "Mirage Jr Wax HIL"},
+ {HPHW_FIO, 0x013, 0x00073, 0x0, "Mirage 100 Wax HIL"},
+ {HPHW_FIO, 0x014, 0x00073, 0x0, "Electra Wax HIL"},
+ {HPHW_FIO, 0x017, 0x00073, 0x0, "Raven Backplane Wax HIL"},
+ {HPHW_FIO, 0x019, 0x00073, 0x0, "Scorpio Sr. Core HIL"},
+ {HPHW_FIO, 0x01E, 0x00073, 0x0, "Raven T' Wax HIL"},
+ {HPHW_FIO, 0x01F, 0x00073, 0x0, "SkyHawk 100/120 Wax HIL"},
+ {HPHW_FIO, 0x020, 0x00073, 0x0, "Scorpio 100 Core HIL"},
+ {HPHW_FIO, 0x021, 0x00073, 0x0, "Spectra 50 Core HIL"},
+ {HPHW_FIO, 0x022, 0x00073, 0x0, "Spectra 75 Core HIL"},
+ {HPHW_FIO, 0x023, 0x00073, 0x0, "Spectra 100 Core HIL"},
+ {HPHW_FIO, 0x024, 0x00073, 0x0, "Fast Pace Core HIL"},
+ {HPHW_FIO, 0x026, 0x00073, 0x0, "CoralII Jaguar Core HIL"},
+ {HPHW_FIO, 0x02B, 0x00073, 0x0, "Mirage 80 Wax HIL"},
+ {HPHW_FIO, 0x02C, 0x00073, 0x0, "Mirage 100+ Wax HIL"},
+ {HPHW_FIO, 0x03A, 0x00073, 0x0, "Merlin+ Wax HIL"},
+ {HPHW_FIO, 0x040, 0x00073, 0x0, "Merlin 132 Wax HIL"},
+ {HPHW_FIO, 0x041, 0x00073, 0x0, "Merlin 160 Wax HIL"},
+ {HPHW_FIO, 0x043, 0x00073, 0x0, "Merlin 132/160 Wax HIL"},
+ {HPHW_FIO, 0x052, 0x00073, 0x0, "Raven+ Hi Power Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x053, 0x00073, 0x0, "Raven+ Hi Power Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x054, 0x00073, 0x0, "Raven+ Lo Power Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x055, 0x00073, 0x0, "Raven+ Lo Power Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x059, 0x00073, 0x0, "FireHawk 200 Wax HIL"},
+ {HPHW_FIO, 0x05A, 0x00073, 0x0, "Raven+ L2 Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x05B, 0x00073, 0x0, "Raven+ L2 Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x05D, 0x00073, 0x0, "SummitHawk Wax HIL"},
+ {HPHW_FIO, 0x800, 0x00073, 0x0, "Hitachi Tiny 64 Wax HIL"},
+ {HPHW_FIO, 0x801, 0x00073, 0x0, "Hitachi Tiny 80 Wax HIL"},
+ {HPHW_FIO, 0x004, 0x00074, 0x0, "Cobra Core Centronics"},
+ {HPHW_FIO, 0x005, 0x00074, 0x0, "Coral Core Centronics"},
+ {HPHW_FIO, 0x006, 0x00074, 0x0, "Bushmaster Core Centronics"},
+ {HPHW_FIO, 0x007, 0x00074, 0x0, "Scorpio Core Centronics"},
+ {HPHW_FIO, 0x008, 0x00074, 0x0, "Flounder Core Centronics"},
+ {HPHW_FIO, 0x009, 0x00074, 0x0, "Outfield Core Centronics"},
+ {HPHW_FIO, 0x00A, 0x00074, 0x0, "CoralII Core Centronics"},
+ {HPHW_FIO, 0x00B, 0x00074, 0x0, "Scorpio Jr. Core Centronics"},
+ {HPHW_FIO, 0x00C, 0x00074, 0x0, "Strider-50 Core Centronics"},
+ {HPHW_FIO, 0x00D, 0x00074, 0x0, "Strider-33 Core Centronics"},
+ {HPHW_FIO, 0x00E, 0x00074, 0x0, "Trailways-50 Core Centronics"},
+ {HPHW_FIO, 0x00F, 0x00074, 0x0, "Trailways-33 Core Centronics"},
+ {HPHW_FIO, 0x010, 0x00074, 0x0, "Pace Core Centronics"},
+ {HPHW_FIO, 0x011, 0x00074, 0x0, "Sidewinder Core Centronics"},
+ {HPHW_FIO, 0x015, 0x00074, 0x0, "KittyHawk GSY Core Centronics"},
+ {HPHW_FIO, 0x016, 0x00074, 0x0, "Gecko Core Centronics"},
+ {HPHW_FIO, 0x019, 0x00074, 0x0, "Scorpio Sr. Core Centronics"},
+ {HPHW_FIO, 0x01A, 0x00074, 0x0, "Anole 64 Core Centronics"},
+ {HPHW_FIO, 0x01B, 0x00074, 0x0, "Anole 100 Core Centronics"},
+ {HPHW_FIO, 0x01C, 0x00074, 0x0, "Gecko 80 Core Centronics"},
+ {HPHW_FIO, 0x01D, 0x00074, 0x0, "Gecko 100 Core Centronics"},
+ {HPHW_FIO, 0x01F, 0x00074, 0x0, "SkyHawk 100/120 Core Centronics"},
+ {HPHW_FIO, 0x020, 0x00074, 0x0, "Scorpio 100 Core Centronics"},
+ {HPHW_FIO, 0x021, 0x00074, 0x0, "Spectra 50 Core Centronics"},
+ {HPHW_FIO, 0x022, 0x00074, 0x0, "Spectra 75 Core Centronics"},
+ {HPHW_FIO, 0x023, 0x00074, 0x0, "Spectra 100 Core Centronics"},
+ {HPHW_FIO, 0x024, 0x00074, 0x0, "Fast Pace Core Centronics"},
+ {HPHW_FIO, 0x026, 0x00074, 0x0, "CoralII Jaguar Core Centronics"},
+ {HPHW_FIO, 0x027, 0x00074, 0x0, "Piranha 100 Core Centronics"},
+ {HPHW_FIO, 0x028, 0x00074, 0x0, "Mirage Jr Core Centronics"},
+ {HPHW_FIO, 0x029, 0x00074, 0x0, "Mirage Core Centronics"},
+ {HPHW_FIO, 0x02A, 0x00074, 0x0, "Electra Core Centronics"},
+ {HPHW_FIO, 0x02B, 0x00074, 0x0, "Mirage 80 Core Centronics"},
+ {HPHW_FIO, 0x02C, 0x00074, 0x0, "Mirage 100+ Core Centronics"},
+ {HPHW_FIO, 0x02E, 0x00074, 0x0, "UL 350 Core Centronics"},
+ {HPHW_FIO, 0x02F, 0x00074, 0x0, "UL 550 Core Centronics"},
+ {HPHW_FIO, 0x032, 0x00074, 0x0, "Raven T' Core Centronics"},
+ {HPHW_FIO, 0x033, 0x00074, 0x0, "Anole T Core Centronics"},
+ {HPHW_FIO, 0x034, 0x00074, 0x0, "SAIC L-80 Core Centronics"},
+ {HPHW_FIO, 0x035, 0x00074, 0x0, "PCX-L2 712/132 Core Centronics"},
+ {HPHW_FIO, 0x036, 0x00074, 0x0, "PCX-L2 712/160 Core Centronics"},
+ {HPHW_FIO, 0x03B, 0x00074, 0x0, "Raven U/L2 Core Centronics"},
+ {HPHW_FIO, 0x03C, 0x00074, 0x0, "Merlin 132 Core Centronics"},
+ {HPHW_FIO, 0x03D, 0x00074, 0x0, "Merlin 160 Core Centronics"},
+ {HPHW_FIO, 0x03E, 0x00074, 0x0, "Merlin+ 132 Core Centronics"},
+ {HPHW_FIO, 0x03F, 0x00074, 0x0, "Merlin+ 180 Core Centronics"},
+ {HPHW_FIO, 0x044, 0x00074, 0x0, "Mohawk Core Centronics"},
+ {HPHW_FIO, 0x045, 0x00074, 0x0, "Rocky1 Core Centronics"},
+ {HPHW_FIO, 0x046, 0x00074, 0x0, "Rocky2 120 Core Centronics"},
+ {HPHW_FIO, 0x047, 0x00074, 0x0, "Rocky2 150 Core Centronics"},
+ {HPHW_FIO, 0x04B, 0x00074, 0x0, "Anole L2 132 Core Centronics"},
+ {HPHW_FIO, 0x04D, 0x00074, 0x0, "Anole L2 165 Core Centronics"},
+ {HPHW_FIO, 0x050, 0x00074, 0x0, "Merlin Jr 132 Core Centronics"},
+ {HPHW_FIO, 0x051, 0x00074, 0x0, "Firehawk Core Centronics"},
+ {HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ wSE FWSCSI Core Centronics"},
+ {HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ wDiff FWSCSI Core Centronics"},
+ {HPHW_FIO, 0x058, 0x00074, 0x0, "FireHawk 200 Core Centronics"},
+ {HPHW_FIO, 0x05C, 0x00074, 0x0, "SummitHawk 230 Core Centronics"},
+ {HPHW_FIO, 0x800, 0x00074, 0x0, "Hitachi Tiny 64 Core Centronics"},
+ {HPHW_FIO, 0x801, 0x00074, 0x0, "Hitachi Tiny 80 Core Centronics"},
+ {HPHW_FIO, 0x004, 0x00075, 0x0, "Cobra Core RS-232"},
+ {HPHW_FIO, 0x005, 0x00075, 0x0, "Coral Core RS-232"},
+ {HPHW_FIO, 0x006, 0x00075, 0x0, "Bushmaster Core RS-232"},
+ {HPHW_FIO, 0x007, 0x00075, 0x0, "Scorpio Core RS-232"},
+ {HPHW_FIO, 0x008, 0x00075, 0x0, "Flounder Core RS-232"},
+ {HPHW_FIO, 0x009, 0x00075, 0x0, "Outfield Core RS-232"},
+ {HPHW_FIO, 0x00A, 0x00075, 0x0, "CoralII Core RS-232"},
+ {HPHW_FIO, 0x00B, 0x00075, 0x0, "Scorpio Jr. Core RS-232"},
+ {HPHW_FIO, 0x00C, 0x00075, 0x0, "Strider-50 Core RS-232"},
+ {HPHW_FIO, 0x00D, 0x00075, 0x0, "Strider-33 Core RS-232"},
+ {HPHW_FIO, 0x00E, 0x00075, 0x0, "Trailways-50 Core RS-232"},
+ {HPHW_FIO, 0x00F, 0x00075, 0x0, "Trailways-33 Core RS-232"},
+ {HPHW_FIO, 0x010, 0x00075, 0x0, "Pace Core RS-232"},
+ {HPHW_FIO, 0x011, 0x00075, 0x0, "Sidewinder Core RS-232"},
+ {HPHW_FIO, 0x019, 0x00075, 0x0, "Scorpio Sr. Core RS-232"},
+ {HPHW_FIO, 0x020, 0x00075, 0x0, "Scorpio 100 Core RS-232"},
+ {HPHW_FIO, 0x021, 0x00075, 0x0, "Spectra 50 Core RS-232"},
+ {HPHW_FIO, 0x022, 0x00075, 0x0, "Spectra 75 Core RS-232"},
+ {HPHW_FIO, 0x023, 0x00075, 0x0, "Spectra 100 Core RS-232"},
+ {HPHW_FIO, 0x024, 0x00075, 0x0, "Fast Pace Core RS-232"},
+ {HPHW_FIO, 0x026, 0x00075, 0x0, "CoralII Jaguar Core RS-232"},
+ {HPHW_FIO, 0x004, 0x00077, 0x0, "Coral SGC Graphics"},
+ {HPHW_FIO, 0x005, 0x00077, 0x0, "Hyperdrive Optional Graphics"},
+ {HPHW_FIO, 0x006, 0x00077, 0x0, "Stinger Optional Graphics"},
+ {HPHW_FIO, 0x007, 0x00077, 0x0, "Scorpio Builtin Graphics"},
+ {HPHW_FIO, 0x008, 0x00077, 0x0, "Anole Hyperdrive Optional Graphics"},
+ {HPHW_FIO, 0x009, 0x00077, 0x0, "Thunder II graphics EISA form"},
+ {HPHW_FIO, 0x00A, 0x00077, 0x0, "Thunder II graphics GSA form"},
+ {HPHW_FIO, 0x00B, 0x00077, 0x0, "Scorpio Jr Builtin Graphics"},
+ {HPHW_FIO, 0x00C, 0x00077, 0x0, "Strider-50 SSC Graphics"},
+ {HPHW_FIO, 0x00D, 0x00077, 0x0, "Strider-33 SSC Graphics"},
+ {HPHW_FIO, 0x00E, 0x00077, 0x0, "Trailways-50 SSC Graphics"},
+ {HPHW_FIO, 0x00F, 0x00077, 0x0, "Trailways-33 SSC Graphics"},
+ {HPHW_FIO, 0x010, 0x00077, 0x0, "Pace SGC Graphics"},
+ {HPHW_FIO, 0x011, 0x00077, 0x0, "Mohawk Opt. 2D Graphics (Kid)"},
+ {HPHW_FIO, 0x012, 0x00077, 0x0, "Raven Opt. 2D Graphics (Goat)"},
+ {HPHW_FIO, 0x016, 0x00077, 0x0, "Lego 24 SCG Graphics"},
+ {HPHW_FIO, 0x017, 0x00077, 0x0, "Lego 24Z SCG Graphics"},
+ {HPHW_FIO, 0x018, 0x00077, 0x0, "Lego 48Z SCG Graphics"},
+ {HPHW_FIO, 0x019, 0x00077, 0x0, "Scorpio Sr Builtin Graphics"},
+ {HPHW_FIO, 0x020, 0x00077, 0x0, "Scorpio 100 Builtin Graphics"},
+ {HPHW_FIO, 0x021, 0x00077, 0x0, "Spectra 50 Builtin Graphics"},
+ {HPHW_FIO, 0x022, 0x00077, 0x0, "Spectra 75 Builtin Graphics"},
+ {HPHW_FIO, 0x023, 0x00077, 0x0, "Spectra 100 Builtin Graphics"},
+ {HPHW_FIO, 0x024, 0x00077, 0x0, "Fast Pace SGC Graphics"},
+ {HPHW_FIO, 0x006, 0x0007A, 0x0, "Bushmaster Audio"},
+ {HPHW_FIO, 0x008, 0x0007A, 0x0, "Flounder Audio"},
+ {HPHW_FIO, 0x004, 0x0007B, 0x0, "UL Optional Audio"},
+ {HPHW_FIO, 0x007, 0x0007B, 0x0, "Scorpio Audio"},
+ {HPHW_FIO, 0x00B, 0x0007B, 0x0, "Scorpio Jr. Audio"},
+ {HPHW_FIO, 0x00C, 0x0007B, 0x0, "Strider-50 Audio"},
+ {HPHW_FIO, 0x00D, 0x0007B, 0x0, "Strider-33 Audio"},
+ {HPHW_FIO, 0x00E, 0x0007B, 0x0, "Trailways-50 Audio"},
+ {HPHW_FIO, 0x00F, 0x0007B, 0x0, "Trailways-33 Audio"},
+ {HPHW_FIO, 0x016, 0x0007B, 0x0, "Gecko Audio"},
+ {HPHW_FIO, 0x019, 0x0007B, 0x0, "Scorpio Sr. Audio"},
+ {HPHW_FIO, 0x01A, 0x0007B, 0x0, "Anole 64 Audio"},
+ {HPHW_FIO, 0x01B, 0x0007B, 0x0, "Anole 100 Audio"},
+ {HPHW_FIO, 0x01C, 0x0007B, 0x0, "Gecko 80 Audio"},
+ {HPHW_FIO, 0x01D, 0x0007B, 0x0, "Gecko 100 Audio"},
+ {HPHW_FIO, 0x01F, 0x0007B, 0x0, "SkyHawk 100/120 Audio"},
+ {HPHW_FIO, 0x020, 0x0007B, 0x0, "Scorpio 100 Audio"},
+ {HPHW_FIO, 0x021, 0x0007B, 0x0, "Spectra 50 Audio"},
+ {HPHW_FIO, 0x022, 0x0007B, 0x0, "Spectra 75 Audio"},
+ {HPHW_FIO, 0x023, 0x0007B, 0x0, "Spectra 100 Audio"},
+ {HPHW_FIO, 0x028, 0x0007B, 0x0, "Mirage Jr Audio"},
+ {HPHW_FIO, 0x029, 0x0007B, 0x0, "Mirage Audio"},
+ {HPHW_FIO, 0x02A, 0x0007B, 0x0, "Electra Audio"},
+ {HPHW_FIO, 0x02B, 0x0007B, 0x0, "Mirage 80 Audio"},
+ {HPHW_FIO, 0x02C, 0x0007B, 0x0, "Mirage 100+ Audio"},
+ {HPHW_FIO, 0x032, 0x0007B, 0x0, "Raven T' Audio"},
+ {HPHW_FIO, 0x034, 0x0007B, 0x0, "SAIC L-80 Audio"},
+ {HPHW_FIO, 0x035, 0x0007B, 0x0, "PCX-L2 712/132 Core Audio"},
+ {HPHW_FIO, 0x036, 0x0007B, 0x0, "PCX-L2 712/160 Core Audio"},
+ {HPHW_FIO, 0x03B, 0x0007B, 0x0, "Raven U/L2 Core Audio"},
+ {HPHW_FIO, 0x03C, 0x0007B, 0x0, "Merlin 132 Core Audio"},
+ {HPHW_FIO, 0x03D, 0x0007B, 0x0, "Merlin 160 Core Audio"},
+ {HPHW_FIO, 0x03E, 0x0007B, 0x0, "Merlin+ 132 Core Audio"},
+ {HPHW_FIO, 0x03F, 0x0007B, 0x0, "Merlin+ 180 Core Audio"},
+ {HPHW_FIO, 0x044, 0x0007B, 0x0, "Mohawk Core Audio"},
+ {HPHW_FIO, 0x046, 0x0007B, 0x0, "Rocky2 120 Core Audio"},
+ {HPHW_FIO, 0x047, 0x0007B, 0x0, "Rocky2 150 Core Audio"},
+ {HPHW_FIO, 0x04B, 0x0007B, 0x0, "Anole L2 132 Core Audio"},
+ {HPHW_FIO, 0x04D, 0x0007B, 0x0, "Anole L2 165 Core Audio"},
+ {HPHW_FIO, 0x04E, 0x0007B, 0x0, "Kiji L2 132 Core Audio"},
+ {HPHW_FIO, 0x050, 0x0007B, 0x0, "Merlin Jr 132 Core Audio"},
+ {HPHW_FIO, 0x051, 0x0007B, 0x0, "Firehawk Audio"},
+ {HPHW_FIO, 0x056, 0x0007B, 0x0, "Raven+ w SE FWSCSU Core Audio"},
+ {HPHW_FIO, 0x057, 0x0007B, 0x0, "Raven+ w Diff FWSCSU Core Audio"},
+ {HPHW_FIO, 0x058, 0x0007B, 0x0, "FireHawk 200 Audio"},
+ {HPHW_FIO, 0x05C, 0x0007B, 0x0, "SummitHawk 230 Core Audio"},
+ {HPHW_FIO, 0x800, 0x0007B, 0x0, "Hitachi Tiny 64 Audio"},
+ {HPHW_FIO, 0x801, 0x0007B, 0x0, "Hitachi Tiny 80 Audio"},
+ {HPHW_FIO, 0x009, 0x0007C, 0x0, "Outfield FW SCSI"},
+ {HPHW_FIO, 0x00A, 0x0007C, 0x0, "CoralII FW SCSI"},
+ {HPHW_FIO, 0x026, 0x0007C, 0x0, "CoralII Jaguar FW SCSI"},
+ {HPHW_FIO, 0x009, 0x0007D, 0x0, "Outfield FDDI"},
+ {HPHW_FIO, 0x00A, 0x0007D, 0x0, "CoralII FDDI"},
+ {HPHW_FIO, 0x026, 0x0007D, 0x0, "CoralII Jaguar FDDI"},
+ {HPHW_FIO, 0x010, 0x0007E, 0x0, "Pace Audio"},
+ {HPHW_FIO, 0x024, 0x0007E, 0x0, "Fast Pace Audio"},
+ {HPHW_FIO, 0x009, 0x0007F, 0x0, "Outfield Audio"},
+ {HPHW_FIO, 0x00A, 0x0007F, 0x0, "CoralII Audio"},
+ {HPHW_FIO, 0x026, 0x0007F, 0x0, "CoralII Jaguar Audio"},
+ {HPHW_FIO, 0x010, 0x00080, 0x0, "Pace Core HPIB"},
+ {HPHW_FIO, 0x024, 0x00080, 0x0, "Fast Pace Core HPIB"},
+ {HPHW_FIO, 0x016, 0x00082, 0x0, "Gecko Core SCSI"},
+ {HPHW_FIO, 0x01A, 0x00082, 0x0, "Anole 64 Core SCSI"},
+ {HPHW_FIO, 0x01B, 0x00082, 0x0, "Anole 100 Core SCSI"},
+ {HPHW_FIO, 0x01C, 0x00082, 0x0, "Gecko 80 Core SCSI"},
+ {HPHW_FIO, 0x01D, 0x00082, 0x0, "Gecko 100 Core SCSI"},
+ {HPHW_FIO, 0x01F, 0x00082, 0x0, "SkyHawk 100/120 Core SCSI"},
+ {HPHW_FIO, 0x027, 0x00082, 0x0, "Piranha 100 Core SCSI"},
+ {HPHW_FIO, 0x028, 0x00082, 0x0, "Mirage Jr Core SCSI"},
+ {HPHW_FIO, 0x029, 0x00082, 0x0, "Mirage Core SCSI"},
+ {HPHW_FIO, 0x02A, 0x00082, 0x0, "Electra Core SCSI"},
+ {HPHW_FIO, 0x02B, 0x00082, 0x0, "Mirage 80 Core SCSI"},
+ {HPHW_FIO, 0x02C, 0x00082, 0x0, "Mirage 100+ Core SCSI"},
+ {HPHW_FIO, 0x02E, 0x00082, 0x0, "UL 350 Core SCSI"},
+ {HPHW_FIO, 0x02F, 0x00082, 0x0, "UL 550 Core SCSI"},
+ {HPHW_FIO, 0x032, 0x00082, 0x0, "Raven T' Core SCSI"},
+ {HPHW_FIO, 0x033, 0x00082, 0x0, "Anole T Core SCSI"},
+ {HPHW_FIO, 0x034, 0x00082, 0x0, "SAIC L-80 Core SCSI"},
+ {HPHW_FIO, 0x035, 0x00082, 0x0, "PCX-L2 712/132 Core SCSI"},
+ {HPHW_FIO, 0x036, 0x00082, 0x0, "PCX-L2 712/160 Core SCSI"},
+ {HPHW_FIO, 0x03B, 0x00082, 0x0, "Raven U/L2 Core SCSI"},
+ {HPHW_FIO, 0x03C, 0x00082, 0x0, "Merlin 132 Core SCSI"},
+ {HPHW_FIO, 0x03D, 0x00082, 0x0, "Merlin 160 Core SCSI"},
+ {HPHW_FIO, 0x03E, 0x00082, 0x0, "Merlin+ 132 Core SCSI"},
+ {HPHW_FIO, 0x03F, 0x00082, 0x0, "Merlin+ 180 Core SCSI"},
+ {HPHW_FIO, 0x044, 0x00082, 0x0, "Mohawk Core SCSI"},
+ {HPHW_FIO, 0x045, 0x00082, 0x0, "Rocky1 Core SCSI"},
+ {HPHW_FIO, 0x046, 0x00082, 0x0, "Rocky2 120 Core SCSI"},
+ {HPHW_FIO, 0x047, 0x00082, 0x0, "Rocky2 150 Core SCSI"},
+ {HPHW_FIO, 0x04B, 0x00082, 0x0, "Anole L2 132 Core SCSI"},
+ {HPHW_FIO, 0x04D, 0x00082, 0x0, "Anole L2 165 Core SCSI"},
+ {HPHW_FIO, 0x04E, 0x00082, 0x0, "Kiji L2 132 Core SCSI"},
+ {HPHW_FIO, 0x050, 0x00082, 0x0, "Merlin Jr 132 Core SCSI"},
+ {HPHW_FIO, 0x051, 0x00082, 0x0, "Firehawk Core SCSI"},
+ {HPHW_FIO, 0x056, 0x00082, 0x0, "Raven+ w SE FWSCSI Core SCSI"},
+ {HPHW_FIO, 0x057, 0x00082, 0x0, "Raven+ w Diff FWSCSI Core SCSI"},
+ {HPHW_FIO, 0x058, 0x00082, 0x0, "FireHawk 200 Core SCSI"},
+ {HPHW_FIO, 0x05C, 0x00082, 0x0, "SummitHawk 230 Core SCSI"},
+ {HPHW_FIO, 0x05E, 0x00082, 0x0, "Staccato 132 Core SCSI"},
+ {HPHW_FIO, 0x05F, 0x00082, 0x0, "Staccato 180 Core SCSI"},
+ {HPHW_FIO, 0x800, 0x00082, 0x0, "Hitachi Tiny 64 Core SCSI"},
+ {HPHW_FIO, 0x801, 0x00082, 0x0, "Hitachi Tiny 80 Core SCSI"},
+ {HPHW_FIO, 0x016, 0x00083, 0x0, "Gecko Core PC Floppy"},
+ {HPHW_FIO, 0x01C, 0x00083, 0x0, "Gecko 80 Core PC Floppy"},
+ {HPHW_FIO, 0x01D, 0x00083, 0x0, "Gecko 100 Core PC Floppy"},
+ {HPHW_FIO, 0x051, 0x00083, 0x0, "Firehawk Core PC Floppy"},
+ {HPHW_FIO, 0x058, 0x00083, 0x0, "FireHawk 200 Core PC Floppy"},
+ {HPHW_FIO, 0x027, 0x00083, 0x0, "Piranha 100 Core PC Floppy"},
+ {HPHW_FIO, 0x028, 0x00083, 0x0, "Mirage Jr Core PC Floppy"},
+ {HPHW_FIO, 0x029, 0x00083, 0x0, "Mirage Core PC Floppy"},
+ {HPHW_FIO, 0x02A, 0x00083, 0x0, "Electra Core PC Floppy"},
+ {HPHW_FIO, 0x02B, 0x00083, 0x0, "Mirage 80 Core PC Floppy"},
+ {HPHW_FIO, 0x02C, 0x00083, 0x0, "Mirage 100+ Core PC Floppy"},
+ {HPHW_FIO, 0x02E, 0x00083, 0x0, "UL 350 Core PC Floppy"},
+ {HPHW_FIO, 0x02F, 0x00083, 0x0, "UL 550 Core PC Floppy"},
+ {HPHW_FIO, 0x032, 0x00083, 0x0, "Raven T' Core PC Floppy"},
+ {HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floopy"},
+ {HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floopy"},
+ {HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floopy"},
+ {HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floopy"},
+ {HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floopy"},
+ {HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floopy"},
+ {HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floopy"},
+ {HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floopy"},
+ {HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floopy"},
+ {HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floopy"},
+ {HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floopy"},
+ {HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floopy"},
+ {HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floopy"},
+ {HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floopy"},
+ {HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floopy"},
+ {HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floopy"},
+ {HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floopy"},
+ {HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PC Keyboard"},
+ {HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PC Keyboard"},
+ {HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PC Keyboard"},
+ {HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PC Keyboard"},
+ {HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PC Keyboard"},
+ {HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PC Keyboard"},
+ {HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PC Keyboard"},
+ {HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PC Keyboard"},
+ {HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PC Keyboard"},
+ {HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PC Keyboard"},
+ {HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PC Keyboard"},
+ {HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PC Keyboard"},
+ {HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PC Keyboard"},
+ {HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PC Keyboard"},
+ {HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PC Keyboard"},
+ {HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PC Keyboard"},
+ {HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PC Keyboard"},
+ {HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PC Keyboard"},
+ {HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PC Keyboard"},
+ {HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core Keyboard"},
+ {HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core Keyboard"},
+ {HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PC Keyboard"},
+ {HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PC Keyboard"},
+ {HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PC Keyboard"},
+ {HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PC Keyboard"},
+ {HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PC Keyboard"},
+ {HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PC Keyboard"},
+ {HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PC Keyboard"},
+ {HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PC Keyboard"},
+ {HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PC Keyboard"},
+ {HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PC Keyboard"},
+ {HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PC Keyboard"},
+ {HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PC Keyboard"},
+ {HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PC Keyboard"},
+ {HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PC Keyboard"},
+ {HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PC Keyboard"},
+ {HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PC Keyboard"},
+ {HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PC Keyboard"},
+ {HPHW_FIO, 0x004, 0x00085, 0x0, "Solo GSC Optional Graphics"},
+ {HPHW_FIO, 0x005, 0x00085, 0x0, "Duet GSC Optional Graphics"},
+ {HPHW_FIO, 0x008, 0x00085, 0x0, "Anole Artist Optional Graphics"},
+ {HPHW_FIO, 0x010, 0x00085, 0x0, "Mirage 80 GSC Builtin Graphics"},
+ {HPHW_FIO, 0x011, 0x00085, 0x0, "Mirage 100+ GSC Builtin Graphics"},
+ {HPHW_FIO, 0x012, 0x00085, 0x0, "Mirage Jr GSC Builtin Graphics"},
+ {HPHW_FIO, 0x013, 0x00085, 0x0, "Mirage GSC Builtin Graphics"},
+ {HPHW_FIO, 0x014, 0x00085, 0x0, "Electra GSC Builtin Graphics"},
+ {HPHW_FIO, 0x016, 0x00085, 0x0, "Gecko GSC Core Graphics"},
+ {HPHW_FIO, 0x017, 0x00085, 0x0, "Gecko GSC Optional Graphics"},
+ {HPHW_FIO, 0x01A, 0x00085, 0x0, "Anole 64 Artist Builtin Graphics"},
+ {HPHW_FIO, 0x01B, 0x00085, 0x0, "Anole 100 Artist Builtin Graphics"},
+ {HPHW_FIO, 0x01C, 0x00085, 0x0, "Gecko 80 GSC Core Graphics"},
+ {HPHW_FIO, 0x01D, 0x00085, 0x0, "Gecko 100 GSC Core Graphics"},
+ {HPHW_FIO, 0x032, 0x00085, 0x0, "Raven T' GSC Core Graphics"},
+ {HPHW_FIO, 0x033, 0x00085, 0x0, "Anole T Artist Builtin Graphics"},
+ {HPHW_FIO, 0x034, 0x00085, 0x0, "SAIC L-80 GSC Core Graphics"},
+ {HPHW_FIO, 0x035, 0x00085, 0x0, "PCX-L2 712/132 Core Graphics"},
+ {HPHW_FIO, 0x036, 0x00085, 0x0, "PCX-L2 712/160 Core Graphics"},
+ {HPHW_FIO, 0x03B, 0x00085, 0x0, "Raven U/L2 Core Graphics"},
+ {HPHW_FIO, 0x03C, 0x00085, 0x0, "Merlin 132 Core Graphics"},
+ {HPHW_FIO, 0x03D, 0x00085, 0x0, "Merlin 160 Core Graphics"},
+ {HPHW_FIO, 0x03E, 0x00085, 0x0, "Merlin+ 132 Core Graphics"},
+ {HPHW_FIO, 0x03F, 0x00085, 0x0, "Merlin+ 180 Core Graphics"},
+ {HPHW_FIO, 0x045, 0x00085, 0x0, "Rocky1 Core Graphics"},
+ {HPHW_FIO, 0x046, 0x00085, 0x0, "Rocky2 120 Core Graphics"},
+ {HPHW_FIO, 0x047, 0x00085, 0x0, "Rocky2 150 Core Graphics"},
+ {HPHW_FIO, 0x04B, 0x00085, 0x0, "Anole L2 132 Core Graphics"},
+ {HPHW_FIO, 0x04D, 0x00085, 0x0, "Anole L2 165 Core Graphics"},
+ {HPHW_FIO, 0x04E, 0x00085, 0x0, "Kiji L2 132 Core Graphics"},
+ {HPHW_FIO, 0x050, 0x00085, 0x0, "Merlin Jr 132 Core Graphics"},
+ {HPHW_FIO, 0x056, 0x00085, 0x0, "Raven+ w SE FWSCSI Core Graphics"},
+ {HPHW_FIO, 0x057, 0x00085, 0x0, "Raven+ w Diff FWSCSI Core Graphics"},
+ {HPHW_FIO, 0x800, 0x00085, 0x0, "Hitachi Tiny 64 Core Graphics"},
+ {HPHW_FIO, 0x801, 0x00085, 0x0, "Hitachi Tiny 80 Core Graphics"},
+ {HPHW_FIO, 0x004, 0x00086, 0x0, "GSC IBM Token Ring"},
+ {HPHW_FIO, 0x015, 0x00087, 0x0, "Gecko Optional ISDN"},
+ {HPHW_FIO, 0x016, 0x00087, 0x0, "Gecko Core ISDN"},
+ {HPHW_FIO, 0x01C, 0x00087, 0x0, "Gecko 80 Core ISDN"},
+ {HPHW_FIO, 0x01D, 0x00087, 0x0, "Gecko 100 Core ISDN"},
+ {HPHW_FIO, 0x010, 0x00088, 0x0, "Pace VME Networking"},
+ {HPHW_FIO, 0x011, 0x00088, 0x0, "Sidewinder VME Networking"},
+ {HPHW_FIO, 0x01A, 0x00088, 0x0, "Anole 64 VME Networking"},
+ {HPHW_FIO, 0x01B, 0x00088, 0x0, "Anole 100 VME Networking"},
+ {HPHW_FIO, 0x024, 0x00088, 0x0, "Fast Pace VME Networking"},
+ {HPHW_FIO, 0x034, 0x00088, 0x0, "Anole T VME Networking"},
+ {HPHW_FIO, 0x04A, 0x00088, 0x0, "Anole L2 132 VME Networking"},
+ {HPHW_FIO, 0x04C, 0x00088, 0x0, "Anole L2 165 VME Networking"},
+ {HPHW_FIO, 0x03B, 0x00089, 0x0, "Raven U/L2 Core FW-SCSI"},
+ {HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core Lan (802.3)"},
+ {HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core Lan (802.3)"},
+ {HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core Lan (802.3)"},
+ {HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core Lan (802.3)"},
+ {HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core Lan (802.3)"},
+ {HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core Lan (802.3)"},
+ {HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional Lan (802.3)"},
+ {HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core Lan (802.3)"},
+ {HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core Lan (802.3)"},
+ {HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core Lan (802.3)"},
+ {HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core Lan (802.3)"},
+ {HPHW_FIO, 0x01F, 0x0008A, 0x0, "SkyHawk 100/120 Core LAN (802.3)"},
+ {HPHW_FIO, 0x027, 0x0008A, 0x0, "Piranha 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x028, 0x0008A, 0x0, "Mirage Jr Core LAN (802.3)"},
+ {HPHW_FIO, 0x029, 0x0008A, 0x0, "Mirage Core LAN (802.3)"},
+ {HPHW_FIO, 0x02A, 0x0008A, 0x0, "Electra Core LAN (802.3)"},
+ {HPHW_FIO, 0x02B, 0x0008A, 0x0, "Mirage 80 Core LAN (802.3)"},
+ {HPHW_FIO, 0x02C, 0x0008A, 0x0, "Mirage 100+ Core LAN (802.3)"},
+ {HPHW_FIO, 0x02E, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"},
+ {HPHW_FIO, 0x02F, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"},
+ {HPHW_FIO, 0x032, 0x0008A, 0x0, "Raven T' Core LAN (802.3)"},
+ {HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core Lan (802.3)"},
+ {HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core Lan (802.3)"},
+ {HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core Lan (802.3)"},
+ {HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core Lan (802.3)"},
+ {HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core Lan (802.3)"},
+ {HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core Lan (802.3)"},
+ {HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core Lan (802.3)"},
+ {HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core Lan (802.3)"},
+ {HPHW_FIO, 0x045, 0x0008A, 0x0, "Rocky1 Core LAN (802.3)"},
+ {HPHW_FIO, 0x046, 0x0008A, 0x0, "Rocky2 120 Core LAN (802.3)"},
+ {HPHW_FIO, 0x047, 0x0008A, 0x0, "Rocky2 150 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04B, 0x0008A, 0x0, "Anole L2 132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04D, 0x0008A, 0x0, "Anole L2 165 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04E, 0x0008A, 0x0, "Kiji L2 132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core Lan (802.3)"},
+ {HPHW_FIO, 0x058, 0x0008A, 0x0, "FireHawk 200 Core LAN (802.3)"},
+ {HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core Lan (802.3)"},
+ {HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core Lan (802.3)"},
+ {HPHW_FIO, 0x004, 0x0008C, 0x0, "SkyHawk 100/120 Wax RS-232"},
+ {HPHW_FIO, 0x005, 0x0008C, 0x0, "SAIC L-80 Wax RS-232"},
+ {HPHW_FIO, 0x006, 0x0008C, 0x0, "Raven U/L2 Dino RS-232"},
+ {HPHW_FIO, 0x007, 0x0008C, 0x0, "Dino RS-232"},
+ {HPHW_FIO, 0x008, 0x0008C, 0x0, "Merlin 132 Dino RS-232"},
+ {HPHW_FIO, 0x009, 0x0008C, 0x0, "Merlin 160 Dino RS-232"},
+ {HPHW_FIO, 0x00A, 0x0008C, 0x0, "Merlin Jr 132 Dino RS-232"},
+ {HPHW_FIO, 0x010, 0x0008C, 0x0, "Mirage 80 Wax RS-232"},
+ {HPHW_FIO, 0x011, 0x0008C, 0x0, "Mirage 100+ Wax RS-232"},
+ {HPHW_FIO, 0x012, 0x0008C, 0x0, "Mirage Jr Wax RS-232"},
+ {HPHW_FIO, 0x013, 0x0008C, 0x0, "Mirage Wax RS-232"},
+ {HPHW_FIO, 0x014, 0x0008C, 0x0, "Electra Wax RS-232"},
+ {HPHW_FIO, 0x015, 0x0008C, 0x0, "KittyHawk GSY Core RS-232"},
+ {HPHW_FIO, 0x016, 0x0008C, 0x0, "Gecko Core RS-232"},
+ {HPHW_FIO, 0x017, 0x0008C, 0x0, "Raven Backplane RS-232"},
+ {HPHW_FIO, 0x018, 0x0008C, 0x0, "Gecko Optional RS-232"},
+ {HPHW_FIO, 0x019, 0x0008C, 0x0, "Merlin+ 180 Dino RS-232"},
+ {HPHW_FIO, 0x01A, 0x0008C, 0x0, "Anole 64 Core RS-232"},
+ {HPHW_FIO, 0x01B, 0x0008C, 0x0, "Anole 100 Core RS-232"},
+ {HPHW_FIO, 0x01C, 0x0008C, 0x0, "Gecko 80 Core RS-232"},
+ {HPHW_FIO, 0x01D, 0x0008C, 0x0, "Gecko 100 Core RS-232"},
+ {HPHW_FIO, 0x01E, 0x0008C, 0x0, "Raven T' Wax RS-232"},
+ {HPHW_FIO, 0x01F, 0x0008C, 0x0, "SkyHawk 100/120 Core RS-232"},
+ {HPHW_FIO, 0x020, 0x0008C, 0x0, "Anole 64 Timi RS-232"},
+ {HPHW_FIO, 0x021, 0x0008C, 0x0, "Anole 100 Timi RS-232"},
+ {HPHW_FIO, 0x022, 0x0008C, 0x0, "Merlin+ 132 Dino RS-232"},
+ {HPHW_FIO, 0x023, 0x0008C, 0x0, "Rocky1 Wax RS-232"},
+ {HPHW_FIO, 0x025, 0x0008C, 0x0, "Armyknife Optional RS-232"},
+ {HPHW_FIO, 0x026, 0x0008C, 0x0, "Piranha 100 Wax RS-232"},
+ {HPHW_FIO, 0x027, 0x0008C, 0x0, "Piranha 100 Core RS-232"},
+ {HPHW_FIO, 0x028, 0x0008C, 0x0, "Mirage Jr Core RS-232"},
+ {HPHW_FIO, 0x029, 0x0008C, 0x0, "Mirage Core RS-232"},
+ {HPHW_FIO, 0x02A, 0x0008C, 0x0, "Electra Core RS-232"},
+ {HPHW_FIO, 0x02B, 0x0008C, 0x0, "Mirage 80 Core RS-232"},
+ {HPHW_FIO, 0x02C, 0x0008C, 0x0, "Mirage 100+ Core RS-232"},
+ {HPHW_FIO, 0x02E, 0x0008C, 0x0, "UL 350 Lasi Core RS-232"},
+ {HPHW_FIO, 0x02F, 0x0008C, 0x0, "UL 550 Lasi Core RS-232"},
+ {HPHW_FIO, 0x030, 0x0008C, 0x0, "UL 350 Wax Core RS-232"},
+ {HPHW_FIO, 0x031, 0x0008C, 0x0, "UL 550 Wax Core RS-232"},
+ {HPHW_FIO, 0x032, 0x0008C, 0x0, "Raven T' Lasi Core RS-232"},
+ {HPHW_FIO, 0x033, 0x0008C, 0x0, "Anole T Core RS-232"},
+ {HPHW_FIO, 0x034, 0x0008C, 0x0, "SAIC L-80 Core RS-232"},
+ {HPHW_FIO, 0x035, 0x0008C, 0x0, "PCX-L2 712/132 Core RS-232"},
+ {HPHW_FIO, 0x036, 0x0008C, 0x0, "PCX-L2 712/160 Core RS-232"},
+ {HPHW_FIO, 0x03A, 0x0008C, 0x0, "Merlin+ Wax RS-232"},
+ {HPHW_FIO, 0x03B, 0x0008C, 0x0, "Raven U/L2 Core RS-232"},
+ {HPHW_FIO, 0x03C, 0x0008C, 0x0, "Merlin 132 Core RS-232"},
+ {HPHW_FIO, 0x03D, 0x0008C, 0x0, "Merlin 160 Core RS-232"},
+ {HPHW_FIO, 0x03E, 0x0008C, 0x0, "Merlin+ 132 Core RS-232"},
+ {HPHW_FIO, 0x03F, 0x0008C, 0x0, "Merlin+ 180 Core RS-232"},
+ {HPHW_FIO, 0x040, 0x0008C, 0x0, "Merlin 132 Wax RS-232"},
+ {HPHW_FIO, 0x041, 0x0008C, 0x0, "Merlin 160 Wax RS-232"},
+ {HPHW_FIO, 0x043, 0x0008C, 0x0, "Merlin 132/160 Wax RS-232"},
+ {HPHW_FIO, 0x044, 0x0008C, 0x0, "Mohawk Core RS-232"},
+ {HPHW_FIO, 0x045, 0x0008C, 0x0, "Rocky1 Core RS-232"},
+ {HPHW_FIO, 0x046, 0x0008C, 0x0, "Rocky2 120 Core RS-232"},
+ {HPHW_FIO, 0x047, 0x0008C, 0x0, "Rocky2 150 Core RS-232"},
+ {HPHW_FIO, 0x048, 0x0008C, 0x0, "Rocky2 120 Dino RS-232"},
+ {HPHW_FIO, 0x049, 0x0008C, 0x0, "Rocky2 150 Dino RS-232"},
+ {HPHW_FIO, 0x04A, 0x0008C, 0x0, "Anole L2 132 TIMI RS-232"},
+ {HPHW_FIO, 0x04B, 0x0008C, 0x0, "Anole L2 l32 Core RS-232"},
+ {HPHW_FIO, 0x04C, 0x0008D, 0x0, "Anole L2 165 TIMI RS-232"},
+ {HPHW_FIO, 0x04D, 0x0008C, 0x0, "Anole L2 165 Core RS-232"},
+ {HPHW_FIO, 0x04E, 0x0008C, 0x0, "Kiji L2 132 Core RS-232"},
+ {HPHW_FIO, 0x04F, 0x0008C, 0x0, "Kiji L2 132 Dino RS-232"},
+ {HPHW_FIO, 0x050, 0x0008C, 0x0, "Merlin Jr 132 Core RS-232"},
+ {HPHW_FIO, 0x051, 0x0008C, 0x0, "Firehawk Core RS-232"},
+ {HPHW_FIO, 0x052, 0x0008C, 0x0, "Raven+ Hi Power Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x053, 0x0008C, 0x0, "Raven+ Hi Power Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x054, 0x0008C, 0x0, "Raven+ Lo Power Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x055, 0x0008C, 0x0, "Raven+ Lo Power Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x056, 0x0008C, 0x0, "Raven+ w SE FWSCSI Core RS-232"},
+ {HPHW_FIO, 0x057, 0x0008C, 0x0, "Raven+ w Diff FWSCSI Core RS-232"},
+ {HPHW_FIO, 0x058, 0x0008C, 0x0, "FireHawk 200 Core RS-232"},
+ {HPHW_FIO, 0x059, 0x0008C, 0x0, "FireHawk 200 Wax RS-232"},
+ {HPHW_FIO, 0x05A, 0x0008C, 0x0, "Raven+ L2 Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x05B, 0x0008C, 0x0, "Raven+ L2 Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x05D, 0x0008C, 0x0, "SummitHawk Dino RS-232"},
+ {HPHW_FIO, 0x05E, 0x0008C, 0x0, "Staccato 132 Core LAN RS-232"},
+ {HPHW_FIO, 0x05F, 0x0008C, 0x0, "Staccato 180 Core LAN RS-232"},
+ {HPHW_FIO, 0x800, 0x0008C, 0x0, "Hitachi Tiny 64 Core RS-232"},
+ {HPHW_FIO, 0x801, 0x0008C, 0x0, "Hitachi Tiny 80 Core RS-232"},
+ {HPHW_FIO, 0x015, 0x0008D, 0x0, "Gecko Optional RJ-16"},
+ {HPHW_FIO, 0x016, 0x0008D, 0x0, "Gecko Core RJ-16"},
+ {HPHW_FIO, 0x01C, 0x0008D, 0x0, "Gecko 80 Core RJ-16"},
+ {HPHW_FIO, 0x01D, 0x0008D, 0x0, "Gecko 100 Core RJ-16"},
+ {HPHW_FIO, 0x004, 0x0008F, 0x0, "Anole Boot Rom"},
+ {HPHW_FIO, 0x005, 0x0008F, 0x0, "Rocky1 Boot Rom"},
+ {HPHW_FIO, 0x006, 0x0008F, 0x0, "Rocky2 120 Boot Rom"},
+ {HPHW_FIO, 0x007, 0x0008F, 0x0, "Rocky2 150 Boot Rom"},
+ {HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG lan"},
+ {HPHW_FIO, 0x023, 0x00099, 0x0, "Rocky1 Wax HPIB"},
+ {HPHW_FIO, 0x048, 0x00099, 0x0, "Rocky2 120 Clark/Dino HPIB"},
+ {HPHW_FIO, 0x049, 0x00099, 0x0, "Rocky2 150 Clark/Dino HPIB"},
+ {HPHW_FIO, 0x004, 0x000A1, 0x0, "SPP2000 Console TTY"},
+ {HPHW_FIO, 0x004, 0x000A2, 0x0, "Forte Core PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x005, 0x000A2, 0x0, "AllegroLow PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x006, 0x000A2, 0x0, "AllegroHIgh Core PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in Lan"},
+ {HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT Lan"},
+ {HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI Lan"},
+ {HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI Lan"},
+ {HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI Lan"},
+ {HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI Lan"},
+ {HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI Lan"},
+ {HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI Lan"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI SE UltraSCSI"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x007, 0x000A3, 0x0, "PCI Plug-in Disk"},
+ {HPHW_FIO, 0x008, 0x000A3, 0x0, "A5158A S FC Tachlite HBA"},
+ {HPHW_FIO, 0x009, 0x000A3, 0x0, "A5157A D FC HBA"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI NSE UltraSCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI WSE UltraSCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x03E, 0x000A3, 0x0, "Merlin+ 132 Core SE FWSCSI PCI Disk"},
+ {HPHW_FIO, 0x03F, 0x000A3, 0x0, "Merlin+ 180 Core SE FWSCSI PCI Disk"},
+ {HPHW_FIO, 0x056, 0x000A3, 0x0, "Raven+ w SE FWSCSI Core PCI Disk"},
+ {HPHW_FIO, 0x057, 0x000A3, 0x0, "Raven+ w Diff FWSCSI Core PCI Disk"},
+ {HPHW_FIO, 0x004, 0x000A4, 0x0, "SPP2000 Core BA"},
+ {HPHW_FIO, 0x004, 0x000A6, 0x0, "Sonic Ethernet 802.3 Card"},
+ {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI USB KB"},
+ {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI USB KB"},
+ {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI USB KB"},
+ {HPHW_FIO, 0x007, 0x000A9, 0x0, "Miscelaneous PCI Plug-in"},
+ {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI USB KB"},
+ {HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"},
+ {HPHW_FIO, 0x004, 0x00340, 0x0, "BARCO CX4500 VME Grphx Cnsl"},
+ {HPHW_FIO, 0x004, 0x00360, 0x0, "Hughes TOG VME FDDI"},
+ {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"},
+ {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"},
+ {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"},
+ {HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"},
+ {HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"},
+ {HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"},
+ {HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"},
+ {HPHW_MEMORY, 0x00C, 0x00008, 0x08, "Kahlua 8MB"},
+ {HPHW_MEMORY, 0x00D, 0x00008, 0x08, "Kahlua 4MB"},
+ {HPHW_MEMORY, 0x00E, 0x00008, 0x08, "Tequila 16MB"},
+ {HPHW_MEMORY, 0x00F, 0x00008, 0x08, "Tequila 32MB"},
+ {HPHW_MEMORY, 0x040, 0x00008, 0x00, "Hitachi"},
+ {HPHW_MEMORY, 0x004, 0x00009, 0x00, "Cheetah"},
+ {HPHW_MEMORY, 0x005, 0x00009, 0x00, "Emerald"},
+ {HPHW_MEMORY, 0x008, 0x00009, 0x00, "Indigo 3MB/5MB"},
+ {HPHW_MEMORY, 0x00C, 0x00009, 0x00, "Indigo 8MB"},
+ {HPHW_MEMORY, 0x00D, 0x00009, 0x00, "Paradise 4MB"},
+ {HPHW_MEMORY, 0x00E, 0x00009, 0x00, "Burgundy Onboard"},
+ {HPHW_MEMORY, 0x012, 0x00009, 0x00, "Indigo 12MB/20MB"},
+ {HPHW_MEMORY, 0x013, 0x00009, 0x00, "Cobra"},
+ {HPHW_MEMORY, 0x014, 0x00009, 0x00, "Nova"},
+ {HPHW_MEMORY, 0x015, 0x00009, 0x00, "Coral"},
+ {HPHW_MEMORY, 0x016, 0x00009, 0x00, "Bushmaster"},
+ {HPHW_MEMORY, 0x017, 0x00009, 0x00, "Scorpio"},
+ {HPHW_MEMORY, 0x018, 0x00009, 0x00, "Flounder"},
+ {HPHW_MEMORY, 0x019, 0x00009, 0x00, "Hardball"},
+ {HPHW_MEMORY, 0x01A, 0x00009, 0x00, "CoralII 99"},
+ {HPHW_MEMORY, 0x01B, 0x00009, 0x00, "Scorpio Jr."},
+ {HPHW_MEMORY, 0x01C, 0x00009, 0x00, "Strider-50 (715T)"},
+ {HPHW_MEMORY, 0x01D, 0x00009, 0x00, "Strider-33 (707T)"},
+ {HPHW_MEMORY, 0x01E, 0x00009, 0x00, "Trailways-50 (715S)"},
+ {HPHW_MEMORY, 0x01F, 0x00009, 0x00, "Trailways-33 (707S)"},
+ {HPHW_MEMORY, 0x020, 0x00009, 0x00, "Pace"},
+ {HPHW_MEMORY, 0x021, 0x00009, 0x00, "Sidewinder"},
+ {HPHW_MEMORY, 0x022, 0x00009, 0x00, "Orville"},
+ {HPHW_MEMORY, 0x023, 0x00009, 0x00, "Wilbur"},
+ {HPHW_MEMORY, 0x026, 0x00009, 0x00, "Gecko"},
+ {HPHW_MEMORY, 0x027, 0x00009, 0x00, "Scorpio Sr."},
+ {HPHW_MEMORY, 0x028, 0x00009, 0x00, "Scorpio 100"},
+ {HPHW_MEMORY, 0x029, 0x00009, 0x00, "Spectra 50"},
+ {HPHW_MEMORY, 0x02A, 0x00009, 0x00, "CoralII 132"},
+ {HPHW_MEMORY, 0x02F, 0x00009, 0x00, "KittyHawk DC2-"},
+ {HPHW_MEMORY, 0x030, 0x00009, 0x00, "Spectra 75"},
+ {HPHW_MEMORY, 0x031, 0x00009, 0x00, "Spectra 100"},
+ {HPHW_MEMORY, 0x032, 0x00009, 0x00, "KittyHawk DC3"},
+ {HPHW_MEMORY, 0x033, 0x00009, 0x00, "Fast Pace"},
+ {HPHW_MEMORY, 0x034, 0x00009, 0x00, "Snake Eagle"},
+ {HPHW_MEMORY, 0x035, 0x00009, 0x00, "Anole 64"},
+ {HPHW_MEMORY, 0x036, 0x00009, 0x00, "Anole 100"},
+ {HPHW_MEMORY, 0x037, 0x00009, 0x00, "Snake Cheetah"},
+ {HPHW_MEMORY, 0x038, 0x00009, 0x00, "Gecko 80"},
+ {HPHW_MEMORY, 0x039, 0x00009, 0x00, "Gecko 100"},
+ {HPHW_MEMORY, 0x03A, 0x00009, 0x00, "Gecko 120"},
+ {HPHW_MEMORY, 0x03B, 0x00009, 0x00, "Gila 80"},
+ {HPHW_MEMORY, 0x03C, 0x00009, 0x00, "Gila 100"},
+ {HPHW_MEMORY, 0x03D, 0x00009, 0x00, "Gila 120"},
+ {HPHW_MEMORY, 0x03E, 0x00009, 0x00, "Scorpio-L 80"},
+ {HPHW_MEMORY, 0x03F, 0x00009, 0x00, "Scorpio-L 100"},
+ {HPHW_MEMORY, 0x040, 0x00009, 0x00, "Scorpio-L 120"},
+ {HPHW_MEMORY, 0x041, 0x00009, 0x00, "Spectra-L 80"},
+ {HPHW_MEMORY, 0x042, 0x00009, 0x00, "Spectra-L 100"},
+ {HPHW_MEMORY, 0x043, 0x00009, 0x00, "Spectra-L 120"},
+ {HPHW_MEMORY, 0x044, 0x00009, 0x00, "Piranha 100"},
+ {HPHW_MEMORY, 0x045, 0x00009, 0x00, "Piranha 120"},
+ {HPHW_MEMORY, 0x046, 0x00009, 0x00, "Jason 50"},
+ {HPHW_MEMORY, 0x047, 0x00009, 0x00, "Jason 100"},
+ {HPHW_MEMORY, 0x049, 0x00009, 0x00, "SkyHawk 100/120"},
+ {HPHW_MEMORY, 0x04A, 0x00009, 0x00, "Mirage Jr"},
+ {HPHW_MEMORY, 0x04B, 0x00009, 0x00, "Mirage 100"},
+ {HPHW_MEMORY, 0x04C, 0x00009, 0x00, "Mirage 100+"},
+ {HPHW_MEMORY, 0x04D, 0x00009, 0x00, "Electra 100"},
+ {HPHW_MEMORY, 0x04E, 0x00009, 0x00, "Electra 120"},
+ {HPHW_MEMORY, 0x04F, 0x00009, 0x00, "Mirage 80"},
+ {HPHW_MEMORY, 0x050, 0x00009, 0x00, "UL Proc 1 way T'100"},
+ {HPHW_MEMORY, 0x051, 0x00009, 0x00, "UL Proc 1 way T'120"},
+ {HPHW_MEMORY, 0x052, 0x00009, 0x00, "UL Proc 2 way T'100"},
+ {HPHW_MEMORY, 0x053, 0x00009, 0x00, "KittyHawk DC3-"},
+ {HPHW_MEMORY, 0x054, 0x00009, 0x00, "UL Proc 2 way T'120"},
+ {HPHW_MEMORY, 0x055, 0x00009, 0x00, "Raven 120 mem"},
+ {HPHW_MEMORY, 0x056, 0x00009, 0x00, "UL Proc L 75"},
+ {HPHW_MEMORY, 0x057, 0x00009, 0x00, "UL Proc L 100"},
+ {HPHW_MEMORY, 0x058, 0x00009, 0x00, "Anole T"},
+ {HPHW_MEMORY, 0x059, 0x00009, 0x00, "SAIC L-80"},
+ {HPHW_MEMORY, 0x05A, 0x00009, 0x00, "Merlin+ L2 180"},
+ {HPHW_MEMORY, 0x05B, 0x00009, 0x00, "Raven U 200 2-way"},
+ {HPHW_MEMORY, 0x05C, 0x00009, 0x00, "Raven U 180+"},
+ {HPHW_MEMORY, 0x05D, 0x00009, 0x00, "Raven U 200"},
+ {HPHW_MEMORY, 0x05E, 0x00009, 0x00, "Rocky2 150 Memory"},
+ {HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"},
+ {HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"},
+ {HPHW_MEMORY, 0x05F, 0x00009, 0x00, "SPP2000 Memory"},
+ {HPHW_MEMORY, 0x060, 0x00009, 0x00, "Merlin L2 132"},
+ {HPHW_MEMORY, 0x061, 0x00009, 0x00, "Merlin+ L2 132"},
+ {HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"},
+ {HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"},
+ {HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"},
+ {HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"},
+ {HPHW_MEMORY, 0x067, 0x00009, 0x00, "Merlin 160/ThunderHawk Memory"},
+ {HPHW_MEMORY, 0x068, 0x00009, 0x00, "LightningHawk Memory"},
+ {HPHW_MEMORY, 0x069, 0x00009, 0x00, "Rocky1 Memory"},
+ {HPHW_MEMORY, 0x06A, 0x00009, 0x00, "Raven L2 132"},
+ {HPHW_MEMORY, 0x06B, 0x00009, 0x00, "Raven L2 160"},
+ {HPHW_MEMORY, 0x06C, 0x00009, 0x00, "Raven L2 187"},
+ {HPHW_MEMORY, 0x06D, 0x00009, 0x00, "Raven L2 200"},
+ {HPHW_MEMORY, 0x06E, 0x00009, 0x00, "Raven U 230"},
+ {HPHW_MEMORY, 0x06F, 0x00009, 0x00, "Raven U 240"},
+ {HPHW_MEMORY, 0x070, 0x00009, 0x00, "Rocky2 120 Memory"},
+ {HPHW_MEMORY, 0x071, 0x00009, 0x00, "Raven U 160"},
+ {HPHW_MEMORY, 0x072, 0x00009, 0x00, "Raven U 180"},
+ {HPHW_MEMORY, 0x072, 0x00009, 0x00, "UL Proc 1 way T'120 1MB/1MB"},
+ {HPHW_MEMORY, 0x073, 0x00009, 0x00, "UL Proc 2 way T'120 1MB/1MB"},
+ {HPHW_MEMORY, 0x074, 0x00009, 0x00, "Anole L2 132 memory"},
+ {HPHW_MEMORY, 0x075, 0x00009, 0x00, "Anole L2 165 memory"},
+ {HPHW_MEMORY, 0x076, 0x00009, 0x00, "UL 1 way U160 512K/512K memory"},
+ {HPHW_MEMORY, 0x077, 0x00009, 0x00, "UL 2 way U160 512K/512K memory"},
+ {HPHW_MEMORY, 0x078, 0x00009, 0x00, "Kiji L2 132 memory"},
+ {HPHW_MEMORY, 0x079, 0x00009, 0x00, "UL 1 way U160 1M/1M memory"},
+ {HPHW_MEMORY, 0x07A, 0x00009, 0x00, "UL 2 way U160 1M/1M memory"},
+ {HPHW_MEMORY, 0x07B, 0x00009, 0x00, "UL 1 way U180 1M/1M memory"},
+ {HPHW_MEMORY, 0x07C, 0x00009, 0x00, "UL 2 way U180 1M/1M memory"},
+ {HPHW_MEMORY, 0x07D, 0x00009, 0x00, "UL 1 way U240 U+ 2M/2M memory"},
+ {HPHW_MEMORY, 0x07E, 0x00009, 0x00, "UL 2 way U240 U+ 2M/2M memory"},
+ {HPHW_MEMORY, 0x07F, 0x00009, 0x00, "UL L2 132 memory"},
+ {HPHW_MEMORY, 0x080, 0x00009, 0x00, "UL L2 160 memory"},
+ {HPHW_MEMORY, 0x081, 0x00009, 0x00, "Merlin Jr 132 memory"},
+ {HPHW_MEMORY, 0x082, 0x00009, 0x00, "FireHawk 200 Memory"},
+ {HPHW_MEMORY, 0x083, 0x00009, 0x00, "SummitHawk Memory"},
+ {HPHW_MEMORY, 0x084, 0x00009, 0x00, "Jade Upgrade Memory"},
+ {HPHW_MEMORY, 0x085, 0x00009, 0x00, "SPP2500 Memory"},
+ {HPHW_MEMORY, 0x086, 0x00009, 0x00, "AllegroHigh Memory"},
+ {HPHW_MEMORY, 0x087, 0x00009, 0x00, "AllegroLow Memory"},
+ {HPHW_MEMORY, 0x088, 0x00009, 0x00, "Forte 2w Memory"},
+ {HPHW_MEMORY, 0x089, 0x00009, 0x00, "Forte 4w Memory"},
+ {HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"},
+ {HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"},
+ {HPHW_MEMORY, 0x090, 0x00009, 0x00, "Prelude SMC Memory"},
+ {HPHW_MEMORY, 0x091, 0x00009, 0x00, "Lego 360 Memory"},
+ {HPHW_MEMORY, 0x7FF, 0x00009, 0x00, "NEC Aska memory"},
+ {HPHW_MEMORY, 0x800, 0x00009, 0x00, "Hitachi Tiny 64"},
+ {HPHW_MEMORY, 0x801, 0x00009, 0x00, "Hitachi Tiny 80"},
+ {HPHW_MEMORY, 0x8FF, 0x00009, 0x00, "Hitachi X memory"},
+ {HPHW_MEMORY, 0x091, 0x00009, 0x00, "M2250 Memory"},
+ {HPHW_MEMORY, 0x092, 0x00009, 0x00, "M2500 Memory"},
+ {HPHW_MEMORY, 0x093, 0x00009, 0x00, "Sonata 440 Memory"},
+ {HPHW_MEMORY, 0x094, 0x00009, 0x00, "Sonata 360 Memory"},
+ {HPHW_MEMORY, 0x095, 0x00009, 0x00, "Rhapsody 440 Memory"},
+ {HPHW_MEMORY, 0x096, 0x00009, 0x00, "Rhapsody 360 Memory"},
+ {HPHW_MEMORY, 0x097, 0x00009, 0x00, "Raven W 360 Memory"},
+ {HPHW_MEMORY, 0x098, 0x00009, 0x00, "Halfdome W 440 Memory"},
+ {HPHW_MEMORY, 0x099, 0x00009, 0x00, "Rhapsody DC- 440 Memory"},
+ {HPHW_MEMORY, 0x09A, 0x00009, 0x00, "Rhapsody DC- 360 Memory"},
+ {HPHW_MEMORY, 0x09B, 0x00009, 0x00, "Crescendo Memory"},
+ {HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"},
+ {HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"},
+ {HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"},
+ {HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"},
+ {0, } /* leave the last entry empty ! */
+};
+
+
+static struct hp_cpu_type_mask {
+ unsigned short model;
+ unsigned short mask;
+ enum cpu_type cpu;
+} hp_cpu_type_mask_list[] = {
+
+ { 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */
+ { 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */
+ { 0x0080, 0x0ff0, pcx }, /* 0x0080 - 0x008f */
+ { 0x0100, 0x0ff0, pcx }, /* 0x0100 - 0x010f */
+ { 0x0182, 0x0ffe, pcx }, /* 0x0182 - 0x0183 */
+ { 0x0182, 0x0ffe, pcxt }, /* 0x0182 - 0x0183 */
+ { 0x0184, 0x0fff, pcxu }, /* 0x0184 - 0x0184 */
+ { 0x0200, 0x0ffe, pcxs }, /* 0x0200 - 0x0201 */
+ { 0x0202, 0x0fff, pcxs }, /* 0x0202 - 0x0202 */
+ { 0x0203, 0x0fff, pcxt }, /* 0x0203 - 0x0203 */
+ { 0x0204, 0x0ffc, pcxt }, /* 0x0204 - 0x0207 */
+ { 0x0280, 0x0ffc, pcxs }, /* 0x0280 - 0x0283 */
+ { 0x0284, 0x0ffc, pcxt }, /* 0x0284 - 0x0287 */
+ { 0x0288, 0x0fff, pcxt }, /* 0x0288 - 0x0288 */
+ { 0x0300, 0x0ffc, pcxs }, /* 0x0300 - 0x0303 */
+ { 0x0310, 0x0ff0, pcxt }, /* 0x0310 - 0x031f */
+ { 0x0320, 0x0ff0, pcxt }, /* 0x0320 - 0x032f */
+ { 0x0400, 0x0ff0, pcxt }, /* 0x0400 - 0x040f */
+ { 0x0480, 0x0ff0, pcxl }, /* 0x0480 - 0x048f */
+ { 0x0500, 0x0ff0, pcxl2 }, /* 0x0500 - 0x050f */
+ { 0x0510, 0x0ff0, pcxl2 }, /* 0x0510 - 0x051f */
+ { 0x0580, 0x0ff8, pcxt_ }, /* 0x0580 - 0x0587 */
+ { 0x0588, 0x0ffc, pcxt_ }, /* 0x0588 - 0x058b */
+ { 0x058c, 0x0ffe, pcxt_ }, /* 0x058c - 0x058d */
+ { 0x058e, 0x0fff, pcxt_ }, /* 0x058e - 0x058e */
+ { 0x058f, 0x0fff, pcxu }, /* 0x058f - 0x058f */
+ { 0x0590, 0x0ffe, pcxu }, /* 0x0590 - 0x0591 */
+ { 0x0592, 0x0fff, pcxt_ }, /* 0x0592 - 0x0592 */
+ { 0x0593, 0x0fff, pcxu }, /* 0x0593 - 0x0593 */
+ { 0x0594, 0x0ffc, pcxu }, /* 0x0594 - 0x0597 */
+ { 0x0598, 0x0ffc, pcxu }, /* 0x0598 - 0x059b */
+ { 0x059c, 0x0ffe, pcxu_ }, /* 0x059c - 0x059d */
+ { 0x059e, 0x0fff, pcxt_ }, /* 0x059e - 0x059e */
+ { 0x059f, 0x0fff, pcxu }, /* 0x059f - 0x059f */
+ { 0x05a0, 0x0ffe, pcxt_ }, /* 0x05a0 - 0x05a1 */
+ { 0x05a2, 0x0ffe, pcxu }, /* 0x05a2 - 0x05a3 */
+ { 0x05a4, 0x0ffc, pcxu }, /* 0x05a4 - 0x05a7 */
+ { 0x05a8, 0x0ffc, pcxu }, /* 0x05a8 - 0x05ab */
+ { 0x05ad, 0x0fff, pcxu_ }, /* 0x05ad - 0x05ad */
+ { 0x05ae, 0x0ffe, pcxu_ }, /* 0x05ae - 0x05af */
+ { 0x05b0, 0x0ffe, pcxu_ }, /* 0x05b0 - 0x05b1 */
+ { 0x05b2, 0x0fff, pcxu_ }, /* 0x05b2 - 0x05b2 */
+ { 0x05b3, 0x0fff, pcxu }, /* 0x05b3 - 0x05b3 */
+ { 0x05b4, 0x0fff, pcxw }, /* 0x05b4 - 0x05b4 */
+ { 0x05b5, 0x0fff, pcxu_ }, /* 0x05b5 - 0x05b5 */
+ { 0x05b6, 0x0ffe, pcxu_ }, /* 0x05b6 - 0x05b7 */
+ { 0x05b8, 0x0ffe, pcxu_ }, /* 0x05b8 - 0x05b9 */
+ { 0x05ba, 0x0fff, pcxu_ }, /* 0x05ba - 0x05ba */
+ { 0x05bb, 0x0fff, pcxw }, /* 0x05bb - 0x05bb */
+ { 0x05bc, 0x0ffc, pcxw }, /* 0x05bc - 0x05bf */
+ { 0x05c0, 0x0fc0, pcxw }, /* 0x05c0 - 0x05ff */
+ { 0x0600, 0x0ff0, pcxl }, /* 0x0600 - 0x060f */
+ { 0x0610, 0x0ff0, pcxl }, /* 0x0610 - 0x061f */
+ { 0x0000, 0x0000, pcx } /* terminate table */
+};
+
+char *cpu_name_version[][2] = {
+ [pcx] { "PA7000 (PCX)", "1.0" },
+ [pcxs] { "PA7000 (PCX-S)", "1.1a" },
+ [pcxt] { "PA7100 (PCX-T)", "1.1b" },
+ [pcxt_] { "PA7200 (PCX-T')", "1.1c" },
+ [pcxl] { "PA7100LC (PCX-L)", "1.1d" },
+ [pcxl2] { "PA7300LC (PCX-L2)", "1.1e" },
+ [pcxu] { "PA8000 (PCX-U)", "2.0" },
+ [pcxu_] { "PA8200 (PCX-U+)", "2.0" },
+ [pcxw] { "PA8500 (PCX-W)", "2.0" },
+ [pcxw_] { "PA8600 (PCX-W+)", "2.0" }
+};
+
+char *parisc_getHWtype(unsigned short hw_type)
+{
+ if (hw_type <= HPHW_CIO) {
+ return hw_type_name[hw_type];
+ } else {
+ return "Unknown Type";
+ }
+}
+
+char *parisc_getHWdescription(unsigned short hw_type, unsigned long hversion,
+ unsigned long sversion)
+{
+ struct hp_hardware *listptr;
+
+ for (listptr = hp_hardware_list; listptr->name; listptr++) {
+ if ((listptr->hw_type==hw_type) &&
+ (listptr->hversion==hversion) &&
+ (listptr->sversion==sversion)){
+ return listptr->name;
+ }
+ }
+ return "unknown device";
+}
+
+
+/* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */
+enum cpu_type parisc_get_cpu_type(unsigned long hversion)
+{
+ struct hp_cpu_type_mask *ptr;
+ unsigned short model = ((unsigned short) (hversion)) >> 4;
+
+ for (ptr = hp_cpu_type_mask_list; 0 != ptr->mask; ptr++) {
+ if (ptr->model == (model & ptr->mask))
+ return ptr->cpu;
+ }
+ panic("parisc_get_cpu_type() could not identify CPU type\n");
+
+ return pcx; /* not reached: */
+}
+
+
+struct hp_hardware *parisc_get_reference(unsigned short hw_type,
+ unsigned long hversion, unsigned long sversion)
+{
+ struct hp_hardware *listptr = hp_hardware_list;
+
+ for (listptr = hp_hardware_list; listptr->name; listptr++) {
+ if ((listptr->hw_type == hw_type) &&
+ (listptr->hversion == hversion) &&
+ (listptr->sversion == sversion)) {
+ return listptr;
+ }
+ }
+ return NULL;
+}
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
new file mode 100644
index 000000000..ce45dd608
--- /dev/null
+++ b/arch/parisc/kernel/head.S
@@ -0,0 +1,156 @@
+/*
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 by Helge Deller
+ * Copyright 1999 SuSE GmbH (Philipp Rumpf)
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ *
+ * Initial Version 04-23-1999 by Helge Deller (helge.deller@ruhr-uni-bochum.de)
+ */
+
+
+#include <asm/offset.h>
+#include <asm/psw.h>
+
+#define __ASSEMBLY__
+/*********
+#include <asm/pdc.h>
+*********/
+#include <asm/assembly.h>
+#include <asm/pgtable.h>
+
+
+ .level 1.1
+
+ .section .initcall.init
+ .align 4
+ .export __initcall_start
+__initcall_start:
+ .export __initcall_end
+__initcall_end:
+ .export __setup_start
+__setup_start:
+ .export __setup_end
+__setup_end:
+
+ .text
+ .align 4
+ .import init_task_union,data
+ .import $global$ /* forward declaration */
+ .import fault_vector_11,code /* IVA parisc 1.1 32 bit */
+ .import fault_vector_20,code /* IVA parisc 2.0 32 bit */
+ .import start_parisc,code /* then enable VM and go here */
+
+ .export stext
+ .export _stext,data /* Kernel want it this way! */
+_stext:
+stext:
+ .proc
+ .callinfo
+
+ /* Make sure sr4-sr7 are set to zero for the kernel address space */
+
+ mtsp %r0,%sr4
+ mtsp %r0,%sr5
+ mtsp %r0,%sr6
+ mtsp %r0,%sr7
+
+ /* Initialize startup VM. Just map first 8 MB of memory */
+
+ ldil L%PA(pg0),%r1
+ ldo R%PA(pg0)(%r1),%r1
+ ldo _PAGE_TABLE(%r1),%r3
+ ldil L%PA(swapper_pg_dir),%r4
+ ldo R%PA(swapper_pg_dir)(%r4),%r4
+ mtctl %r4,%cr24 /* Initialize kernel root pointer */
+ mtctl %r4,%cr25 /* Initialize user root pointer */
+ stw %r3,0xc00(%r4) /* Hardwired 0xc0000000 kernel vaddr start */
+ ldo 0x1000(%r3),%r3
+ stw %r3,0xc04(%r4)
+ ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0x0 phys addr start */
+$pgt_fill_loop:
+ stwm %r3,4(%r1)
+ ldo 0x1000(%r3),%r3
+ bb,>= %r3,8,$pgt_fill_loop
+ nop
+
+ /* Initialize the global data pointer */
+ ldil L%$global$,%dp
+ ldo R%$global$(%dp),%dp
+
+ /* And the stack pointer, physical too */
+ ldil L%init_task_union+TASK_SZ_ALGN,%sp
+ ldo R%init_task_union+TASK_SZ_ALGN(%sp),%sp
+
+ /* we need this to take interruptions directly after the rfi below */
+ /* (which we need for PA2.0 boxes) */
+ mtctl %r0, %cr30
+
+ /*
+ * Set up our interrupt table. HPMCs might not work after this!
+ *
+ * We need to install the correct iva for PA1.1 or PA2.0. The
+ * following short sequence of instructions can determine this
+ * (without being illegal on a PA1.1 machine).
+ */
+
+ ldi 32,%r10
+ mtctl %r10,%cr11
+ .level 2.0
+ mfctl,w %cr11,%r10
+ .level 1.1
+ comib,<>,n 0,%r10,$is_pa20
+ ldil L%PA(fault_vector_11),%r10
+ b $install_iva
+ ldo R%PA(fault_vector_11)(%r10),%r10
+
+$is_pa20:
+ ldil L%PA(fault_vector_20),%r10
+ ldo R%PA(fault_vector_20)(%r10),%r10
+
+$install_iva:
+ mtctl %r10,%cr14
+
+ /* Disable (most) interruptions */
+ mtsm %r0
+
+ /* kernel PSW:
+ * - no interruptions except for HPMC and TOC (which are handled by PDC)
+ * - Q bit set (IODC / PDC interruptions)
+ * - big-endian
+ * - virtually mapped
+ */
+
+ ldil L%KERNEL_PSW,%r10
+ ldo R%KERNEL_PSW(%r10),%r10
+ mtctl %r10,%ipsw
+
+ /* Set the space pointers for the post-RFI world */
+ mtctl %r0,%cr17 /* Clear two-level IIA Space Queue */
+ mtctl %r0,%cr17 /* effectively setting kernel space. */
+
+ /* And the return address(es) too */
+ ldil L%start_parisc,%r10
+ ldo R%start_parisc(%r10),%r10
+ mtctl %r10,%cr18
+ ldo 4(%r10),%r10
+ mtctl %r10,%cr18
+
+ /* Jump to hyperspace */
+ rfi
+ nop
+
+ .procend
+
+ .data
+
+ .align 4
+ .export $global$,data
+
+ .type $global$,@object
+ .size $global$,4
+$global$:
+ .word 0
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
new file mode 100644
index 000000000..c77aee04e
--- /dev/null
+++ b/arch/parisc/kernel/hpmc.S
@@ -0,0 +1,319 @@
+/*
+ * HPMC (High Priority Machine Check) handler.
+ *
+ * Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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 HPMC handler retrieves the HPMC pim data, resets IO and
+ * returns to the default trap handler with code set to 1 (HPMC).
+ * The default trap handler calls handle interruption, which
+ * does a stack and register dump. This at least allows kernel
+ * developers to get back to C code in virtual mode, where they
+ * have the option to examine and print values from memory that
+ * would help in debugging an HPMC caused by a software bug.
+ *
+ * There is more to do here:
+ *
+ * 1) On MP systems we need to synchronize processors
+ * before calling pdc/iodc.
+ * 2) We should be checking the system state and not
+ * returning to the fault handler if things are really
+ * bad.
+ *
+ */
+
+ .level 1.1
+ .data
+
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/pdc.h>
+
+ /*
+ * stack for os_hpmc, the HPMC handler.
+ * buffer for IODC procedures (for the HPMC handler).
+ *
+ * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc.
+ */
+
+ .align 4096
+hpmc_stack:
+ .block 16384
+
+#define HPMC_IODC_BUF_SIZE 0x8000
+
+ .align 4096
+hpmc_iodc_buf:
+ .block HPMC_IODC_BUF_SIZE
+
+ .align 8
+hpmc_raddr:
+ .block 128
+
+#define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */
+
+ .export hpmc_pim_data, data
+ .align 8
+hpmc_pim_data:
+ .block HPMC_PIM_DATA_SIZE
+
+ .text
+
+ .export os_hpmc, code
+ .import intr_save, code
+
+os_hpmc:
+
+ /*
+ * registers modified:
+ *
+ * Using callee saves registers without saving them. The
+ * original values are in the pim dump if we need them.
+ *
+ * r2 (rp) return pointer
+ * r3 address of PDCE_PROC
+ * r4 scratch
+ * r5 scratch
+ * r23 (arg3) procedure arg
+ * r24 (arg2) procedure arg
+ * r25 (arg1) procedure arg
+ * r26 (arg0) procedure arg
+ * r30 (sp) stack pointer
+ *
+ * registers read:
+ *
+ * r26 contains address of PDCE_PROC on entry
+ * r28 (ret0) return value from procedure
+ */
+
+ copy arg0, %r3 /* save address of PDCE_PROC */
+
+ /*
+ * disable nested HPMCs
+ *
+ * Increment os_hpmc checksum to invalidate it.
+ * Do this before turning the PSW M bit off.
+ */
+
+ mfctl %cr14, %r4
+ ldw 52(%r4),%r5
+ addi 1,%r5,%r5
+ stw %r5,52(%r4)
+
+ /* MP_FIXME: synchronize all processors. */
+
+ /* Setup stack pointer. */
+
+ ldil L%PA(hpmc_stack),sp
+ ldo R%PA(hpmc_stack)(sp),sp
+
+ ldo 128(sp),sp /* leave room for arguments */
+
+ /*
+ * Most PDC routines require that the M bit be off.
+ * So turn on the Q bit and turn off the M bit.
+ */
+
+ ldo 8(%r0),%r4 /* PSW Q on, PSW M off */
+ mtctl %r4,ipsw
+ mtctl %r0,pcsq
+ mtctl %r0,pcsq
+ ldil L%PA(os_hpmc_1),%r4
+ ldo R%PA(os_hpmc_1)(%r4),%r4
+ mtctl %r4,pcoq
+ ldo 4(%r4),%r4
+ mtctl %r4,pcoq
+ rfi
+ nop
+
+os_hpmc_1:
+
+ /* Call PDC_PIM to get HPMC pim info */
+
+ /*
+ * Note that on some newer boxes, PDC_PIM must be called
+ * before PDC_IO if you want IO to be reset. PDC_PIM sets
+ * a flag that PDC_IO examines.
+ */
+
+ ldo PDC_PIM(%r0), arg0
+ ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */
+ ldil L%PA(hpmc_raddr),arg2
+ ldo R%PA(hpmc_raddr)(arg2),arg2
+ ldil L%PA(hpmc_pim_data),arg3
+ ldo R%PA(hpmc_pim_data)(arg3),arg3
+ ldil L%HPMC_PIM_DATA_SIZE,%r4
+ ldo R%HPMC_PIM_DATA_SIZE(%r4),%r4
+ stw %r4,-52(sp)
+
+ ldil L%PA(os_hpmc_2), rp
+ bv (r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_2)(rp), rp
+
+os_hpmc_2:
+ comib,<> 0,ret0, os_hpmc_fail
+
+ /* Reset IO by calling the hversion dependent PDC_IO routine */
+
+ ldo PDC_IO(%r0),arg0
+ ldo 0(%r0),arg1 /* log IO errors */
+ ldo 0(%r0),arg2 /* reserved */
+ ldo 0(%r0),arg3 /* reserved */
+ stw %r0,-52(sp) /* reserved */
+
+ ldil L%PA(os_hpmc_3),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_3)(rp),rp
+
+os_hpmc_3:
+
+ /* FIXME? Check for errors from PDC_IO (-1 might be OK) */
+
+ /*
+ * Initialize the IODC console device (HPA,SPA, path etc.
+ * are stored on page 0.
+ */
+
+ /*
+ * Load IODC into hpmc_iodc_buf by calling PDC_IODC.
+ * Note that PDC_IODC handles flushing the appropriate
+ * data and instruction cache lines.
+ */
+
+ ldo PDC_IODC(%r0),arg0
+ ldo PDC_IODC_READ(%r0),arg1
+ ldil L%PA(hpmc_raddr),arg2
+ ldo R%PA(hpmc_raddr)(arg2),arg2
+ ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */
+ ldo PDC_IODC_RI_INIT(%r0),%r4
+ stw %r4,-52(sp)
+ ldil L%PA(hpmc_iodc_buf),%r4
+ ldo R%PA(hpmc_iodc_buf)(%r4),%r4
+ stw %r4,-56(sp)
+ ldil L%HPMC_IODC_BUF_SIZE,%r4
+ ldo R%HPMC_IODC_BUF_SIZE(%r4),%r4
+ stw %r4,-60(sp)
+
+ ldil L%PA(os_hpmc_4),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_4)(rp),rp
+
+os_hpmc_4:
+ comib,<> 0,ret0,os_hpmc_fail
+
+ /* Call the entry init (just loaded by PDC_IODC) */
+
+ ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg0 /* console hpa */
+ ldo ENTRY_INIT_MOD_DEV(%r0), arg1
+ ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */
+ depi 0,31,11,arg2 /* clear bits 21-31 */
+ ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */
+ ldil L%PA(hpmc_raddr),%r4
+ ldo R%PA(hpmc_raddr)(%r4),%r4
+ stw %r4, -52(sp)
+ stw %r0, -56(sp) /* HV */
+ stw %r0, -60(sp) /* HV */
+ stw %r0, -64(sp) /* HV */
+ stw %r0, -68(sp) /* lang, must be zero */
+
+ ldil L%PA(hpmc_iodc_buf),%r5
+ ldo R%PA(hpmc_iodc_buf)(%r5),%r5
+ ldil L%PA(os_hpmc_5),rp
+ bv (%r5)
+ ldo R%PA(os_hpmc_5)(rp),rp
+
+os_hpmc_5:
+ comib,<> 0,ret0,os_hpmc_fail
+
+ /* Prepare to call intr_save */
+
+ /*
+ * Load kernel page directory (load into user also, since
+ * we don't intend to ever return to user land anyway)
+ */
+
+ ldil L%PA(swapper_pg_dir),%r4
+ ldo R%PA(swapper_pg_dir)(%r4),%r4
+ mtctl %r4,%cr24 /* Initialize kernel root pointer */
+ mtctl %r4,%cr25 /* Initialize user root pointer */
+
+ /* Clear sr4-sr7 */
+
+ mtsp %r0, %sr4
+ mtsp %r0, %sr5
+ mtsp %r0, %sr6
+ mtsp %r0, %sr7
+
+ tovirt %r30 /* make sp virtual */
+
+ rsm 8,%r0 /* Clear Q bit */
+ ldi 1,%r1
+ mtctl %r1,%cr29 /* Set trap code to "1" for HPMC */
+ mtctl %r0,%cr30 /* Force interruptions to use hpmc stack */
+ ldil L%PA(intr_save), %r1
+ ldo R%PA(intr_save)(%r1), %r1
+ be 0(%sr7,%r1)
+ nop
+
+os_hpmc_fail:
+
+ /*
+ * Reset the system
+ *
+ * Some systems may lockup from a broadcast reset, so try the
+ * hversion PDC_BROADCAST_RESET() first.
+ * MP_FIXME: reset all processors if more than one central bus.
+ */
+
+ /* PDC_BROADCAST_RESET() */
+
+ ldo PDC_BROADCAST_RESET(%r0),arg0
+ ldo 0(%r0),arg1 /* do reset */
+
+ ldil L%PA(os_hpmc_6),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_6)(rp),rp
+
+os_hpmc_6:
+
+ /*
+ * possible return values:
+ * -1 non-existent procedure
+ * -2 non-existent option
+ * -16 unaligned stack
+ *
+ * If call returned, do a broadcast reset.
+ */
+
+ ldil L%0xfffc0000,%r4 /* IO_BROADCAST */
+ ldo 5(%r0),%r5
+ stw %r5,48(%r4) /* CMD_RESET to IO_COMMAND offset */
+
+ b .
+ nop
+
+ /* this label used to compute os_hpmc checksum */
+
+ .export os_hpmc_end, code
+
+os_hpmc_end:
+
+ nop
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
new file mode 100644
index 000000000..a838548de
--- /dev/null
+++ b/arch/parisc/kernel/init_task.c
@@ -0,0 +1,29 @@
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.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;
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * We need to make sure that this is 16384-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union task_union init_task_union
+ __attribute__((section("init_task"), aligned(4096))) = { INIT_TASK(init_task_union.task) };
+
+unsigned long swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(4096))) = { 0, };
+#ifdef __LP64__
+unsigned long pmd0[PTRS_PER_PMD] __attribute__ ((aligned(4096))) = { 0, };
+#endif
+unsigned long pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(4096))) = { 0, };
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c
new file mode 100644
index 000000000..ab97cff1e
--- /dev/null
+++ b/arch/parisc/kernel/inventory.c
@@ -0,0 +1,397 @@
+
+/* Copyright (c) 1999 The Puffin Group */
+/* Written by David Kennedy and Alex deVries */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/pdc.h>
+
+/*
+** Debug options
+** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices.
+*/
+#undef DEBUG_PAT
+
+extern char *parisc_getHWtype(unsigned short hw_type);
+
+extern struct hp_device * register_module(void *hpa);
+extern void print_devices(char * buf);
+
+
+int pdc_hpa_processor(void *address);
+
+#ifndef __LP64__
+static u8 iodc_data[32] __attribute__ ((aligned (64)));
+static struct pdc_model model __attribute__ ((aligned (8)));
+#endif
+static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
+static struct pdc_hpa processor_hpa __attribute__ ((aligned (8)));
+static struct pdc_system_map module_result __attribute__ ((aligned (8)));
+static struct pdc_module_path module_path __attribute__ ((aligned (8)));
+
+#ifdef __LP64__
+#include <asm/pdcpat.h>
+
+int pdc_pat = 0;
+
+/*
+** The module object is filled via PDC_PAT_CELL[Return Cell Module].
+** If a module is found, register module will get the IODC bytes via
+** pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter.
+**
+** The IO view can be used by PDC_PAT_CELL[Return Cell Module]
+** only for SBAs and LBAs. This view will cause an invalid
+** argument error for all other cell module types.
+**
+*/
+
+static int
+pat_query_module( ulong pcell_loc, ulong mod_index)
+{
+ extern int num_devices;
+ extern struct hp_device devices[];
+
+ pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+ struct hp_device * dev = &devices[num_devices];
+ uint64_t temp; /* 64-bit scratch value */
+ long status; /* PDC return value status */
+
+ /* return cell module (PA or Processor view) */
+ status = pdc_pat_cell_module(& pdc_result, pcell_loc, mod_index,
+ PA_VIEW, & pa_pdc_cell);
+
+ if (status != PDC_RET_OK) {
+ /* no more cell modules or error */
+ return status;
+ }
+
+ /*
+ ** save parameters in the hp_device
+ ** (The idea being the device driver will call pdc_pat_cell_module()
+ ** and store the results in it's own data structure.)
+ */
+ dev->pcell_loc = pcell_loc;
+ dev->mod_index = mod_index;
+
+ /* save generic info returned from the call */
+ /* REVISIT: who is the consumer of this? not sure yet... */
+ dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */
+ dev->pmod_loc = pa_pdc_cell.mod_location;
+ dev->mod_path = pa_pdc_cell.mod_path;
+
+ temp = pa_pdc_cell.cba;
+ register_module((void *) PAT_GET_CBA(temp)); /* fills in dev->hpa */
+
+#ifdef DEBUG_PAT
+ /* dump what we see so far... */
+ switch (PAT_GET_ENTITY(dev->mod_info)) {
+ ulong i;
+
+ case PAT_ENTITY_PROC:
+ printk ("PAT_ENTITY_PROC: id_eid 0x%lx\n", pa_pdc_cell.mod[0]);
+ break;
+
+ case PAT_ENTITY_MEM:
+ printk ("PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",
+ pa_pdc_cell.mod[0],
+ pa_pdc_cell.mod[1],
+ pa_pdc_cell.mod[2]);
+ break;
+ case PAT_ENTITY_CA:
+ printk ("PAT_ENTITY_CA: %ld\n",pcell_loc);
+ break;
+
+ case PAT_ENTITY_PBC:
+ printk ("PAT_ENTITY_PBC: ");
+ goto print_ranges;
+
+ case PAT_ENTITY_SBA:
+ printk ("PAT_ENTITY_SBA: ");
+ goto print_ranges;
+
+ case PAT_ENTITY_LBA:
+ printk ("PAT_ENTITY_LBA: ");
+
+print_ranges:
+ printk ("ranges %ld\n", pa_pdc_cell.mod[1]);
+ for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
+ printk (" %ld: 0x%016lx 0x%016lx 0x%016lx\n", i,
+ pa_pdc_cell.mod[2+i*3], /* type */
+ pa_pdc_cell.mod[3+i*3], /* start */
+ pa_pdc_cell.mod[4+i*3]); /* finish (ie end) */
+ }
+ printk("\n");
+ break;
+ }
+#endif /* DEBUG_PAT */
+ return PDC_RET_OK;
+}
+
+
+static int do_pat_inventory(void)
+{
+ ulong mod_index=0;
+ int status;
+ ulong cell_num;
+ ulong pcell_loc;
+
+ pdc_pat = (pdc_pat_cell_get_number(&pdc_result) == PDC_OK);
+ if (!pdc_pat)
+ {
+ return 0;
+ }
+
+ cell_num = pdc_result[0]; /* Cell number call was made */
+
+ /* As of PDC PAT ARS 2.5, ret[1] is NOT architected! */
+ pcell_loc = pdc_result[1]; /* Physical location of the cell */
+
+#ifdef DEBUG_PAT
+ printk("CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_num, pcell_loc);
+#endif
+
+ status = pdc_pat_cell_num_to_loc(&pdc_result, cell_num);
+ if (status == PDC_BAD_OPTION)
+ {
+ /* Prelude (and it's successors: Lclass, A400/500) only
+ ** implement PDC_PAT_CELL sub-options 0 and 2.
+ ** "Home cook'n is best anyhow!"
+ */
+ } else if (PDC_OK == status) {
+ /* so far only Halfdome supports this */
+ pcell_loc = pdc_result[0];
+ } else {
+ panic("WTF? CELL_GET_NUMBER give me invalid cell number?");
+ }
+
+ while (PDC_RET_OK == pat_query_module(pcell_loc, mod_index))
+ {
+ mod_index++;
+ }
+
+ return mod_index;
+}
+#endif /* __LP64__ */
+
+static int do_newer_workstation_inventory(void)
+{
+ long status;
+ int i, num = 0;
+
+ /* So the idea here is to simply try one SYSTEM_MAP call. If
+ that one works, great, otherwise do it another way */
+
+ status = pdc_system_map_find_mods(&module_result,&module_path,0);
+
+ if (status == PDC_RET_OK) {
+ /* This is for newer non-PDC-PAT boxes */
+
+ printk("a newer box...\n");
+ for(i=0, status=PDC_RET_OK; status != PDC_RET_NE_PROC &&
+ status != PDC_RET_NE_MOD ;i++) {
+
+ status = pdc_system_map_find_mods(&module_result,&module_path,i);
+ if (status == PDC_RET_OK) {
+ num++;
+ register_module(module_result.mod_addr);
+ }
+ }
+ }
+
+ return (num > 0);
+}
+
+#ifndef __LP64__
+static struct pdc_memory_map r_addr __attribute__ ((aligned (8)));
+
+static int really_do_oldhw_inventory(void)
+{
+ int i, mod, num = 0;
+ int status;
+ unsigned int hw_type;
+ unsigned int func;
+
+ /* This is undocumented at the time of writing, but basically
+ we're setting up mod_path so that bc[0..4]=0xff, and step
+ through mod to get the "Path Structure for GSC Modules". If
+ it works, use the returned HPA and determine the hardware type. */
+
+ for (i=0;i<6;i++) module_path.bc[i]=0xff;
+
+ for (mod=0;mod<16;mod++) {
+ char *stype = NULL;
+
+ module_path.mod=mod;
+ status = pdc_mem_map_hpa(&r_addr, &module_path);
+ if (status!=PDC_RET_OK) continue;
+
+ status = pdc_iodc_read(&pdc_result,(void *) r_addr.hpa,
+ 0, &iodc_data,32 );
+ if (status!=PDC_RET_OK) continue;
+ hw_type = iodc_data[3]&0x1f;
+
+ switch (hw_type)
+ {
+ case HPHW_NPROC: /* 0 */
+ stype="Processor"; break;
+
+ case HPHW_MEMORY: /* 1 */
+ stype="Memory"; break;
+
+ case HPHW_B_DMA: /* 2 */
+ stype="Type B DMA"; break;
+
+ case HPHW_A_DMA: /* 4 */
+ stype="Type A DMA"; break;
+
+ case HPHW_A_DIRECT: /* 5 */
+ stype="Type A Direct"; break;
+
+ case HPHW_BCPORT: /* 7 */
+ stype="Bus Converter Port"; break;
+
+ case HPHW_CONSOLE: /* 9 */
+ stype="Console"; break;
+
+ case HPHW_FIO: /* 10 - Graphics */
+ stype="Foreign I/O (Graphics)"; break;
+
+ case HPHW_BA: /* 11 - Bus Adapter */
+ stype="Bus Adapter"; break;
+
+ case HPHW_IOA: /* 12 */
+ stype="I/O Adapter"; break;
+
+ case HPHW_BRIDGE: /* 13 */
+ stype="Bridge"; break;
+
+ case HPHW_FABRIC: /* 14 */
+ stype="Fabric"; break;
+
+ case HPHW_FAULTY: /* 31 */
+ stype="Faulty HW"; break;
+
+ case HPHW_OTHER: /* 42 */
+ default:
+ printk("Don't know this hw_type: %d\n", hw_type);
+ break;
+ }
+
+ // This is kluged. But don't want to replicate code for
+ // most of the above cases.
+ if (stype) {
+#ifdef DBG_PDC_QUERY
+ // parisc/kernel/drivers.c
+ extern int num_devices;
+ extern struct hp_device devices[];
+ struct hp_hardware *h;
+#endif
+
+ status = pdc_mem_map_hpa(&r_addr, &module_path);
+ if (status==PDC_RET_OK && register_module((void *) r_addr.hpa) != NULL)
+ num++;
+
+
+ if (hw_type == HPHW_BA) {
+ /* Now, we're checking for devices for each
+ module. I seem to think that the
+ modules in question are Lasi (2), 2nd Lasi (6)
+ Wax (5). To do this, set bc[5]=0, and set
+ bc[4] to the module, and step through the
+ functions. */
+
+ for (i=0;i<4;i++) module_path.bc[i]=0xff;
+ module_path.bc[4]=mod;
+ for (func=0;func<16;func++) {
+ module_path.mod = func;
+ module_path.bc[5]=0;
+ status = pdc_mem_map_hpa(&r_addr, &module_path);
+ if (status!=PDC_RET_OK) continue;
+ if (register_module((void *) r_addr.hpa) != NULL)
+ num++;
+ }
+ }
+ // reset module_path.bc[]
+ for (i=0;i<6;i++) module_path.bc[i]=0xff;
+
+
+#ifdef DBG_PDC_QUERY
+//
+// Let print_devices() dump everything which is registered.
+//
+ h = devices[num_devices-1].reference;
+
+ if (h) stype = h->name;
+ printk("Found %s at %d\n", stype, module_path.mod);
+#endif
+ }
+ }
+ return num;
+}
+
+static int
+do_old_inventory(void)
+{
+ unsigned int bus_id;
+ long status;
+ int ok = 0;
+
+ printk(" an older box...\n");
+
+ /* Here, we're going to check the model, and decide
+ if we should even bother trying. */
+
+ status = pdc_model_info(&model);
+
+ bus_id = (model.hversion >> (4+7) ) &0x1f;
+
+ /* Here, we're checking the HVERSION of the CPU.
+ We're only checking the 0th CPU, since it'll
+ be the same on an SMP box. */
+
+ switch (bus_id) {
+ case 0x4: /* 720, 730, 750, 735, 755 */
+ case 0x6: /* 705, 710 */
+ case 0x7: /* 715, 725 */
+ case 0x8: /* 745, 747, 742 */
+ case 0xA: /* 712 and similiar */
+ case 0xC: /* 715/64, at least */
+
+ /* Do inventory using MEM_MAP */
+ really_do_oldhw_inventory();
+ ok = 1;
+ break;
+ default: /* Everything else */
+ printk("This is a very very old machine, with a bus_id of 0x%x.\n",bus_id);
+ panic("This will probably never run Linux.\n");
+ }
+
+ return ok;
+}
+
+#endif /* !__LP64__ */
+
+void do_inventory(void){
+ if((pdc_hpa_processor(&processor_hpa))<0){
+ printk(KERN_INFO "Couldn't get the HPA of the processor.\n" );
+ }
+
+ printk("Searching for devices in PDC firmware... ");
+ printk("processor hpa 0x%lx\n", processor_hpa.hpa);
+
+ if (!(
+ do_newer_workstation_inventory()
+#ifdef __LP64__
+ || do_pat_inventory()
+#else /* __LP64__ */
+ || do_old_inventory()
+#endif /* __LP64__ */
+ ))
+ {
+ panic("I can't get the hardware inventory on this machine");
+ }
+ print_devices(NULL);
+}
+
diff --git a/arch/parisc/kernel/iosapic.c b/arch/parisc/kernel/iosapic.c
new file mode 100644
index 000000000..688cbf9bb
--- /dev/null
+++ b/arch/parisc/kernel/iosapic.c
@@ -0,0 +1,1100 @@
+/*
+** I/O Sapic Driver - PCI interrupt line support
+**
+** (c) Copyright 1999 Grant Grundler
+** (c) Copyright 1999 Hewlett-Packard Company
+**
+** 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.
+**
+** The I/O sapic driver manages the Interrupt Redirection Table which is
+** the control logic to convert PCI line based interrupts into a Message
+** Signaled Interrupt (aka Transaction Based Interrupt, TBI).
+**
+** Acronyms
+** --------
+** HPA Hard Physical Address (aka MMIO address)
+** IRQ Interrupt ReQuest. Implies Line based interrupt.
+** IRT Interrupt Routing Table (provided by PAT firmware)
+** IRdT Interrupt Redirection Table. IRQ line to TXN ADDR/DATA
+** table which is implemented in I/O SAPIC.
+** ISR Interrupt Service Routine. aka Interrupt handler.
+** MSI Message Signaled Interrupt. PCI 2.2 functionality.
+** aka Transaction Based Interrupt (or TBI).
+** PA Precision Architecture. HP's RISC architecture.
+** RISC Reduced Instruction Set Computer.
+**
+**
+** What's a Message Signalled Interrupt?
+** -------------------------------------
+** MSI is a write transaction which targets a processor and is similar
+** to a processor write to memory or MMIO. MSIs can be generated by I/O
+** devices as well as processors and require *architecture* to work.
+**
+** PA only supports MSI. So I/O subsystems must either natively generate
+** MSIs (e.g. GSC or HP-PB) or convert line based interrupts into MSIs
+** (e.g. PCI and EISA). IA64 supports MSIs via a "local SAPIC" which
+** acts on behalf of a processor.
+**
+** MSI allows any I/O device to interrupt any processor. This makes
+** load balancing of the interrupt processing possible on an SMP platform.
+** Interrupts are also ordered WRT to DMA data. It's possible on I/O
+** coherent systems to completely eliminate PIO reads from the interrupt
+** path. The device and driver must be designed and implemented to
+** guarantee all DMA has been issued (issues about atomicity here)
+** before the MSI is issued. I/O status can then safely be read from
+** DMA'd data by the ISR.
+**
+**
+** PA Firmware
+** -----------
+** PA-RISC platforms have two fundementally different types of firmware.
+** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register
+** and BARs similar to a traditional PC BIOS.
+** The newer "PAT" firmware supports PDC calls which return tables.
+** PAT firmware only initializes PCI Console and Boot interface.
+** With these tables, the OS can progam all other PCI devices.
+**
+** One such PAT PDC call returns the "Interrupt Routing Table" (IRT).
+** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
+** input line. If the IRT is not available, this driver assumes
+** INTERRUPT_LINE register has been programmed by firmware. The latter
+** case also means online addition of PCI cards can NOT be supported
+** even if HW support is present.
+**
+** All platforms with PAT firmware to date (Oct 1999) use one Interrupt
+** Routing Table for the entire platform.
+**
+** Where's the iosapic?
+** --------------------
+** I/O sapic is part of the "Core Electronics Complex". And on HP platforms
+** it's integrated as part of the PCI bus adapter, "lba". So no bus walk
+** will discover I/O Sapic. I/O Sapic driver learns about each device
+** when lba driver advertises the presence of the I/O sapic by calling
+** iosapic_register().
+**
+**
+** IRQ region notes
+** ----------------
+** The data passed to iosapic_interrupt() is per IRQ line.
+** Each IRQ line will get one txn_addr/data pair. Thus each IRQ region,
+** will have several txn_addr/data pairs (up to 7 for current I/O SAPIC
+** implementations). The IRQ region "sysdata" will NOT be directly passed
+** to the interrupt handler like GSCtoPCI (dino.c).
+**
+** iosapic interrupt handler will NOT call do_irq_mask().
+** It doesn't need to read a bit mask to determine which IRQ line was pulled
+** since it already knows based on vector_info passed to iosapic_interrupt().
+**
+** One IRQ number represents both an IRQ line and a driver ISR.
+** The I/O sapic driver can't manage shared IRQ lines because
+** additional data besides the IRQ number must be passed via
+** irq_region_ops. do_irq() and request_irq() must manage
+** a sharing a bit in the mask.
+**
+** iosapic_interrupt() replaces do_irq_mask() and calls do_irq().
+** Which IRQ line was asserted is already known since each
+** line has unique data associated with it. We could omit
+** iosapic_interrupt() from the calling path if it did NOT need
+** to write EOI. For unshared lines, it really doesn't.
+**
+** Unfortunately, can't optimize out EOI if IRQ line isn't "shared".
+** N-class console "device" and some sort of heartbeat actually share
+** one line though only one driver is registered...<sigh>...this was
+** true for HP-UX at least. May not be true for parisc-linux.
+**
+**
+** Overview of exported iosapic functions
+** --------------------------------------
+** (caveat: code isn't finished yet - this is just the plan)
+**
+** iosapic_init:
+** o initialize globals (lock, etc)
+** o try to read IRT. Presence of IRT determines if this is
+** a PAT platform or not.
+**
+** iosapic_register():
+** o create iosapic_info instance data structure
+** o allocate vector_info array for this iosapic
+** o initialize vector_info - read corresponding IRdT?
+**
+** iosapic_xlate_pin: (only called by fixup_irq for PAT platform)
+** o intr_pin = read cfg (INTERRUPT_PIN);
+** o if (device under PCI-PCI bridge)
+** translate slot/pin
+**
+** iosapic_fixup_irq:
+** o if PAT platform (IRT present)
+** intr_pin = iosapic_xlate_pin(isi,pcidev):
+** intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin)
+** save IRT entry into vector_info later
+** write cfg INTERRUPT_LINE (with intr_line)?
+** else
+** intr_line = pcidev->irq
+** IRT pointer = NULL
+** endif
+** o locate vector_info (needs: isi, intr_line)
+** o allocate processor "irq" and get txn_addr/data
+** o request_irq(processor_irq, iosapic_interrupt, vector_info,...)
+** o pcidev->irq = isi->isi_region...base + intr_line;
+**
+** iosapic_interrupt:
+** o call do_irq(vector->isi->irq_region, vector->irq_line, regs)
+** o assume level triggered and write EOI
+**
+** iosapic_enable_irq:
+** o clear any pending IRQ on that line
+** o enable IRdT - call enable_irq(vector[line]->processor_irq)
+** o write EOI in case line is already asserted.
+**
+** iosapic_disable_irq:
+** o disable IRdT - call disable_irq(vector[line]->processor_irq)
+**
+** FIXME: mask/unmask
+*/
+
+
+/* FIXME: determine which include files are really needed */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h> /* pci cfg accessor functions */
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h> /* irqaction */
+#include <linux/irq.h> /* irq_region support */
+
+#include <asm/byteorder.h> /* get in-line asm for swab */
+#include <asm/pdc.h>
+#include <asm/pdcpat.h>
+#include <asm/page.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/gsc.h> /* gsc_read/write functions */
+
+#include <asm/iosapic.h>
+#include "./iosapic_private.h"
+
+#define MODULE_NAME "iosapic"
+
+/* "local" compile flags */
+#undef IOSAPIC_CALLBACK
+#undef PCI_BRIDGE_FUNCS
+#undef DEBUG_IOSAPIC
+#undef DEBUG_IOSAPIC_IRT
+
+
+#ifdef DEBUG_IOSAPIC
+static char assert_buf[128];
+
+static int
+assert_failed (char *a, char *f, int l)
+{
+ sprintf(assert_buf,
+ "ASSERT(%s) failed!\nline %d in %s\n",
+ a, /* assertion text */
+ l, /* line number */
+ f); /* file name */
+ panic(assert_buf);
+ return 0;
+}
+
+#undef ASSERT
+#define ASSERT(EX) { if (!(EX)) assert_failed(# EX, __FILE__, __LINE__); }
+
+#define DBG(x...) printk(x)
+
+#else /* DEBUG_IOSAPIC */
+
+#define DBG(x...)
+#define ASSERT(EX)
+
+#endif /* DEBUG_IOSAPIC */
+
+#ifdef DEBUG_IOSAPIC_IRT
+#define DBG_IRT(x...) printk(x)
+#else
+#define DBG_IRT(x...)
+#endif
+
+
+#define READ_U8(addr) gsc_readb(addr)
+#define READ_U16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
+#define READ_U32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
+#define READ_REG16(addr) gsc_readw((u16 *) (addr))
+#define READ_REG32(addr) gsc_readl((u32 *) (addr))
+#define WRITE_U8(value, addr) gsc_writeb(value, addr)
+#define WRITE_U16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
+#define WRITE_U32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
+#define WRITE_REG16(value, addr) gsc_writew(value, (u16 *) (addr))
+#define WRITE_REG32(value, addr) gsc_writel(value, (u32 *) (addr))
+
+
+#define IOSAPIC_REG_SELECT 0
+#define IOSAPIC_REG_WINDOW 0x10
+#define IOSAPIC_REG_EOI 0x40
+
+#define IOSAPIC_REG_VERSION 0x1
+
+#define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2)
+#define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2)
+
+/*
+** FIXME: revisit which GFP flags we should really be using.
+** GFP_KERNEL includes __GFP_WAIT flag and that may not
+** be acceptable. Since this is boot time, we shouldn't have
+** to wait ever and this code should (will?) never get called
+** from the interrrupt context.
+*/
+#define IOSAPIC_KALLOC(a_type, cnt) \
+ (a_type *) kmalloc(sizeof(a_type)*(cnt), GFP_KERNEL)
+#define IOSAPIC_FREE(addr, f_type, cnt) kfree((void *)addr)
+
+
+#define IOSAPIC_LOCK(lck) spin_lock_irqsave(lck, irqflags)
+#define IOSAPIC_UNLOCK(lck) spin_unlock_irqrestore(lck, irqflags)
+
+
+#define IOSAPIC_VERSION_MASK 0x000000ff
+#define IOSAPIC_VERSION_SHIFT 0x0
+#define IOSAPIC_VERSION(ver) \
+ (int) ((ver & IOSAPIC_VERSION_MASK) >> IOSAPIC_VERSION_SHIFT)
+
+#define IOSAPIC_MAX_ENTRY_MASK 0x00ff0000
+
+#define IOSAPIC_MAX_ENTRY_SHIFT 0x10
+#define IOSAPIC_IRDT_MAX_ENTRY(ver) \
+ (int) ((ver&IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
+
+/* bits in the "low" I/O Sapic IRdT entry */
+#define IOSAPIC_IRDT_ENABLE 0x10000
+#define IOSAPIC_IRDT_PO_LOW 0x02000
+#define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
+#define IOSAPIC_IRDT_MODE_LPRI 0x00100
+
+/* bits in the "high" I/O Sapic IRdT entry */
+#define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
+
+
+
+#define IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr)
+
+#if IOSAPIC_CALLBACK
+/*
+** Shouldn't use callback since SAPIC doesn't have an officially assigned
+** H or S version numbers. Slight long term risk the number chosen would
+** collide with something else.
+** But benefit is cleaner lba/sapic interface.
+** Might be worth it but for just use direct calls for now.
+**
+** Entry below is copied from lba driver.
+** Only thing different is hw_type.
+*/
+static struct pa_iodc_driver iosapic_driver_for[] = {
+ {HPHW_OTHER, 0x782, 0, 0x0000A, 0, 0x00,
+ DRIVER_CHECK_HWTYPE + DRIVER_CHECK_HVERSION + DRIVER_CHECK_SVERSION,
+ "I/O Sapic", "",(void *) iosapic_callback},
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL,(char *) NULL,(void *) NULL}
+};
+#endif /* IOSAPIO_CALLBACK */
+
+
+static struct iosapic_info *iosapic_list;
+static spinlock_t iosapic_lock;
+static int iosapic_count;
+
+
+/*
+** REVISIT: future platforms may have more than one IRT.
+** If so, the following three fields form a structure which
+** then be linked into a list. Names are chosen to make searching
+** for them easy - not necessarily accurate (eg "cell").
+**
+** Alternative: iosapic_info could point to the IRT it's in.
+** iosapic_register() could search a list of IRT's.
+*/
+static struct irt_entry *irt_cell;
+static size_t irt_num_entry;
+
+
+
+/*
+** iosapic_load_irt
+**
+** The "Get PCI INT Routing Table Size" option returns the number of
+** entries in the PCI interrupt routing table for the cell specified
+** in the cell_number argument. The cell number must be for a cell
+** within the caller's protection domain.
+**
+** The "Get PCI INT Routing Table" option returns, for the cell
+** specified in the cell_number argument, the PCI interrupt routing
+** table in the caller allocated memory pointed to by mem_addr.
+** We assume the IRT only contains entries for I/O SAPIC and
+** calculate the size based on the size of I/O sapic entries.
+**
+** The PCI interrupt routing table entry format is derived from the
+** IA64 SAL Specification 2.4. The PCI interrupt routing table defines
+** the routing of PCI interrupt signals between the PCI device output
+** "pins" and the IO SAPICs' input "lines" (including core I/O PCI
+** devices). This table does NOT include information for devices/slots
+** behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
+** for the architected method of routing of IRQ's behind PPB's.
+*/
+
+
+static int __init /* return number of entries as success/fail flag */
+iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
+{
+ struct pdc_pat_io_num pdc_io_num; /* PAT PDC return block */
+ long status; /* PDC return value status */
+ struct irt_entry *table = NULL; /* start of interrupt routing tbl */
+ unsigned long num_entries = 0UL;
+
+ ASSERT(NULL != irt);
+ /* FIXME ASSERT(((&pdc_io_num) & (0x3f)) == 0); enforce 32-byte alignment */
+
+ /* Try PAT_PDC to get interrupt routing table size */
+ DBG(KERN_DEBUG "calling get_irt_size\n");
+ status = pdc_pat_get_irt_size( &pdc_io_num, cell_num);
+ DBG(KERN_DEBUG "get_irt_size: %ld\n", status);
+
+ switch(status) {
+
+ case PDC_RET_OK: /* PAT box. Proceed to get the IRT */
+
+ /* save the number of entries in the table */
+ num_entries = pdc_io_num.num;
+ ASSERT(0UL != num_entries);
+
+ /*
+ ** allocate memory for interrupt routing table
+ ** This interface isn't really right. We are assuming
+ ** the contents of the table are exclusively
+ ** for I/O sapic devices.
+ */
+ table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
+ if (table == NULL) {
+ printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
+ return 0;
+ }
+
+ /* get PCI INT routing table */
+ status = pdc_pat_get_irt( (void *) table, cell_num);
+ DBG(KERN_DEBUG "pdc_pat_get_irt: %ld\n", status);
+ ASSERT(status == PDC_RET_OK);
+ break;
+
+ case PDC_RET_NE_PROC: /* Not a PAT platform. Try PDC_PCI extensions */
+ /*
+ ** C3000/J5000 (and similar) platforms with "legacy" PDC
+ ** will return exactly one IRT.
+ ** So if we have one, don't need to get it again.
+ */
+ if (NULL != irt_cell)
+ break;
+
+ status = pdc_pci_irt_size( (void *)&pdc_io_num,
+ /* elroy HPA (really a NOP) */ 0);
+ DBG(KERN_WARNING "pdc_pci_irt_size: %ld\n", status);
+
+ if (PDC_RET_OK != status) {
+ /* Not a "legacy" system with I/O SAPIC either */
+ return 0;
+ }
+
+ num_entries = pdc_io_num.num;
+ ASSERT(0UL != num_entries);
+
+ table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
+ if (table == NULL) {
+ printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
+ return 0;
+ }
+
+ status = pdc_pci_irt( (void *) &pdc_io_num,
+ (void *) NULL, /* Elroy HPA - not used */
+ (void *) table);
+
+ ASSERT(PDC_RET_OK == status);
+ break;
+
+ default:
+ printk(KERN_WARNING MODULE_NAME ": PDC_PAT_IO call failed with %ld\n", status);
+ break;
+ }
+
+ /* return interrupt table address */
+ *irt = table;
+
+
+#ifdef DEBUG_IOSAPIC_IRT
+ {
+ struct irt_entry *p = table;
+ int i;
+
+ printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
+ printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
+ table,
+ num_entries,
+ (int) sizeof(struct irt_entry));
+
+ for (i = 0 ; i < num_entries ; i++, p++)
+ {
+ printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
+ p->entry_type, p->entry_length, p->interrupt_type,
+ p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
+ p->src_seg_id, p->dest_iosapic_intin,
+ ((u32 *) p)[2],
+ ((u32 *) p)[3]
+ );
+ }
+ }
+#endif /* DEBUG_IOSAPIC_IRT */
+
+ return num_entries;
+}
+
+
+
+void __init
+iosapic_init(void)
+{
+ /* init global data */
+ iosapic_lock = SPIN_LOCK_UNLOCKED;
+ iosapic_list = (struct iosapic_info *) NULL;
+ iosapic_count = 0;
+
+ DBG("iosapic_init()\n");
+
+ /*
+ ** get IRT for this cell.
+ */
+ irt_num_entry = iosapic_load_irt(0L, &irt_cell);
+ if (0 == irt_num_entry)
+ irt_cell = NULL; /* old PDC w/o iosapic */
+
+#ifdef IOSAPIC_CALLBACK
+ /*
+ ** When new I/O SAPICs are discovered, this callback
+ ** will get invoked. Implies lba driver will register
+ ** I/O Sapic as a device it "discovered" with faked
+ ** IODC data.
+ */
+ register_driver(iosapic_driver_for);
+#endif /* IOSAPIC_CALLBACK */
+}
+
+
+/*
+** Return the IRT entry in case we need to look something else up.
+*/
+static struct irt_entry *
+irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
+{
+ struct irt_entry *i = irt_cell;
+ int cnt; /* track how many entries we've looked at */
+ u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1);
+
+ DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin);
+
+ for (cnt=0; cnt < irt_num_entry; cnt++, i++) {
+
+ /*
+ ** Validate: entry_type, entry_length, interrupt_type
+ **
+ ** Difference between validate vs compare is the former
+ ** should print debug info and is not expected to "fail"
+ ** on current platforms.
+ */
+ if (i->entry_type != IRT_IOSAPIC_TYPE) {
+ DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type);
+ continue;
+ }
+
+ if (i->entry_length != IRT_IOSAPIC_LENGTH) {
+ DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length);
+ continue;
+ }
+
+ if (i->interrupt_type != IRT_VECTORED_INTR) {
+ DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type);
+ continue;
+ }
+
+ /*
+ ** Compare: dest_iosapic_addr, src_bus_irq_devno
+ */
+ if (i->dest_iosapic_addr != (u64) ((long) isi->isi_hpa))
+ continue;
+
+ if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
+ continue;
+
+ /*
+ ** Ignore: src_bus_id and rc_seg_id correlate with
+ ** iosapic_info->isi_hpa on HP platforms.
+ ** If needed, pass in "PFA" (aka config space addr)
+ ** instead of slot.
+ */
+
+ /* Found it! */
+ return i;
+ }
+
+ printk(KERN_WARNING MODULE_NAME ": 0x%p : no IRT entry for slot %d, pin %d\n",
+ isi->isi_hpa, slot, intr_pin);
+ return NULL;
+}
+
+
+/*
+** xlate_pin() supports the skewing of IRQ lines done by subsidiary bridges.
+** Legacy PDC already does this translation for us and stores it in INTR_LINE.
+**
+** PAT PDC needs to basically do what legacy PDC does:
+** o read PIN
+** o adjust PIN in case device is "behind" a PPB
+** (eg 4-port 100BT and SCSI/LAN "Combo Card")
+** o convert slot/pin to I/O SAPIC input line.
+**
+** HP platforms only support:
+** o one level of skewing for any number of PPBs
+** o only support PCI-PCI Bridges.
+*/
+static struct irt_entry *
+iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
+{
+ u8 intr_pin, intr_slot;
+
+ (void) pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
+
+ DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n", PCI_SLOT(pcidev->devfn), intr_pin);
+
+ if (0 == intr_pin)
+ {
+ /*
+ ** The device does NOT support/use IRQ lines.
+ */
+ return NULL;
+ }
+
+ /* Check if pcidev behind a PPB */
+ if (NULL != pcidev->bus->self)
+ {
+ /* Convert pcidev INTR_PIN into something we
+ ** can lookup in the IRT.
+ */
+#ifdef PCI_BRIDGE_FUNCS
+ /*
+ ** Proposal #1:
+ **
+ ** call implementation specific translation function
+ ** This is architecturally "cleaner". HP-UX doesn't
+ ** support other secondary bus types (eg. E/ISA) directly.
+ ** May be needed for other processor (eg IA64) architectures
+ ** or by some ambitous soul who wants to watch TV.
+ */
+ if (pci_bridge_funcs->xlate_intr_line) {
+ intr_pin = (*pci_bridge_funcs->xlate_intr_line)(pcidev);
+ }
+#else /* PCI_BRIDGE_FUNCS */
+ struct pci_bus *p = pcidev->bus;
+ /*
+ ** Proposal #2:
+ ** The "pin" is skewed ((pin + dev - 1) % 4).
+ **
+ ** This isn't very clean since I/O SAPIC must assume:
+ ** - all platforms only have PCI busses.
+ ** - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA)
+ ** - IRQ routing is only skewed once regardless of
+ ** the number of PPB's between iosapic and device.
+ ** (Bit3 expansion chassis follows this rule)
+ **
+ ** Advantage is it's really easy to implement.
+ */
+ intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4;
+ intr_pin++; /* convert back to INTA-D (1-4) */
+#endif /* PCI_BRIDGE_FUNCS */
+
+ /*
+ ** Locate the host slot the PPB nearest the Host bus
+ ** adapter.
+ */
+ while (NULL != p->parent->self)
+ p = p->parent;
+
+ intr_slot = PCI_SLOT(p->self->devfn);
+ } else {
+ intr_slot = PCI_SLOT(pcidev->devfn);
+ }
+ DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n",
+ pcidev->bus->secondary, intr_slot, intr_pin);
+
+ return irt_find_irqline(isi, intr_slot, intr_pin);
+}
+
+
+static void
+iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct vector_info *vi = (struct vector_info *)dev_id;
+ extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
+ int irq_num = vi->vi_ios->isi_region->data.irqbase + vi->vi_irqline;
+
+ DBG("iosapic_interrupt(): irq %d line %d eoi %p\n", irq, vi->vi_irqline,
+ vi->vi_eoi_addr);
+
+/* FIXME: Need to mask/unmask? processor IRQ is already masked... */
+ do_irq(&vi->vi_ios->isi_region->action[vi->vi_irqline], irq_num, regs);
+
+ /*
+ ** PCI only supports level triggered in order to share IRQ lines.
+ ** I/O SAPIC must always issue EOI.
+ */
+ IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data);
+}
+
+
+int
+iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
+{
+ struct iosapic_info *isi = (struct iosapic_info *)isi_obj;
+ struct irt_entry *irte = NULL; /* only used if PAT PDC */
+ struct vector_info *vi;
+ int isi_line; /* line used by device */
+ int tmp;
+
+ if (NULL == isi) {
+ printk(KERN_WARNING MODULE_NAME ": 0x%p hpa not registered\n", isi->isi_hpa);
+ return(-1);
+ }
+
+ /* lookup IRT entry for isi/slot/pin set */
+ irte = iosapic_xlate_pin(isi, pcidev);
+ if (NULL == irte) {
+ return(-1);
+ }
+ DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
+ irte,
+ irte->entry_type,
+ irte->entry_length,
+ irte->polarity_trigger,
+ irte->src_bus_irq_devno,
+ irte->src_bus_id,
+ irte->src_seg_id,
+ irte->dest_iosapic_intin,
+ (u32) irte->dest_iosapic_addr);
+ isi_line = irte->dest_iosapic_intin;
+
+ /* get vector info for this input line */
+ ASSERT(NULL != isi->isi_vector);
+ vi = &(isi->isi_vector[isi_line]);
+ DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi);
+ vi->vi_irte = irte;
+
+ /* Allocate processor IRQ */
+ vi->vi_txn_irq = txn_alloc_irq();
+
+/* XXX/FIXME The txn_alloc_irq() code and related code should be moved
+** to enable_irq(). That way we only allocate processor IRQ bits
+** for devices that actually have drivers claiming them.
+** Right now we assign an IRQ to every PCI device present regardless
+** of whether it's used or not.
+*/
+ if (vi->vi_txn_irq < 0)
+ panic("I/O sapic: couldn't get TXN IRQ\n");
+
+ /* enable_irq() will use txn_* to program IRdT */
+ vi->vi_txn_addr = txn_alloc_addr(vi->vi_txn_irq);
+ vi->vi_txn_data = txn_alloc_data(vi->vi_txn_irq, 8);
+ ASSERT(vi->vi_txn_data < 256); /* matches 8 above */
+
+ tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0, "iosapic", vi);
+ ASSERT(tmp == 0);
+
+ vi->vi_eoi_addr = ((void *) isi->isi_hpa) + IOSAPIC_REG_EOI;
+ vi->vi_eoi_data = cpu_to_le32(vi->vi_irqline);
+
+ ASSERT(NULL != isi->isi_region);
+ /*
+ ** pcidev->irq still needs to be virtualized.
+ */
+ pcidev->irq = isi->isi_region->data.irqbase + isi_line;
+
+ DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n", PCI_SLOT(pcidev->devfn),
+ PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
+
+ return(pcidev->irq);
+}
+
+
+static void
+iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)
+{
+ struct iosapic_info *isp = vi->vi_ios;
+ u8 idx = vi->vi_irqline;
+
+ /* point the window register to the lower word */
+ WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
+ *dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+
+ /* point the window register to the higher word */
+ WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
+ *dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+}
+
+
+static void
+iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1)
+{
+ struct iosapic_info *isp = vi->vi_ios;
+
+ ASSERT(NULL != isp);
+ ASSERT(NULL != isp->isi_hpa);
+ DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p 0x%x 0x%x\n",
+ vi->vi_irqline,
+ isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW,
+ dp0, dp1);
+
+ /* point the window register to the lower word */
+ WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
+ WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW);
+
+ /* Read the window register to flush the writes down to HW */
+ dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+
+ /* point the window register to the higher word */
+ WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
+ WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW);
+
+ /* Read the window register to flush the writes down to HW */
+ dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+}
+
+
+/*
+** set_irt prepares the data (dp0, dp1) according to the vector_info
+** and target cpu (id_eid). dp0/dp1 are then used to program I/O SAPIC
+** IRdT for the given "vector" (aka IRQ line).
+*/
+static void
+iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
+{
+ u32 mode = 0;
+ struct irt_entry *p = vi->vi_irte;
+ ASSERT(NULL != vi->vi_irte);
+
+ if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
+ mode |= IOSAPIC_IRDT_PO_LOW;
+
+ if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG)
+ mode |= IOSAPIC_IRDT_LEVEL_TRIG;
+
+ /*
+ ** IA64 REVISIT
+ ** PA doesn't support EXTINT or LPRIO bits.
+ */
+
+ ASSERT(vi->vi_txn_data);
+ *dp0 = mode | (u32) vi->vi_txn_data;
+
+ /*
+ ** Extracting id_eid isn't a real clean way of getting it.
+ ** But the encoding is the same for both PA and IA64 platforms.
+ */
+#ifdef __LP64__
+ if (pdc_pat) {
+ /*
+ ** PAT PDC just hands it to us "right".
+ ** vi_txn_addr comes from cpu_data[x].txn_addr.
+ */
+ *dp1 = (u32) (vi->vi_txn_addr);
+ } else
+#endif
+ {
+ /*
+ ** eg if base_addr == 0xfffa0000),
+ ** we want to get 0xa0ff0000.
+ **
+ ** eid 0x0ff00000 -> 0x00ff0000
+ ** id 0x000ff000 -> 0xff000000
+ */
+ *dp1 = (((u32)vi->vi_txn_addr & 0x0ff00000) >> 4) |
+ (((u32)vi->vi_txn_addr & 0x000ff000) << 12);
+ }
+ DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1);
+}
+
+
+static void
+iosapic_disable_irq(void *irq_dev, int irq)
+{
+ ulong irqflags;
+ struct vector_info *vi = &(((struct vector_info *) irq_dev)[irq]);
+ u32 d0, d1;
+
+ ASSERT(NULL != vi);
+
+ IOSAPIC_LOCK(&iosapic_lock);
+
+#ifdef REVISIT_DESIGN_ISSUE
+/*
+** XXX/FIXME
+
+disable_irq()/enable_irq(): drawback of using IRQ as a "handle"
+
+Current disable_irq interface only allows the irq_region support routines
+to manage sharing of "irq" objects. The problem is the disable_irq()
+interface specifies which IRQ line needs to be disabled but does not
+identify the particular ISR which needs to be disabled. IO sapic
+(and similar code in Dino) can only support one handler per IRQ
+since they don't further encode the meaning of the IRQ number.
+irq_region support has to hide it's implementation of "shared IRQ"
+behind a function call.
+
+Encoding the IRQ would be possible by I/O SAPIC but makes life really
+complicated for the IRQ handler and not help performance.
+
+Need more info on how Linux supports shared IRQ lines on a PC.
+*/
+#endif /* REVISIT_DESIGN_ISSUE */
+
+ iosapic_rd_irt_entry(vi, &d0, &d1);
+ d0 |= IOSAPIC_IRDT_ENABLE;
+ iosapic_wr_irt_entry(vi, d0, d1);
+
+ IOSAPIC_UNLOCK(&iosapic_lock);
+
+ /* disable ISR for parent */
+ disable_irq(vi->vi_txn_irq);
+}
+
+
+static void
+iosapic_enable_irq(void *dev, int irq)
+{
+ struct vector_info *vi = &(((struct vector_info *) dev)[irq]);
+ u32 d0, d1;
+
+ ASSERT(NULL != vi);
+ ASSERT(NULL != vi->vi_irte);
+
+ /* data is initialized by fixup_irq */
+ ASSERT(0 < vi->vi_txn_irq);
+ ASSERT(0UL != vi->vi_txn_addr);
+ ASSERT(0UL != vi->vi_txn_data);
+
+ iosapic_set_irt_data(vi, &d0, &d1);
+ iosapic_wr_irt_entry(vi, d0, d1);
+
+
+#ifdef DEBUG_IOSAPIC_IRT
+{
+u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL);
+printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr);
+while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++));
+printk("\n");
+}
+
+printk("iosapic_enable_irq(): sel ");
+{
+ struct iosapic_info *isp = vi->vi_ios;
+
+ for (d0=0x10; d0<0x1e; d0++) {
+ /* point the window register to the lower word */
+ WRITE_U32(d0, isp->isi_hpa+IOSAPIC_REG_SELECT);
+
+ /* read the word */
+ d1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+ printk(" %x", d1);
+ }
+}
+printk("\n");
+#endif
+
+ /*
+ ** KLUGE: IRQ should not be asserted when Drivers enabling their IRQ.
+ ** PCI supports level triggered in order to share IRQ lines.
+ **
+ ** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is
+ ** asserted.
+ */
+ IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data);
+}
+
+
+static void
+iosapic_mask_irq(void *dev, int irq)
+{
+ BUG();
+}
+
+
+static void
+iosapic_unmask_irq(void *dev, int irq)
+{
+ BUG();
+}
+
+
+static struct irq_region_ops iosapic_irq_ops = {
+ iosapic_disable_irq,
+ iosapic_enable_irq,
+ iosapic_mask_irq,
+ iosapic_unmask_irq
+};
+
+
+/*
+** squirrel away the I/O Sapic Version
+*/
+static unsigned int
+iosapic_rd_version(struct iosapic_info *isi)
+{
+ ASSERT(isi);
+ ASSERT(isi->isi_hpa);
+
+ /* point window to the version register */
+ WRITE_U32(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT);
+
+ /* now read the version register */
+ return (READ_U32(isi->isi_hpa+IOSAPIC_REG_WINDOW));
+}
+
+
+#ifndef IOSAPIC_CALLBACK
+/*
+** iosapic_register() is the alternative to iosapic_driver_for().
+** (Only one or the other should be implemented.)
+*/
+
+/*
+** iosapic_register() is called by "drivers" with an integrated I/O SAPIC.
+** Caller must be certain they have an I/O SAPIC and know it's MMIO address.
+**
+** o allocate iosapic_info and add it to the list
+** o read iosapic version and squirrel that away
+** o read size of IRdT.
+** o allocate and initialize isi_vector[]
+** o allocate isi_region (registers region handlers)
+*/
+void *
+iosapic_register(void *hpa)
+{
+ struct iosapic_info *isi = NULL;
+ struct irt_entry *irte = irt_cell;
+ struct vector_info *vip;
+ int cnt; /* track how many entries we've looked at */
+
+ /*
+ ** Astro based platforms can't support PCI OLARD if they
+ ** implement the legacy PDC (not PAT). Though Legacy PDC
+ ** supports an IRT, LBA's with no device under them
+ ** are *not* listed in the IRT.
+ ** Search the IRT and ignore iosapic's which aren't
+ ** in the IRT.
+ */
+ ASSERT(NULL != irte); /* always have built-in devices */
+ for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
+ ASSERT(IRT_IOSAPIC_TYPE == irte->entry_type);
+ /*
+ ** We need sign extension of the hpa on 32-bit kernels.
+ ** The address in the IRT is *always* 64 bit and really
+ ** is an unsigned quantity (like all physical addresses).
+ */
+ if (irte->dest_iosapic_addr == (s64) ((long) hpa))
+ break;
+ }
+
+ if (cnt >= irt_num_entry)
+ return (NULL);
+
+ if ((isi = IOSAPIC_KALLOC(struct iosapic_info, 1)) == NULL) {
+ BUG();
+ return (NULL);
+ }
+
+ memset(isi, 0, sizeof(struct iosapic_info));
+
+ isi->isi_hpa = (unsigned char *) hpa;
+ isi->isi_version = iosapic_rd_version(isi);
+ isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
+
+ vip = isi->isi_vector =
+ IOSAPIC_KALLOC(struct vector_info, isi->isi_num_vectors);
+
+ if (vip == NULL) {
+ IOSAPIC_FREE(isi, struct iosapic_info, 1);
+ return (NULL);
+ }
+
+ memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
+
+ /*
+ ** Initialize vector array
+ */
+ for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
+ vip->vi_irqline = (unsigned char) cnt;
+ vip->vi_ios = isi;
+ }
+
+ isi->isi_region = alloc_irq_region(isi->isi_num_vectors,
+ &iosapic_irq_ops, IRQ_REG_DIS|IRQ_REG_MASK,
+ "I/O Sapic", (void *) isi->isi_vector);
+
+ ASSERT(NULL != isi->isi_region);
+ return ((void *) isi);
+}
+#endif /* !IOSAPIC_CALLBACK */
+
+
+
+#ifdef DEBUG_IOSAPIC
+
+static void
+iosapic_prt_irt(void *irt, long num_entry)
+{
+ unsigned int i, *irp = (unsigned int *) irt;
+
+ ASSERT(NULL != irt);
+
+ printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
+
+ for (i=0; i<num_entry; i++, irp += 4) {
+ printk(KERN_DEBUG "%p : %2d %.8x %.8x %.8x %.8x\n",
+ irp, i, irp[0], irp[1], irp[2], irp[3]);
+ }
+}
+
+
+static void
+iosapic_prt_vi(struct vector_info *vi)
+{
+ ASSERT(NULL != vi);
+
+ printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->vi_irqline, vi);
+ printk(KERN_DEBUG "\t\tvi_status: %.4x\n", vi->vi_status);
+ printk(KERN_DEBUG "\t\tvi_txn_irq: %d\n", vi->vi_txn_irq);
+ printk(KERN_DEBUG "\t\tvi_txn_addr: %lx\n", vi->vi_txn_addr);
+ printk(KERN_DEBUG "\t\tvi_txn_data: %lx\n", vi->vi_txn_data);
+ printk(KERN_DEBUG "\t\tvi_eoi_addr: %p\n", vi->vi_eoi_addr);
+ printk(KERN_DEBUG "\t\tvi_eoi_data: %x\n", vi->vi_eoi_data);
+}
+
+
+static void
+iosapic_prt_isi(struct iosapic_info *isi)
+{
+ ASSERT(NULL != isi);
+ printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
+ printk(KERN_DEBUG "\t\tisi_hpa: %p\n", isi->isi_hpa);
+ printk(KERN_DEBUG "\t\tisi_satus: %x\n", isi->isi_status);
+ printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version);
+ printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector);
+}
+#endif /* DEBUG_IOSAPIC */
diff --git a/arch/parisc/kernel/iosapic_private.h b/arch/parisc/kernel/iosapic_private.h
new file mode 100644
index 000000000..f310501c4
--- /dev/null
+++ b/arch/parisc/kernel/iosapic_private.h
@@ -0,0 +1,165 @@
+/*
+** This file is private to iosapic driver.
+** If stuff needs to be used by another driver, move it to a common file.
+**
+** WARNING: fields most data structures here are ordered to make sure
+** they pack nicely for 64-bit compilation. (ie sizeof(long) == 8)
+*/
+
+
+/*
+** Interrupt Routing Stuff
+** -----------------------
+** The interrupt routing table consists of entries derived from
+** MP Specification Draft 1.5. There is one interrupt routing
+** table per cell. N- and L-class consist of a single cell.
+*/
+struct irt_entry {
+
+ /* Entry Type 139 identifies an I/O SAPIC interrupt entry */
+ u8 entry_type;
+
+ /* Entry Length 16 indicates entry is 16 bytes long */
+ u8 entry_length;
+
+ /*
+ ** Interrupt Type of 0 indicates a vectored interrupt,
+ ** all other values are reserved
+ */
+ u8 interrupt_type;
+
+ /*
+ ** PO and EL
+ ** Polarity of SAPIC I/O input signals:
+ ** 00 = Reserved
+ ** 01 = Active high
+ ** 10 = Reserved
+ ** 11 = Active low
+ ** Trigger mode of SAPIC I/O input signals:
+ ** 00 = Reserved
+ ** 01 = Edge-triggered
+ ** 10 = Reserved
+ ** 11 = Level-triggered
+ */
+ u8 polarity_trigger;
+
+ /*
+ ** IRQ and DEVNO
+ ** irq identifies PCI interrupt signal where
+ ** 0x0 corresponds to INT_A#,
+ ** 0x1 corresponds to INT_B#,
+ ** 0x2 corresponds to INT_C#
+ ** 0x3 corresponds to INT_D#
+ ** PCI device number where interrupt originates
+ */
+ u8 src_bus_irq_devno;
+
+ /* Source Bus ID identifies the bus where interrupt signal comes from */
+ u8 src_bus_id;
+
+ /*
+ ** Segment ID is unique across a protection domain and
+ ** identifies a segment of PCI buses (reserved in
+ ** MP Specification Draft 1.5)
+ */
+ u8 src_seg_id;
+
+ /*
+ ** Destination I/O SAPIC INTIN# identifies the INTIN n pin
+ ** to which the signal is connected
+ */
+ u8 dest_iosapic_intin;
+
+ /*
+ ** Destination I/O SAPIC Address identifies the I/O SAPIC
+ ** to which the signal is connected
+ */
+ u64 dest_iosapic_addr;
+};
+
+#define IRT_IOSAPIC_TYPE 139
+#define IRT_IOSAPIC_LENGTH 16
+
+#define IRT_VECTORED_INTR 0
+
+#define IRT_PO_MASK 0x3
+#define IRT_ACTIVE_HI 1
+#define IRT_ACTIVE_LO 3
+
+#define IRT_EL_MASK 0x3
+#define IRT_EL_SHIFT 2
+#define IRT_EDGE_TRIG 1
+#define IRT_LEVEL_TRIG 3
+
+#define IRT_IRQ_MASK 0x3
+#define IRT_DEV_MASK 0x1f
+#define IRT_DEV_SHIFT 2
+
+#define IRT_IRQ_DEVNO_MASK ((IRT_DEV_MASK << IRT_DEV_SHIFT) | IRT_IRQ_MASK)
+
+#ifdef SUPPORT_MULTI_CELL
+struct iosapic_irt {
+ struct iosapic_irt *irt_next; /* next routing table */
+ struct irt_entry *irt_base; /* intr routing table address */
+ size_t irte_count; /* number of entries in the table */
+ size_t irte_size; /* size (bytes) of each entry */
+};
+#endif
+
+struct vector_info {
+ struct iosapic_info *vi_ios; /* I/O SAPIC this vector is on */
+ struct irt_entry *vi_irte; /* IRT entry */
+ u32 *vi_eoi_addr; /* precalculate EOI reg address */
+ u32 vi_eoi_data; /* IA64: ? PA: swapped txn_data */
+ u8 vi_status; /* status/flags */
+ u8 vi_irqline; /* INTINn(IRQ) */
+ int vi_txn_irq; /* virtual IRQ number for processor */
+ ulong vi_txn_addr; /* IA64: id_eid PA: partial HPA */
+ ulong vi_txn_data; /* IA64: vector PA: EIR bit */
+};
+
+
+struct iosapic_info {
+ struct iosapic_info *isi_next; /* list of I/O SAPIC */
+ volatile void *isi_hpa; /* physical base address */
+ struct irq_region *isi_region; /* each I/O SAPIC is one region */
+ struct vector_info *isi_vector; /* IRdT (IRQ line) array */
+ int isi_num_vectors; /* size of IRdT array */
+ int isi_status; /* status/flags */
+ unsigned int isi_version; /* DEBUG: data fr version reg */
+};
+
+
+
+#ifdef __IA64__
+/*
+** PA risc does NOT have any local sapics. IA64 does.
+** PIB (Processor Interrupt Block) is handled by Astro or Dew (Stretch CEC).
+**
+** PA: Get id_eid from IRT and hardcode PIB to 0xfeeNNNN0
+** Emulate the data on PAT platforms.
+*/
+struct local_sapic_info {
+ struct local_sapic_info *lsi_next; /* point to next CPU info */
+ int *lsi_cpu_id; /* point to logical CPU id */
+ unsigned long *lsi_id_eid; /* point to IA-64 CPU id */
+ int *lsi_status; /* point to CPU status */
+ void *lsi_private; /* point to special info */
+};
+
+/*
+** "root" data structure which ties everything together.
+** Should always be able to start with sapic_root and locate
+** the desired information.
+*/
+struct sapic_info {
+ struct sapic_info *si_next; /* info is per cell */
+ int si_cellid; /* cell id */
+ unsigned int si_status; /* status */
+ char *si_pib_base; /* intr blk base address */
+ local_sapic_info_t *si_local_info;
+ io_sapic_info_t *si_io_info;
+ extint_info_t *si_extint_info;/* External Intr info */
+};
+#endif
+
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
new file mode 100644
index 000000000..aec36f7cc
--- /dev/null
+++ b/arch/parisc/kernel/irq.c
@@ -0,0 +1,538 @@
+/* $Id: irq.c,v 1.8 2000/02/08 02:01:17 grundler Exp $
+ *
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * This is not in any way SMP-clean.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1999 SuSE GmbH (Author: Philipp Rumpf, prumpf@tux.org)
+ * Copyright (C) 2000 Hewlett Packard Corp (Co-Author: Grant Grundler, grundler@cup.hp.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, 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/bitops.h>
+#include <asm/bitops.h>
+#include <asm/pdc.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/cache.h>
+
+#undef DEBUG_IRQ
+
+extern void timer_interrupt(int, void *, struct pt_regs *);
+extern void ipi_interrupt(int, void *, struct pt_regs *);
+
+#ifdef DEBUG_IRQ
+#define DBG_IRQ(x...) printk(x)
+#else /* DEBUG_IRQ */
+#define DBG_IRQ(x...)
+#endif /* DEBUG_IRQ */
+
+#define EIEM_MASK(irq) (1L<<(MAX_CPU_IRQ-IRQ_OFFSET(irq)))
+#define CLEAR_EIEM_BIT(irq) set_eiem(get_eiem() & ~EIEM_MASK(irq))
+#define SET_EIEM_BIT(irq) set_eiem(get_eiem() | EIEM_MASK(irq))
+
+static void disable_cpu_irq(void *unused, int irq)
+{
+ CLEAR_EIEM_BIT(irq);
+}
+
+static void enable_cpu_irq(void *unused, int irq)
+{
+ unsigned long mask = EIEM_MASK(irq);
+
+ mtctl(mask, 23);
+ SET_EIEM_BIT(irq);
+}
+
+static struct irqaction cpu_irq_actions[IRQ_PER_REGION] = {
+ [IRQ_OFFSET(TIMER_IRQ)] { timer_interrupt, 0, 0, "timer", NULL, NULL },
+ [IRQ_OFFSET(IPI_IRQ)] { ipi_interrupt, 0, 0, "IPI", NULL, NULL },
+};
+
+struct irq_region cpu_irq_region = {
+ { disable_cpu_irq, enable_cpu_irq, NULL, NULL },
+ { &cpu_data[0], "PA-PIC", IRQ_REG_MASK|IRQ_REG_DIS, IRQ_FROM_REGION(CPU_IRQ_REGION)},
+ cpu_irq_actions
+};
+
+struct irq_region *irq_region[NR_IRQ_REGS] = {
+ [ 0 ] NULL, /* abuse will data page fault (aka code 15) */
+ [ CPU_IRQ_REGION ] &cpu_irq_region,
+};
+
+
+
+/* we special-case the real IRQs here, which feels right given the relatively
+ * high cost of indirect calls. If anyone is bored enough to benchmark this
+ * and find out whether I am right, feel free to. prumpf */
+
+static inline void mask_irq(int irq)
+{
+ struct irq_region *region;
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("mask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+
+ if(IRQ_REGION(irq) != CPU_IRQ_REGION) {
+ region = irq_region[IRQ_REGION(irq)];
+ if(region->data.flags & IRQ_REG_MASK)
+ region->ops.mask_irq(region->data.dev, IRQ_OFFSET(irq));
+ } else {
+ CLEAR_EIEM_BIT(irq);
+ }
+}
+
+static inline void unmask_irq(int irq)
+{
+ struct irq_region *region;
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("unmask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+
+ if(IRQ_REGION(irq) != CPU_IRQ_REGION) {
+ region = irq_region[IRQ_REGION(irq)];
+ if(region->data.flags & IRQ_REG_MASK)
+ region->ops.unmask_irq(region->data.dev, IRQ_OFFSET(irq));
+ } else {
+ SET_EIEM_BIT(irq);
+ }
+}
+
+void disable_irq(int irq)
+{
+ struct irq_region *region;
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("disable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+ region = irq_region[IRQ_REGION(irq)];
+
+ if(region->data.flags & IRQ_REG_DIS)
+ region->ops.disable_irq(region->data.dev, IRQ_OFFSET(irq));
+ else
+ BUG();
+}
+
+void enable_irq(int irq)
+{
+ struct irq_region *region;
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("enable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+ region = irq_region[IRQ_REGION(irq)];
+
+ if(region->data.flags & IRQ_REG_DIS)
+ region->ops.enable_irq(region->data.dev, IRQ_OFFSET(irq));
+ else
+ BUG();
+}
+
+int get_irq_list(char *buf)
+{
+#ifdef CONFIG_PROC_FS
+ char *p = buf;
+ int i, j;
+ int regnr, irq_no;
+ struct irq_region *region;
+ struct irqaction *action, *mainaction;
+
+ p += sprintf(p, " ");
+ for (j=0; j<smp_num_cpus; j++)
+ p += sprintf(p, "CPU%d ",j);
+ *p++ = '\n';
+
+ for (regnr = 0; regnr < NR_IRQ_REGS; regnr++) {
+ region = irq_region[regnr];
+ if (!region || !region->action)
+ continue;
+
+ mainaction = region->action;
+
+ for (i = 0; i <= MAX_CPU_IRQ; i++) {
+ action = mainaction++;
+ if (!action || !action->name)
+ continue;
+
+ irq_no = IRQ_FROM_REGION(regnr) + i;
+
+ p += sprintf(p, "%3d: ", irq_no);
+#ifndef CONFIG_SMP
+ p += sprintf(p, "%10u ", kstat_irqs(irq_no));
+#else
+ for (j = 0; j < smp_num_cpus; j++)
+ p += sprintf(p, "%10u ",
+ kstat.irqs[cpu_logical_map(j)][irq_no]);
+#endif
+ p += sprintf(p, " %14s",
+ region->data.name ? region->data.name : "N/A");
+ p += sprintf(p, " %s", action->name);
+
+ for (action=action->next; action; action = action->next)
+ p += sprintf(p, ", %s", action->name);
+ *p++ = '\n';
+ }
+ }
+
+ p += sprintf(p, "\n");
+#if CONFIG_SMP
+ p += sprintf(p, "LOC: ");
+ for (j = 0; j < smp_num_cpus; j++)
+ p += sprintf(p, "%10u ",
+ apic_timer_irqs[cpu_logical_map(j)]);
+ p += sprintf(p, "\n");
+#endif
+
+ return p - buf;
+
+#else /* CONFIG_PROC_FS */
+
+ return 0;
+
+#endif /* CONFIG_PROC_FS */
+}
+
+
+
+/*
+** The following form a "set": Virtual IRQ, Transaction Address, Trans Data.
+** Respectively, these map to IRQ region+EIRR, Processor HPA, EIRR bit.
+**
+** To use txn_XXX() interfaces, get a Virtual IRQ first.
+** Then use that to get the Transaction address and data.
+*/
+
+int
+txn_alloc_irq(void)
+{
+ int irq;
+
+ /* never return irq 0 cause that's the interval timer */
+ for(irq=1; irq<=MAX_CPU_IRQ; irq++) {
+ if(cpu_irq_region.action[irq].handler == NULL) {
+ return (IRQ_FROM_REGION(CPU_IRQ_REGION) + irq);
+ }
+ }
+
+ /* unlikely, but be prepared */
+ return -1;
+}
+
+int
+txn_claim_irq(int irq)
+{
+ if (irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)].handler ==NULL)
+ {
+ return irq;
+ }
+
+ /* unlikely, but be prepared */
+ return -1;
+}
+
+unsigned long
+txn_alloc_addr(int virt_irq)
+{
+ struct cpuinfo_parisc *dev = (struct cpuinfo_parisc *) (irq_region[IRQ_REGION(virt_irq)]->data.dev);
+
+ if (0==dev) {
+ printk(KERN_ERR "txn_alloc_addr(0x%x): CPU IRQ region? dev %p\n",
+ virt_irq,dev);
+ return(0UL);
+ }
+ return (dev->txn_addr);
+}
+
+
+/*
+** The alloc process needs to accept a parameter to accomodate limitations
+** of the HW/SW which use these bits:
+** Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register)
+** V-class (EPIC): 6 bits
+** N/L-class/A500: 8 bits (iosapic)
+** PCI 2.2 MSI: 16 bits (I think)
+** Existing PCI devices: 32-bits (NCR c720/ATM/GigE/HyperFabric)
+**
+** On the service provider side:
+** o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register)
+** o PA 2.0 wide mode 6-bits (per processor)
+** o IA64 8-bits (0-256 total)
+**
+** So a Legacy PA I/O device on a PA 2.0 box can't use all
+** the bits supported by the processor...and the N/L-class
+** I/O subsystem supports more bits than PA2.0 has. The first
+** case is the problem.
+*/
+unsigned int
+txn_alloc_data(int virt_irq, unsigned int bits_wide)
+{
+ /* XXX FIXME : bits_wide indicates how wide the transaction
+ ** data is allowed to be...we may need a different virt_irq
+ ** if this one won't work. Another reason to index virtual
+ ** irq's into a table which can manage CPU/IRQ bit seperately.
+ */
+ if (IRQ_OFFSET(virt_irq) > (1 << (bits_wide -1)))
+ {
+ panic("Sorry -- didn't allocate valid IRQ for this device\n");
+ }
+
+ return(IRQ_OFFSET(virt_irq));
+}
+
+
+/* FIXME: SMP, flags, bottom halves, rest */
+void do_irq(struct irqaction *action, int irq, struct pt_regs * regs)
+{
+ int cpu = smp_processor_id();
+
+ irq_enter(cpu, irq);
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+ if (action->handler == NULL)
+ printk(KERN_ERR "No handler for interrupt %d !\n", irq);
+
+ for(; action && action->handler; action = action->next) {
+ action->handler(irq, action->dev_id, regs);
+ }
+
+ irq_exit(cpu, irq);
+
+ /* don't need to care about unmasking and stuff */
+ do_softirq();
+}
+
+void do_irq_mask(unsigned long mask, struct irq_region *region, struct pt_regs *regs)
+{
+ unsigned long bit;
+ int irq;
+ int cpu = smp_processor_id();
+
+#ifdef DEBUG_IRQ
+ if (mask != (1L << MAX_CPU_IRQ))
+ printk("do_irq_mask %08lx %p %p\n", mask, region, regs);
+#endif
+
+ for(bit=(1L<<MAX_CPU_IRQ), irq = 0; mask && bit; bit>>=1, irq++) {
+ int irq_num;
+ if(!(bit&mask))
+ continue;
+
+ irq_num = region->data.irqbase + irq;
+
+ ++kstat.irqs[cpu][IRQ_FROM_REGION(CPU_IRQ_REGION) | irq];
+ if (IRQ_REGION(irq_num) != CPU_IRQ_REGION)
+ ++kstat.irqs[cpu][irq_num];
+
+ mask_irq(irq_num);
+ do_irq(&region->action[irq], irq_num, regs);
+ unmask_irq(irq_num);
+ }
+}
+
+static inline int alloc_irqregion(void)
+{
+ int irqreg;
+
+ for(irqreg=1; irqreg<=(NR_IRQ_REGS); irqreg++) {
+ if(irq_region[irqreg] == NULL)
+ return irqreg;
+ }
+
+ return 0;
+}
+
+struct irq_region *alloc_irq_region(
+ int count, struct irq_region_ops *ops, unsigned long flags,
+ const char *name, void *dev)
+{
+ struct irq_region *region;
+ int index;
+
+ index = alloc_irqregion();
+
+ if((IRQ_REGION(count-1)))
+ return NULL;
+
+ if (count < IRQ_PER_REGION) {
+ DBG_IRQ("alloc_irq_region() using minimum of %d irq lines for %s (%d)\n",
+ IRQ_PER_REGION, name, count);
+ count = IRQ_PER_REGION;
+ }
+
+ if(flags & IRQ_REG_MASK)
+ if(!(ops->mask_irq && ops->unmask_irq))
+ return NULL;
+
+ if(flags & IRQ_REG_DIS)
+ if(!(ops->disable_irq && ops->enable_irq))
+ return NULL;
+
+ if((irq_region[index]))
+ return NULL;
+
+ region = kmalloc(sizeof *region, GFP_ATOMIC);
+ if(!region)
+ return NULL;
+
+ region->action = kmalloc(sizeof *region->action * count, GFP_ATOMIC);
+ if(!region->action) {
+ kfree(region);
+ return NULL;
+ }
+ memset(region->action, 0, sizeof *region->action * count);
+
+ region->ops = *ops;
+ region->data.irqbase = IRQ_FROM_REGION(index);
+ region->data.flags = flags;
+ region->data.name = name;
+ region->data.dev = dev;
+
+ irq_region[index] = region;
+
+ return irq_region[index];
+}
+
+
+
+/* FIXME: SMP, flags, bottom halves, rest */
+
+int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char * devname,
+ void *dev_id)
+{
+ struct irqaction * action;
+
+#if 0
+ printk(KERN_INFO "request_irq(%d, %p, 0x%lx, %s, %p)\n",irq, handler, irqflags, devname, dev_id);
+#endif
+ if(!handler) {
+ printk(KERN_ERR "request_irq(%d,...): Augh! No handler for irq!\n",
+ irq);
+ return -EINVAL;
+ }
+
+ if ((IRQ_REGION(irq) == 0) || irq_region[IRQ_REGION(irq)] == NULL) {
+ /*
+ ** Bug catcher for drivers which use "char" or u8 for
+ ** the IRQ number. They lose the region number which
+ ** is in pcidev->irq (an int).
+ */
+ printk(KERN_ERR "%p (%s?) called request_irq with an invalid irq %d\n",
+ __builtin_return_address(0), devname, irq);
+ return -EINVAL;
+ }
+
+ action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)];
+
+ if(action->handler) {
+ while(action->next)
+ action = action->next;
+
+ action->next = kmalloc(sizeof *action, GFP_ATOMIC);
+
+ action = action->next;
+ }
+
+ if(!action) {
+ printk(KERN_ERR "request_irq():Augh! No action!\n") ;
+ return -ENOMEM;
+ }
+
+ action->handler = handler;
+ action->flags = irqflags;
+ action->mask = 0;
+ action->name = devname;
+ action->next = NULL;
+ action->dev_id = dev_id;
+
+ enable_irq(irq);
+ return 0;
+}
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+ struct irqaction *action, **p;
+
+ action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)];
+
+ if(action->dev_id == dev_id) {
+ if(action->next == NULL)
+ action->handler = NULL;
+ else
+ memcpy(action, action->next, sizeof *action);
+
+ return;
+ }
+
+ p = &action->next;
+ action = action->next;
+
+ for (; (action = *p) != NULL; p = &action->next) {
+ if (action->dev_id != dev_id)
+ continue;
+
+ /* Found it - now free it */
+ *p = action->next;
+ kfree(action);
+
+ return;
+ }
+
+ printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
+}
+
+unsigned long probe_irq_on (void)
+{
+ return 0;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+ return 0;
+}
+
+
+void __init init_IRQ(void)
+{
+}
+
+void init_irq_proc(void)
+{
+}
diff --git a/arch/parisc/kernel/keyboard.c b/arch/parisc/kernel/keyboard.c
new file mode 100644
index 000000000..05044db49
--- /dev/null
+++ b/arch/parisc/kernel/keyboard.c
@@ -0,0 +1,82 @@
+/*
+ * linux/arch/parisc/kernel/keyboard.c
+ *
+ * Alex deVries <adevries@thepuffingroup.com>
+ * Copyright (1999) The Puffin Group
+ * Mostly rewritten by Philipp Rumpf <prumpf@tux.org>
+ * Copyright 2000 Philipp Rumpf
+ */
+
+#include <linux/keyboard.h>
+#include <asm/keyboard.h>
+
+static int def_setkeycode(unsigned int x, unsigned int y)
+{
+ return 0;
+}
+
+static int def_getkeycode(unsigned int x)
+{
+ return 0;
+}
+
+static int def_translate(unsigned char scancode, unsigned char *keycode,
+ char raw)
+{
+ *keycode = scancode;
+
+ return 1;
+}
+
+static char def_unexpected_up(unsigned char c)
+{
+ return 128;
+}
+
+static void def_leds(unsigned char leds)
+{
+}
+
+static void def_init_hw(void)
+{
+}
+
+static char def_sysrq_xlate[NR_KEYS];
+
+static struct kbd_ops def_kbd_ops = {
+ setkeycode: def_setkeycode,
+ getkeycode: def_getkeycode,
+ translate: def_translate,
+ unexpected_up: def_unexpected_up,
+ leds: def_leds,
+ init_hw: def_init_hw,
+
+ sysrq_key: 0xff,
+ sysrq_xlate: def_sysrq_xlate,
+};
+
+struct kbd_ops *kbd_ops = &def_kbd_ops;
+
+void register_kbd_ops(struct kbd_ops *ops)
+{
+ if(ops->setkeycode)
+ kbd_ops->setkeycode = ops->setkeycode;
+
+ if(ops->getkeycode)
+ kbd_ops->getkeycode = ops->getkeycode;
+
+ if(ops->translate)
+ kbd_ops->translate = ops->translate;
+
+ if(ops->unexpected_up)
+ kbd_ops->unexpected_up = ops->unexpected_up;
+
+ if(ops->leds)
+ kbd_ops->leds = ops->leds;
+
+ if(ops->init_hw)
+ kbd_ops->init_hw = ops->init_hw;
+
+ kbd_ops->sysrq_key = ops->sysrq_key;
+ kbd_ops->sysrq_xlate = ops->sysrq_xlate;
+}
diff --git a/arch/parisc/kernel/lasimap.map b/arch/parisc/kernel/lasimap.map
new file mode 100644
index 000000000..2a9ee223c
--- /dev/null
+++ b/arch/parisc/kernel/lasimap.map
@@ -0,0 +1,322 @@
+# HP 712 kernel keymap. This uses 7 modifier combinations.
+
+keymaps 0-2,4-5,8,12
+# ie, plain, Shift, AltGr, Control, Control+Shift, Alt and Control+Alt
+
+
+# Change the above line into
+# keymaps 0-2,4-6,8,12
+# in case you want the entries
+# altgr control keycode 83 = Boot
+# altgr control keycode 111 = Boot
+# below.
+#
+# In fact AltGr is used very little, and one more keymap can
+# be saved by mapping AltGr to Alt (and adapting a few entries):
+# keycode 100 = Alt
+#
+keycode 1 = F9 F19 Console_21
+ control keycode 1 = F9
+ alt keycode 1 = Console_9
+ control alt keycode 1 = Console_9
+keycode 2 =
+keycode 3 = F5 F15 Console_17
+ control keycode 3 = F5
+ alt keycode 3 = Console_5
+ control alt keycode 3 = Console_5
+keycode 4 = F3 F13 Console_15
+ control keycode 4 = F3
+ alt keycode 4 = Console_3
+ control alt keycode 4 = Console_3
+keycode 5 = F1 F11 Console_13
+ control keycode 5 = F1
+ alt keycode 5 = Console_1
+ control alt keycode 5 = Console_1
+keycode 6 = F2 F12 Console_14
+ control keycode 6 = F2
+ alt keycode 6 = Console_2
+ control alt keycode 6 = Console_2
+keycode 7 = F12 F12 Console_24
+ control keycode 7 = F12
+ alt keycode 7 = Console_12
+ control alt keycode 7 = Console_12
+keycode 8 =
+keycode 9 = F10 F20 Console_22
+ control keycode 9 = F10
+ alt keycode 9 = Console_10
+ control alt keycode 9 = Console_10
+keycode 10 = F8 F18 Console_20
+ control keycode 10 = F8
+ alt keycode 10 = Console_8
+ control alt keycode 10 = Console_8
+keycode 11 = F6 F16 Console_18
+ control keycode 11 = F6
+ alt keycode 11 = Console_6
+ control alt keycode 11 = Console_6
+keycode 12 = F4 F14 Console_16
+ control keycode 12 = F4
+ alt keycode 12 = Console_4
+ control alt keycode 12 = Console_4
+keycode 13 = Tab Tab
+ alt keycode 13 = Meta_Tab
+keycode 14 = grave asciitilde
+ control keycode 14 = nul
+ alt keycode 14 = Meta_grave
+keycode 15 =
+keycode 16 =
+keycode 17 = Alt
+keycode 18 = Shift
+keycode 19 =
+keycode 20 = Control
+keycode 21 = q
+keycode 22 = one exclam exclam
+keycode 23 =
+keycode 24 =
+keycode 25 =
+keycode 26 = z
+keycode 27 = s
+keycode 28 = a
+ altgr keycode 28 = Hex_A
+keycode 29 = w
+keycode 30 = two at at
+keycode 31 =
+keycode 32 =
+keycode 33 = c
+ altgr keycode 46 = Hex_C
+keycode 34 = x
+keycode 35 = d
+ altgr keycode 35 = Hex_D
+keycode 36 = e
+ altgr keycode 36 = Hex_E
+keycode 37 = four dollar
+keycode 38 = three numbersign
+keycode 39 =
+keycode 40 =
+keycode 41 =
+keycode 42 = v
+keycode 43 = f
+ altgr keycode 43 = Hex_F
+keycode 44 = t
+keycode 45 = r
+keycode 46 = five percent
+keycode 47 =
+keycode 48 =
+keycode 49 = n
+keycode 50 = b
+ altgr keycode 50 = Hex_B
+keycode 51 = h
+keycode 52 = g
+keycode 53 = y
+keycode 54 = six asciicircum
+keycode 55 =
+keycode 56 =
+keycode 57 =
+keycode 58 = m
+keycode 59 = j
+keycode 60 = u
+keycode 61 = seven ampersand
+keycode 62 = eight asterisk asterisk
+keycode 63 =
+keycode 64 =
+keycode 65 = comma less
+ alt keycode 65 = Meta_comma
+keycode 66 = k
+keycode 67 = i
+keycode 68 = o
+keycode 69 = zero parenright bracketright
+keycode 70 = nine parenleft bracketleft
+keycode 71 =
+keycode 72 =
+keycode 73 = period greater
+ control keycode 73 = Compose
+ alt keycode 73 = Meta_period
+keycode 74 = slash question
+ control keycode 74 = Delete
+ alt keycode 53 = Meta_slash
+keycode 75 = l
+keycode 76 = semicolon colon
+ alt keycode 39 = Meta_semicolon
+keycode 77 = p
+keycode 78 = minus underscore
+keycode 79 =
+keycode 80 =
+keycode 81 =
+keycode 82 = apostrophe quotedbl
+ control keycode 82 = Control_g
+ alt keycode 40 = Meta_apostrophe
+keycode 83 =
+keycode 84 = bracketleft braceleft
+ control keycode 84 = Escape
+ alt keycode 26 = Meta_bracketleft
+keycode 85 = equal plus
+keycode 86 =
+keycode 87 =
+keycode 88 = Caps_Lock
+keycode 88 =
+keycode 89 =
+keycode 89 =
+keycode 89 =
+keycode 90 = Return
+ alt keycode 90 = Meta_Control_m
+keycode 91 = bracketright braceright asciitilde
+ control keycode 91 = Control_bracketright
+ alt keycode 91 = Meta_bracketright
+keycode 92 =
+keycode 93 = backslash bar
+ control keycode 43 = Control_backslash
+ alt keycode 43 = Meta_backslash
+keycode 94 =
+keycode 95 =
+keycode 96 =
+keycode 97 =
+keycode 98 =
+keycode 99 =
+keycode 100 =
+keycode 101 =
+keycode 102 = BackSpace
+keycode 103 =
+keycode 104 =
+keycode 105 = KP_1
+ alt keycode 105 = Ascii_1
+ altgr keycode 105 = Hex_1
+keycode 106 =
+keycode 107 = KP_4
+ alt keycode 107 = Ascii_4
+ altgr keycode 107 = Hex_4
+keycode 108 = KP_7
+ alt keycode 108 = Ascii_7
+ altgr keycode 108 = Hex_7
+keycode 109 =
+keycode 110 =
+keycode 111 =
+keycode 112 = KP_0
+ alt keycode 82 = Ascii_0
+ altgr keycode 82 = Hex_0
+keycode 113 = KP_Period
+keycode 114 = KP_2
+ alt keycode 114 = Ascii_2
+ altgr keycode 114 = Hex_2
+keycode 115 = KP_5
+ alt keycode 115 = Ascii_5
+ altgr keycode 115 = Hex_5
+keycode 116 = KP_6
+ alt keycode 116 = Ascii_6
+ altgr keycode 116 = Hex_6
+keycode 117 = KP_8
+ alt keycode 117 = Ascii_8
+ altgr keycode 117 = Hex_8
+keycode 118 = Escape
+keycode 119 =
+keycode 120 = F11
+keycode 121 = KP_Add
+keycode 122 = KP_3
+ alt keycode 122 = Ascii_3
+ altgr keycode 122 = Hex_3
+keycode 123 = KP_Subtract
+keycode 124 = KP_Multiply
+keycode 125 = KP_9
+ alt keycode 125 = Ascii_9
+ altgr keycode 125 = Hex_9
+keycode 126 =
+# 131!!
+keycode 127 = F7 F17 Console_19
+ control keycode 127 = F7
+ alt keycode 127 = Console_7
+ control alt keycode 127 = Console_7
+
+string F1 = "\033[[A"
+string F2 = "\033[[B"
+string F3 = "\033[[C"
+string F4 = "\033[[D"
+string F5 = "\033[[E"
+string F6 = "\033[17~"
+string F7 = "\033[18~"
+string F8 = "\033[19~"
+string F9 = "\033[20~"
+string F10 = "\033[21~"
+string F11 = "\033[23~"
+string F12 = "\033[24~"
+string F13 = "\033[25~"
+string F14 = "\033[26~"
+string F15 = "\033[28~"
+string F16 = "\033[29~"
+string F17 = "\033[31~"
+string F18 = "\033[32~"
+string F19 = "\033[33~"
+string F20 = "\033[34~"
+string Find = "\033[1~"
+string Insert = "\033[2~"
+string Remove = "\033[3~"
+string Select = "\033[4~"
+string Prior = "\033[5~"
+string Next = "\033[6~"
+string Macro = "\033[M"
+string Pause = "\033[P"
+compose '`' 'A' to 'À'
+compose '`' 'a' to 'à'
+compose '\'' 'A' to 'Á'
+compose '\'' 'a' to 'á'
+compose '^' 'A' to 'Â'
+compose '^' 'a' to 'â'
+compose '~' 'A' to 'Ã'
+compose '~' 'a' to 'ã'
+compose '"' 'A' to 'Ä'
+compose '"' 'a' to 'ä'
+compose 'O' 'A' to 'Å'
+compose 'o' 'a' to 'å'
+compose '0' 'A' to 'Å'
+compose '0' 'a' to 'å'
+compose 'A' 'A' to 'Å'
+compose 'a' 'a' to 'å'
+compose 'A' 'E' to 'Æ'
+compose 'a' 'e' to 'æ'
+compose ',' 'C' to 'Ç'
+compose ',' 'c' to 'ç'
+compose '`' 'E' to 'È'
+compose '`' 'e' to 'è'
+compose '\'' 'E' to 'É'
+compose '\'' 'e' to 'é'
+compose '^' 'E' to 'Ê'
+compose '^' 'e' to 'ê'
+compose '"' 'E' to 'Ë'
+compose '"' 'e' to 'ë'
+compose '`' 'I' to 'Ì'
+compose '`' 'i' to 'ì'
+compose '\'' 'I' to 'Í'
+compose '\'' 'i' to 'í'
+compose '^' 'I' to 'Î'
+compose '^' 'i' to 'î'
+compose '"' 'I' to 'Ï'
+compose '"' 'i' to 'ï'
+compose '-' 'D' to 'Ð'
+compose '-' 'd' to 'ð'
+compose '~' 'N' to 'Ñ'
+compose '~' 'n' to 'ñ'
+compose '`' 'O' to 'Ò'
+compose '`' 'o' to 'ò'
+compose '\'' 'O' to 'Ó'
+compose '\'' 'o' to 'ó'
+compose '^' 'O' to 'Ô'
+compose '^' 'o' to 'ô'
+compose '~' 'O' to 'Õ'
+compose '~' 'o' to 'õ'
+compose '"' 'O' to 'Ö'
+compose '"' 'o' to 'ö'
+compose '/' 'O' to 'Ø'
+compose '/' 'o' to 'ø'
+compose '`' 'U' to 'Ù'
+compose '`' 'u' to 'ù'
+compose '\'' 'U' to 'Ú'
+compose '\'' 'u' to 'ú'
+compose '^' 'U' to 'Û'
+compose '^' 'u' to 'û'
+compose '"' 'U' to 'Ü'
+compose '"' 'u' to 'ü'
+compose '\'' 'Y' to 'Ý'
+compose '\'' 'y' to 'ý'
+compose 'T' 'H' to 'Þ'
+compose 't' 'h' to 'þ'
+compose 's' 's' to 'ß'
+compose '"' 'y' to 'ÿ'
+compose 's' 'z' to 'ß'
+compose 'i' 'j' to 'ÿ'
diff --git a/arch/parisc/kernel/lba_pci.c b/arch/parisc/kernel/lba_pci.c
new file mode 100644
index 000000000..6096d0153
--- /dev/null
+++ b/arch/parisc/kernel/lba_pci.c
@@ -0,0 +1,1346 @@
+/*
+** PCI Lower Bus Adapter (LBA) manager
+**
+** (c) Copyright 1999,2000 Grant Grundler
+** (c) Copyright 1999,2000 Hewlett-Packard Company
+**
+** 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 module primarily provides access to PCI bus (config/IOport
+** spaces) on platforms with an SBA/LBA chipset. A/B/C/J/L/N-class
+** with 4 digit model numbers - eg C3000 (and A400...sigh).
+**
+** LBA driver isn't as simple as the Dino driver because:
+** (a) this chip has substantial bug fixes between revisions
+** (Only one Dino bug has a software workaround :^( )
+** (b) has more options which we don't (yet) support (DMA hints, OLARD)
+** (c) IRQ support lives in the I/O SAPIC driver (not with PCI driver)
+** (d) play nicely with both PAT and "Legacy" PA-RISC firmware (PDC).
+** (dino only deals with "Legacy" PDC)
+**
+** LBA driver passes the I/O SAPIC HPA to the I/O SAPIC driver.
+** (I/O SAPIC is integratd in the LBA chip).
+**
+** FIXME: Add support to SBA and LBA drivers for DMA hint sets
+** FIXME: Add support for PCI card hot-plug (OLARD).
+*/
+
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/init.h> /* for __init and __devinit */
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/smp_lock.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h> /* for struct irq_region support */
+#include <asm/pdc.h>
+#include <asm/pdcpat.h>
+#include <asm/page.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+#include <asm/hardware.h> /* for register_driver() stuff */
+#include <asm/iosapic.h> /* for iosapic_register() */
+#include <asm/gsc.h> /* gsc_read/write stuff */
+
+
+#ifndef TRUE
+#define TRUE (1 == 1)
+#define FALSE (1 == 0)
+#endif
+
+#undef DEBUG_LBA /* general stuff */
+#undef DEBUG_LBA_PORT /* debug I/O Port access */
+#undef DEBUG_LBA_CFG /* debug Config Space Access (ie PCI Bus walk) */
+#undef DEBUG_LBA_PAT /* debug PCI Resource Mgt code - PDC PAT only */
+
+#ifdef DEBUG_LBA
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#ifdef DEBUG_LBA_PORT
+#define DBG_PORT(x...) printk(x)
+#else
+#define DBG_PORT(x...)
+#endif
+
+#ifdef DEBUG_LBA_CFG
+#define DBG_CFG(x...) printk(x)
+#else
+#define DBG_CFG(x...)
+#endif
+
+#ifdef DEBUG_LBA_PAT
+#define DBG_PAT(x...) printk(x)
+#else
+#define DBG_PAT(x...)
+#endif
+
+/*
+** Config accessor functions only pass in the 8-bit bus number and not
+** the 8-bit "PCI Segment" number. Each LBA will be assigned a PCI bus
+** number based on what firmware wrote into the scratch register.
+**
+** The "secondary" bus number is set to this before calling
+** pci_register_ops(). If any PPB's are present, the scan will
+** discover them and update the "secondary" and "subordinate"
+** fields in the pci_bus structure.
+**
+** Changes in the configuration *may* result in a different
+** bus number for each LBA depending on what firmware does.
+*/
+
+#define MODULE_NAME "lba"
+
+static int lba_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+
+static struct pa_iodc_driver lba_drivers_for[]= {
+
+ {HPHW_BRIDGE, 0x782, 0x0, 0xa, 0,0,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "tbd", (void *) lba_driver_callback},
+
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL}
+};
+
+
+#define LBA_FUNC_ID 0x0000 /* function id */
+#define LBA_FCLASS 0x0008 /* function class, bist, header, rev... */
+#define LBA_CAPABLE 0x0030 /* capabilities register */
+
+#define LBA_PCI_CFG_ADDR 0x0040 /* poke CFG address here */
+#define LBA_PCI_CFG_DATA 0x0048 /* read or write data here */
+
+#define LBA_PMC_MTLT 0x0050 /* Firmware sets this - read only. */
+#define LBA_FW_SCRATCH 0x0058 /* Firmware writes the PCI bus number here. */
+#define LBA_ERROR_ADDR 0x0070 /* On error, address gets logged here */
+
+#define LBA_ARB_MASK 0x0080 /* bit 0 enable arbitration. PAT/PDC enables */
+#define LBA_ARB_PRI 0x0088 /* firmware sets this. */
+#define LBA_ARB_MODE 0x0090 /* firmware sets this. */
+#define LBA_ARB_MTLT 0x0098 /* firmware sets this. */
+
+#define LBA_MOD_ID 0x0100 /* Module ID. PDC_PAT_CELL reports 4 */
+
+#define LBA_STAT_CTL 0x0108 /* Status & Control */
+#define HF_ENABLE 0x40 /* enable HF mode (default is -1 mode) */
+
+#define LBA_LMMIO_BASE 0x0200 /* < 4GB I/O address range */
+#define LBA_LMMIO_MASK 0x0208
+
+#define LBA_GMMIO_BASE 0x0210 /* > 4GB I/O address range */
+#define LBA_GMMIO_MASK 0x0218
+
+#define LBA_WLMMIO_BASE 0x0220 /* All < 4GB ranges under the same *SBA* */
+#define LBA_WLMMIO_MASK 0x0228
+
+#define LBA_WGMMIO_BASE 0x0230 /* All > 4GB ranges under the same *SBA* */
+#define LBA_WGMMIO_MASK 0x0238
+
+#define LBA_IOS_BASE 0x0240 /* I/O port space for this LBA */
+#define LBA_IOS_MASK 0x0248
+
+#define LBA_ELMMIO_BASE 0x0250 /* Extra LMMIO range */
+#define LBA_ELMMIO_MASK 0x0258
+
+#define LBA_EIOS_BASE 0x0260 /* Extra I/O port space */
+#define LBA_EIOS_MASK 0x0268
+
+#define LBA_DMA_CTL 0x0278 /* firmware sets this */
+
+/* RESET: ignore DMA stuff until we can measure performance */
+#define LBA_IBASE 0x0300 /* DMA support */
+#define LBA_IMASK 0x0308
+#define LBA_HINT_CFG 0x0310
+#define LBA_HINT_BASE 0x0380 /* 14 registers at every 8 bytes. */
+
+/* ERROR regs are needed for config cycle kluges */
+#define LBA_ERROR_CONFIG 0x0680
+#define LBA_ERROR_STATUS 0x0688
+
+#define LBA_IOSAPIC_BASE 0x800 /* Offset of IRQ logic */
+
+/* non-postable I/O port space, densely packed */
+#ifdef __LP64__
+#define LBA_ASTRO_PORT_BASE (0xfffffffffee00000UL)
+#else
+#define LBA_ASTRO_PORT_BASE (0xfee00000UL)
+#endif
+
+
+/*
+** lba_device: Per instance Elroy data structure
+*/
+struct lba_device {
+ struct pci_hba_data hba;
+
+ spinlock_t lba_lock;
+ void *iosapic_obj;
+
+#ifdef __LP64__
+ unsigned long lmmio_base; /* PA_VIEW - fixup MEM addresses */
+ unsigned long gmmio_base; /* PA_VIEW - Not used (yet) */
+ unsigned long iop_base; /* PA_VIEW - for IO port accessor funcs */
+#endif
+
+ int flags; /* state/functionality enabled */
+ int hw_rev; /* HW revision of chip */
+};
+
+
+static u32 lba_t32;
+
+/*
+** lba "flags"
+*/
+#define LBA_FLAG_NO_DMA_DURING_CFG 0x01
+#define LBA_FLAG_SKIP_PROBE 0x10
+
+/* Tape Release 4 == hw_rev 5 */
+#define LBA_TR4PLUS(d) ((d)->hw_rev > 0x4)
+#define LBA_DMA_DURING_CFG_DISABLED(d) ((d)->flags & LBA_FLAG_NO_DMA_DURING_CFG)
+#define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE)
+
+
+/* Looks nice and keeps the compiler happy */
+#define LBA_DEV(d) ((struct lba_device *) (d))
+
+
+/*
+** Only allow 8 subsidiary busses per LBA
+** Problem is the PCI bus numbering is globally shared.
+*/
+#define LBA_MAX_NUM_BUSES 8
+
+/************************************
+ * LBA register read and write support
+ *
+ * BE WARNED: register writes are posted.
+ * (ie follow writes which must reach HW with a read)
+ */
+#define READ_U8(addr) gsc_readb(addr)
+#define READ_U16(addr) gsc_readw((u16 *) (addr))
+#define READ_U32(addr) gsc_readl((u32 *) (addr))
+#define WRITE_U8(value, addr) gsc_writeb(value, addr)
+#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr))
+#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
+
+#define READ_REG8(addr) gsc_readb(addr)
+#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
+#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
+#define WRITE_REG8(value, addr) gsc_writeb(value, addr)
+#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
+#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
+
+
+#define LBA_CFG_TOK(bus,dfn) ((u32) ((bus)<<16 | (dfn)<<8))
+#define LBA_CFG_BUS(tok) ((u8) ((tok)>>16))
+#define LBA_CFG_DEV(tok) ((u8) ((tok)>>11) & 0x1f)
+#define LBA_CFG_FUNC(tok) ((u8) ((tok)>>8 ) & 0x7)
+
+
+#ifdef DEBUG_LBA
+/* Extract LBA (Rope) number from HPA */
+#define LBA_NUM(x) ((((uintptr_t) x) >> 13) & 0xf)
+#endif /* DEBUG_LBA */
+
+#ifdef __LP64__
+/* PDC_PAT */
+static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
+#endif
+
+/*
+** One time initialization to let the world know the LBA was found.
+** This is the only routine which is NOT static.
+** Must be called exactly once before pci_init().
+*/
+void __init lba_init(void)
+{
+ register_driver(lba_drivers_for);
+}
+
+
+static void
+lba_dump_res(struct resource *r, int d)
+{
+ int i;
+
+ if (NULL == r)
+ return;
+
+ printk("(%p)", r->parent);
+ for (i = d; i ; --i) printk(" ");
+ printk("%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags);
+ lba_dump_res(r->child, d+2);
+ lba_dump_res(r->sibling, d);
+}
+
+
+/*
+** LBA rev 2.0, 2.1, 2.2, and 3.0 bus walks require a complex
+** workaround for cfg cycles:
+** -- preserve LBA state
+** -- LBA_FLAG_NO_DMA_DURING_CFG workaround
+** -- turn on smart mode
+** -- probe with config writes before doing config reads
+** -- check ERROR_STATUS
+** -- clear ERROR_STATUS
+** -- restore LBA state
+**
+** The workaround is only used for device discovery.
+*/
+
+static int
+lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
+{
+ u8 first_bus = d->hba.hba_bus->secondary;
+ u8 last_sub_bus = d->hba.hba_bus->subordinate;
+#if 0
+/* FIXME - see below in this function */
+ u8 dev = PCI_SLOT(dfn);
+ u8 func = PCI_FUNC(dfn);
+#endif
+
+ ASSERT(bus >= first_bus);
+ ASSERT(bus <= last_sub_bus);
+ ASSERT((bus - first_bus) < LBA_MAX_NUM_BUSES);
+
+ if ((bus < first_bus) ||
+ (bus > last_sub_bus) ||
+ ((bus - first_bus) >= LBA_MAX_NUM_BUSES))
+ {
+ /* devices that fall into any of these cases won't get claimed */
+ return(FALSE);
+ }
+
+#if 0
+/*
+** FIXME: Need to implement code to fill the devices bitmap based
+** on contents of the local pci_bus tree "data base".
+** pci_register_ops() walks the bus for us and builds the tree.
+** For now, always do the config cycle.
+*/
+ bus -= first_bus;
+
+ return (((d->devices[bus][dev]) >> func) & 0x1);
+#else
+ return TRUE;
+#endif
+}
+
+
+
+#define LBA_CFG_SETUP(d, tok) { \
+ /* Save contents of error config register. */ \
+ error_config = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG); \
+\
+ /* Save contents of status control register. */ \
+ status_control = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); \
+\
+ /* For LBA rev 2.0, 2.1, 2.2, and 3.0, we must disable DMA \
+ ** arbitration for full bus walks. \
+ */ \
+ if (LBA_DMA_DURING_CFG_DISABLED(d)) { \
+ /* Save contents of arb mask register. */ \
+ arb_mask = READ_REG32(d->hba.base_addr + LBA_ARB_MASK); \
+\
+ /* \
+ * Turn off all device arbitration bits (i.e. everything \
+ * except arbitration enable bit). \
+ */ \
+ WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK); \
+ } \
+\
+ /* \
+ * Set the smart mode bit so that master aborts don't cause \
+ * LBA to go into PCI fatal mode (required). \
+ */ \
+ WRITE_REG32(error_config | 0x20, d->hba.base_addr + LBA_ERROR_CONFIG); \
+}
+
+
+#define LBA_CFG_PROBE(d, tok) { \
+ /* \
+ * Setup Vendor ID write and read back the address register \
+ * to make sure that LBA is the bus master. \
+ */ \
+ WRITE_REG32(tok | PCI_VENDOR_ID, (d)->hba.base_addr + LBA_PCI_CFG_ADDR);\
+ /* \
+ * Read address register to ensure that LBA is the bus master, \
+ * which implies that DMA traffic has stopped when DMA arb is off. \
+ */ \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ /* \
+ * Generate a cfg write cycle (will have no affect on \
+ * Vendor ID register since read-only). \
+ */ \
+ WRITE_REG32(~0, (d)->hba.base_addr + LBA_PCI_CFG_DATA); \
+ /* \
+ * Make sure write has completed before proceeding further, \
+ * i.e. before setting clear enable. \
+ */ \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+}
+
+
+/*
+ * HPREVISIT:
+ * -- Can't tell if config cycle got the error.
+ *
+ * OV bit is broken until rev 4.0, so can't use OV bit and
+ * LBA_ERROR_LOG_ADDR to tell if error belongs to config cycle.
+ *
+ * As of rev 4.0, no longer need the error check.
+ *
+ * -- Even if we could tell, we still want to return -1
+ * for **ANY** error (not just master abort).
+ *
+ * -- Only clear non-fatal errors (we don't want to bring
+ * LBA out of pci-fatal mode).
+ *
+ * Actually, there is still a race in which
+ * we could be clearing a fatal error. We will
+ * live with this during our real mode bus walk
+ * until rev 4.0 (no driver activity during
+ * real mode bus walk). The real mode bus walk
+ * has race conditions concerning the use of
+ * smart mode as well.
+ */
+
+#define LBA_MASTER_ABORT_ERROR 0xc
+#define LBA_FATAL_ERROR 0x10
+
+#define LBA_CFG_MASTER_ABORT_CHECK(d, base, tok, error) { \
+ u32 error_status = 0; \
+ /* \
+ * Set clear enable (CE) bit. Unset by HW when new \
+ * errors are logged -- LBA HW ERS section 14.3.3). \
+ */ \
+ WRITE_REG32(status_control | 0x20, base + LBA_STAT_CTL); \
+ error_status = READ_REG32(base + LBA_ERROR_STATUS); \
+ if ((error_status & 0x1f) != 0) { \
+ /* \
+ * Fail the config read request. \
+ */ \
+ error = 1; \
+ if ((error_status & LBA_FATAL_ERROR) == 0) { \
+ /* \
+ * Clear error status (if fatal bit not set) by setting \
+ * clear error log bit (CL). \
+ */ \
+ WRITE_REG32(status_control | 0x10, base + LBA_STAT_CTL); \
+ } \
+ } \
+}
+
+#define LBA_CFG_TR4_ADDR_SETUP(d, addr) \
+ WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR)
+
+#define LBA_CFG_ADDR_SETUP(d, addr) { \
+ WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ /* \
+ * HPREVISIT: \
+ * -- Potentially could skip this once DMA bug fixed. \
+ * \
+ * Read address register to ensure that LBA is the bus master, \
+ * which implies that DMA traffic has stopped when DMA arb is off. \
+ */ \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+}
+
+
+#define LBA_CFG_RESTORE(d, base) { \
+ /* \
+ * Restore status control register (turn off clear enable). \
+ */ \
+ WRITE_REG32(status_control, base + LBA_STAT_CTL); \
+ /* \
+ * Restore error config register (turn off smart mode). \
+ */ \
+ WRITE_REG32(error_config, base + LBA_ERROR_CONFIG); \
+ if (LBA_DMA_DURING_CFG_DISABLED(d)) { \
+ /* \
+ * Restore arb mask register (reenables DMA arbitration). \
+ */ \
+ WRITE_REG32(arb_mask, base + LBA_ARB_MASK); \
+ } \
+}
+
+
+
+static unsigned int
+lba_rd_cfg( struct lba_device *d, u32 tok, u8 reg, u32 size)
+{
+ u32 data = ~0;
+ int error = 0;
+ u32 arb_mask = 0; /* used by LBA_CFG_SETUP/RESTORE */
+ u32 error_config = 0; /* used by LBA_CFG_SETUP/RESTORE */
+ u32 status_control = 0; /* used by LBA_CFG_SETUP/RESTORE */
+
+ ASSERT((size == sizeof(u8)) ||
+ (size == sizeof(u16)) ||
+ (size == sizeof(u32)));
+
+ if ((size != sizeof(u8)) &&
+ (size != sizeof(u16)) &&
+ (size != sizeof(u32))) {
+ return(data);
+ }
+
+ LBA_CFG_SETUP(d, tok);
+ LBA_CFG_PROBE(d, tok);
+ LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
+ if (!error) {
+ LBA_CFG_ADDR_SETUP(d, tok | reg);
+ switch (size) {
+ case sizeof(u8):
+ data = (u32) READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 3));
+ break;
+ case sizeof(u16):
+ data = (u32) READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 2));
+ break;
+ case sizeof(u32):
+ data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA);
+ break;
+ default:
+ break; /* leave data as -1 */
+ }
+ }
+ LBA_CFG_RESTORE(d, d->hba.base_addr);
+ return(data);
+}
+
+
+
+#define LBA_CFG_RD(size, mask) \
+static int lba_cfg_read##size (struct pci_dev *dev, int pos, u##size *data) \
+{ \
+ struct lba_device *d = LBA_DEV(dev->bus->sysdata); \
+ u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \
+ u32 tok = LBA_CFG_TOK(local_bus,dev->devfn); \
+ \
+ if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \
+ /* original - Generate config cycle on broken elroy \
+ with risk we will miss PCI bus errors. */ \
+ *data = (u##size) lba_rd_cfg(d, tok, pos, sizeof(u##size)); \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, *data); \
+ return(*data == (u##size) -1); \
+ } \
+ \
+ if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) \
+ { \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos, *data); \
+ /* either don't want to look or know device isn't present. */ \
+ *data = (u##size) -1; \
+ return(0); \
+ } \
+ \
+ /* Basic Algorithm \
+ ** Should only get here on fully working LBA rev. \
+ ** This is how simple the code should have been. \
+ */ \
+ LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \
+ *data = READ_REG##size(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask));\
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, *data);\
+ return(*data == (u##size) -1); \
+}
+
+LBA_CFG_RD( 8, 3)
+LBA_CFG_RD(16, 2)
+LBA_CFG_RD(32, 0)
+
+
+
+static void
+lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
+{
+ int error = 0;
+ u32 arb_mask = 0;
+ u32 error_config = 0;
+ u32 status_control = 0;
+
+ ASSERT((size == sizeof(u8)) ||
+ (size == sizeof(u16)) ||
+ (size == sizeof(u32)));
+
+ if ((size != sizeof(u8)) &&
+ (size != sizeof(u16)) &&
+ (size != sizeof(u32))) {
+ return;
+ }
+
+ LBA_CFG_SETUP(d, tok);
+ LBA_CFG_ADDR_SETUP(d, tok | reg);
+ switch (size) {
+ case sizeof(u8):
+ WRITE_REG8((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA + (reg&3));
+ break;
+ case sizeof(u16):
+ WRITE_REG16((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA +(reg&2));
+ break;
+ case sizeof(u32):
+ WRITE_REG32(data, d->hba.base_addr + LBA_PCI_CFG_DATA);
+ break;
+ default:
+ break;
+ }
+ LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
+ LBA_CFG_RESTORE(d, d->hba.base_addr);
+}
+
+
+/*
+ * LBA 4.0 config write code implements non-postable semantics
+ * by doing a read of CONFIG ADDR after the write.
+ */
+
+#define LBA_CFG_WR(size, mask) \
+static int lba_cfg_write##size (struct pci_dev *dev, int pos, u##size data) \
+{ \
+ struct lba_device *d = LBA_DEV(dev->bus->sysdata); \
+ u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \
+ u32 tok = LBA_CFG_TOK(local_bus,dev->devfn); \
+ \
+ ASSERT((tok & 0xff) == 0); \
+ ASSERT(pos < 0x100); \
+ \
+ if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \
+ /* Original Workaround */ \
+ lba_wr_cfg(d, tok, pos, (u32) data, sizeof(u##size)); \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, data); \
+ return 0; \
+ } \
+ \
+ if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) { \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (b)\n", __FUNCTION__, dev->slot_name, pos, data); \
+ return 1; /* New Workaround */ \
+ } \
+ \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, data); \
+ /* Basic Algorithm */ \
+ LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \
+ WRITE_REG##size(data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask)); \
+ lba_t32 = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ return 0; \
+}
+
+
+LBA_CFG_WR( 8, 3)
+LBA_CFG_WR(16, 2)
+LBA_CFG_WR(32, 0)
+
+static struct pci_ops lba_cfg_ops = {
+ lba_cfg_read8, lba_cfg_read16, lba_cfg_read32,
+ lba_cfg_write8, lba_cfg_write16, lba_cfg_write32
+
+};
+
+
+
+static void
+lba_bios_init(void)
+{
+ DBG(KERN_DEBUG MODULE_NAME ": lba_bios_init\n");
+}
+
+
+#ifdef __LP64__
+
+/*
+** Determine if a device is already configured.
+** If so, reserve it resources.
+**
+** Read PCI cfg command register and see if I/O or MMIO is enabled.
+** PAT has to enable the devices it's using.
+**
+** Note: resources are fixed up before we try to claim them.
+*/
+static void
+lba_claim_dev_resources(struct pci_dev *dev)
+{
+ u16 cmd;
+ int i, srch_flags;
+
+ (void) lba_cfg_read16(dev, PCI_COMMAND, &cmd);
+
+ srch_flags = (cmd & PCI_COMMAND_IO) ? IORESOURCE_IO : 0;
+ if (cmd & PCI_COMMAND_MEMORY)
+ srch_flags |= IORESOURCE_MEM;
+
+ if (!srch_flags)
+ return;
+
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ if (dev->resource[i].flags & srch_flags) {
+ pci_claim_resource(dev, i);
+ DBG(" claimed %s %d [%lx,%lx]/%x\n",
+ dev->slot_name, i,
+ dev->resource[i].start,
+ dev->resource[i].end,
+ (int) dev->resource[i].flags
+ );
+ }
+ }
+}
+#endif
+
+
+/*
+** The algorithm is generic code.
+** But it needs to access local data structures to get the IRQ base.
+** Could make this a "pci_fixup_irq(bus, region)" but not sure
+** it's worth it.
+**
+** Called by do_pci_scan_bus() immediately after each PCI bus is walked.
+** Resources aren't allocated until recursive buswalk below HBA is completed.
+*/
+static void
+lba_fixup_bus(struct pci_bus *bus)
+{
+ struct list_head *ln;
+ struct pci_dev *dev;
+ u16 fbb_enable = PCI_STATUS_FAST_BACK;
+ u16 status;
+ struct lba_device *ldev = LBA_DEV(bus->sysdata);
+#ifdef __LP64__
+ int i;
+#endif
+ DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n",
+ bus, bus->secondary, bus->sysdata);
+
+ /*
+ ** Properly Setup MMIO resources for this bus.
+ ** pci_alloc_primary_bus() mangles this.
+ */
+ if (NULL == bus->self) {
+ int err;
+
+ DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
+ ldev->hba.io_space.name,
+ ldev->hba.io_space.start,
+ ldev->hba.io_space.end,
+ (int) ldev->hba.io_space.flags);
+ DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
+ ldev->hba.mem_space.name,
+ ldev->hba.mem_space.start,
+ ldev->hba.mem_space.end,
+ (int) ldev->hba.mem_space.flags);
+
+ err = request_resource(&ioport_resource, &(ldev->hba.io_space));
+ if (err < 0) {
+ BUG();
+ lba_dump_res(&ioport_resource, 2);
+ }
+ err = request_resource(&iomem_resource, &(ldev->hba.mem_space));
+ if (err < 0) {
+ BUG();
+ lba_dump_res(&iomem_resource, 2);
+ }
+
+ bus->resource[0] = &(ldev->hba.io_space);
+ bus->resource[1] = &(ldev->hba.mem_space);
+ }
+
+ list_for_each(ln, &bus->devices) {
+
+ dev = pci_dev_b(ln);
+
+#ifdef __LP64__
+ /*
+ ** 0-5 are the "standard PCI regions"
+ ** (see comments near PCI_NUM_RESOURCES in include/linux/pci.h)
+ */
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *res = &(dev->resource[i]);
+
+ if (res->flags & IORESOURCE_MEM) {
+ /* "Globalize" PCI address */
+ res->start |= ldev->lmmio_base;
+ res->end |= ldev->lmmio_base;
+ }
+ }
+#endif
+
+ /*
+ ** If one device does not support FBB transfers,
+ ** No one on the bus can be allowed to use them.
+ */
+ (void) lba_cfg_read16(dev, PCI_STATUS, &status);
+ fbb_enable &= status;
+
+#ifdef __LP64__
+ if (pdc_pat) {
+ /* Claim resources for PDC's devices */
+ lba_claim_dev_resources(dev);
+ }
+#endif /* __LP64__ */
+
+ /*
+ ** P2PB's have no IRQs. ignore them.
+ */
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ continue;
+
+ /* Adjust INTERRUPT_LINE for this dev */
+ iosapic_fixup_irq(LBA_DEV(bus->sysdata)->iosapic_obj, dev);
+ }
+
+#if 0
+/* FIXME/REVISIT - finish figuring out to set FBB on both
+** pbus_set_ranges() clobbers PCI_BRIDGE_CONTROL.
+** Can't fixup here anyway....garr...
+*/
+ if (fbb_enable) {
+ if (bus->self) {
+ u8 control;
+ /* enable on PPB */
+ (void) lba_cfg_read8(bus->self, PCI_BRIDGE_CONTROL, &control);
+ (void) lba_cfg_write8(bus->self, PCI_BRIDGE_CONTROL, control | PCI_STATUS_FAST_BACK);
+
+ } else {
+ /* enable on LBA */
+ }
+ fbb_enable = PCI_COMMAND_FAST_BACK;
+ }
+
+ /* Lastly enable FBB/PERR/SERR on all devices too */
+ list_for_each(ln, &bus->devices) {
+ (void) lba_cfg_read16(dev, PCI_COMMAND, &status);
+ status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable;
+ (void) lba_cfg_write16(dev, PCI_COMMAND, status);
+ }
+#endif
+}
+
+
+struct pci_bios_ops lba_bios_ops = {
+ lba_bios_init,
+ lba_fixup_bus /* void lba_fixup_bus(struct pci_bus *bus) */
+};
+
+
+
+
+/*******************************************************
+**
+** LBA Sprockets "I/O Port" Space Accessor Functions
+**
+** This set of accessor functions is intended for use with
+** "legacy firmware" (ie Sprockets on Allegro/Forte boxes).
+**
+** Many PCI devices don't require use of I/O port space (eg Tulip,
+** NCR720) since they export the same registers to both MMIO and
+** I/O port space. In general I/O port space is slower than
+** MMIO since drivers are designed so PIO writes can be posted.
+**
+********************************************************/
+
+#define LBA_PORT_IN(size, mask) \
+static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \
+{ \
+ u##size t; \
+ ASSERT(bus != NULL); \
+ DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, bus, addr); \
+ t = READ_REG##size(LBA_ASTRO_PORT_BASE + addr); \
+ DBG_PORT(" 0x%x\n", t); \
+ return (t); \
+}
+
+LBA_PORT_IN( 8, 3)
+LBA_PORT_IN(16, 2)
+LBA_PORT_IN(32, 0)
+
+
+
+/*
+** BUG X4107: Ordering broken - DMA RD return can bypass PIO WR
+**
+** Fixed in Elroy 2.2. The READ_U32(..., LBA_FUNC_ID) below is
+** guarantee non-postable completion semantics - not avoid X4107.
+** The READ_U32 only guarantees the write data gets to elroy but
+** out to the PCI bus. We can't read stuff from I/O port space
+** since we don't know what has side-effects. Attempting to read
+** from configuration space would be suicidal given the number of
+** bugs in that elroy functionality.
+**
+** Description:
+** DMA read results can improperly pass PIO writes (X4107). The
+** result of this bug is that if a processor modifies a location in
+** memory after having issued PIO writes, the PIO writes are not
+** guaranteed to be completed before a PCI device is allowed to see
+** the modified data in a DMA read.
+**
+** Note that IKE bug X3719 in TR1 IKEs will result in the same
+** symptom.
+**
+** Workaround:
+** The workaround for this bug is to always follow a PIO write with
+** a PIO read to the same bus before starting DMA on that PCI bus.
+**
+*/
+#define LBA_PORT_OUT(size, mask) \
+static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \
+{ \
+ ASSERT(bus != NULL); \
+ DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \
+ WRITE_REG##size(val, LBA_ASTRO_PORT_BASE + addr); \
+ if (LBA_DEV(d)->hw_rev < 3) \
+ lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \
+}
+
+LBA_PORT_OUT( 8, 3)
+LBA_PORT_OUT(16, 2)
+LBA_PORT_OUT(32, 0)
+
+
+static struct pci_port_ops lba_astro_port_ops = {
+ lba_astro_in8, lba_astro_in16, lba_astro_in32,
+ lba_astro_out8, lba_astro_out16, lba_astro_out32
+};
+
+
+#ifdef __LP64__
+
+#define PIOP_TO_GMMIO(lba, addr) \
+ ((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3))
+
+/*******************************************************
+**
+** LBA PAT "I/O Port" Space Accessor Functions
+**
+** This set of accessor functions is intended for use with
+** "PAT PDC" firmware (ie Prelude/Rhapsody/Piranha boxes).
+**
+** This uses the PIOP space located in the first 64MB of GMMIO.
+** Each rope gets a full 64*KB* (ie 4 bytes per page) this way.
+** bits 1:0 stay the same. bits 15:2 become 25:12.
+** Then add the base and we can generate an I/O Port cycle.
+********************************************************/
+#undef LBA_PORT_IN
+#define LBA_PORT_IN(size, mask) \
+static u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \
+{ \
+ u##size t; \
+ ASSERT(bus != NULL); \
+ DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \
+ t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \
+ DBG_PORT(" 0x%x\n", t); \
+ return (t); \
+}
+
+LBA_PORT_IN( 8, 3)
+LBA_PORT_IN(16, 2)
+LBA_PORT_IN(32, 0)
+
+
+#undef LBA_PORT_OUT
+#define LBA_PORT_OUT(size, mask) \
+static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \
+{ \
+ void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \
+ ASSERT(bus != NULL); \
+ DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \
+ WRITE_REG##size(val, where); \
+ /* flush the I/O down to the elroy at least */ \
+ lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \
+}
+
+LBA_PORT_OUT( 8, 3)
+LBA_PORT_OUT(16, 2)
+LBA_PORT_OUT(32, 0)
+
+
+static struct pci_port_ops lba_pat_port_ops = {
+ lba_pat_in8, lba_pat_in16, lba_pat_in32,
+ lba_pat_out8, lba_pat_out16, lba_pat_out32
+};
+
+
+
+/*
+** make range information from PDC available to PCI subsystem.
+** We make the PDC call here in order to get the PCI bus range
+** numbers. The rest will get forwarded in pcibios_fixup_bus().
+** We don't have a struct pci_bus assigned to us yet.
+*/
+static void
+lba_pat_resources( struct hp_device *d, struct lba_device *lba_dev)
+{
+ pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */
+#ifdef DONT_NEED_THIS_FOR_ASTRO
+ pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */
+ long io_count;
+#endif
+ long status; /* PDC return status */
+ long pa_count;
+ int i;
+
+ /* return cell module (IO view) */
+ status = pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index,
+ PA_VIEW, & pa_pdc_cell);
+ pa_count = pa_pdc_cell.mod[1];
+
+#ifdef DONT_NEED_THIS_FOR_ASTRO
+ status |= pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index,
+ IO_VIEW, & io_pdc_cell);
+ io_count = io_pdc_cell.mod[1];
+#endif
+
+ /* We've already done this once for device discovery...*/
+ if (status != PDC_RET_OK) {
+ panic("pdc_pat_cell_module() call failed for LBA!\n");
+ }
+
+ if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) {
+ panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n");
+ }
+
+ /*
+ ** Inspect the resources PAT tells us about
+ */
+ for (i = 0; i < pa_count; i++) {
+ struct {
+ unsigned long type;
+ unsigned long start;
+ unsigned long end; /* aka finish */
+ } *p;
+ struct resource *r;
+
+ p = (void *) &(pa_pdc_cell.mod[2+i*3]);
+
+ /* Convert the PAT range data to PCI "struct resource" */
+ switch(p->type & 0xff) {
+ case PAT_PBNUM:
+ lba_dev->hba.bus_num.start = p->start;
+ lba_dev->hba.bus_num.end = p->end;
+ break;
+ case PAT_LMMIO:
+ /* used to fix up pre-initialized MEM BARs */
+ lba_dev->lmmio_base = p->start;
+
+ r = &(lba_dev->hba.mem_space);
+ r->name = "LBA LMMIO";
+ r->start = p->start;
+ r->end = p->end;
+ r->flags = IORESOURCE_MEM;
+ r->parent = r->sibling = r->child = NULL;
+ break;
+ case PAT_GMMIO:
+ printk(KERN_WARNING MODULE_NAME
+ " range[%d] : ignoring GMMIO (0x%lx)\n",
+ i, p->start);
+ lba_dev->gmmio_base = p->start;
+ break;
+ case PAT_NPIOP:
+ printk(KERN_WARNING MODULE_NAME
+ " range[%d] : ignoring NPIOP (0x%lx)\n",
+ i, p->start);
+ break;
+ case PAT_PIOP:
+ /*
+ ** Postable I/O port space is per PCI host adapter.
+ */
+
+ /* save base of 64MB PIOP region */
+ lba_dev->iop_base = p->start;
+
+ r = &(lba_dev->hba.io_space);
+ r->name = "LBA I/O Port";
+ r->start = lba_dev->hba.hba_num << 16;
+ r->end = r->start + 0xffffUL;
+ r->flags = IORESOURCE_IO;
+ r->parent = r->sibling = r->child = NULL;
+ break;
+ default:
+ printk(KERN_WARNING MODULE_NAME
+ " range[%d] : unknown pat range type (0x%lx)\n",
+ i, p->type & 0xff);
+ break;
+ }
+ }
+}
+#endif /* __LP64__ */
+
+
+static void
+lba_legacy_resources( struct hp_device *d, struct lba_device *lba_dev)
+{
+ int lba_num;
+ struct resource *r;
+#ifdef __LP64__
+ /*
+ ** Used to sign extend instead BAR values are only 32-bit.
+ ** 64-bit BARs have the upper 32-bit's zero'd by firmware.
+ ** "Sprockets" PDC initializes for 32-bit OS.
+ */
+ lba_dev->lmmio_base = 0xffffffff00000000UL;
+#endif
+
+ /*
+ ** With "legacy" firmware, the lowest byte of FW_SCRATCH
+ ** represents bus->secondary and the second byte represents
+ ** bus->subsidiary (i.e. highest PPB programmed by firmware).
+ ** PCI bus walk *should* end up with the same result.
+ ** FIXME: But we don't have sanity checks in PCI or LBA.
+ */
+ lba_num = READ_REG32(d->hpa + LBA_FW_SCRATCH);
+ r = &(lba_dev->hba.bus_num);
+ r->name = "LBA PCI Busses";
+ r->start = lba_num & 0xff;
+ r->end = (lba_num>>8) & 0xff;
+
+ /* Set up local PCI Bus resources - we don't really need
+ ** them for Legacy boxes but it's nice to see in /proc.
+ */
+ r = &(lba_dev->hba.mem_space);
+ r->name = "LBA PCI LMMIO";
+ r->flags = IORESOURCE_MEM;
+ r->start = READ_REG32(d->hpa + LBA_LMMIO_BASE);
+ r->end = r->start + ~ (READ_REG32(d->hpa + LBA_LMMIO_MASK));
+
+ r = &(lba_dev->hba.io_space);
+ r->name = "LBA PCI I/O Ports";
+ r->flags = IORESOURCE_IO;
+ r->start = READ_REG32(d->hpa + LBA_IOS_BASE);
+ r->end = r->start + (READ_REG32(d->hpa + LBA_IOS_MASK) ^ 0xffff);
+
+ lba_num = lba_dev->hba.hba_num << 16;
+ r->start |= lba_num;
+ r->end |= lba_num;
+}
+
+
+/**************************************************************************
+**
+** LBA initialization code (HW and SW)
+**
+** o identify LBA chip itself
+** o initialize LBA chip modes (HardFail)
+** o FIXME: initialize DMA hints for reasonable defaults
+** o enable configuration functions
+** o call pci_register_ops() to discover devs (fixup/fixup_bus get invoked)
+**
+**************************************************************************/
+
+static void
+lba_hw_init(struct lba_device *d)
+{
+ u32 stat;
+
+ /* Set HF mode as the default (vs. -1 mode). */
+ stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL);
+ WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL);
+
+ /*
+ ** FIXME: Hint registers are programmed with default hint
+ ** values by firmware. Hints should be sane even if we
+ ** can't reprogram them the way drivers want.
+ */
+}
+
+
+
+static void
+lba_common_init(struct lba_device *lba_dev)
+{
+ pci_bios = &lba_bios_ops;
+ pcibios_register_hba((struct pci_hba_data *)lba_dev);
+ lba_dev->lba_lock = SPIN_LOCK_UNLOCKED;
+
+ /*
+ ** Set flags which depend on hw_rev
+ */
+ if (!LBA_TR4PLUS(lba_dev)) {
+ lba_dev->flags |= LBA_FLAG_NO_DMA_DURING_CFG;
+ }
+}
+
+
+
+/*
+** Determine if lba should claim this chip (return 0) or not (return 1).
+** If so, initialize the chip and tell other partners in crime they
+** have work to do.
+*/
+static __init int
+lba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ struct lba_device *lba_dev;
+ struct pci_bus *lba_bus;
+ u32 func_class;
+ void *tmp_obj;
+
+ /* from drivers/pci/setup-bus.c */
+ extern void __init pbus_set_ranges(struct pci_bus *, struct pbus_set_ranges_data *);
+
+ /* Read HW Rev First */
+ func_class = READ_REG32(d->hpa + LBA_FCLASS);
+ func_class &= 0xf;
+
+ switch (func_class) {
+ case 0: dri->version = "TR1.0"; break;
+ case 1: dri->version = "TR2.0"; break;
+ case 2: dri->version = "TR2.1"; break;
+ case 3: dri->version = "TR2.2"; break;
+ case 4: dri->version = "TR3.0"; break;
+ case 5: dri->version = "TR4.0"; break;
+ default: dri->version = "TR4+";
+ }
+
+ printk("%s version %s (0x%x) found at 0x%p\n", dri->name, dri->version, func_class & 0xf, d->hpa);
+
+ /* Just in case we find some prototypes... */
+ if (func_class < 2) {
+ printk(KERN_WARNING "Can't support LBA older than TR2.1 "
+ "- continuing under adversity.\n");
+ }
+
+ /*
+ ** Tell I/O SAPIC driver we have a IRQ handler/region.
+ */
+ tmp_obj = iosapic_register(d->hpa+LBA_IOSAPIC_BASE);
+ if (NULL == tmp_obj) {
+ /* iosapic may have failed. But more likely the
+ ** slot isn't occupied and thus has no IRT entries.
+ ** iosapic_register looks for this iosapic in the IRT
+ ** before bothering to allocating data structures
+ ** we don't need.
+ */
+ DBG(KERN_WARNING MODULE_NAME ": iosapic_register says not used\n");
+ return (1);
+ }
+
+ lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
+ if (NULL == lba_dev)
+ {
+ printk("lba_init_chip - couldn't alloc lba_device\n");
+ return(1);
+ }
+
+ memset(lba_dev, 0, sizeof(struct lba_device));
+
+
+ /* ---------- First : initialize data we already have --------- */
+
+ /*
+ ** Need hw_rev to adjust configuration space behavior.
+ ** LBA_TR4PLUS macro uses hw_rev field.
+ */
+ lba_dev->hw_rev = func_class;
+
+ lba_dev->hba.base_addr = d->hpa; /* faster access */
+ lba_dev->iosapic_obj = tmp_obj; /* save interrupt handle */
+
+ /* ------------ Second : initialize common stuff ---------- */
+ lba_common_init(lba_dev);
+ lba_hw_init(lba_dev);
+
+ /* ---------- Third : setup I/O Port and MMIO resources --------- */
+#ifdef __LP64__
+
+ if (pdc_pat) {
+ /* PDC PAT firmware uses PIOP region of GMMIO space. */
+ pci_port = &lba_pat_port_ops;
+
+ /* Go ask PDC PAT what resources this LBA has */
+ lba_pat_resources(d, lba_dev);
+
+ } else {
+#endif
+ /* Sprockets PDC uses NPIOP region */
+ pci_port = &lba_astro_port_ops;
+
+ /* Poke the chip a bit for /proc output */
+ lba_legacy_resources(d, lba_dev);
+#ifdef __LP64__
+ }
+#endif
+
+ /*
+ ** Tell PCI support another PCI bus was found.
+ ** Walks PCI bus for us too.
+ */
+ lba_bus = lba_dev->hba.hba_bus =
+ pci_scan_bus( lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *) lba_dev);
+
+#ifdef __LP64__
+ if (pdc_pat) {
+
+ /* determine window sizes needed by PCI-PCI bridges */
+ DBG_PAT("LBA pcibios_size_bridge()\n");
+ pcibios_size_bridge(lba_bus, NULL);
+
+ /* assign resources to un-initialized devices */
+ DBG_PAT("LBA pcibios_assign_unassigned_resources()\n");
+ pcibios_assign_unassigned_resources(lba_bus);
+
+#ifdef DEBUG_LBA_PAT
+ DBG_PAT("\nLBA PIOP resource tree\n");
+ lba_dump_res(&lba_dev->hba.io_space, 2);
+ DBG_PAT("\nLBA LMMIO resource tree\n");
+ lba_dump_res(&lba_dev->hba.mem_space, 2);
+#endif
+
+ /* program *all* PCI-PCI bridge range registers */
+ DBG_PAT("LBA pbus_set_ranges()\n");
+ pbus_set_ranges(lba_bus, NULL);
+ }
+#endif /* __LP64__ */
+
+ /*
+ ** Once PCI register ops has walked the bus, access to config
+ ** space is restricted. Avoids master aborts on config cycles.
+ ** Early LBA revs go fatal on *any* master abort.
+ */
+ if (!LBA_TR4PLUS(lba_dev)) {
+ lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
+ }
+
+ /* Whew! Finally done! Tell services we got this one covered. */
+ return 0;
+}
+
+
+/*
+** Initialize the IBASE/IMASK registers for LBA (Elroy).
+** Only called from sba_iommu.c initialization sequence.
+*/
+void lba_init_iregs(void *sba_hpa, u32 ibase, u32 imask)
+{
+ extern struct pci_hba_data *hba_list; /* arch/parisc/kernel/pci.c */
+ struct pci_hba_data *lba;
+
+ imask <<= 2; /* adjust for hints - 2 more bits */
+
+ ASSERT((ibase & 0x003fffff) == 0);
+ ASSERT((imask & 0x003fffff) == 0);
+
+ /* FIXME: sba_hpa is intended to search some table to
+ ** determine which LBA's belong to the caller's SBA.
+ ** IS_ASTRO: just assume only one SBA for now.
+ */
+ ASSERT(NULL != hba_list);
+ DBG(KERN_DEBUG "%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask);
+
+ for (lba = hba_list; NULL != lba; lba = lba->next) {
+ DBG(KERN_DEBUG "%s() base_addr %p\n", __FUNCTION__, lba->base_addr);
+ WRITE_REG32( imask, lba->base_addr + LBA_IMASK);
+ WRITE_REG32( ibase, lba->base_addr + LBA_IBASE);
+ }
+ DBG(KERN_DEBUG "%s() done\n", __FUNCTION__);
+}
+
diff --git a/arch/parisc/kernel/led.c b/arch/parisc/kernel/led.c
new file mode 100644
index 000000000..a375423f3
--- /dev/null
+++ b/arch/parisc/kernel/led.c
@@ -0,0 +1,451 @@
+/*
+ * Chassis LCD/LED driver for HP-PARISC workstations
+ *
+ * (c) Copyright 2000 Red Hat Software
+ * (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/bitops.h>
+#include <asm/io.h>
+#include <asm/gsc.h>
+#include <asm/processor.h>
+#include <asm/hardware.h>
+#include <asm/param.h> /* HZ */
+#include <asm/led.h>
+
+
+/* define to disable all LED functions */
+#undef DISABLE_LEDS
+
+
+#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
+
+
+struct lcd_block {
+ unsigned char command; /* stores the command byte */
+ unsigned char on; /* value for turning LED on */
+ unsigned char off; /* value for turning LED off */
+};
+
+/* Structure returned by PDC_RETURN_CHASSIS_INFO */
+struct pdc_chassis_lcd_info_ret_block {
+ unsigned long model:16; /* DISPLAY_MODEL_XXXX (see below) */
+ unsigned long lcd_width:16; /* width of the LCD in chars (DISPLAY_MODEL_LCD only) */
+ char *lcd_cmd_reg_addr; /* ptr to LCD cmd-register & data ptr for LED */
+ char *lcd_data_reg_addr; /* ptr to LCD data-register (LCD only) */
+ unsigned int min_cmd_delay; /* delay in uS after cmd-write (LCD only) */
+ unsigned char reset_cmd1; /* command #1 for writing LCD string (LCD only) */
+ unsigned char reset_cmd2; /* command #2 for writing LCD string (LCD only) */
+ unsigned char act_enable; /* 0 = no activity (LCD only) */
+ struct lcd_block heartbeat;
+ struct lcd_block disk_io;
+ struct lcd_block lan_rcv;
+ struct lcd_block lan_tx;
+ char _pad;
+};
+
+/* values for pdc_chassis_lcd_info_ret_block.model: */
+#define DISPLAY_MODEL_LCD 0 /* KittyHawk LED or LCD */
+#define DISPLAY_MODEL_NONE 1 /* no LED or LCD */
+#define DISPLAY_MODEL_LASI 2 /* LASI style 8 bit LED */
+#define DISPLAY_MODEL_OLD_ASP 0x7F /* faked: ASP style 8 x 1 bit LED (only very old ASP versions) */
+
+
+/* LCD_CMD and LCD_DATA for KittyHawk machines */
+#ifdef __LP64__
+#define KITTYHAWK_LCD_CMD 0xfffffffff0190000L
+#else
+#define KITTYHAWK_LCD_CMD 0xf0190000
+#endif
+#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD + 1)
+
+
+/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's */
+static struct pdc_chassis_lcd_info_ret_block
+lcd_info __attribute__((aligned(8))) =
+{
+ model:DISPLAY_MODEL_LCD,
+ lcd_width:16,
+ lcd_cmd_reg_addr:(char *) KITTYHAWK_LCD_CMD,
+ lcd_data_reg_addr:(char *) KITTYHAWK_LCD_DATA,
+ min_cmd_delay:40,
+ reset_cmd1:0x80,
+ reset_cmd2:0xc0,
+};
+
+
+/* direct access to some of the lcd_info variables */
+#define LCD_CMD_REG lcd_info.lcd_cmd_reg_addr
+#define LCD_DATA_REG lcd_info.lcd_data_reg_addr
+#define LED_DATA_REG lcd_info.lcd_cmd_reg_addr /* LASI & ASP only */
+
+
+
+
+/*
+ **
+ ** led_ASP_driver()
+ **
+ */
+#define LED_DATA 0x01 /* data to shift (0:on 1:off) */
+#define LED_STROBE 0x02 /* strobe to clock data */
+static void led_ASP_driver(unsigned char leds)
+{
+ int i;
+
+ leds = ~leds;
+ for (i = 0; i < 8; i++) {
+ unsigned char value;
+ value = (leds & 0x80) >> 7;
+ gsc_writeb( value, LED_DATA_REG );
+ gsc_writeb( value | LED_STROBE, LED_DATA_REG );
+ leds <<= 1;
+ }
+}
+
+
+/*
+ **
+ ** led_LASI_driver()
+ **
+ */
+static void led_LASI_driver(unsigned char leds)
+{
+ leds = ~leds;
+ gsc_writeb( leds, LED_DATA_REG );
+}
+
+
+/*
+ **
+ ** led_LCD_driver()
+ **
+ ** The logic of the LCD driver is, that we write at every interrupt
+ ** only to one of LCD_CMD_REG _or_ LCD_DATA_REG - registers.
+ ** That way we don't need to let this interrupt routine busywait
+ ** the "min_cmd_delay", since idlewaiting in an interrupt-routine is
+ ** allways a BAD IDEA !
+ **
+ ** TODO: check the value of "min_cmd_delay" against the value of HZ.
+ **
+ */
+
+static void led_LCD_driver(unsigned char leds)
+{
+ static int last_index; /* 0:heartbeat, 1:disk, 2:lan_in, 3:lan_out */
+ static int last_was_cmd;/* 0: CMD was written last, 1: DATA was last */
+ struct lcd_block *block_ptr;
+ int value;
+
+ // leds = ~leds; /* needed ? */
+
+ switch (last_index) {
+ case 0: block_ptr = &lcd_info.heartbeat;
+ value = leds & LED_HEARTBEAT;
+ break;
+ case 1: block_ptr = &lcd_info.disk_io;
+ value = leds & LED_DISK_IO;
+ break;
+ case 2: block_ptr = &lcd_info.lan_rcv;
+ value = leds & LED_LAN_RCV;
+ break;
+ case 3: block_ptr = &lcd_info.lan_tx;
+ value = leds & LED_LAN_TX;
+ break;
+ default: /* should never happen: */
+ BUG();
+ return;
+ }
+
+ if (last_was_cmd) {
+ /* write the value to the LCD data port */
+ gsc_writeb( value ? block_ptr->on : block_ptr->off, LCD_DATA_REG );
+ } else {
+ /* write the command-byte to the LCD command register */
+ gsc_writeb( block_ptr->command, LCD_CMD_REG );
+ }
+
+ /* now update the vars for the next interrupt iteration */
+ if (++last_was_cmd == 2) {
+ last_was_cmd = 0;
+ if (++last_index == 4)
+ last_index = 0;
+ }
+}
+
+
+
+static char currentleds; /* stores current value of the LEDs */
+
+static void (*led_func_ptr) (unsigned char); /* ptr to LCD/LED-specific function */
+
+/*
+ ** led_interrupt_func()
+ **
+ ** is called at every timer interrupt from time.c,
+ ** updates the chassis LCD/LED
+ */
+
+#define HEARTBEAT_LEN (HZ/16)
+
+void led_interrupt_func(void)
+{
+#ifndef DISABLE_LEDS
+ static int count;
+ static int lastleds = -1;
+ static int nr;
+
+ /* exit, if not initialized */
+ if (!led_func_ptr)
+ return;
+
+ /* increment the local counter */
+ if (count == (HZ-1))
+ count = 0;
+ else
+ count++;
+
+ /* calculate the Heartbeat */
+ if ((count % (HZ/2)) < HEARTBEAT_LEN)
+ currentleds |= LED_HEARTBEAT;
+ else
+ currentleds &= ~LED_HEARTBEAT;
+
+ /* roll LEDs 0..2 */
+ if (count == 0) {
+ if (nr++ >= 2)
+ nr = 0;
+ currentleds &= ~7;
+ currentleds |= (1 << nr);
+ }
+
+ /* now update the LEDs */
+ if (currentleds != lastleds) {
+ led_func_ptr(currentleds);
+ lastleds = currentleds;
+ }
+#endif
+}
+
+
+/*
+ ** register_led_driver()
+ **
+ ** All information in lcd_info needs to be set up prior
+ ** calling this function.
+ */
+
+static void __init register_led_driver(void)
+{
+#ifndef DISABLE_LEDS
+ switch (lcd_info.model) {
+ case DISPLAY_MODEL_LCD:
+ printk(KERN_INFO "LCD display at (%p,%p)\n",
+ LCD_CMD_REG , LCD_DATA_REG);
+ led_func_ptr = led_LCD_driver;
+ break;
+
+ case DISPLAY_MODEL_LASI:
+ printk(KERN_INFO "LED display at %p\n",
+ LED_DATA_REG);
+ led_func_ptr = led_LASI_driver;
+ break;
+
+ case DISPLAY_MODEL_OLD_ASP:
+ printk(KERN_INFO "LED (ASP-style) display at %p\n",
+ LED_DATA_REG);
+ led_func_ptr = led_ASP_driver;
+ break;
+
+ default:
+ printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n",
+ __FUNCTION__, lcd_info.model);
+ return;
+ }
+#endif
+}
+
+/*
+ * XXX - could this move to lasi.c ??
+ */
+
+/*
+ ** lasi_led_init()
+ **
+ ** lasi_led_init() is called from lasi.c with the base hpa
+ ** of the lasi controller chip.
+ ** Since Mirage and Electra machines use a different LED
+ ** address register, we need to check for these machines
+ ** explicitly.
+ */
+
+#ifdef CONFIG_GSC_LASI
+void __init lasi_led_init(unsigned long lasi_hpa)
+{
+ if (lcd_info.model != DISPLAY_MODEL_NONE ||
+ lasi_hpa == 0)
+ return;
+
+ printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION);
+
+ /* Mirage and Electra machines need special offsets */
+ switch (CPU_HVERSION) {
+ case 0x60A: /* Mirage Jr (715/64) */
+ case 0x60B: /* Mirage 100 */
+ case 0x60C: /* Mirage 100+ */
+ case 0x60D: /* Electra 100 */
+ case 0x60E: /* Electra 120 */
+ LED_DATA_REG = (char *) (lasi_hpa - 0x00020000);
+ break;
+ default:
+ LED_DATA_REG = (char *) (lasi_hpa + 0x0000C000);
+ break;
+ } /* switch() */
+
+ lcd_info.model = DISPLAY_MODEL_LASI;
+ register_led_driver();
+}
+#endif
+
+
+/*
+ ** asp_led_init()
+ **
+ ** asp_led_init() is called from asp.c with the ptr
+ ** to the LED display.
+ */
+
+#ifdef CONFIG_GSC_LASI
+void __init asp_led_init(unsigned long led_ptr)
+{
+ if (lcd_info.model != DISPLAY_MODEL_NONE ||
+ led_ptr == 0)
+ return;
+
+ lcd_info.model = DISPLAY_MODEL_OLD_ASP;
+ LED_DATA_REG = (char *) led_ptr;
+
+ register_led_driver();
+}
+
+#endif
+
+
+
+/*
+ ** register_led_regions()
+ **
+ ** Simple function, which registers the LCD/LED regions for /procfs.
+ ** At bootup - where the initialisation of the LCD/LED normally happens -
+ ** not all internal structures of request_region() are properly set up,
+ ** so that we delay the registration until busdevice.c is executed.
+ **
+ */
+
+void __init register_led_regions(void)
+{
+ switch (lcd_info.model) {
+ case DISPLAY_MODEL_LCD:
+ request_region((unsigned long)LCD_CMD_REG, 1, "lcd_cmd");
+ request_region((unsigned long)LCD_DATA_REG, 1, "lcd_data");
+ break;
+ case DISPLAY_MODEL_LASI:
+ case DISPLAY_MODEL_OLD_ASP:
+ request_region((unsigned long)LED_DATA_REG, 1, "led_data");
+ break;
+ }
+}
+
+
+
+/*
+ ** led_init()
+ **
+ ** led_init() is called very early in the bootup-process from setup.c
+ ** and asks the PDC for an usable chassis LCD or LED.
+ ** If the PDC doesn't return any info, then the LED
+ ** is detected by lasi.c or asp.c and registered with the
+ ** above functions lasi_led_init() or asp_led_init().
+ ** KittyHawk machines have often a buggy PDC, so that
+ ** we explicitly check for those machines here.
+ */
+
+int __init led_init(void)
+{
+#ifndef DISABLE_LEDS
+ long pdc_result[32];
+
+ printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION);
+
+ /* Work around the buggy PDC of KittyHawk-machines */
+ switch (CPU_HVERSION) {
+ case 0x580: /* KittyHawk DC2-100 (K100) */
+ case 0x581: /* KittyHawk DC3-120 (K210) */
+ case 0x582: /* KittyHawk DC3 100 (K400) */
+ case 0x583: /* KittyHawk DC3 120 (K410) */
+ case 0x58B: /* KittyHawk DC2 100 (K200) */
+ printk("%s: KittyHawk-Machine found !!\n", __FUNCTION__);
+ goto found; /* use the preinitialized values of lcd_info */
+
+ default:
+ break;
+ }
+
+ /* initialize pdc_result, so we can check the return values of pdc_chassis_info() */
+ pdc_result[0] = pdc_result[1] = 0;
+
+ if (pdc_chassis_info(&pdc_result, &lcd_info, sizeof(lcd_info)) == PDC_OK) {
+ printk("%s: chassis info: model %d, ret0=%d, ret1=%d\n",
+ __FUNCTION__, lcd_info.model, pdc_result[0], pdc_result[1]);
+
+ /* check the results. Some machines have a buggy PDC */
+ if (pdc_result[0] <= 0 || pdc_result[0] != pdc_result[1])
+ goto not_found;
+
+ switch (lcd_info.model) {
+ case DISPLAY_MODEL_LCD: /* LCD display */
+ if (pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block)
+ && pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block) - 1)
+ goto not_found;
+ printk("%s: min_cmd_delay = %d uS\n",
+ __FUNCTION__, lcd_info.min_cmd_delay);
+ break;
+
+ case DISPLAY_MODEL_NONE: /* no LED or LCD available */
+ goto not_found;
+
+ case DISPLAY_MODEL_LASI: /* Lasi style 8 bit LED display */
+ if (pdc_result[0] != 8 && pdc_result[0] != 32)
+ goto not_found;
+ break;
+
+ default:
+ printk(KERN_WARNING "Unknown LCD/LED model %d\n",
+ lcd_info.model);
+ goto not_found;
+ } /* switch() */
+
+found:
+ /* register the LCD/LED driver */
+ register_led_driver();
+ return 0;
+
+ } /* if() */
+
+not_found:
+ lcd_info.model = DISPLAY_MODEL_NONE;
+ return 1;
+#endif
+}
diff --git a/arch/parisc/kernel/pa7300lc.c b/arch/parisc/kernel/pa7300lc.c
new file mode 100644
index 000000000..307e4b2fd
--- /dev/null
+++ b/arch/parisc/kernel/pa7300lc.c
@@ -0,0 +1,54 @@
+/*
+ * linux/arch/parisc/kernel/pa7300lc.c
+ * - PA7300LC-specific functions
+ *
+ * Copyright (C) 2000 Philipp Rumpf */
+
+#include <asm/gsc.h>
+#include <asm/ptrace.h>
+#include <asm/machdep.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+
+/* CPU register indices */
+
+#define MIOC_STATUS 0xf040
+#define MIOC_CONTROL 0xf080
+#define MDERRADD 0xf0e0
+#define DMAERR 0xf0e8
+#define DIOERR 0xf0ec
+#define HIDMAMEM 0xf0f4
+
+/* read CPU Diagnose register index */
+static u32 diag_read(int index)
+{
+ return 0;
+}
+
+/* this returns the HPA of the CPU it was called on */
+static u32 cpu_hpa(void)
+{
+ return 0xfffb0000;
+}
+
+static void pa7300lc_lpmc(int code, struct pt_regs *regs)
+{
+ u32 hpa;
+ printk(KERN_WARNING "LPMC on CPU %d\n", smp_processor_id());
+
+ show_regs(regs);
+
+ hpa = cpu_hpa();
+ printk(KERN_WARNING
+ "MIOC_CONTROL %08x\n" "MIOC_STATUS %08x\n"
+ "MDERRADD %08x\n" "DMAERR %08x\n"
+ "DIOERR %08x\n" "HIDMAMEM %08x\n",
+ gsc_readl(hpa+MIOC_CONTROL), gsc_readl(hpa+MIOC_STATUS),
+ gsc_readl(hpa+MDERRADD), gsc_readl(hpa+DMAERR),
+ gsc_readl(hpa+DIOERR), gsc_readl(hpa+HIDMAMEM));
+}
+
+void pa7300lc_init(void)
+{
+ cpu_lpmc = pa7300lc_lpmc;
+}
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
new file mode 100644
index 000000000..2b4dbd74c
--- /dev/null
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -0,0 +1,138 @@
+/*
+ * Architecture-specific kernel symbols
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/string.h>
+EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strtok);
+
+#include <linux/pci.h>
+EXPORT_SYMBOL(hppa_dma_ops);
+
+#include <asm/irq.h>
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+
+#include <asm/processor.h>
+EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(boot_cpu_data);
+
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(synchronize_irq);
+
+#include <asm/smplock.h>
+EXPORT_SYMBOL(kernel_flag);
+
+#include <asm/system.h>
+EXPORT_SYMBOL(__global_sti);
+EXPORT_SYMBOL(__global_cli);
+EXPORT_SYMBOL(__global_save_flags);
+EXPORT_SYMBOL(__global_restore_flags);
+
+#endif
+
+#include <asm/uaccess.h>
+EXPORT_SYMBOL(lcopy_to_user);
+EXPORT_SYMBOL(lcopy_from_user);
+
+/* Needed so insmod can set dp value */
+
+extern int data_start;
+
+EXPORT_SYMBOL_NOVERS(data_start);
+
+#include <asm/gsc.h>
+EXPORT_SYMBOL(_gsc_writeb);
+EXPORT_SYMBOL(_gsc_writew);
+EXPORT_SYMBOL(_gsc_writel);
+EXPORT_SYMBOL(_gsc_readb);
+EXPORT_SYMBOL(_gsc_readw);
+EXPORT_SYMBOL(_gsc_readl);
+EXPORT_SYMBOL(busdevice_alloc_irq);
+EXPORT_SYMBOL(register_driver);
+EXPORT_SYMBOL(gsc_alloc_irq);
+EXPORT_SYMBOL(pdc_iodc_read);
+
+extern void $$divI(void);
+extern void $$divU(void);
+extern void $$remI(void);
+extern void $$remU(void);
+extern void $$mulI(void);
+extern void $$mulU(void);
+extern void $$divU_3(void);
+extern void $$divU_5(void);
+extern void $$divU_6(void);
+extern void $$divU_9(void);
+extern void $$divU_10(void);
+extern void $$divU_12(void);
+extern void $$divU_7(void);
+extern void $$divU_14(void);
+extern void $$divU_15(void);
+extern void $$divI_3(void);
+extern void $$divI_5(void);
+extern void $$divI_6(void);
+extern void $$divI_7(void);
+extern void $$divI_9(void);
+extern void $$divI_10(void);
+extern void $$divI_12(void);
+extern void $$divI_14(void);
+extern void $$divI_15(void);
+
+EXPORT_SYMBOL_NOVERS($$divI);
+EXPORT_SYMBOL_NOVERS($$divU);
+EXPORT_SYMBOL_NOVERS($$remI);
+EXPORT_SYMBOL_NOVERS($$remU);
+EXPORT_SYMBOL_NOVERS($$mulI);
+EXPORT_SYMBOL_NOVERS($$mulU);
+EXPORT_SYMBOL_NOVERS($$divU_3);
+EXPORT_SYMBOL_NOVERS($$divU_5);
+EXPORT_SYMBOL_NOVERS($$divU_6);
+EXPORT_SYMBOL_NOVERS($$divU_9);
+EXPORT_SYMBOL_NOVERS($$divU_10);
+EXPORT_SYMBOL_NOVERS($$divU_12);
+EXPORT_SYMBOL_NOVERS($$divU_7);
+EXPORT_SYMBOL_NOVERS($$divU_14);
+EXPORT_SYMBOL_NOVERS($$divU_15);
+EXPORT_SYMBOL_NOVERS($$divI_3);
+EXPORT_SYMBOL_NOVERS($$divI_5);
+EXPORT_SYMBOL_NOVERS($$divI_6);
+EXPORT_SYMBOL_NOVERS($$divI_7);
+EXPORT_SYMBOL_NOVERS($$divI_9);
+EXPORT_SYMBOL_NOVERS($$divI_10);
+EXPORT_SYMBOL_NOVERS($$divI_12);
+EXPORT_SYMBOL_NOVERS($$divI_14);
+EXPORT_SYMBOL_NOVERS($$divI_15);
+
+extern void __ashrdi3(void);
+
+EXPORT_SYMBOL_NOVERS(__ashrdi3);
+
+#ifdef __LP64__
+extern void __divdi3(void);
+extern void __udivdi3(void);
+
+EXPORT_SYMBOL_NOVERS(__divdi3);
+EXPORT_SYMBOL_NOVERS(__udivdi3);
+#endif
+
+#ifndef __LP64__
+extern void $$dyncall(void);
+EXPORT_SYMBOL_NOVERS($$dyncall);
+#endif
+
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
new file mode 100644
index 000000000..88a9ddc77
--- /dev/null
+++ b/arch/parisc/kernel/pci-dma.c
@@ -0,0 +1,547 @@
+/*
+** Dynamic DMA mapping support.
+** See Documentation/DMA-mapping.txt for interface definitions.
+**
+** (c) Copyright 1999,2000 Hewlett-Packard Company
+** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2000 Philipp Rumpf <prumpf@tux.org>
+** (c) Copyright 2000 John Marvin
+**
+** This implementation is for PA-RISC platforms that do not support
+** I/O TLBs (aka DMA address translation hardware).
+**
+** "leveraged" from 2.3.47: arch/ia64/kernel/pci-dma.c.
+** (I assume it's from David Mosberger-Tang but there was no Copyright)
+**
+** AFAIK, all PA7100LC and PA7300LC platforms can use this code.
+** All PA2.0 machines but V-class can alias xxx_alloc_consistent()
+** to use regular cacheable memory.
+**
+** - ggg
+*/
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#include <asm/io.h>
+#include <asm/page.h> /* get_order */
+#include <asm/dma.h> /* for DMA_CHUNK_SIZE */
+
+#include <linux/proc_fs.h>
+
+static struct proc_dir_entry * proc_gsc_root = NULL;
+static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
+static unsigned long pcxl_used_bytes = 0;
+static unsigned long pcxl_used_pages = 0;
+
+extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */
+static spinlock_t pcxl_res_lock;
+static char *pcxl_res_map;
+static int pcxl_res_hint;
+static int pcxl_res_size;
+
+#ifdef DEBUG_PCXL_RESOURCE
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+
+/*
+** Dump a hex representation of the resource map.
+*/
+
+#ifdef DUMP_RESMAP
+static
+void dump_resmap(void)
+{
+ u_long *res_ptr = (unsigned long *)pcxl_res_map;
+ u_long i = 0;
+
+ printk("res_map: ");
+ for(; i < (pcxl_res_size / sizeof(unsigned long)); ++i, ++res_ptr)
+ printk("%08lx ", *res_ptr);
+
+ printk("\n");
+}
+#else
+static inline void dump_resmap(void) {;}
+#endif
+
+static int pa11_dma_supported( struct pci_dev *dev, dma_addr_t mask)
+{
+ return 1;
+}
+
+static inline int map_pte_uncached(pte_t * pte,
+ unsigned long vaddr,
+ unsigned long size, unsigned long *paddr_ptr)
+{
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ vaddr &= ~PMD_MASK;
+ end = vaddr + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ if (!pte_none(*pte))
+ printk(KERN_ERR "map_pte_uncached: page already exists\n");
+ set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
+ pdtlb_kernel(orig_vaddr);
+ vaddr += PAGE_SIZE;
+ orig_vaddr += PAGE_SIZE;
+ (*paddr_ptr) += PAGE_SIZE;
+ pte++;
+ } while (vaddr < end);
+ return 0;
+}
+
+static inline int map_pmd_uncached(pmd_t * pmd, unsigned long vaddr,
+ unsigned long size, unsigned long *paddr_ptr)
+{
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ vaddr &= ~PGDIR_MASK;
+ end = vaddr + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ pte_t * pte = pte_alloc_kernel(pmd, vaddr);
+ if (!pte)
+ return -ENOMEM;
+ if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr))
+ return -ENOMEM;
+ vaddr = (vaddr + PMD_SIZE) & PMD_MASK;
+ orig_vaddr += PMD_SIZE;
+ pmd++;
+ } while (vaddr < end);
+ return 0;
+}
+
+static inline int map_uncached_pages(unsigned long vaddr, unsigned long size,
+ unsigned long paddr)
+{
+ pgd_t * dir;
+ unsigned long end = vaddr + size;
+
+ dir = pgd_offset_k(vaddr);
+ do {
+ pmd_t *pmd;
+
+ pmd = pmd_alloc_kernel(dir, vaddr);
+ if (!pmd)
+ return -ENOMEM;
+ if (map_pmd_uncached(pmd, vaddr, end - vaddr, &paddr))
+ return -ENOMEM;
+ vaddr = vaddr + PGDIR_SIZE;
+ dir++;
+ } while (vaddr && (vaddr < end));
+ return 0;
+}
+
+static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr,
+ unsigned long size)
+{
+ pte_t * pte;
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = pte_offset(pmd, vaddr);
+ vaddr &= ~PMD_MASK;
+ end = vaddr + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ pte_t page = *pte;
+ pte_clear(pte);
+ pdtlb_kernel(orig_vaddr);
+ vaddr += PAGE_SIZE;
+ orig_vaddr += PAGE_SIZE;
+ pte++;
+ if (pte_none(page) || pte_present(page))
+ continue;
+ printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n");
+ } while (vaddr < end);
+}
+
+static inline void unmap_uncached_pmd(pgd_t * dir, unsigned long vaddr,
+ unsigned long size)
+{
+ pmd_t * pmd;
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ if (pgd_none(*dir))
+ return;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return;
+ }
+ pmd = pmd_offset(dir, vaddr);
+ vaddr &= ~PGDIR_MASK;
+ end = vaddr + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ unmap_uncached_pte(pmd, orig_vaddr, end - vaddr);
+ vaddr = (vaddr + PMD_SIZE) & PMD_MASK;
+ orig_vaddr += PMD_SIZE;
+ pmd++;
+ } while (vaddr < end);
+}
+
+static void unmap_uncached_pages(unsigned long vaddr, unsigned long size)
+{
+ pgd_t * dir;
+ unsigned long end = vaddr + size;
+
+ dir = pgd_offset_k(vaddr);
+ do {
+ unmap_uncached_pmd(dir, vaddr, end - vaddr);
+ vaddr = vaddr + PGDIR_SIZE;
+ dir++;
+ } while (vaddr && (vaddr < end));
+}
+
+#define PCXL_SEARCH_LOOP(idx, mask, size) \
+ for(; res_ptr < res_end; ++res_ptr) \
+ { \
+ if(0 == ((*res_ptr) & mask)) { \
+ *res_ptr |= mask; \
+ idx = (int)((u_long)res_ptr - (u_long)pcxl_res_map); \
+ pcxl_res_hint = idx + (size >> 3); \
+ goto resource_found; \
+ } \
+ }
+
+#define PCXL_FIND_FREE_MAPPING(idx, mask, size) { \
+ u##size *res_ptr = (u##size *)&(pcxl_res_map[pcxl_res_hint & ~((size >> 3) - 1)]); \
+ u##size *res_end = (u##size *)&pcxl_res_map[pcxl_res_size]; \
+ PCXL_SEARCH_LOOP(idx, mask, size); \
+ res_ptr = (u##size *)&pcxl_res_map[0]; \
+ PCXL_SEARCH_LOOP(idx, mask, size); \
+}
+
+unsigned long
+pcxl_alloc_range(size_t size)
+{
+ int res_idx;
+ u_long mask, flags;
+ unsigned int pages_needed = size >> PAGE_SHIFT;
+
+ ASSERT(pages_needed);
+ ASSERT((pages_needed * PAGE_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_needed < (BITS_PER_LONG - PAGE_SHIFT));
+
+ mask = (u_long) -1L;
+ mask >>= BITS_PER_LONG - pages_needed;
+
+ DBG_RES("pcxl_alloc_range() size: %d pages_needed %d pages_mask 0x%08lx\n",
+ size, pages_needed, mask);
+
+ spin_lock_irqsave(&pcxl_res_lock, flags);
+
+ if(pages_needed <= 8) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 8);
+ } else if(pages_needed <= 16) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 16);
+ } else if(pages_needed <= 32) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 32);
+ } else {
+ panic(__FILE__ ": pcxl_alloc_range() Too many pages to map.\n");
+ }
+
+ dump_resmap();
+ panic(__FILE__ ": pcxl_alloc_range() out of dma mapping resources\n");
+
+resource_found:
+
+ DBG_RES("pcxl_alloc_range() res_idx %d mask 0x%08lx res_hint: %d\n",
+ res_idx, mask, pcxl_res_hint);
+
+ pcxl_used_pages += pages_needed;
+ pcxl_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1);
+
+ spin_unlock_irqrestore(&pcxl_res_lock, flags);
+
+ dump_resmap();
+
+ /*
+ ** return the corresponding vaddr in the pcxl dma map
+ */
+ return (pcxl_dma_start + (res_idx << (PAGE_SHIFT + 3)));
+}
+
+#define PCXL_FREE_MAPPINGS(idx, m, size) \
+ u##size *res_ptr = (u##size *)&(pcxl_res_map[(idx) + (((size >> 3) - 1) & (~((size >> 3) - 1)))]); \
+ ASSERT((*res_ptr & m) == m); \
+ *res_ptr &= ~m;
+
+/*
+** clear bits in the pcxl resource map
+*/
+static void
+pcxl_free_range(unsigned long vaddr, size_t size)
+{
+ u_long mask, flags;
+ unsigned int res_idx = (vaddr - pcxl_dma_start) >> (PAGE_SHIFT + 3);
+ unsigned int pages_mapped = size >> PAGE_SHIFT;
+
+ ASSERT(pages_mapped);
+ ASSERT((pages_mapped * PAGE_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_mapped < (BITS_PER_LONG - PAGE_SHIFT));
+
+ mask = (u_long) -1L;
+ mask >>= BITS_PER_LONG - pages_mapped;
+
+ DBG_RES("pcxl_free_range() res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n",
+ res_idx, size, pages_mapped, mask);
+
+ spin_lock_irqsave(&pcxl_res_lock, flags);
+
+ if(pages_mapped <= 8) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 8);
+ } else if(pages_mapped <= 16) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 16);
+ } else if(pages_mapped <= 32) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 32);
+ } else {
+ panic(__FILE__ ": pcxl_free_range() Too many pages to unmap.\n");
+ }
+
+ pcxl_used_pages -= (pages_mapped ? pages_mapped : 1);
+ pcxl_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1);
+
+ spin_unlock_irqrestore(&pcxl_res_lock, flags);
+
+ dump_resmap();
+}
+
+static int __init
+pcxl_dma_init(void)
+{
+ if (pcxl_dma_start == 0)
+ return 0;
+
+ spin_lock_init(&pcxl_res_lock);
+ pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3);
+ pcxl_res_hint = 0;
+ pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
+ get_order(pcxl_res_size));
+
+ proc_gsc_root = proc_mkdir("gsc", 0);
+ create_proc_info_entry("dino", 0, proc_gsc_root, pcxl_proc_info);
+ return 0;
+}
+
+__initcall(pcxl_dma_init);
+
+static void * pa11_dma_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+{
+ unsigned long vaddr;
+ unsigned long paddr;
+ int order;
+
+ order = get_order(size);
+ size = 1 << (order + PAGE_SHIFT);
+ vaddr = pcxl_alloc_range(size);
+ paddr = __get_free_pages(GFP_ATOMIC, order);
+ flush_kernel_dcache_range(paddr, size);
+ paddr = __pa(paddr);
+ map_uncached_pages(vaddr, size, paddr);
+ *dma_handle = (dma_addr_t) paddr;
+
+#if 0
+/* This probably isn't needed to support EISA cards.
+** ISA cards will certainly only support 24-bit DMA addressing.
+** Not clear if we can, want, or need to support ISA.
+*/
+ if (!hwdev || hwdev->dma_mask != 0xffffffff)
+ gfp |= GFP_DMA;
+#endif
+ return (void *)vaddr;
+}
+
+static void pa11_dma_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ int order;
+
+ order = get_order(size);
+ size = 1 << (order + PAGE_SHIFT);
+ unmap_uncached_pages((unsigned long)vaddr, size);
+ pcxl_free_range((unsigned long)vaddr, size);
+ free_pages((unsigned long)__va(dma_handle), order);
+}
+
+static dma_addr_t pa11_dma_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE) {
+ printk(KERN_ERR "pa11_dma_map_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
+ BUG();
+ }
+
+ flush_kernel_dcache_range((unsigned long) addr, size);
+ return virt_to_phys(addr);
+}
+
+static void pa11_dma_unmap_single(struct pci_dev *dev, dma_addr_t dma_handle, size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE) {
+ printk(KERN_ERR "pa11_dma_unmap_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
+ BUG();
+ }
+
+ if (direction == PCI_DMA_TODEVICE)
+ return;
+
+ /*
+ * For PCI_DMA_FROMDEVICE this flush is not necessary for the
+ * simple map/unmap case. However, it IS necessary if if
+ * pci_dma_sync_single has been called and the buffer reused.
+ */
+
+ flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size);
+ return;
+}
+
+static int pa11_dma_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int i;
+
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
+ for (i = 0; i < nents; i++, sglist++ ) {
+ sg_dma_address(sglist) = (dma_addr_t) virt_to_phys(sglist->address);
+ sg_dma_len(sglist) = sglist->length;
+ flush_kernel_dcache_range((unsigned long)sglist->address,
+ sglist->length);
+ }
+ return nents;
+}
+
+static void pa11_dma_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int i;
+
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
+ if (direction == PCI_DMA_TODEVICE)
+ return;
+
+ /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
+
+ for (i = 0; i < nents; i++, sglist++ )
+ flush_kernel_dcache_range((unsigned long) sglist->address, sglist->length);
+ return;
+}
+
+static void pa11_dma_sync_single(struct pci_dev *dev, dma_addr_t dma_handle, size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
+ flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size);
+}
+
+static void pa11_dma_sync_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int i;
+
+ /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
+
+ for (i = 0; i < nents; i++, sglist++ )
+ flush_kernel_dcache_range((unsigned long) sglist->address, sglist->length);
+}
+
+struct pci_dma_ops pcxl_dma_ops = {
+ pa11_dma_supported, /* dma_support */
+ pa11_dma_alloc_consistent,
+ pa11_dma_free_consistent,
+ pa11_dma_map_single, /* map_single */
+ pa11_dma_unmap_single, /* unmap_single */
+ pa11_dma_map_sg, /* map_sg */
+ pa11_dma_unmap_sg, /* unmap_sg */
+ pa11_dma_sync_single, /* dma_sync_single */
+ pa11_dma_sync_sg /* dma_sync_sg */
+};
+
+static void *fail_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ return NULL;
+}
+
+static void fail_free_consistent(struct pci_dev *dev, size_t size,
+ void *vaddr, dma_addr_t iova)
+{
+ return;
+}
+
+struct pci_dma_ops pcx_dma_ops = {
+ pa11_dma_supported, /* dma_support */
+ fail_alloc_consistent,
+ fail_free_consistent,
+ pa11_dma_map_single, /* map_single */
+ pa11_dma_unmap_single, /* unmap_single */
+ pa11_dma_map_sg, /* map_sg */
+ pa11_dma_unmap_sg, /* unmap_sg */
+ pa11_dma_sync_single, /* dma_sync_single */
+ pa11_dma_sync_sg /* dma_sync_sg */
+};
+
+struct pci_dma_ops *hppa_dma_ops;
+
+static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
+{
+ u_long i = 0;
+ unsigned long *res_ptr = (u_long *)pcxl_res_map;
+ unsigned long total_pages = pcxl_res_size << 3; /* 8 bits per byte */
+
+ sprintf(buf, "\nDMA Mapping Area size : %d bytes (%d pages)\n",
+ PCXL_DMA_MAP_SIZE,
+ (pcxl_res_size << 3) ); /* 1 bit per page */
+
+ sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
+ buf, pcxl_res_size, pcxl_res_size << 3); /* 8 bits per byte */
+
+ strcat(buf, " total: free: used: % used:\n");
+ sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size,
+ pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes,
+ (pcxl_used_bytes * 100) / pcxl_res_size);
+
+ sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
+ total_pages - pcxl_used_pages, pcxl_used_pages,
+ (pcxl_used_pages * 100 / total_pages));
+
+ strcat(buf, "\nResource bitmap:");
+
+ for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
+ if ((i & 7) == 0)
+ strcat(buf,"\n ");
+ sprintf(buf, "%s %08lx", buf, *res_ptr);
+ }
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
new file mode 100644
index 000000000..a46f69832
--- /dev/null
+++ b/arch/parisc/kernel/pci.c
@@ -0,0 +1,535 @@
+/* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997, 1998 Ralf Baechle
+ * Copyright (C) 1999 SuSE GmbH
+ * Copyright (C) 1999 Hewlett-Packard Company
+ * Copyright (C) 1999, 2000 Grant Grundler
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h> /* for __init and __devinit */
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/string.h> /* for memcpy() */
+
+#include <asm/system.h>
+
+#ifdef CONFIG_PCI
+
+#undef DEBUG_RESOURCES
+
+#ifdef DEBUG_RESOURCES
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+/* To be used as: mdelay(pci_post_reset_delay);
+**
+** post_reset is the time the kernel should stall to prevent anyone from
+** accessing the PCI bus once #RESET is de-asserted.
+** PCI spec somewhere says 1 second but with multi-PCI bus systems,
+** this makes the boot time much longer than necessary.
+** 20ms seems to work for all the HP PCI implementations to date.
+*/
+int pci_post_reset_delay = 50;
+
+struct pci_port_ops *pci_port;
+struct pci_bios_ops *pci_bios;
+
+struct pci_hba_data *hba_list = NULL;
+int hba_count = 0;
+
+/*
+** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data.
+*/
+#define PCI_HBA_MAX 32
+static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX];
+
+
+/********************************************************************
+**
+** I/O port space support
+**
+*********************************************************************/
+
+#define PCI_PORT_HBA(a) ((a)>>16)
+#define PCI_PORT_ADDR(a) ((a) & 0xffffUL)
+
+/* KLUGE : inb needs to be defined differently for PCI devices than
+** for other bus interfaces. Doing this at runtime sucks but is the
+** only way one driver binary can support devices on different bus types.
+**
+*/
+
+#define PCI_PORT_IN(type, size) \
+u##size in##type (int addr) \
+{ \
+ int b = PCI_PORT_HBA(addr); \
+ u##size d = (u##size) -1; \
+ ASSERT(pci_port); /* make sure services are defined */ \
+ ASSERT(parisc_pci_hba[b]); /* make sure ioaddr are "fixed up" */ \
+ if (parisc_pci_hba[b] == NULL) { \
+ printk(KERN_WARNING "\nPCI Host Bus Adapter %d not registered. in" #size "(0x%x) returning -1\n", b, addr); \
+ } else { \
+ d = pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \
+ } \
+ return d; \
+}
+
+PCI_PORT_IN(b, 8)
+PCI_PORT_IN(w, 16)
+PCI_PORT_IN(l, 32)
+
+
+#define PCI_PORT_OUT(type, size) \
+void out##type (u##size d, int addr) \
+{ \
+ int b = PCI_PORT_HBA(addr); \
+ ASSERT(pci_port); \
+ pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \
+}
+
+PCI_PORT_OUT(b, 8)
+PCI_PORT_OUT(w, 16)
+PCI_PORT_OUT(l, 32)
+
+
+
+/*
+ * BIOS32 replacement.
+ */
+void pcibios_init(void)
+{
+ ASSERT(pci_bios != NULL);
+
+ if (pci_bios)
+ {
+ if (pci_bios->init) {
+ (*pci_bios->init)();
+ } else {
+ printk(KERN_WARNING "pci_bios != NULL but init() is!\n");
+ }
+ }
+}
+
+
+/* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */
+void pcibios_fixup_bus(struct pci_bus *bus)
+{
+ ASSERT(pci_bios != NULL);
+
+ /* If this is a bridge, get the current bases */
+ if (bus->self) {
+ pci_read_bridge_bases(bus);
+ }
+
+ if (pci_bios) {
+ if (pci_bios->fixup_bus) {
+ (*pci_bios->fixup_bus)(bus);
+ } else {
+ printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n");
+ }
+ }
+}
+
+
+char *pcibios_setup(char *str)
+{
+ return str;
+}
+
+#endif /* defined(CONFIG_PCI) */
+
+
+
+/* -------------------------------------------------------------------
+** linux-2.4: NEW STUFF
+** --------------------
+*/
+
+/*
+** Used in drivers/pci/quirks.c
+*/
+struct pci_fixup pcibios_fixups[] = { {0} };
+
+
+/*
+** called by drivers/pci/setup.c:pdev_fixup_irq()
+*/
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+/*
+** updates IRQ_LINE cfg register to reflect PCI-PCI bridge skewing.
+**
+** Calling path for Alpha is:
+** alpha/kernel/pci.c:common_init_pci(swizzle_func, pci_map_irq_func )
+** drivers/pci/setup.c:pci_fixup_irqs()
+** drivers/pci/setup.c:pci_fixup_irq() (for each PCI device)
+** invoke swizzle and map functions
+** alpha/kernel/pci.c:pcibios_update_irq()
+**
+** Don't need this for PA legacy PDC systems.
+**
+** On PAT PDC systems, We only support one "swizzle" for any number
+** of PCI-PCI bridges deep. That's how bit3 PCI expansion chassis
+** are implemented. The IRQ lines are "skewed" for all devices but
+** *NOT* routed through the PCI-PCI bridge. Ie any device "0" will
+** share an IRQ line. Legacy PDC is expecting this IRQ line routing
+** as well.
+**
+** Unfortunately, PCI spec allows the IRQ lines to be routed
+** around the PCI bridge as long as the IRQ lines are skewed
+** based on the device number...<sigh>...
+**
+** Lastly, dino.c might be able to use pci_fixup_irq() to
+** support RS-232 and PS/2 children. Not sure how but it's
+** something to think about.
+*/
+}
+
+
+/* ------------------------------------
+**
+** Program one BAR in PCI config space.
+**
+** ------------------------------------
+** PAT PDC systems need this routine. PA legacy PDC does not.
+**
+** Used by alpha/arm:
+** alpha/kernel/pci.c:common_init_pci()
+** (or arm/kernel/pci.c:pcibios_init())
+** drivers/pci/setup.c:pci_assign_unassigned_resources()
+** drivers/pci/setup.c:pdev_assign_unassigned_resources()
+** arch/<foo>/kernel/pci.c:pcibios_update_resource()
+**
+** When BAR's are configured by linux, this routine
+** will update configuration space with the "normalized"
+** address. "root" indicates where the range starts and res
+** is some portion of that range.
+**
+** For all PA-RISC systems except V-class, root->start would be zero.
+**
+** PAT PDC can tell us which MMIO ranges are available or already in use.
+** I/O port space and such are not memory mapped anyway for PA-Risc.
+*/
+void __devinit
+pcibios_update_resource(
+ struct pci_dev *dev,
+ struct resource *root,
+ struct resource *res,
+ int barnum
+ )
+{
+ int where;
+ u32 barval = 0;
+
+ DBG_RES("pcibios_update_resource(%s, ..., %d) [%lx,%lx]/%x\n",
+ dev->slot_name,
+ barnum, res->start, res->end, (int) res->flags);
+
+ if (barnum >= PCI_BRIDGE_RESOURCES) {
+ /* handled in pbus_set_ranges_data() */
+ return;
+ }
+
+ if (barnum == PCI_ROM_RESOURCE) {
+ where = PCI_ROM_ADDRESS;
+ } else {
+ /* 0-5 standard PCI "regions" */
+ where = PCI_BASE_ADDRESS_0 + (barnum * 4);
+ }
+
+ if (res->flags & IORESOURCE_IO) {
+ barval = PCI_PORT_ADDR(res->start);
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* This should work for VCLASS too */
+ barval = res->start & 0xffffffffUL;
+ } else {
+ panic("pcibios_update_resource() WTF? flags not IO or MEM");
+ }
+
+ pci_write_config_dword(dev, where, barval);
+
+/* XXX FIXME - Elroy does support 64-bit (dual cycle) addressing.
+** But at least one device (Symbios 53c896) which has 64-bit BAR
+** doesn't actually work right with dual cycle addresses.
+** So ignore the whole mess for now.
+*/
+
+ if ((res->flags & (PCI_BASE_ADDRESS_SPACE
+ | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
+ == (PCI_BASE_ADDRESS_SPACE_MEMORY
+ | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+ pci_write_config_dword(dev, where+4, 0);
+ printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->name);
+ }
+}
+
+/*
+** Called by pci_set_master() - a driver interface.
+**
+** Legacy PDC guarantees to set:
+** Map Memory BAR's into PA IO space.
+** Map Expansion ROM BAR into one common PA IO space per bus.
+** Map IO BAR's into PCI IO space.
+** Command (see below)
+** Cache Line Size
+** Latency Timer
+** Interrupt Line
+** PPB: secondary latency timer, io/mmio base/limit,
+** bus numbers, bridge control
+**
+*/
+void
+pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat >= 16) return;
+
+ /*
+ ** HP generally has fewer devices on the bus than other architectures.
+ */
+ printk("PCIBIOS: Setting latency timer of %s to 128\n", dev->slot_name);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+}
+
+
+/*
+** called by drivers/pci/setup-res.c:pbus_set_ranges().
+*/
+void pcibios_fixup_pbus_ranges(
+ struct pci_bus *bus,
+ struct pbus_set_ranges_data *ranges
+ )
+{
+ /*
+ ** I/O space may see busnumbers here. Something
+ ** in the form of 0xbbxxxx where bb is the bus num
+ ** and xxxx is the I/O port space address.
+ ** Remaining address translation are done in the
+ ** PCI Host adapter specific code - ie dino_out8.
+ */
+ ranges->io_start = PCI_PORT_ADDR(ranges->io_start);
+ ranges->io_end = PCI_PORT_ADDR(ranges->io_end);
+
+ DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n", bus->number,
+ ranges->io_start, ranges->io_end,
+ ranges->mem_start, ranges->mem_end);
+}
+
+#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
+
+
+/*
+** pcibios align resources() is called everytime generic PCI code
+** wants to generate a new address. The process of looking for
+** an available address, each candidate is first "aligned" and
+** then checked if the resource is available until a match is found.
+**
+** Since we are just checking candidates, don't use any fields other
+** than res->start.
+*/
+void __devinit
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+ unsigned long mask, align;
+
+ DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx)\n",
+ ((struct pci_dev *) data)->slot_name,
+ res->parent, res->start, res->end, (int) res->flags, size);
+
+ /* has resource already been aligned/assigned? */
+ if (res->parent)
+ return;
+
+ /* If it's not IO, then it's gotta be MEM */
+ align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+
+ /* Align to largest of MIN or input size */
+ mask = MAX(size, align) - 1;
+ res->start += mask;
+ res->start &= ~mask;
+
+ /*
+ ** WARNING : caller is expected to update "end" field.
+ ** We can't since it might really represent the *size*.
+ ** The difference is "end = start + size" vs "end += size".
+ */
+}
+
+
+#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
+
+void __devinit
+pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
+{
+ struct pbus_set_ranges_data inner;
+ struct pci_dev *dev;
+ struct pci_dev *bridge = bus->self;
+ struct list_head *ln;
+
+ /* set reasonable default "window" for pcibios_align_resource */
+ inner.io_start = inner.io_end = 0;
+ inner.mem_start = inner.mem_end = 0;
+
+ /* Collect information about how our direct children are layed out. */
+ for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+ int i;
+ dev = pci_dev_b(ln);
+
+ /* Skip bridges here - we'll catch them below */
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ continue;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource res;
+ unsigned long size;
+
+ if (dev->resource[i].flags == 0)
+ continue;
+
+ memcpy(&res, &dev->resource[i], sizeof(res));
+ size = res.end - res.start + 1;
+
+ if (res.flags & IORESOURCE_IO) {
+ res.start = inner.io_end;
+ pcibios_align_resource(dev, &res, size);
+ inner.io_end += res.start + size;
+ } else if (res.flags & IORESOURCE_MEM) {
+ res.start = inner.mem_end;
+ pcibios_align_resource(dev, &res, size);
+ inner.mem_end = res.start + size;
+ }
+
+ DBG_RES(" %s inner size %lx/%x IO %lx MEM %lx\n",
+ dev->slot_name,
+ size, res.flags, inner.io_end, inner.mem_end);
+ }
+ }
+
+ /* And for all of the subordinate busses. */
+ for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
+ pcibios_size_bridge(pci_bus_b(ln), &inner);
+
+ /* turn the ending locations into sizes (subtract start) */
+ inner.io_end -= inner.io_start - 1;
+ inner.mem_end -= inner.mem_start - 1;
+
+ /* Align the sizes up by bridge rules */
+ inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1;
+ inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1;
+
+ /* PPB - PCI bridge Device will normaller also have "outer" != NULL. */
+ if (bridge) {
+ /* Adjust the bus' allocation requirements */
+ /* PPB's pci device Bridge resources */
+
+ bus->resource[0] = &bridge->resource[PCI_BRIDGE_RESOURCES];
+ bus->resource[1] = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
+
+ bus->resource[0]->start = bus->resource[1]->start = 0;
+ bus->resource[0]->parent= bus->resource[1]->parent = NULL;
+
+ bus->resource[0]->end = inner.io_end;
+ bus->resource[0]->flags = IORESOURCE_IO;
+
+ bus->resource[1]->end = inner.mem_end;
+ bus->resource[1]->flags = IORESOURCE_MEM;
+ }
+
+ /* adjust parent's resource requirements */
+ if (outer) {
+ outer->io_end = ROUND_UP(outer->io_end, 4*1024);
+ outer->io_end += inner.io_end;
+
+ outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024);
+ outer->mem_end += inner.mem_end;
+ }
+}
+
+#undef ROUND_UP
+
+
+int __devinit
+pcibios_enable_device(struct pci_dev *dev)
+{
+ u16 cmd, old_cmd;
+ int idx;
+
+ /*
+ ** The various platform PDC's (aka "BIOS" for PCs) don't
+ ** enable all the same bits. We just make sure they are here.
+ */
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+
+ /*
+ ** See if any resources have been allocated
+ */
+ for (idx=0; idx<6; idx++) {
+ struct resource *r = &dev->resource[idx];
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+
+ /*
+ ** System error and Parity Error reporting are enabled by default.
+ ** Devices that do NOT want those behaviors should clear them
+ ** (eg PCI graphics, possibly networking).
+ ** Interfaces like SCSI certainly should not. We want the
+ ** system to crash if a system or parity error is detected.
+ ** At least until the device driver can recover from such an error.
+ */
+ cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+
+ if (cmd != old_cmd) {
+ printk("PCIBIOS: Enabling device %s (%04x -> %04x)\n",
+ dev->slot_name, old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+
+ return 0;
+}
+
+
+void __devinit
+pcibios_assign_unassigned_resources(struct pci_bus *bus)
+{
+ struct list_head *ln;
+
+ for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next)
+ {
+ pdev_assign_unassigned_resources(pci_dev_b(ln));
+ }
+
+ /* And for all of the sub-busses. */
+ for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
+ pcibios_assign_unassigned_resources(pci_bus_b(ln));
+
+}
+
+/*
+** PARISC specific (unfortunately)
+*/
+void pcibios_register_hba(struct pci_hba_data *hba)
+{
+ hba->next = hba_list;
+ hba_list = hba;
+
+ ASSERT(hba_count < PCI_HBA_MAX);
+
+ /*
+ ** pci_port->in/out() uses parisc_pci_hba to lookup parameter.
+ */
+ parisc_pci_hba[hba_count] = hba;
+ hba->hba_num = hba_count++;
+}
diff --git a/arch/parisc/kernel/pdc.c b/arch/parisc/kernel/pdc.c
new file mode 100644
index 000000000..4fa4327c0
--- /dev/null
+++ b/arch/parisc/kernel/pdc.c
@@ -0,0 +1,217 @@
+/* arch/parisc/kernel/pdc.c - safe pdc access routines
+ *
+ * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org)
+ * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
+ *
+ * only these routines should be used out of the real kernel (i.e. everything
+ * using virtual addresses) for obvious reasons */
+
+/* I think it would be in everyone's best interest to follow this
+ * guidelines when writing PDC wrappers:
+ *
+ * - the name of the pdc wrapper should match one of the macros
+ * used for the first two arguments
+ * - don't use caps for random parts of the name
+ * - use ASSERT_ALIGN to ensure the aligment of the arguments is
+ * correct
+ * - use __pa() to convert virtual (kernel) pointers to physical
+ * ones.
+ * - the name of the struct used for pdc return values should equal
+ * one of the macros used for the first two arguments to the
+ * corresponding PDC call
+ * - keep the order of arguments
+ * - don't be smart (setting trailing NUL bytes for strings, return
+ * something useful even if the call failed) unless you are sure
+ * it's not going to affect functionality or performance
+ *
+ * Example:
+ * int pdc_cache_info(struct pdc_cache_info *cache_info )
+ * {
+ * ASSERT_ALIGN(cache_info, 8);
+ *
+ * return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
+ * }
+ * prumpf 991016
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/real.h>
+#include <asm/system.h>
+
+
+#define ASSERT_ALIGN(ptr, align) \
+ do { if(((unsigned long)(ptr)) & (align-1)) { \
+ printk("PDC: %s:%d %s() called with " \
+ "unaligned argument from %p", __FILE__, __LINE__, \
+ __FUNCTION__, __builtin_return_address(0)); \
+ \
+ return -1; \
+ } } while(0)
+
+/* verify address can be accessed without an HPMC */
+int pdc_add_valid(void *address)
+{
+ ASSERT_ALIGN(address, 4);
+
+ return mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, (unsigned long)address);
+}
+
+#if 0
+int pdc_chassis_warn(struct pdc_chassis_warn *address)
+{
+ ASSERT_ALIGN(address, 4);
+
+ return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(address), 0);
+}
+#endif
+
+int pdc_chassis_disp(unsigned long disp)
+{
+ return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
+}
+
+int pdc_chassis_info(void *pdc_result, void *chassis_info, unsigned long len)
+{
+ ASSERT_ALIGN(pdc_result, 4);
+ ASSERT_ALIGN(chassis_info, 4);
+ return mem_pdc_call(PDC_CHASSIS,PDC_RETURN_CHASSIS_INFO,
+ __pa(pdc_result), __pa(chassis_info), len);
+}
+
+int pdc_hpa_processor(void *address)
+{
+ /* We're using 0 for the last parameter just to make sure.
+ It's actually HVERSION dependant. And remember, life is
+ hard without a backspace. */
+ ASSERT_ALIGN(address, 4);
+
+ return mem_pdc_call(PDC_HPA, PDC_HPA_PROCESSOR, __pa(address),0);
+}
+
+#if 0
+int pdc_hpa_modules(void *address)
+{
+ return mem_pdc_call(PDC_HPA, PDC_HPA_MODULES, address);
+}
+#endif
+
+int pdc_iodc_read(void *address, void * hpa, unsigned int index,
+ void * iodc_data, unsigned int iodc_data_size)
+{
+ ASSERT_ALIGN(address, 4);
+ ASSERT_ALIGN(iodc_data, 8);
+ return mem_pdc_call(PDC_IODC, PDC_IODC_READ,
+ __pa(address), hpa, index, __pa(iodc_data), iodc_data_size);
+}
+
+
+int pdc_system_map_find_mods(void *pdc_mod_info,
+ void *mod_path, int index)
+{
+ return mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE,
+ __pa(pdc_mod_info), __pa(mod_path), (long)index);
+}
+
+
+int pdc_model_info(struct pdc_model *model) {
+ ASSERT_ALIGN(model, 8);
+ return mem_pdc_call(PDC_MODEL,PDC_MODEL_INFO,__pa(model),0);
+}
+
+/* get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) */
+int pdc_model_sysmodel(char * name)
+{
+ struct pdc_model_sysmodel sys_model;
+ int retval;
+
+ ASSERT_ALIGN(&sys_model, 8);
+ ASSERT_ALIGN(name, 4);
+
+ sys_model.mod_len = 0;
+ retval = mem_pdc_call(PDC_MODEL,PDC_MODEL_SYSMODEL,__pa(&sys_model),
+ OS_ID_HPUX,__pa(name));
+
+ if (retval == PDC_RET_OK)
+ name[sys_model.mod_len] = '\0'; /* add trailing '\0' */
+ else
+ name[0] = 0;
+
+ return retval;
+}
+
+/* id: 0 = cpu revision, 1 = boot-rom-version */
+int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id) {
+ return mem_pdc_call(PDC_MODEL,PDC_MODEL_VERSIONS,__pa(cpu_id),id);
+}
+
+int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id) {
+ cpu_id->cpuid = 0; /* preset zero (call maybe not implemented!) */
+ return mem_pdc_call(PDC_MODEL,6,__pa(cpu_id),0); /* 6="return CPU ID" */
+}
+
+int pdc_cache_info(struct pdc_cache_info *cache_info) {
+ ASSERT_ALIGN(cache_info, 8);
+
+ return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
+}
+
+#ifndef __LP64__
+int pdc_btlb_info( struct pdc_btlb_info *btlb ) {
+ int status;
+ status = mem_pdc_call(PDC_BLOCK_TLB,PDC_BTLB_INFO,__pa(btlb),0);
+ if (status<0) btlb->max_size = 0;
+ return status;
+}
+
+int pdc_mem_map_hpa(void *r_addr, void *mod_path) {
+ return mem_pdc_call(PDC_MEM_MAP,PDC_MEM_MAP_HPA,
+ __pa(r_addr),__pa(mod_path));
+}
+
+int pdc_lan_station_id(char *lan_addr, void *net_hpa) {
+ struct pdc_lan_station_id id;
+ unsigned char *addr;
+
+ if (mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
+ __pa(&id), net_hpa) < 0)
+ addr = 0; /* FIXME: else read MAC from NVRAM */
+ else
+ addr = id.addr;
+ if (addr)
+ memmove( lan_addr, addr, PDC_LAN_STATION_ID_SIZE);
+ else
+ memset( lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
+ return (addr != 0);
+}
+#endif
+
+
+/* Similar to PDC_PAT stuff in pdcpat.c - but added for Forte/Allegro boxes */
+int pdc_pci_irt_size(void *r_addr, void *hpa)
+{
+ return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE,
+ __pa(r_addr), hpa);
+
+}
+
+int pdc_pci_irt(void *r_addr, void *hpa, void *tbl)
+{
+ return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
+ __pa(r_addr), hpa, __pa(tbl));
+}
+
+/* access the TOD clock */
+int pdc_tod_read(struct pdc_tod *tod)
+{
+ ASSERT_ALIGN(tod, 8);
+ return mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(tod), 0);
+}
+
+int pdc_tod_set(unsigned long sec, unsigned long usec)
+{
+ return mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
+}
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
new file mode 100644
index 000000000..f2d45862b
--- /dev/null
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -0,0 +1,179 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/page.h>
+#include <asm/types.h>
+#include <asm/system.h>
+#include <asm/pdc.h> /* for iodc_call() proto and friends */
+#include <asm/real.h>
+
+static int __attribute__((aligned(8))) iodc_retbuf[32];
+static char __attribute__((aligned(64))) iodc_dbuf[4096];
+
+/*
+ * pdc_putc:
+ * Console character print using IODC.
+ *
+ * Note that only these special chars are architected for console IODC io:
+ * BEL, BS, CR, and LF. Others are passed through.
+ * Since the HP console requires CR+LF to perform a 'newline', we translate
+ * "\n" to "\r\n".
+ */
+
+static int posx; /* for simple TAB-Simulation... */
+
+/* XXX Should we spinlock posx usage */
+
+void pdc_putc(unsigned char c)
+{
+ unsigned int n;
+ unsigned long flags;
+
+ switch (c) {
+ case '\n':
+ iodc_dbuf[0] = '\r';
+ iodc_dbuf[1] = '\n';
+ n = 2;
+ posx = 0;
+ break;
+ case '\t':
+ pdc_putc(' ');
+ while (posx & 7) /* expand TAB */
+ pdc_putc(' ');
+ return; /* return since IODC can't handle this */
+ case '\b':
+ posx-=2; /* BS */
+ default:
+ iodc_dbuf[0] = c;
+ n = 1;
+ posx++;
+ break;
+ }
+ {
+ real32_call(PAGE0->mem_cons.iodc_io,
+ (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
+ PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
+ }
+}
+
+static void pdc_console_write(struct console *co, const char *s, unsigned count)
+{
+ while(count--)
+ pdc_putc(*s++);
+}
+
+int pdc_console_wait_key(struct console *co)
+{
+ int ch = 'X';
+ int status;
+
+ /* Bail if no console input device. */
+ if (!PAGE0->mem_kbd.iodc_io)
+ return 0;
+
+ /* wait for a keyboard (rs232)-input */
+ do {
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ status = real32_call(PAGE0->mem_kbd.iodc_io,
+ (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
+ PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
+ restore_flags(flags);
+ ch = *iodc_dbuf; /* save the character directly to ch */
+ } while (*iodc_retbuf == 0); /* wait for a key */
+ return ch;
+}
+
+int pdc_getc(void)
+{
+ return pdc_console_wait_key(NULL);
+}
+
+static int pdc_console_setup(struct console *co, char *options)
+{
+ return 0;
+}
+
+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,
+};
+
+static int pdc_console_initialized;
+
+void pdc_console_init(void)
+{
+ if (pdc_console_initialized)
+ return;
+ ++pdc_console_initialized;
+
+ /* If the console is duplex then copy the COUT parameters to CIN. */
+ if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
+ memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
+
+ pdc_console_write(0, "PDC Console Initialized\n", 24);
+ /* register the pdc console */
+ register_console(&pdc_cons);
+}
+
+
+/* Unregister the pdc console with the printk console layer */
+void pdc_console_die(void)
+{
+ printk("Switching from PDC console\n");
+ if (!pdc_console_initialized)
+ return;
+ --pdc_console_initialized;
+
+#ifdef CONFIG_VT_CONSOLE
+ {
+ /* fixme (needed?): Wait for console-tasklet to finish !*/
+ extern struct tasklet_struct console_tasklet;
+ tasklet_schedule(&console_tasklet);
+ }
+#endif
+
+ unregister_console(&pdc_cons);
+}
+
+
+/*
+ * Used for emergencies. Currently only used if an HPMC occurs. If an
+ * HPMC occurs, it is possible that the current console may not be
+ * properly initialed after the PDC IO reset. This routine unregisters all
+ * of the current consoles, reinitializes the pdc console and
+ * registers it.
+ */
+
+void pdc_console_restart(void)
+{
+ struct console *console;
+ extern int log_size;
+
+ if (pdc_console_initialized)
+ return;
+
+ while ((console = console_drivers) != (struct console *)0)
+ unregister_console(console_drivers);
+
+ log_size = 0;
+ pdc_console_init();
+ printk("Switched to PDC console\n");
+ return;
+}
+
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
new file mode 100644
index 000000000..a8d7a707e
--- /dev/null
+++ b/arch/parisc/kernel/process.c
@@ -0,0 +1,250 @@
+/*
+ * linux/arch/parisc/kernel/process.c
+ * based on the work for i386
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#define __KERNEL_SYSCALLS__
+#include <stdarg.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/elf.h>
+
+#include <asm/machdep.h>
+#include <asm/offset.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/gsc.h>
+#include <asm/processor.h>
+
+spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
+
+#ifdef __LP64__
+/* The 64-bit code should work equally well in 32-bit land but I didn't
+ * want to take the time to confirm that. -PB
+ */
+extern unsigned int ret_from_kernel_thread;
+#else
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
+#endif
+
+
+int hlt_counter=0;
+
+void disable_hlt(void)
+{
+ hlt_counter++;
+}
+
+void enable_hlt(void)
+{
+ hlt_counter--;
+}
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+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) {
+ }
+ schedule();
+ check_pgt_cache();
+ }
+}
+
+void __init reboot_setup(char *str, int *ints)
+{
+}
+
+struct notifier_block *mach_notifier;
+
+void machine_restart(char *ptr)
+{
+ notifier_call_chain(&mach_notifier, MACH_RESTART, ptr);
+}
+
+void machine_halt(void)
+{
+ notifier_call_chain(&mach_notifier, MACH_HALT, NULL);
+}
+
+void machine_power_on(void)
+{
+ notifier_call_chain(&mach_notifier, MACH_POWER_ON, NULL);
+}
+
+void machine_power_off(void)
+{
+ notifier_call_chain(&mach_notifier, MACH_POWER_OFF, NULL);
+}
+
+
+void machine_heartbeat(void)
+{
+}
+
+
+/*
+ * Create a kernel thread
+ */
+
+extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+
+ /*
+ * FIXME: Once we are sure we don't need any debug here,
+ * kernel_thread can become a #define.
+ */
+
+ return __kernel_thread(fn, arg, flags);
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+ set_fs(USER_DS);
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Fill in the FPU structure for a core dump.
+ */
+int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
+{
+ memcpy(r, regs->fr, sizeof *r);
+ return 1;
+}
+
+/* Note that "fork()" is implemented in terms of clone, with
+ parameters (SIGCHLD, regs->gr[30], regs). */
+int
+sys_clone(unsigned long clone_flags, unsigned long usp,
+ struct pt_regs *regs)
+{
+ return do_fork(clone_flags, usp, regs, 0);
+}
+
+int
+sys_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+ regs->gr[30], regs, 0);
+}
+
+int
+copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused, /* in ia64 this is "user_stack_size" */
+ struct task_struct * p, struct pt_regs * pregs)
+{
+ struct pt_regs * cregs = &(p->thread.regs);
+ long ksp;
+
+ *cregs = *pregs;
+
+ /* Set the return value for the child. Note that this is not
+ actually restored by the syscall exit path, but we put it
+ here for consistency in case of signals. */
+ cregs->gr[28] = 0; /* child */
+
+ /*
+ * We need to differentiate between a user fork and a
+ * kernel fork. We can't use user_mode, because the
+ * the syscall path doesn't save iaoq. Right now
+ * We rely on the fact that kernel_thread passes
+ * in zero for usp.
+ */
+ if (usp == 0) {
+ /* Kernel Thread */
+ ksp = (((unsigned long)(p)) + TASK_SZ_ALGN);
+ cregs->ksp = ksp; /* always return to kernel */
+#ifdef __LP64__
+ cregs->kpc = (unsigned long) &ret_from_kernel_thread;
+#else
+ cregs->kpc = (unsigned long) ret_from_kernel_thread;
+#endif
+
+ /*
+ * Copy function and argument to be called from
+ * ret_from_kernel_thread.
+ */
+ cregs->gr[26] = pregs->gr[26];
+ cregs->gr[25] = pregs->gr[25];
+
+ } else {
+ /* User Thread:
+ *
+ * Use same stack depth as parent when in wrapper
+ *
+ * Note that the fork wrappers are responsible
+ * for setting gr[20] and gr[21].
+ */
+
+ cregs->ksp = ((unsigned long)(p))
+ + (pregs->gr[20] & (INIT_TASK_SIZE - 1));
+ cregs->kpc = pregs->gr[21];
+ }
+
+ return 0;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+
+asmlinkage int sys_execve(struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname((char *) regs->gr[26]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, (char **) regs->gr[25],
+ (char **) regs->gr[24], regs);
+ if (error == 0)
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+out:
+
+ return error;
+}
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
new file mode 100644
index 000000000..176b4386a
--- /dev/null
+++ b/arch/parisc/kernel/ptrace.c
@@ -0,0 +1,305 @@
+/*
+ * Kernel support for the ptrace() and syscall tracing interfaces.
+ *
+ * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc.
+ * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/offset.h>
+
+/* These are used in entry.S, syscall_restore_rfi. We need to record the
+ * current stepping mode somewhere other than in PSW, because there is no
+ * concept of saving and restoring the users PSW over a syscall. We choose
+ * to use these two bits in task->ptrace. These bits must not clash with
+ * any PT_* defined in include/linux/sched.h, and must match with the bit
+ * tests in entry.S
+ */
+#define PT_SINGLESTEP 0x10000
+#define PT_BLOCKSTEP 0x20000
+
+long sys_ptrace(long request, pid_t pid, long addr, long data)
+{
+ struct task_struct *child;
+ long ret;
+
+ lock_kernel();
+ ret = -EPERM;
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+ /* set the ptrace bit in the process flags. */
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+ ret = -EPERM;
+ if (pid == 1) /* no messing around with init! */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ if (child == current)
+ goto out_tsk;
+ if ((!child->dumpable ||
+ (current->uid != child->euid) ||
+ (current->uid != child->suid) ||
+ (current->uid != child->uid) ||
+ (current->gid != child->egid) ||
+ (current->gid != child->sgid) ||
+ (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ goto out_tsk;
+ /* the same process cannot be attached many times */
+ if (child->ptrace & PT_PTRACED)
+ goto out_tsk;
+ child->ptrace |= PT_PTRACED;
+ if (child->p_pptr != current) {
+ unsigned long flags;
+
+ write_lock_irqsave(&tasklist_lock, flags);
+ REMOVE_LINKS(child);
+ child->p_pptr = current;
+ SET_LINKS(child);
+ write_unlock_irqrestore(&tasklist_lock, flags);
+ }
+ send_sig(SIGSTOP, child, 1);
+ ret = 0;
+ goto out_tsk;
+ }
+ ret = -ESRCH;
+ if (!(child->ptrace & PT_PTRACED))
+ goto out_tsk;
+ if (child->state != TASK_STOPPED) {
+ if (request != PTRACE_KILL)
+ goto out_tsk;
+ }
+ if (child->p_pptr != current)
+ goto out_tsk;
+
+ switch (request) {
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ goto out_tsk;
+ ret = put_user(tmp,(unsigned long *) data);
+ goto out_tsk;
+ }
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ ret = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ goto out_tsk;
+ ret = -EIO;
+ goto out_tsk;
+
+ /* Read the word at location addr in the USER area. This will need
+ to change when the kernel no longer saves all regs on a syscall. */
+ case PTRACE_PEEKUSR: {
+ unsigned long tmp;
+
+ ret = -EIO;
+ if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs))
+ goto out_tsk;
+
+ tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
+ ret = put_user(tmp, (unsigned long *) data);
+ goto out_tsk;
+ }
+
+ /* Write the word at location addr in the USER area. This will need
+ to change when the kernel no longer saves all regs on a syscall.
+ FIXME. There is a problem at the moment in that r3-r18 are only
+ saved if the process is ptraced on syscall entry, and even then
+ those values are overwritten by actual register values on syscall
+ exit. */
+ case PTRACE_POKEUSR:
+ ret = -EIO;
+ if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs))
+ goto out_tsk;
+ /* XXX This test probably needs adjusting. We probably want to
+ * allow writes to some bits of PSW, and may want to block writes
+ * to (some) space registers. Some register values written here
+ * may be ignored in entry.S:syscall_restore_rfi; e.g. iaoq is
+ * written with r31/r31+4, and not with the values in pt_regs.
+ */
+ /* Allow writing of gr1-gr31, fr*, sr*, iasq*, iaoq*, sar */
+ if (addr == PT_PSW || (addr > PT_IAOQ1 && addr != PT_SAR))
+ goto out_tsk;
+
+ *(unsigned long *) ((char *) task_regs(child) + addr) = data;
+ ret = 0;
+ goto out_tsk;
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
+ if (request == PTRACE_SYSCALL)
+ child->ptrace |= PT_TRACESYS;
+ else
+ child->ptrace &= ~PT_TRACESYS;
+ child->exit_code = data;
+ goto out_wake_notrap;
+
+ case PTRACE_KILL:
+ /*
+ * make the child exit. Best I can do is send it a
+ * sigkill. perhaps it should be put in the status
+ * that it wants to exit.
+ */
+ if (child->state == TASK_ZOMBIE) /* already dead */
+ goto out_tsk;
+ child->exit_code = SIGKILL;
+ goto out_wake_notrap;
+
+ case PTRACE_SINGLEBLOCK:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_TRACESYS|PT_SINGLESTEP);
+ child->ptrace |= PT_BLOCKSTEP;
+ child->exit_code = data;
+
+ /* Enable taken branch trap. */
+ pa_psw(child)->r = 0;
+ pa_psw(child)->t = 1;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+ goto out_wake;
+
+ case PTRACE_SINGLESTEP:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_TRACESYS|PT_BLOCKSTEP);
+ child->ptrace |= PT_SINGLESTEP;
+ child->exit_code = data;
+
+ if (pa_psw(child)->n) {
+ struct siginfo si;
+
+ /* Nullified, just crank over the queue. */
+ task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1];
+ task_regs(child)->iasq[0] = task_regs(child)->iasq[1];
+ task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4;
+ pa_psw(child)->n = 0;
+ pa_psw(child)->x = 0;
+ pa_psw(child)->y = 0;
+ pa_psw(child)->z = 0;
+ pa_psw(child)->b = 0;
+ pa_psw(child)->r = 0;
+ pa_psw(child)->t = 0;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+ /* Don't wake up the child, but let the
+ parent know something happened. */
+ si.si_code = TRAP_TRACE;
+ si.si_addr = (void *) (task_regs(child)->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ si.si_errno = 0;
+ force_sig_info(SIGTRAP, &si, child);
+ //notify_parent(child, SIGCHLD);
+ //ret = 0;
+ goto out_wake;
+ }
+
+ /* Enable recovery counter traps. The recovery counter
+ * itself will be set to zero on a task switch. If the
+ * task is suspended on a syscall then the syscall return
+ * path will overwrite the recovery counter with a suitable
+ * value such that it traps once back in user space. We
+ * disable interrupts in the childs PSW here also, to avoid
+ * interrupts while the recovery counter is decrementing.
+ */
+ pa_psw(child)->r = 1;
+ pa_psw(child)->t = 0;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+ /* give it a chance to run. */
+ goto out_wake;
+
+ case PTRACE_DETACH:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS|PT_SINGLESTEP|PT_BLOCKSTEP);
+ child->exit_code = data;
+ write_lock_irq(&tasklist_lock);
+ REMOVE_LINKS(child);
+ child->p_pptr = child->p_opptr;
+ SET_LINKS(child);
+ write_unlock_irq(&tasklist_lock);
+ goto out_wake_notrap;
+
+ default:
+ ret = -EIO;
+ goto out_tsk;
+ }
+
+out_wake_notrap:
+ /* make sure the trap bits are not set */
+ pa_psw(child)->r = 0;
+ pa_psw(child)->t = 0;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+out_wake:
+ wake_up_process(child);
+ ret = 0;
+out_tsk:
+ free_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
+
+void syscall_trace(void)
+{
+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) !=
+ (PT_PTRACED|PT_TRACESYS))
+ return;
+ current->exit_code = SIGTRAP;
+ current->state = TASK_STOPPED;
+ notify_parent(current, SIGCHLD);
+ schedule();
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/parisc/kernel/real1.c b/arch/parisc/kernel/real1.c
new file mode 100644
index 000000000..2bb26bc88
--- /dev/null
+++ b/arch/parisc/kernel/real1.c
@@ -0,0 +1,154 @@
+/*
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
+ *
+ * most of these calls might reasonably be moved to ../kernel -PB
+ *
+ * The basic principle is to construct a stack frame in C then call
+ * some assembly which adopts that stack, does some rfi magic, may
+ * switch wide/narrow mode, and calls the routine described by the
+ * 'fn' parameter WHICH IS NOT A FUNCTION POINTER!!!!!!!!!!!!!!!!
+ */
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <stdarg.h>
+#include <asm/pgtable.h> /* for __pa() */
+#include <asm/pdc.h>
+
+static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
+
+/***************** 32-bit real-mode calls ***********/
+/* The struct below is used
+ * to overlay real_stack (real2.S), preparing a 32-bit call frame.
+ * real32_call_asm() then uses this stack in narrow real mode
+ */
+
+struct narrow_stack {
+ /* use int, not long which is 64 bits */
+ unsigned int arg13;
+ unsigned int arg12;
+ unsigned int arg11;
+ unsigned int arg10;
+ unsigned int arg9;
+ unsigned int arg8;
+ unsigned int arg7;
+ unsigned int arg6;
+ unsigned int arg5;
+ unsigned int arg4;
+ unsigned int arg3;
+ unsigned int arg2;
+ unsigned int arg1;
+ unsigned int arg0;
+ unsigned int frame_marker[8];
+ unsigned int sp;
+ /* in reality, there's nearly 8k of stack after this */
+};
+
+long
+real32_call(unsigned long fn, ...)
+{
+ unsigned long r;
+ va_list args;
+ unsigned long flags;
+ extern struct narrow_stack real_stack;
+ extern unsigned long real32_call_asm(unsigned int *,
+ unsigned int *, unsigned int);
+
+ va_start(args, fn);
+ real_stack.arg0 = va_arg(args, unsigned int);
+ real_stack.arg1 = va_arg(args, unsigned int);
+ real_stack.arg2 = va_arg(args, unsigned int);
+ real_stack.arg3 = va_arg(args, unsigned int);
+ real_stack.arg4 = va_arg(args, unsigned int);
+ real_stack.arg5 = va_arg(args, unsigned int);
+ real_stack.arg6 = va_arg(args, unsigned int);
+ real_stack.arg7 = va_arg(args, unsigned int);
+ real_stack.arg8 = va_arg(args, unsigned int);
+ real_stack.arg9 = va_arg(args, unsigned int);
+ real_stack.arg10 = va_arg(args, unsigned int);
+ real_stack.arg11 = va_arg(args, unsigned int);
+ real_stack.arg12 = va_arg(args, unsigned int);
+ real_stack.arg13 = va_arg(args, unsigned int);
+ va_end(args);
+
+ if (fn == 0) {
+ /* mem_pdc call */
+ fn = PAGE0->mem_pdc;
+ }
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ r = real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
+ spin_unlock_irqrestore(&pdc_lock, flags);
+
+ return r;
+}
+
+#ifdef __LP64__
+/***************** 64-bit real-mode calls ***********/
+
+struct wide_stack {
+ unsigned long arg0;
+ unsigned long arg1;
+ unsigned long arg2;
+ unsigned long arg3;
+ unsigned long arg4;
+ unsigned long arg5;
+ unsigned long arg6;
+ unsigned long arg7;
+ unsigned long arg8;
+ unsigned long arg9;
+ unsigned long arg10;
+ unsigned long arg11;
+ unsigned long arg12;
+ unsigned long arg13;
+ unsigned long frame_marker[2]; /* rp, previous sp */
+ unsigned long sp;
+ /* in reality, there's nearly 8k of stack after this */
+};
+
+long
+real64_call(unsigned long fn, ...)
+{
+ unsigned long r;
+ va_list args;
+ unsigned long flags;
+ extern struct wide_stack real_stack;
+ extern unsigned long real64_call_asm(unsigned long *,
+ unsigned long *, unsigned long);
+
+ va_start(args, fn);
+ real_stack.arg0 = va_arg(args, unsigned long);
+ real_stack.arg1 = va_arg(args, unsigned long);
+ real_stack.arg2 = va_arg(args, unsigned long);
+ real_stack.arg3 = va_arg(args, unsigned long);
+ real_stack.arg4 = va_arg(args, unsigned long);
+ real_stack.arg5 = va_arg(args, unsigned long);
+ real_stack.arg6 = va_arg(args, unsigned long);
+ real_stack.arg7 = va_arg(args, unsigned long);
+ real_stack.arg8 = va_arg(args, unsigned long);
+ real_stack.arg9 = va_arg(args, unsigned long);
+ real_stack.arg10 = va_arg(args, unsigned long);
+ real_stack.arg11 = va_arg(args, unsigned long);
+ real_stack.arg12 = va_arg(args, unsigned long);
+ real_stack.arg13 = va_arg(args, unsigned long);
+ va_end(args);
+
+ if (fn == 0) {
+ /* mem_pdc call */
+ fn = PAGE0->mem_pdc_hi;
+ fn <<= 32;
+ fn |= PAGE0->mem_pdc;
+ }
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn);
+ spin_unlock_irqrestore(&pdc_lock, flags);
+
+ return r;
+}
+
+#endif
diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S
new file mode 100644
index 000000000..eb1425ec4
--- /dev/null
+++ b/arch/parisc/kernel/real2.S
@@ -0,0 +1,274 @@
+/*
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
+ *
+ */
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/psw.h>
+
+ .section .bss
+ .export real_stack
+ .align 64
+real_stack:
+ .block 8192
+
+#ifdef __LP64__
+# define REG_SZ 8
+#else
+# define REG_SZ 4
+#endif
+
+#define N_SAVED_REGS 9
+
+save_cr_space:
+ .block REG_SZ * N_SAVED_REGS
+
+
+/************************ 32-bit real-mode calls ***********************/
+/* This can be called in both narrow and wide kernels */
+ .text
+ .export real32_call_asm
+ /* unsigned long real32_call_asm(unsigned int *sp,
+ * unsigned int *arg0p,
+ * unsigned int iodc_fn)
+ * sp is value of stack pointer to adopt before calling PDC (virt)
+ * arg0p points to where saved arg values may be found
+ * iodc_fn is the IODC function to call
+ */
+real32_call_asm:
+ STREG %rp, -RP_OFFSET(%sp) /* save RP */
+#ifdef __LP64__
+ callee_save
+ ldo 2*REG_SZ(%sp), %sp /* room for a couple more saves */
+ STREG %r27, -1*REG_SZ(%sp)
+ STREG %r29, -2*REG_SZ(%sp)
+#endif
+ STREG %sp, -REG_SZ(%arg0) /* save SP on real-mode stack */
+ copy %arg0, %sp /* adopt the real-mode SP */
+
+ /* save iodc_fn */
+ copy %arg2, %r31
+
+ /* load up the arg registers from the saved arg area */
+ /* 32-bit calling convention passes first 4 args in registers */
+ ldw 0(%arg1), %arg0 /* note overwriting arg0 */
+ ldw -8(%arg1), %arg2
+ ldw -12(%arg1), %arg3
+ ldw -4(%arg1), %arg1 /* obviously must do this one last! */
+
+ tophys %sp
+
+ b,l rfi_virt2real,%r2
+ nop
+
+ b,l save_control_regs,%r2 /* modifies r1, r2, r28 */
+ nop
+
+#ifdef __LP64__
+ rsm PSW_SM_W, %r0 /* go narrow */
+#endif
+
+ ldil L%PA(ric_ret), %r2
+ ldo R%PA(ric_ret)(%r2), %r2
+ bv 0(%r31)
+ nop
+ric_ret:
+#ifdef __LP64__
+ ssm PSW_SM_W, %r0 /* go wide */
+#endif
+ /* restore CRs before going virtual in case we page fault */
+ b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */
+ nop
+
+ b,l rfi_real2virt,%r2
+ nop
+
+ tovirt %sp
+ LDREG -REG_SZ(%sp), %sp /* restore SP */
+#ifdef __LP64__
+ LDREG -1*REG_SZ(%sp), %r27
+ LDREG -2*REG_SZ(%sp), %r29
+ ldo -2*REG_SZ(%sp), %sp
+ callee_rest
+#endif
+ LDREG -RP_OFFSET(%sp), %rp /* restore RP */
+ bv 0(%rp)
+ nop
+
+
+# define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where)
+# define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r
+
+ .text
+save_control_regs:
+ load32 PA(save_cr_space), %r28
+ PUSH_CR(%cr24, %r28)
+ PUSH_CR(%cr25, %r28)
+ PUSH_CR(%cr26, %r28)
+ PUSH_CR(%cr27, %r28)
+ PUSH_CR(%cr28, %r28)
+ PUSH_CR(%cr29, %r28)
+ PUSH_CR(%cr30, %r28)
+ PUSH_CR(%cr31, %r28)
+ PUSH_CR(%cr15, %r28)
+ bv 0(%r2)
+ nop
+
+restore_control_regs:
+ load32 PA(save_cr_space + (N_SAVED_REGS * REG_SZ)), %r26
+ POP_CR(%cr15, %r26)
+ POP_CR(%cr31, %r26)
+ POP_CR(%cr30, %r26)
+ POP_CR(%cr29, %r26)
+ POP_CR(%cr28, %r26)
+ POP_CR(%cr27, %r26)
+ POP_CR(%cr26, %r26)
+ POP_CR(%cr25, %r26)
+ POP_CR(%cr24, %r26)
+ bv 0(%r2)
+ nop
+
+/* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for
+ * more general-purpose use by the several places which need RFIs
+ */
+ .align 128
+ .text
+rfi_virt2real:
+ /* switch to real mode... */
+ ssm 0,0 /* See "relied upon translation" */
+ nop /* comment in interruption.S */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mtsm 0 /* disable interruptions */
+ mtctl 0, %cr17 /* space 0 */
+ mtctl 0, %cr17
+ load32 PA(rfi_v2r_1), %r1
+ mtctl %r1, %cr18
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18
+ load32 PDC_PSW, %r1
+ mtctl %r1, %cr22
+ rfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+rfi_v2r_1:
+ tophys %r2
+ bv 0(%r2)
+ nop
+
+ .text
+ .align 128
+rfi_real2virt:
+ ssm 0,0 /* See "relied upon translation" */
+ nop /* comment in interruption.S */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mtsm 0 /* disable interruptions */
+ mtctl 0, %cr17 /* space 0 */
+ mtctl 0, %cr17
+ load32 (rfi_r2v_1), %r1
+ mtctl %r1, %cr18
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18
+ load32 KERNEL_PSW, %r1
+ mtctl %r1, %cr22
+ rfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+rfi_r2v_1:
+ tovirt %r2
+ bv 0(%r2)
+ nop
+
+#ifdef __LP64__
+
+/************************ 64-bit real-mode calls ***********************/
+/* This is only usable in wide kernels right now and will probably stay so */
+ .text
+ .export real64_call_asm
+ /* unsigned long real64_call_asm(unsigned long *sp,
+ * unsigned long *arg0p,
+ * unsigned long fn)
+ * sp is value of stack pointer to adopt before calling PDC (virt)
+ * arg0p points to where saved arg values may be found
+ * iodc_fn is the IODC function to call
+ */
+real64_call_asm:
+ std %rp, -0x10(%sp) /* save RP */
+ std %sp, -8(%arg0) /* save SP on real-mode stack */
+ copy %arg0, %sp /* adopt the real-mode SP */
+
+ /* save fn */
+ copy %arg2, %r31
+
+ /* set up the new ap */
+ ldo 64(%arg1), %r29
+
+ /* load up the arg registers from the saved arg area */
+ /* 32-bit calling convention passes first 4 args in registers */
+ ldd 0*REG_SZ(%arg1), %arg0 /* note overwriting arg0 */
+ ldd 2*REG_SZ(%arg1), %arg2
+ ldd 3*REG_SZ(%arg1), %arg3
+ ldd 4*REG_SZ(%arg1), %r22
+ ldd 5*REG_SZ(%arg1), %r21
+ ldd 6*REG_SZ(%arg1), %r20
+ ldd 7*REG_SZ(%arg1), %r19
+ ldd 1*REG_SZ(%arg1), %arg1 /* do this one last! */
+
+ tophys %sp
+
+ b,l rfi_virt2real,%r2
+ nop
+
+ b,l save_control_regs,%r2 /* modifies r1, r2, r28 */
+ nop
+
+ load32 PA(r64_ret), %r2
+ bv 0(%r31)
+ nop
+r64_ret:
+ /* restore CRs before going virtual in case we page fault */
+ b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */
+ nop
+
+ b,l rfi_real2virt,%r2
+ nop
+
+ tovirt %sp
+ ldd -8(%sp), %sp /* restore SP */
+ ldd -0x10(%sp), %rp /* restore RP */
+ bv 0(%rp)
+ nop
+
+#endif
diff --git a/arch/parisc/kernel/sba_iommu.c b/arch/parisc/kernel/sba_iommu.c
new file mode 100644
index 000000000..b7b541478
--- /dev/null
+++ b/arch/parisc/kernel/sba_iommu.c
@@ -0,0 +1,1752 @@
+/*
+** System Bus Adapter (SBA) I/O MMU manager
+**
+** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2000 Hewlett-Packard Company
+**
+** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code)
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+**
+** This module initializes the IOC (I/O Controller) found on B1000/C3000/
+** J5000/J7000/N-class/L-class machines and their successors.
+**
+** FIXME: Multi-IOC support missing - depends on hp_device data
+** FIXME: add DMA hint support programming in both sba and lba modules.
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <linux/mm.h>
+#include <linux/string.h>
+#define PCI_DEBUG /* for ASSERT */
+#include <linux/pci.h>
+#undef PCI_DEBUG
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/dma.h> /* for DMA_CHUNK_SIZE */
+
+#include <asm/hardware.h> /* for register_driver() stuff */
+#include <asm/gsc.h> /* FIXME: for gsc_read/gsc_write */
+
+#include <linux/proc_fs.h>
+#include <asm/runway.h> /* for proc_runway_root */
+
+
+#define MODULE_NAME "SBA"
+
+/*
+** The number of debug flags is a clue - this code is fragile.
+** Don't even think about messing with it unless you have
+** plenty of 710's to sacrafice to the computer gods. :^)
+*/
+#undef DEBUG_SBA_INIT
+#undef DEBUG_SBA_RUN
+#undef DEBUG_SBA_RUN_SG
+#undef DEBUG_SBA_RESOURCE
+#undef ASSERT_PDIR_SANITY
+#undef DEBUG_LARGE_SG_ENTRIES
+
+#if 1
+#define SBA_INLINE
+#else
+#define SBA_INLINE __inline__
+#endif
+
+#ifdef DEBUG_SBA_INIT
+#define DBG_INIT(x...) printk(x)
+#else
+#define DBG_INIT(x...)
+#endif
+
+#ifdef DEBUG_SBA_RUN
+#define DBG_RUN(x...) printk(x)
+#else
+#define DBG_RUN(x...)
+#endif
+
+#ifdef DEBUG_SBA_RUN_SG
+#define DBG_RUN_SG(x...) printk(x)
+#else
+#define DBG_RUN_SG(x...)
+#endif
+
+
+#ifdef DEBUG_SBA_RESOURCE
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+/*
+** The number of pdir entries to "free" before issueing
+** a read to PCOM register to flush out PCOM writes.
+** Interacts with allocation granularity (ie 4 or 8 entries
+** allocated and free'd/purged at a time might make this
+** less interesting).
+*/
+#if 0
+#define DELAYED_RESOURCE_CNT 16
+#else
+#undef DELAYED_RESOURCE_CNT
+#endif
+
+#define DEFAULT_DMA_HINT_REG 0
+
+#define ASTRO_RUNWAY_PORT 0x582
+#define ASTRO_ROPES_PORT 0x780
+
+#define IKE_MERCED_PORT 0x803
+#define IKE_ROPES_PORT 0x781
+
+int sba_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+static struct pa_iodc_driver sba_drivers_for[] = {
+
+/* FIXME: why is SVERSION checked? */
+
+ {HPHW_IOA, ASTRO_RUNWAY_PORT, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
+
+ {HPHW_BCPORT, ASTRO_ROPES_PORT, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
+
+#if 0
+/* FIXME : N-class! Use a different "callback"? */
+ {HPHW_BCPORT, IKE_MERCED_PORT, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
+
+ {HPHW_BCPORT, IKE_ROPES_PORT, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
+#endif
+
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL }
+};
+
+
+#define SBA_FUNC_ID 0x0000 /* function id */
+#define SBA_FCLASS 0x0008 /* function class, bist, header, rev... */
+
+#define IS_ASTRO(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == ASTRO_RUNWAY_PORT)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == ASTRO_ROPES_PORT)) \
+)
+
+#define CONFIG_FUNC_SIZE 4096 /* SBA configuration function reg set */
+
+#define ASTRO_IOC_OFFSET 0x20000
+/* Ike's IOC's occupy functions 2 and 3 (not 0 and 1) */
+#define IKE_IOC_OFFSET(p) ((p+2)*CONFIG_FUNC_SIZE)
+
+#define IOC_CTRL 0x8 /* IOC_CTRL offset */
+#define IOC_CTRL_TE (0x1 << 0) /* TOC Enable */
+#define IOC_CTRL_RM (0x1 << 8) /* Real Mode */
+#define IOC_CTRL_NC (0x1 << 9) /* Non Coherent Mode */
+
+#define MAX_IOC 2 /* per Ike. Astro only has 1 */
+
+
+/*
+** Offsets into MBIB (Function 0 on Ike and hopefully Astro)
+** Firmware programs this stuff. Don't touch it.
+*/
+#define IOS_DIST_BASE 0x390
+#define IOS_DIST_MASK 0x398
+#define IOS_DIST_ROUTE 0x3A0
+
+#define IOS_DIRECT_BASE 0x3C0
+#define IOS_DIRECT_MASK 0x3C8
+#define IOS_DIRECT_ROUTE 0x3D0
+
+/*
+** Offsets into I/O TLB (Function 2 and 3 on Ike)
+*/
+#define ROPE0_CTL 0x200 /* "regbus pci0" */
+#define ROPE1_CTL 0x208
+#define ROPE2_CTL 0x210
+#define ROPE3_CTL 0x218
+#define ROPE4_CTL 0x220
+#define ROPE5_CTL 0x228
+#define ROPE6_CTL 0x230
+#define ROPE7_CTL 0x238
+
+#define HF_ENABLE 0x40
+
+
+#define IOC_IBASE 0x300 /* IO TLB */
+#define IOC_IMASK 0x308
+#define IOC_PCOM 0x310
+#define IOC_TCNFG 0x318
+#define IOC_PDIR_BASE 0x320
+
+#define IOC_IOVA_SPACE_BASE 0 /* IOVA ranges start at 0 */
+
+/*
+** IOC supports 4/8/16/64KB page sizes (see TCNFG register)
+** It's safer (avoid memory corruption) to keep DMA page mappings
+** equivalently sized to VM PAGE_SIZE.
+**
+** We really can't avoid generating a new mapping for each
+** page since the Virtual Coherence Index has to be generated
+** and updated for each page.
+**
+** IOVP_SIZE could only be greater than PAGE_SIZE if we are
+** confident the drivers really only touch the next physical
+** page iff that driver instance owns it.
+*/
+#define IOVP_SIZE PAGE_SIZE
+#define IOVP_SHIFT PAGE_SHIFT
+#define IOVP_MASK PAGE_MASK
+
+#define SBA_PERF_CFG 0x708 /* Performance Counter stuff */
+#define SBA_PERF_MASK1 0x718
+#define SBA_PERF_MASK2 0x730
+
+
+/*
+** Offsets into PCI Performance Counters (functions 12 and 13)
+** Controlled by PERF registers in function 2 & 3 respectively.
+*/
+#define SBA_PERF_CNT1 0x200
+#define SBA_PERF_CNT2 0x208
+#define SBA_PERF_CNT3 0x210
+
+
+struct ioc {
+ char *ioc_hpa; /* I/O MMU base address */
+ char *res_map; /* resource map, bit == pdir entry */
+ u64 *pdir_base; /* physical base address */
+
+ unsigned long *res_hint; /* next available IOVP - circular search */
+ unsigned int res_bitshift; /* from the LEFT! */
+ unsigned int res_size; /* size of resource map in bytes */
+ unsigned int hint_shift_pdir;
+ spinlock_t res_lock;
+ unsigned long hint_mask_pdir; /* bits used for DMA hints */
+#ifdef DELAYED_RESOURCE_CNT
+ dma_addr_t res_delay[DELAYED_RESOURCE_CNT];
+#endif
+
+#ifdef CONFIG_PROC_FS
+#define SBA_SEARCH_SAMPLE 0x100
+ unsigned long avg_search[SBA_SEARCH_SAMPLE];
+ unsigned long avg_idx; /* current index into avg_search */
+ unsigned long used_pages;
+ unsigned long msingle_calls;
+ unsigned long msingle_pages;
+ unsigned long msg_calls;
+ unsigned long msg_pages;
+ unsigned long usingle_calls;
+ unsigned long usingle_pages;
+ unsigned long usg_calls;
+ unsigned long usg_pages;
+#endif
+
+ /* STUFF We don't need in performance path */
+ unsigned int pdir_size; /* in bytes, determined by IOV Space size */
+ unsigned long ibase; /* pdir IOV Space base - shared w/lba_pci */
+ unsigned long imask; /* pdir IOV Space mask - shared w/lba_pci */
+};
+
+struct sba_device {
+ struct sba_device *next; /* list of LBA's in system */
+ struct hp_device *iodc; /* data about dev from firmware */
+ char *sba_hpa; /* base address */
+ spinlock_t sba_lock;
+ unsigned int flags; /* state/functionality enabled */
+ unsigned int hw_rev; /* HW revision of chip */
+
+ unsigned int num_ioc; /* number of on-board IOC's */
+ struct ioc ioc[MAX_IOC];
+};
+
+
+static struct sba_device *sba_list;
+static int sba_count;
+
+/* Ratio of Host MEM to IOV Space size */
+static unsigned long sba_mem_ratio = 4;
+
+/* Looks nice and keeps the compiler happy */
+#define SBA_DEV(d) ((struct sba_device *) (d))
+
+
+#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
+
+
+/************************************
+** SBA register read and write support
+**
+** BE WARNED: register writes are posted.
+** (ie follow writes which must reach HW with a read)
+*/
+#define READ_U8(addr) gsc_readb(addr)
+#define READ_U16(addr) gsc_readw((u16 *) (addr))
+#define READ_U32(addr) gsc_readl((u32 *) (addr))
+#define WRITE_U8(value, addr) gsc_writeb(value, addr)
+#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr))
+#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
+
+#define READ_REG8(addr) gsc_readb(addr)
+#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
+#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
+#define READ_REG64(addr) le64_to_cpu(gsc_readq((u64 *) (addr)))
+#define WRITE_REG8(value, addr) gsc_writeb(value, addr)
+#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
+#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
+#define WRITE_REG64(value, addr) gsc_writeq(cpu_to_le64(value), (u64 *) (addr))
+
+#ifdef DEBUG_SBA_INIT
+
+static void
+sba_dump_ranges(char *hpa)
+{
+ printk("SBA at 0x%p\n", hpa);
+ printk("IOS_DIST_BASE : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIST_BASE+4),
+ READ_REG32(hpa+IOS_DIST_BASE));
+ printk("IOS_DIST_MASK : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIST_MASK+4),
+ READ_REG32(hpa+IOS_DIST_MASK));
+ printk("IOS_DIST_ROUTE : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIST_ROUTE+4),
+ READ_REG32(hpa+IOS_DIST_ROUTE));
+ printk("\n");
+ printk("IOS_DIRECT_BASE : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIRECT_BASE+4),
+ READ_REG32(hpa+IOS_DIRECT_BASE));
+ printk("IOS_DIRECT_MASK : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIRECT_MASK+4),
+ READ_REG32(hpa+IOS_DIRECT_MASK));
+ printk("IOS_DIRECT_ROUTE: %08x %08x\n",
+ READ_REG32(hpa+IOS_DIRECT_ROUTE+4),
+ READ_REG32(hpa+IOS_DIRECT_ROUTE));
+}
+
+static void
+sba_dump_tlb(char *hpa)
+{
+ printk("IO TLB at 0x%p\n", hpa);
+ printk("IOC_IBASE : %08x %08x\n",
+ READ_REG32(hpa+IOC_IBASE+4),
+ READ_REG32(hpa+IOC_IBASE));
+ printk("IOC_IMASK : %08x %08x\n",
+ READ_REG32(hpa+IOC_IMASK+4),
+ READ_REG32(hpa+IOC_IMASK));
+ printk("IOC_TCNFG : %08x %08x\n",
+ READ_REG32(hpa+IOC_TCNFG+4),
+ READ_REG32(hpa+IOC_TCNFG));
+ printk("IOC_PDIR_BASE: %08x %08x\n",
+ READ_REG32(hpa+IOC_PDIR_BASE+4),
+ READ_REG32(hpa+IOC_PDIR_BASE));
+ printk("\n");
+}
+#endif
+
+
+#ifdef ASSERT_PDIR_SANITY
+
+static void
+sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide)
+{
+ /* start printing from lowest pde in rval */
+ u64 *ptr = &(ioc->pdir_base[pide & (~0U * BITS_PER_LONG)]);
+ unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]);
+ uint rcnt;
+
+ printk("SBA: %s rp %p bit %d rval 0x%lx\n",
+ msg,
+ rptr, pide & (BITS_PER_LONG - 1), *rptr);
+
+ rcnt = 0;
+ while (rcnt < BITS_PER_LONG) {
+ printk("%s %2d %p %016Lx\n",
+ (rcnt == (pide & (BITS_PER_LONG - 1)))
+ ? " -->" : " ",
+ rcnt, ptr, *ptr );
+ rcnt++;
+ ptr++;
+ }
+ printk(msg);
+}
+
+
+/* Verify the resource map and pdir state is consistent */
+static int
+sba_check_pdir(struct ioc *ioc, char *msg)
+{
+ u32 *rptr_end = (u32 *) &(ioc->res_map[ioc->res_size]);
+ u32 *rptr = (u32 *) ioc->res_map; /* resource map ptr */
+ u64 *pptr = ioc->pdir_base; /* pdir ptr */
+ uint pide = 0;
+
+ while (rptr < rptr_end) {
+ u32 rval = *rptr;
+ int rcnt = 32; /* number of bits we might check */
+
+ while (rcnt) {
+ /* Get last byte and highest bit from that */
+ u32 pde = ((u32) (((char *)pptr)[7])) << 24;
+ if ((rval ^ pde) & 0x80000000)
+ {
+ /*
+ ** BUMMER! -- res_map != pdir --
+ ** Dump rval and matching pdir entries
+ */
+ sba_dump_pdir_entry(ioc, msg, pide);
+ return(1);
+ }
+ rcnt--;
+ rval <<= 1; /* try the next bit */
+ pptr++;
+ pide++;
+ }
+ rptr++; /* look at next word of res_map */
+ }
+ /* It'd be nice if we always got here :^) */
+ return 0;
+}
+
+
+static void
+sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
+{
+ while (nents-- > 0) {
+ printk(" %d : %08lx/%05x %p/%05x\n",
+ nents,
+ (unsigned long) sg_dma_address(startsg),
+ sg_dma_len(startsg),
+ startsg->address, startsg->length);
+ startsg++;
+ }
+}
+
+#endif /* ASSERT_PDIR_SANITY */
+
+
+
+/*
+** One time initialization to let the world know the LBA was found.
+** This is the only routine which is NOT static.
+** Must be called exactly once before pci_init().
+*/
+void __init
+sba_init(void)
+{
+ sba_list = (struct sba_device *) NULL;
+ sba_count = 0;
+
+#ifdef DEBUG_SBA_INIT
+ sba_dump_ranges((char *) 0xFED00000L);
+#endif
+
+ register_driver(sba_drivers_for);
+}
+
+
+
+/**************************************************************
+*
+* I/O Pdir Resource Management
+*
+* Bits set in the resource map are in use.
+* Each bit can represent a number of pages.
+* LSbs represent lower addresses (IOVA's).
+*
+***************************************************************/
+#define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */
+
+/* Convert from IOVP to IOVA and vice versa. */
+#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir)))
+#define SBA_IOVP(ioc,iova) ((iova) & ioc->hint_mask_pdir)
+
+/* FIXME : review these macros to verify correctness and usage */
+#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT)
+#define MKIOVP(dma_hint,pide) (dma_addr_t)((long)(dma_hint) | ((long)(pide) << IOVP_SHIFT))
+#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
+
+#define RESMAP_MASK(n) (~0UL << (BITS_PER_LONG - (n)))
+#define RESMAP_IDX_MASK (sizeof(unsigned long) - 1)
+
+
+/*
+** Perf optimizations:
+** o search for log2(size) bits at a time.
+**
+** Search should use register width as "stride" to search the res_map.
+*/
+
+static SBA_INLINE unsigned long
+sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
+{
+ unsigned long *res_ptr = ioc->res_hint;
+ unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
+ unsigned long pide = ~0UL;
+
+ ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
+ ASSERT(res_ptr < res_end);
+ if (bits_wanted > (BITS_PER_LONG/2)) {
+ /* Search word at a time - no mask needed */
+ for(; res_ptr < res_end; ++res_ptr) {
+ if (*res_ptr == 0) {
+ *res_ptr = RESMAP_MASK(bits_wanted);
+ pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+ pide <<= 3; /* convert to bit address */
+ ASSERT(0 != pide);
+ break;
+ }
+ }
+ /* point to the next word on next pass */
+ res_ptr++;
+ ioc->res_bitshift = 0;
+ } else {
+ /*
+ ** Search the resource bit map on well-aligned values.
+ ** "o" is the alignment.
+ ** We need the alignment to invalidate I/O TLB using
+ ** SBA HW features in the unmap path.
+ */
+ unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT);
+ uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
+ unsigned long mask;
+
+ if (bitshiftcnt >= BITS_PER_LONG) {
+ bitshiftcnt = 0;
+ res_ptr++;
+ }
+ mask = RESMAP_MASK(bits_wanted) >> bitshiftcnt;
+
+ DBG_RES("sba_search_bitmap() o %ld %p", o, res_ptr);
+ while(res_ptr < res_end)
+ {
+ DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
+ ASSERT(0 != mask);
+ if(0 == ((*res_ptr) & mask)) {
+ *res_ptr |= mask; /* mark resources busy! */
+ pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+ pide <<= 3; /* convert to bit address */
+ pide += bitshiftcnt;
+ ASSERT(0 != pide);
+ break;
+ }
+ mask >>= o;
+ bitshiftcnt += o;
+ if (0 == mask) {
+ mask = RESMAP_MASK(bits_wanted);
+ bitshiftcnt=0;
+ res_ptr++;
+ }
+ }
+ /* look in the same word on the next pass */
+ ioc->res_bitshift = bitshiftcnt + bits_wanted;
+ }
+
+ /* wrapped ? */
+ ioc->res_hint = (res_end == res_ptr) ? (unsigned long *) ioc->res_map : res_ptr;
+ return (pide);
+}
+
+
+static int
+sba_alloc_range(struct ioc *ioc, size_t size)
+{
+ unsigned int pages_needed = size >> IOVP_SHIFT;
+#ifdef CONFIG_PROC_FS
+ unsigned long cr_start = mfctl(16);
+#endif
+ unsigned long pide;
+
+ ASSERT(pages_needed);
+ ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_needed < BITS_PER_LONG);
+ ASSERT(0 == (size & ~IOVP_MASK));
+
+ /*
+ ** "seek and ye shall find"...praying never hurts either...
+ ** ggg sacrifices another 710 to the computer gods.
+ */
+
+ pide = sba_search_bitmap(ioc, pages_needed);
+ if (pide >= (ioc->res_size << 3)) {
+ pide = sba_search_bitmap(ioc, pages_needed);
+ if (pide >= (ioc->res_size << 3))
+ panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", ioc->ioc_hpa);
+ }
+
+#ifdef ASSERT_PDIR_SANITY
+ /* verify the first enable bit is clear */
+ if(0x00 != ((u8 *) ioc->pdir_base)[pide*sizeof(u64) + 7]) {
+ sba_dump_pdir_entry(ioc, "sba_search_bitmap() botched it?", pide);
+ }
+#endif
+
+ DBG_RES("sba_alloc_range(%x) %d -> %lx hint %x/%x\n",
+ size, pages_needed, pide,
+ (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map),
+ ioc->res_bitshift );
+
+#ifdef CONFIG_PROC_FS
+ {
+ unsigned long cr_end = mfctl(16);
+ unsigned long tmp = cr_end - cr_start;
+ /* check for roll over */
+ cr_start = (cr_end < cr_start) ? -(tmp) : (tmp);
+ }
+ ioc->avg_search[ioc->avg_idx++] = cr_start;
+ ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1;
+
+ ioc->used_pages += pages_needed;
+#endif
+
+ return (pide);
+}
+
+
+/*
+** clear bits in the ioc's resource map
+*/
+static SBA_INLINE void
+sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
+{
+ unsigned long iovp = SBA_IOVP(ioc, iova);
+ unsigned int pide = PDIR_INDEX(iovp);
+ unsigned int ridx = pide >> 3; /* convert bit to byte address */
+ unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]);
+
+ int bits_not_wanted = size >> IOVP_SHIFT;
+
+ /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */
+ unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1));
+
+ DBG_RES("sba_free_range( ,%x,%x) %x/%lx %x %p %lx\n",
+ (uint) iova, size,
+ bits_not_wanted, m, pide, res_ptr, *res_ptr);
+
+#ifdef CONFIG_PROC_FS
+ ioc->used_pages -= bits_not_wanted;
+#endif
+
+ ASSERT(m != 0);
+ ASSERT(bits_not_wanted);
+ ASSERT((bits_not_wanted * IOVP_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(bits_not_wanted < BITS_PER_LONG);
+ ASSERT((*res_ptr & m) == m); /* verify same bits are set */
+ *res_ptr &= ~m;
+}
+
+
+/**************************************************************
+*
+* "Dynamic DMA Mapping" support (aka "Coherent I/O")
+*
+***************************************************************/
+
+#define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir)
+
+
+typedef unsigned long space_t;
+#define KERNEL_SPACE 0
+
+/*
+* SBA Mapping Routine
+*
+* Given a virtual address (vba, arg2) and space id, (sid, arg1)
+* sba_io_pdir_entry() loads the I/O PDIR entry pointed to by
+* pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as
+* shown below (MSB == bit 0):
+*
+* 0 19 51 55 63
+* +-+---------------------+----------------------------------+----+--------+
+* |V| U | PPN[43:12] | U | VI |
+* +-+---------------------+----------------------------------+----+--------+
+*
+* V == Valid Bit
+* U == Unused
+* PPN == Physical Page Number
+* VI == Virtual Index (aka Coherent Index)
+*
+* The physical address fields are filled with the results of the LPA
+* instruction. The virtual index field is filled with the results of
+* of the LCI (Load Coherence Index) instruction. The 8 bits used for
+* the virtual index are bits 12:19 of the value returned by LCI.
+*
+* We need to pre-swap the bytes since PCX-W is Big Endian.
+*/
+
+void SBA_INLINE
+sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba)
+{
+ u64 pa; /* physical address */
+ register unsigned ci; /* coherent index */
+
+ /* We currently only support kernel addresses */
+ ASSERT(sid == 0);
+ ASSERT(((unsigned long) vba & 0xc0000000UL) == 0xc0000000UL);
+
+ pa = virt_to_phys(vba);
+ pa &= ~4095ULL; /* clear out offset bits */
+
+ mtsp(sid,1);
+ asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+ pa |= (ci >> 12) & 0xff; /* move CI (8 bits) into lowest byte */
+
+ pa |= 0x8000000000000000ULL; /* set "valid" bit */
+ *pdir_ptr = cpu_to_le64(pa); /* swap and store into I/O Pdir */
+}
+
+
+/***********************************************************
+ * The Ike PCOM (Purge Command Register) is to purge
+ * stale entries in the IO TLB when unmapping entries.
+ *
+ * The PCOM register supports purging of multiple pages, with a minium
+ * of 1 page and a maximum of 2GB. Hardware requires the address be
+ * aligned to the size of the range being purged. The size of the range
+ * must be a power of 2.
+ ***********************************************************/
+static SBA_INLINE void
+sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
+{
+ u32 iovp = (u32) SBA_IOVP(ioc,iova);
+
+ /* Even though this is a big-endian machine, the entries
+ ** in the iopdir are swapped. That's why we clear the byte
+ ** at +7 instead of at +0.
+ */
+ int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
+
+ /* Must be non-zero and rounded up */
+ ASSERT(byte_cnt > 0);
+ ASSERT(0 == (byte_cnt & ~IOVP_MASK));
+
+#ifdef ASSERT_PDIR_SANITY
+ /* Assert first pdir entry is set */
+ if (0x80 != (((u8 *) ioc->pdir_base)[off])) {
+ sba_dump_pdir_entry(ioc,"sba_mark_invalid()", PDIR_INDEX(iovp));
+ }
+#endif
+
+ if (byte_cnt <= IOVP_SIZE)
+ {
+ ASSERT( off < ioc->pdir_size);
+
+ iovp |= IOVP_SHIFT; /* set "size" field for PCOM */
+
+ /*
+ ** clear I/O PDIR entry "valid" bit
+ ** Do NOT clear the rest - save it for debugging.
+ ** We should only clear bits that have previously
+ ** been enabled.
+ */
+ ((u8 *)(ioc->pdir_base))[off] = 0;
+ } else {
+ u32 t = get_order(byte_cnt) + PAGE_SHIFT;
+
+ iovp |= t;
+ ASSERT(t <= 31); /* 2GB! Max value of "size" field */
+
+ do {
+ /* verify this pdir entry is enabled */
+ ASSERT(0x80 == (((u8 *) ioc->pdir_base)[off] & 0x80));
+ /* clear I/O Pdir entry "valid" bit first */
+ ((u8 *)(ioc->pdir_base))[off] = 0;
+ off += sizeof(u64);
+ byte_cnt -= IOVP_SIZE;
+ } while (byte_cnt > 0);
+ }
+
+ WRITE_REG32(iovp, ioc->ioc_hpa+IOC_PCOM);
+}
+
+static int
+sba_dma_supported( struct pci_dev *dev, dma_addr_t mask)
+{
+ if (dev == NULL) {
+ printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+ BUG();
+ return(0);
+ }
+
+ dev->dma_mask = mask; /* save it */
+
+ /* only support PCI devices */
+ return((int) (mask >= 0xffffffff));
+}
+
+
+/*
+** map_single returns a fully formed IOVA
+*/
+static dma_addr_t
+sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+{
+ struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */
+ unsigned long flags;
+ dma_addr_t iovp;
+ dma_addr_t offset;
+ u64 *pdir_start;
+ int pide;
+
+ ASSERT(size > 0);
+
+ /* save offset bits */
+ offset = ((dma_addr_t) addr) & ~IOVP_MASK;
+
+ /* round up to nearest IOVP_SIZE */
+ size = (size + offset + ~IOVP_MASK) & IOVP_MASK;
+
+ spin_lock_irqsave(&ioc->res_lock, flags);
+#ifdef ASSERT_PDIR_SANITY
+ sba_check_pdir(ioc,"Check before sba_map_single()");
+#endif
+
+#ifdef CONFIG_PROC_FS
+ ioc->msingle_calls++;
+ ioc->msingle_pages += size >> IOVP_SHIFT;
+#endif
+ pide = sba_alloc_range(ioc, size);
+ iovp = (dma_addr_t) pide << IOVP_SHIFT;
+
+ DBG_RUN("sba_map_single() 0x%p -> 0x%lx", addr, (long) iovp | offset);
+
+ pdir_start = &(ioc->pdir_base[pide]);
+
+ while (size > 0) {
+ ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */
+ sba_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long) addr);
+
+ DBG_RUN(" pdir 0x%p %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ pdir_start,
+ (u8) (((u8 *) pdir_start)[7]),
+ (u8) (((u8 *) pdir_start)[6]),
+ (u8) (((u8 *) pdir_start)[5]),
+ (u8) (((u8 *) pdir_start)[4]),
+ (u8) (((u8 *) pdir_start)[3]),
+ (u8) (((u8 *) pdir_start)[2]),
+ (u8) (((u8 *) pdir_start)[1]),
+ (u8) (((u8 *) pdir_start)[0])
+ );
+
+ addr += IOVP_SIZE;
+ size -= IOVP_SIZE;
+ pdir_start++;
+ }
+ /* form complete address */
+#ifdef ASSERT_PDIR_SANITY
+ sba_check_pdir(ioc,"Check after sba_map_single()");
+#endif
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG);
+}
+
+
+static void
+sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction)
+{
+#ifdef FIXME
+/* Multi-IOC (ie N-class) : need to lookup IOC from dev
+** o If we can't know about lba PCI data structs, that eliminates ->sysdata.
+** o walking up pcidev->parent dead ends at elroy too
+** o leaves hashing dev->bus->number into some lookup.
+** (may only work for N-class)
+** o use (struct pci_hba) and put fields in there for DMA.
+** (ioc and per device dma_hint.)
+**
+** Last one seems the clearest and most promising.
+** sba_dma_supported() fill in those fields when the driver queries
+** the system for support.
+*/
+ struct ioc *ioc = (struct ioc *) ((struct pci_hba *) (dev->sysdata))->dma_data;
+#else
+ struct ioc *ioc = &sba_list->ioc[0];
+#endif
+
+ unsigned long flags;
+ dma_addr_t offset;
+ offset = iova & ~IOVP_MASK;
+
+ DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size);
+
+ iova ^= offset; /* clear offset bits */
+ size += offset;
+ size = ROUNDUP(size, IOVP_SIZE);
+
+ ASSERT(0 != iova);
+
+ spin_lock_irqsave(&ioc->res_lock, flags);
+#ifdef CONFIG_PROC_FS
+ ioc->usingle_calls++;
+ ioc->usingle_pages += size >> IOVP_SHIFT;
+#endif
+#ifdef DELAYED_RESOURCE_CNT
+ if (ioc->saved_cnt < DELAYED_RESOURCE_CNT) {
+ ioc->saved_iova[ioc->saved_cnt] = iova;
+ ioc->saved_size[ioc->saved_cnt] = size;
+ ioc_saved_cnt++;
+ } else {
+ do {
+#endif
+ sba_mark_invalid(ioc, iova, size);
+ sba_free_range(ioc, iova, size);
+
+#ifdef DELAYED_RESOURCE_CNT
+ ioc->saved_cnt--;
+ iova = ioc->saved_iova[ioc->saved_cnt];
+ size = ioc->saved_size[ioc->saved_cnt];
+ } while (ioc->saved_cnt)
+
+ /* flush purges */
+ (void) (volatile) READ_REG32(ioc->ioc_hpa+IOC_PCOM);
+ }
+#else
+ /* flush purges */
+ READ_REG32(ioc->ioc_hpa+IOC_PCOM);
+#endif
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+}
+
+
+static void *
+sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+{
+ void *ret;
+
+ if (!hwdev) {
+ /* only support PCI */
+ *dma_handle = 0;
+ return 0;
+ }
+
+ ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size));
+
+ if (ret) {
+ memset(ret, 0, size);
+ *dma_handle = sba_map_single(hwdev, ret, size, 0);
+ }
+
+ return ret;
+}
+
+
+static void
+sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ sba_unmap_single(hwdev, dma_handle, size, 0);
+ free_pages((unsigned long) vaddr, get_order(size));
+}
+
+/*
+** Two address ranges are "virtually contiguous" iff:
+** 1) end of prev == start of next, or... append case
+** 3) end of next == start of prev prepend case
+**
+** and they are DMA contiguous *iff*:
+** 2) end of prev and start of next are both on a page boundry
+**
+** (shift left is a quick trick to mask off upper bits)
+*/
+#define DMA_CONTIG(__X, __Y) \
+ (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL)
+
+/*
+** Assumption is two transactions are mutually exclusive.
+** ie both go to different parts of memory.
+** If both are true, then both transaction are on the same page.
+*/
+#define DMA_SAME_PAGE(s1,e1,s2,e2) \
+ ( ((((s1) ^ (s2)) >> PAGE_SHIFT) == 0) \
+ && ((((e1) ^ (e2)) >> PAGE_SHIFT) == 0) )
+
+/*
+** Since 0 is a valid pdir_base index value, can't use that
+** to determine if a value is valid or not. Use a flag to indicate
+** the SG list entry contains a valid pdir index.
+*/
+#define PIDE_FLAG 0x80000000UL
+
+#ifdef DEBUG_LARGE_SG_ENTRIES
+int dump_run_sg = 0;
+#endif
+
+static SBA_INLINE int
+sba_fill_pdir(
+ struct ioc *ioc,
+ struct scatterlist *startsg,
+ int nents)
+{
+ struct scatterlist *dma_sg = startsg; /* pointer to current DMA */
+ int n_mappings = 0;
+ u64 *pdirp = 0;
+ unsigned long dma_offset = 0;
+
+ dma_sg--;
+ while (nents-- > 0) {
+ int cnt = sg_dma_len(startsg);
+ sg_dma_len(startsg) = 0;
+
+#ifdef DEBUG_LARGE_SG_ENTRIES
+ if (dump_run_sg)
+ printk(" %d : %08lx/%05x %p/%05x\n",
+ nents,
+ (unsigned long) sg_dma_address(startsg), cnt,
+ startsg->address, startsg->length
+ );
+#else
+ DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n",
+ nents,
+ (unsigned long) sg_dma_address(startsg), cnt,
+ startsg->address, startsg->length
+ );
+#endif
+ /*
+ ** Look for the start of a new DMA stream
+ */
+ if (sg_dma_address(startsg) & PIDE_FLAG) {
+ u32 pide = sg_dma_address(startsg) & ~PIDE_FLAG;
+ dma_offset = (unsigned long) pide & ~IOVP_MASK;
+ pide >>= IOVP_SHIFT;
+ pdirp = &(ioc->pdir_base[pide]);
+ sg_dma_address(startsg) = 0;
+ ++dma_sg;
+ sg_dma_address(dma_sg) = (pide << IOVP_SHIFT) + dma_offset;
+ n_mappings++;
+ }
+
+ /*
+ ** Look for a VCONTIG chunk
+ */
+ if (cnt) {
+ unsigned long vaddr = (unsigned long) startsg->address;
+ ASSERT(pdirp);
+
+ sg_dma_len(dma_sg) += cnt;
+ cnt += dma_offset;
+ dma_offset=0; /* only want offset on first chunk */
+ cnt = ROUNDUP(cnt, IOVP_SIZE);
+#ifdef CONFIG_PROC_FS
+ ioc->msg_pages += cnt >> IOVP_SHIFT;
+#endif
+ do {
+ sba_io_pdir_entry(pdirp, KERNEL_SPACE, vaddr);
+ vaddr += IOVP_SIZE;
+ cnt -= IOVP_SIZE;
+ pdirp++;
+ } while (cnt > 0);
+ }
+ startsg++;
+ }
+#ifdef DEBUG_LARGE_SG_ENTRIES
+ dump_run_sg = 0;
+#endif
+ return(n_mappings);
+}
+
+
+
+/*
+** First pass is to walk the SG list and determine where the breaks are
+** in the DMA stream. Allocates PDIR entries but does not fill them.
+** Returns the number of DMA chunks.
+**
+** Doing the fill seperate from the coalescing/allocation keeps the
+** code simpler. Future enhancement could make one pass through
+** the sglist do both.
+*/
+static SBA_INLINE int
+sba_coalesce_chunks( struct ioc *ioc,
+ struct scatterlist *startsg,
+ int nents)
+{
+ int n_mappings = 0;
+
+ while (nents > 0) {
+ struct scatterlist *dma_sg; /* next DMA stream head */
+ unsigned long dma_offset, dma_len; /* start/len of DMA stream */
+ struct scatterlist *chunksg; /* virtually contig chunk head */
+ unsigned long chunk_addr, chunk_len; /* start/len of VCONTIG chunk */
+
+ /*
+ ** Prepare for first/next DMA stream
+ */
+ dma_sg = chunksg = startsg;
+ dma_len = chunk_len = startsg->length;
+ chunk_addr = (unsigned long) startsg->address;
+ dma_offset = 0UL;
+
+ /*
+ ** This loop terminates one iteration "early" since
+ ** it's always looking one "ahead".
+ */
+ while (--nents > 0) {
+ /* ptr to coalesce prev and next */
+ struct scatterlist *prev_sg = startsg;
+ unsigned long prev_end = (unsigned long) prev_sg->address + prev_sg->length;
+ unsigned long current_end;
+
+ /* PARANOID: clear entries */
+ sg_dma_address(startsg) = 0;
+ sg_dma_len(startsg) = 0;
+
+ /* Now start looking ahead */
+ startsg++;
+ current_end = (unsigned long) startsg->address + startsg->length;
+
+ /*
+ ** First look for virtually contiguous blocks.
+ ** PARISC needs this since it's cache is virtually
+ ** indexed and we need the associated virtual
+ ** address for each I/O address we map.
+ **
+ ** 1) can we *prepend* the next transaction?
+ */
+ if (current_end == (unsigned long) prev_sg->address)
+ {
+ /* prepend : get new offset */
+ chunksg = startsg;
+ chunk_addr = (unsigned long) prev_sg->address;
+ chunk_len += startsg->length;
+ dma_len += startsg->length;
+ continue;
+ }
+
+ /*
+ ** 2) or append the next transaction?
+ */
+ if (prev_end == (unsigned long) startsg->address)
+ {
+ chunk_len += startsg->length;
+ dma_len += startsg->length;
+ continue;
+ }
+
+#ifdef DEBUG_LARGE_SG_ENTRIES
+ dump_run_sg = (chunk_len > IOVP_SIZE);
+#endif
+ /*
+ ** Not virtually contigous.
+ ** Terminate prev chunk.
+ ** Start a new chunk.
+ **
+ ** Once we start a new VCONTIG chunk, the offset
+ ** can't change. And we need the offset from the first
+ ** chunk - not the last one. Ergo Successive chunks
+ ** must start on page boundaries and dove tail
+ ** with it's predecessor.
+ */
+ sg_dma_len(prev_sg) = chunk_len;
+
+ chunk_len = startsg->length;
+ dma_offset |= (chunk_addr & ~IOVP_MASK);
+ ASSERT((0 == (chunk_addr & ~IOVP_MASK)) ||
+ (dma_offset == (chunk_addr & ~IOVP_MASK)));
+
+#if 0
+ /*
+ ** 4) do the chunks end/start on page boundaries?
+ ** Easier than 3 since no offsets are involved.
+ */
+ if (DMA_CONTIG(prev_end, startsg->address))
+ {
+ /*
+ ** Yes.
+ ** Reset chunk ptr.
+ */
+ chunksg = startsg;
+ chunk_addr = (unsigned long) startsg->address;
+
+ continue;
+ } else
+#endif
+ {
+ break;
+ }
+ }
+
+ /*
+ ** End of DMA Stream
+ ** Terminate chunk.
+ ** Allocate space for DMA stream.
+ */
+ sg_dma_len(startsg) = chunk_len;
+ dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK;
+ sg_dma_address(dma_sg) =
+ PIDE_FLAG
+ | (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT)
+ | dma_offset;
+ n_mappings++;
+ }
+
+ return n_mappings;
+}
+
+
+/*
+** And this algorithm still generally only ends up coalescing entries
+** that happens to be on the same page due to how sglists are assembled.
+*/
+static int
+sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */
+ int coalesced, filled = 0;
+ unsigned long flags;
+
+ DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
+
+ /* Fast path single entry scatterlists. */
+ if (nents == 1) {
+ sg_dma_address(sglist)= sba_map_single(dev, sglist->address,
+ sglist->length, direction);
+ sg_dma_len(sglist)= sglist->length;
+ return 1;
+ }
+
+ spin_lock_irqsave(&ioc->res_lock, flags);
+
+#ifdef ASSERT_PDIR_SANITY
+ if (sba_check_pdir(ioc,"Check before sba_map_sg()"))
+ {
+ sba_dump_sg(ioc, sglist, nents);
+ panic("Check before sba_map_sg()");
+ }
+#endif
+
+#ifdef CONFIG_PROC_FS
+ ioc->msg_calls++;
+#endif
+
+ /*
+ ** First coalesce the chunks and allocate I/O pdir space
+ **
+ ** If this is one DMA stream, we can properly map using the
+ ** correct virtual address associated with each DMA page.
+ ** w/o this association, we wouldn't have coherent DMA!
+ ** Access to the virtual address is what forces a two pass algorithm.
+ */
+ coalesced = sba_coalesce_chunks(ioc, sglist, nents);
+
+ /*
+ ** Program the I/O Pdir
+ **
+ ** map the virtual addresses to the I/O Pdir
+ ** o dma_address will contain the pdir index
+ ** o dma_len will contain the number of bytes to map
+ ** o address contains the virtual address.
+ */
+ filled = sba_fill_pdir(ioc, sglist, nents);
+
+#ifdef ASSERT_PDIR_SANITY
+ if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
+ {
+ sba_dump_sg(ioc, sglist, nents);
+ panic("Check after sba_map_sg()\n");
+ }
+#endif
+
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+
+ ASSERT(coalesced == filled);
+ DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled);
+
+ return filled;
+}
+
+
+static void
+sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */
+#ifdef ASSERT_PDIR_SANITY
+ unsigned long flags;
+#endif
+
+ DBG_RUN_SG("%s() START %d entries, %p,%x\n",
+ __FUNCTION__, nents, sglist->address, sglist->length);
+
+#ifdef CONFIG_PROC_FS
+ ioc->usg_calls++;
+#endif
+
+#ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+ sba_check_pdir(ioc,"Check before sba_unmap_sg()");
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+#endif
+
+ while (sg_dma_len(sglist) && nents--) {
+
+#ifdef CONFIG_PROC_FS
+ ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
+#endif
+ sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
+ ++sglist;
+ }
+
+ DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents);
+
+#ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+ sba_check_pdir(ioc,"Check after sba_unmap_sg()");
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+#endif
+
+}
+
+static struct pci_dma_ops sba_ops = {
+ sba_dma_supported,
+ sba_alloc_consistent, /* allocate cacheable host mem */
+ sba_free_consistent, /* release cacheable host mem */
+ sba_map_single,
+ sba_unmap_single,
+ sba_map_sg,
+ sba_unmap_sg,
+ NULL, /* dma_sync_single */
+ NULL /* dma_sync_sg */
+};
+
+
+/**************************************************************************
+**
+** SBA PAT PDC support
+**
+** o call pdc_pat_cell_module()
+** o store ranges in PCI "resource" structures
+**
+**************************************************************************/
+
+static void
+sba_get_pat_resources(struct sba_device *sba_dev)
+{
+#if 0
+/*
+** TODO/REVISIT/FIXME: support for directed ranges requires calls to
+** PAT PDC to program the SBA/LBA directed range registers...this
+** burden may fall on the LBA code since it directly supports the
+** PCI subsystem. It's not clear yet. - ggg
+*/
+PAT_MOD(mod)->mod_info.mod_pages = PAT_GET_MOD_PAGES(temp);
+ FIXME : ???
+PAT_MOD(mod)->mod_info.dvi = PAT_GET_DVI(temp);
+ Tells where the dvi bits are located in the address.
+PAT_MOD(mod)->mod_info.ioc = PAT_GET_IOC(temp);
+ FIXME : ???
+#endif
+}
+
+
+/**************************************************************
+*
+* Initialization and claim
+*
+***************************************************************/
+
+
+static void
+sba_ioc_init(struct ioc *ioc)
+{
+ extern unsigned long mem_max; /* arch.../setup.c */
+ extern void lba_init_iregs(void *, u32, u32); /* arch.../lba_pci.c */
+
+ u32 iova_space_size, iova_space_mask;
+ void * pdir_base;
+ int pdir_size, iov_order;
+
+ /*
+ ** Determine IOVA Space size from memory size.
+ ** Using "mem_max" is a kluge.
+ **
+ ** Ideally, PCI drivers would register the maximum number
+ ** of DMA they can have outstanding for each device they
+ ** own. Next best thing would be to guess how much DMA
+ ** can be outstanding based on PCI Class/sub-class. Both
+ ** methods still require some "extra" to support PCI
+ ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
+ **
+ ** While we have 32-bits "IOVA" space, top two 2 bits are used
+ ** for DMA hints - ergo only 30 bits max.
+ */
+ /* limit IOVA space size to 1MB-1GB */
+ if (mem_max < (sba_mem_ratio*1024*1024)) {
+ iova_space_size = 1024*1024;
+#ifdef __LP64__
+ } else if (mem_max > (sba_mem_ratio*512*1024*1024)) {
+ iova_space_size = 512*1024*1024;
+#endif
+ } else {
+ iova_space_size = (u32) (mem_max/sba_mem_ratio);
+ }
+
+ /*
+ ** iova space must be log2() in size.
+ ** thus, pdir/res_map will also be log2().
+ */
+ iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT));
+ ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */
+ ASSERT(iov_order >= (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */
+ iova_space_size = 1 << (iov_order + IOVP_SHIFT);
+
+ ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
+
+ ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */
+
+ /* Verify it's a power of two */
+ ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
+
+ DBG_INIT("%s() hpa 0x%p mem %dMBIOV %dMB (%d bits) PDIR size 0x%0x",
+ __FUNCTION__, ioc->ioc_hpa, (int) (mem_max>>20),
+ iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size);
+
+ /* FIXME : DMA HINTs not used */
+ ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
+ ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
+
+ ioc->pdir_base =
+ pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
+ if (NULL == pdir_base)
+ {
+ panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__);
+ }
+ memset(pdir_base, 0, pdir_size);
+
+ DBG_INIT("sba_ioc_init() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n",
+ pdir_base, pdir_size,
+ ioc->hint_shift_pdir, ioc->hint_mask_pdir);
+
+ ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base);
+ WRITE_REG64(virt_to_phys(pdir_base), (u64 *)(ioc->ioc_hpa+IOC_PDIR_BASE));
+
+ DBG_INIT(" base %p\n", pdir_base);
+
+ /* build IMASK for IOC and Elroy */
+ iova_space_mask = 0xffffffff;
+ iova_space_mask <<= (iov_order + PAGE_SHIFT);
+
+ /*
+ ** On C3000 w/512MB mem, HP-UX 10.20 reports:
+ ** ibase=0, imask=0xFE000000, size=0x2000000.
+ */
+ ioc->ibase = IOC_IOVA_SPACE_BASE | 1; /* bit 0 == enable bit */
+ ioc->imask = iova_space_mask; /* save it */
+
+ DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", __FUNCTION__,
+ ioc->ibase, ioc->imask);
+
+ /*
+ ** FIXME: Hint registers are programmed with default hint
+ ** values during boot, so hints should be sane even if we
+ ** can't reprogram them the way drivers want.
+ */
+
+ /*
+ ** setup Elroy IBASE/IMASK registers as well.
+ */
+ lba_init_iregs(ioc->ioc_hpa, ioc->ibase, ioc->imask);
+
+ /*
+ ** Program the IOC's ibase and enable IOVA translation
+ */
+ WRITE_REG32(ioc->ibase, ioc->ioc_hpa+IOC_IBASE);
+ WRITE_REG32(ioc->imask, ioc->ioc_hpa+IOC_IMASK);
+
+ /* Set I/O PDIR Page size to 4K */
+ WRITE_REG32(0, ioc->ioc_hpa+IOC_TCNFG);
+
+ /*
+ ** Clear I/O TLB of any possible entries.
+ ** (Yes. This is a it paranoid...but so what)
+ */
+ WRITE_REG32(0 | 31, ioc->ioc_hpa+IOC_PCOM);
+
+ DBG_INIT("%s() DONE\n", __FUNCTION__);
+}
+
+
+
+/**************************************************************************
+**
+** SBA initialization code (HW and SW)
+**
+** o identify SBA chip itself
+** o initialize SBA chip modes (HardFail)
+** o initialize SBA chip modes (HardFail)
+** o FIXME: initialize DMA hints for reasonable defaults
+**
+**************************************************************************/
+
+static void
+sba_hw_init(struct sba_device *sba_dev)
+{
+ int i;
+ int num_ioc;
+ u32 ioc_ctl;
+
+ ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL);
+ DBG_INIT("%s() hpa 0x%p ioc_ctl 0x%x ->", __FUNCTION__, sba_dev->sba_hpa, ioc_ctl );
+ ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC);
+ ASSERT(ioc_ctl & IOC_CTRL_TE); /* astro: firmware enables this */
+
+ WRITE_REG32(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
+
+#ifdef SBA_DEBUG_INIT
+ ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL);
+ DBG_INIT(" 0x%x\n", ioc_ctl );
+#endif
+
+ if (IS_ASTRO(sba_dev->iodc)) {
+ /* PAT_PDC (L-class) also reports the same goofy base */
+ sba_dev->ioc[0].ioc_hpa = (char *) ASTRO_IOC_OFFSET;
+ num_ioc = 1;
+ } else {
+ sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0;
+ num_ioc = 2;
+ }
+
+ sba_dev->num_ioc = num_ioc;
+ for( i = 0; i < num_ioc; i++)
+ {
+ (unsigned long) sba_dev->ioc[i].ioc_hpa += (unsigned long) sba_dev->sba_hpa + IKE_IOC_OFFSET(i);
+
+ /*
+ ** Make sure the box crashes if we get any errors on a rope.
+ */
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
+
+ /* flush out the writes */
+ READ_REG32(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
+
+ sba_ioc_init(&(sba_dev->ioc[i]));
+ }
+}
+
+static void
+sba_common_init(struct sba_device *sba_dev)
+{
+ int i;
+
+ /* add this one to the head of the list (order doesn't matter)
+ ** This will be useful for debugging - especially if we get coredumps
+ */
+ sba_dev->next = sba_list;
+ sba_list = sba_dev;
+ sba_count++;
+
+ for(i=0; i< sba_dev->num_ioc; i++) {
+ int res_size;
+#ifdef CONFIG_DMB_TRAP
+ extern void iterate_pages(unsigned long , unsigned long ,
+ void (*)(pte_t * , unsigned long),
+ unsigned long );
+ void set_data_memory_break(pte_t * , unsigned long);
+#endif
+ /* resource map size dictated by pdir_size */
+ res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */
+ res_size >>= 3; /* convert bit count to byte count */
+ DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, res_size);
+
+ sba_dev->ioc[i].res_size = res_size;
+ sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size));
+
+#ifdef CONFIG_DMB_TRAP
+ iterate_pages( sba_dev->ioc[i].res_map, res_size,
+ set_data_memory_break, 0);
+#endif
+
+ if (NULL == sba_dev->ioc[i].res_map)
+ {
+ panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__ );
+ }
+
+ memset(sba_dev->ioc[i].res_map, 0, res_size);
+ /* next available IOVP - circular search */
+ sba_dev->ioc[i].res_hint = (unsigned long *)
+ &(sba_dev->ioc[i].res_map[L1_CACHE_BYTES]);
+
+#ifdef ASSERT_PDIR_SANITY
+ /* Mark first bit busy - ie no IOVA 0 */
+ sba_dev->ioc[i].res_map[0] = 0x80;
+ sba_dev->ioc[i].pdir_base[0] = 0xeeffc0addbba0080ULL;
+#endif
+
+#ifdef CONFIG_DMB_TRAP
+ iterate_pages( sba_dev->ioc[i].res_map, res_size,
+ set_data_memory_break, 0);
+ iterate_pages( sba_dev->ioc[i].pdir_base, sba_dev->ioc[i].pdir_size,
+ set_data_memory_break, 0);
+#endif
+
+ DBG_INIT("sba_common_init() %d res_map %x %p\n",
+ i, res_size, sba_dev->ioc[i].res_map);
+ }
+
+ sba_dev->sba_lock = SPIN_LOCK_UNLOCKED;
+}
+
+#ifdef CONFIG_PROC_FS
+static int sba_proc_info(char *buf, char **start, off_t offset, int len)
+{
+ struct sba_device *sba_dev = sba_list;
+/* FIXME: Multi-IOC support broken! */
+ struct ioc *ioc = &sba_dev->ioc[0];
+ int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
+ unsigned long i = 0, avg = 0, min, max;
+
+ sprintf(buf, "%s rev %d.%d\n",
+ parisc_getHWdescription(sba_dev->iodc->hw_type,
+ sba_dev->iodc->hversion, sba_dev->iodc->sversion),
+ (sba_dev->hw_rev & 0x7) + 1,
+ (sba_dev->hw_rev & 0x18) >> 3
+ );
+ sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n",
+ buf,
+ ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits per byte */
+ total_pages); /* 8 bits per byte */
+
+ sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf,
+ total_pages - ioc->used_pages, ioc->used_pages,
+ (int) (ioc->used_pages * 100 / total_pages));
+
+ sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
+ buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
+
+ min = max = ioc->avg_search[0];
+ for (i = 0; i < SBA_SEARCH_SAMPLE; i++) {
+ avg += ioc->avg_search[i];
+ if (ioc->avg_search[i] > max) max = ioc->avg_search[i];
+ if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
+ }
+ avg /= SBA_SEARCH_SAMPLE;
+ sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+ buf, min, avg, max);
+
+ sprintf(buf, "%spci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n",
+ buf, ioc->msingle_calls, ioc->msingle_pages,
+ (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
+
+ /* KLUGE - unmap_sg calls unmap_single for each mapped page */
+ min = ioc->usingle_calls - ioc->usg_calls;
+ max = ioc->usingle_pages - ioc->usg_pages;
+ sprintf(buf, "%spci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
+ buf, min, max,
+ (int) ((max * 1000)/min));
+
+ sprintf(buf, "%spci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
+ buf, ioc->msg_calls, ioc->msg_pages,
+ (int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
+
+ sprintf(buf, "%spci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
+ buf, ioc->usg_calls, ioc->usg_pages,
+ (int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
+
+ return strlen(buf);
+}
+
+static int
+sba_resource_map(char *buf, char **start, off_t offset, int len)
+{
+ struct sba_device *sba_dev = sba_list;
+ struct ioc *ioc = &sba_dev->ioc[0];
+ unsigned long *res_ptr = (unsigned long *)ioc->res_map;
+ int i;
+
+ for(i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr) {
+ if ((i & 7) == 0)
+ strcat(buf,"\n ");
+ sprintf(buf, "%s %08lx", buf, *res_ptr);
+ }
+ strcat(buf, "\n");
+
+ return strlen(buf);
+}
+#endif
+
+/*
+** Determine if lba should claim this chip (return 0) or not (return 1).
+** If so, initialize the chip and tell other partners in crime they
+** have work to do.
+*/
+int
+sba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ struct sba_device *sba_dev;
+ u32 func_class;
+ int i;
+
+ if (IS_ASTRO(d)) {
+ static char astro_rev[]="Astro ?.?";
+
+ /* Read HW Rev First */
+ func_class = READ_REG32(d->hpa);
+
+ astro_rev[6] = '1' + (char) (func_class & 0x7);
+ astro_rev[8] = '0' + (char) ((func_class & 0x18) >> 3);
+ dri->version = astro_rev;
+ } else {
+ static char ike_rev[]="Ike rev ?";
+
+ /* Read HW Rev First */
+ func_class = READ_REG32(d->hpa + SBA_FCLASS);
+
+ ike_rev[8] = '0' + (char) (func_class & 0xff);
+ dri->version = ike_rev;
+ }
+
+ printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+
+ sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
+ if (NULL == sba_dev)
+ {
+ printk(MODULE_NAME " - couldn't alloc sba_device\n");
+ return(1);
+ }
+ memset(sba_dev, 0, sizeof(struct sba_device));
+ for(i=0; i<MAX_IOC; i++)
+ spin_lock_init(&(sba_dev->ioc[i].res_lock));
+
+
+ sba_dev->hw_rev = func_class;
+ sba_dev->iodc = d;
+ sba_dev->sba_hpa = d->hpa; /* faster access */
+
+ sba_get_pat_resources(sba_dev);
+ sba_hw_init(sba_dev);
+ sba_common_init(sba_dev);
+
+ hppa_dma_ops = &sba_ops;
+
+#ifdef CONFIG_PROC_FS
+ if (IS_ASTRO(d)) {
+ create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info);
+ } else {
+ create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info);
+ }
+ create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map);
+#endif
+ return 0;
+}
diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c
new file mode 100644
index 000000000..81156de7d
--- /dev/null
+++ b/arch/parisc/kernel/semaphore.c
@@ -0,0 +1,239 @@
+/*
+ * Just taken from alpha implementation.
+ * This can't work well, perhaps.
+ */
+/*
+ * Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit. ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore. The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+ wake_one_more(sem);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function. Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible. This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return. If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+
+#define DOWN_HEAD(task_state) \
+ \
+ \
+ current->state = (task_state); \
+ add_wait_queue(&sem->wait, &wait); \
+ \
+ /* \
+ * Ok, we're set up. sem->count is known to be less than zero \
+ * so we must wait. \
+ * \
+ * We can let go the lock for purposes of waiting. \
+ * We re-acquire it after awaking so as to protect \
+ * all semaphore operations. \
+ * \
+ * If "up()" is called before we call waking_non_zero() then \
+ * we will catch it right away. If it is called later then \
+ * we will have to go through a wakeup cycle to catch it. \
+ * \
+ * Multiple waiters contend for the semaphore lock to see \
+ * who gets to gate through and who has to wait some more. \
+ */ \
+ for (;;) {
+
+#define DOWN_TAIL(task_state) \
+ current->state = (task_state); \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+ if (waking_non_zero(sem))
+ break;
+ schedule();
+ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int ret = 0;
+
+ DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+ ret = waking_non_zero_interruptible(sem, current);
+ if (ret)
+ {
+ if (ret == 1)
+ /* ret != 0 only if we get interrupted -arca */
+ ret = 0;
+ break;
+ }
+ schedule();
+ DOWN_TAIL(TASK_INTERRUPTIBLE)
+ return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+ return waking_non_zero_trylock(sem);
+}
+
+
+/* Wait for the lock to become unbiased. Readers
+ * are non-exclusive. =)
+ */
+void down_read_failed(struct rw_semaphore *sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ __up_read(sem); /* this takes care of granting the lock */
+
+ add_wait_queue(&sem->wait, &wait);
+
+ while (atomic_read(&sem->count) < 0) {
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
+ if (atomic_read(&sem->count) >= 0)
+ break;
+ schedule();
+ }
+
+ remove_wait_queue(&sem->wait, &wait);
+ current->state = TASK_RUNNING;
+}
+
+void down_read_failed_biased(struct rw_semaphore *sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */
+
+ for (;;) {
+ if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
+ break;
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
+ if (!sem->read_bias_granted)
+ schedule();
+ }
+
+ remove_wait_queue(&sem->wait, &wait);
+ current->state = TASK_RUNNING;
+}
+
+
+/* Wait for the lock to become unbiased. Since we're
+ * a writer, we'll make ourselves exclusive.
+ */
+void down_write_failed(struct rw_semaphore *sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ __up_write(sem); /* this takes care of granting the lock */
+
+ add_wait_queue_exclusive(&sem->wait, &wait);
+
+ while (atomic_read(&sem->count) < 0) {
+ set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+ if (atomic_read(&sem->count) >= 0)
+ break; /* we must attempt to aquire or bias the lock */
+ schedule();
+ }
+
+ remove_wait_queue(&sem->wait, &wait);
+ current->state = TASK_RUNNING;
+}
+
+void down_write_failed_biased(struct rw_semaphore *sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
+
+ for (;;) {
+ if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
+ break;
+ set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+ if (!sem->write_bias_granted)
+ schedule();
+ }
+
+ remove_wait_queue(&sem->write_bias_wait, &wait);
+ current->state = TASK_RUNNING;
+
+ /* if the lock is currently unbiased, awaken the sleepers
+ * FIXME: this wakes up the readers early in a bit of a
+ * stampede -> bad!
+ */
+ if (atomic_read(&sem->count) >= 0)
+ wake_up(&sem->wait);
+}
+
+
+/* Called when someone has done an up that transitioned from
+ * negative to non-negative, meaning that the lock has been
+ * granted to whomever owned the bias.
+ */
+void rwsem_wake_readers(struct rw_semaphore *sem)
+{
+ if (xchg(&sem->read_bias_granted, 1))
+ BUG();
+ wake_up(&sem->wait);
+}
+
+void rwsem_wake_writer(struct rw_semaphore *sem)
+{
+ if (xchg(&sem->write_bias_granted, 1))
+ BUG();
+ wake_up(&sem->write_bias_wait);
+}
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
new file mode 100644
index 000000000..16a35df30
--- /dev/null
+++ b/arch/parisc/kernel/setup.c
@@ -0,0 +1,614 @@
+/* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $
+ *
+ * Initial setup-routines for HP 9000 based hardware.
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Modifications for PA-RISC (C) 1999 Helge Deller <helge.deller@ruhr-uni-bochum.de>
+ * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
+ * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
+ * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * Initial PA-RISC Version: 04-23-1999 by Helge Deller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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/errno.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/user.h>
+#include <linux/tty.h>
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/threads.h>
+
+#include <asm/cache.h>
+#include <asm/hardware.h> /* for register_driver() stuff */
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/led.h>
+#include <asm/real.h>
+#include <asm/system.h>
+#include <asm/machdep.h> /* for pa7300lc_init() proto */
+
+#include <asm/irq.h> /* for struct irq_region */
+#include <asm/pdcpat.h> /* for PA_VIEW PDC_PAT_CPU_GET_NUMBER etc */
+
+#include <linux/proc_fs.h>
+
+#define COMMAND_LINE_SIZE 1024
+char saved_command_line[COMMAND_LINE_SIZE];
+
+/*
+** KLUGE ALERT!
+**
+** We *really* should be using a combination of request_resource()
+** and request_region()! But request_region() requires kmalloc since
+** returns a new struct resource. And kmalloc just isn't available
+** until after mem_init() is called from start_kernel().
+**
+** FIXME: assume contiguous memory initially.
+** Additional chunks of memory might be added to sysram_resource.sibling.
+*/
+static struct resource sysrom_resource = {
+ name: "System ROM", start: 0x0f0000000UL, end: 0x0f00fffffUL,
+ flags: IORESOURCE_BUSY | IORESOURCE_MEM,
+ parent: &iomem_resource, sibling: NULL, child: NULL };
+
+static struct resource pdcdata_resource;
+
+static struct resource sysram_resource = {
+ name: "System RAM", start: 0UL, end: ~0UL /* bogus */,
+ flags: IORESOURCE_MEM,
+ parent: &iomem_resource, sibling: &sysrom_resource, child: &pdcdata_resource};
+
+extern char _text; /* start of kernel code, defined by linker */
+extern int data_start;
+extern char _edata; /* end of data, begin BSS, defined by linker */
+extern char _end; /* end of BSS, defined by linker */
+
+static struct resource data_resource = {
+ name: "kernel Data", start: virt_to_phys(&data_start), end: virt_to_phys(&_end)-1,
+ flags: IORESOURCE_BUSY | IORESOURCE_MEM,
+ parent: &sysram_resource, sibling: NULL, child: NULL};
+
+static struct resource code_resource = {
+ name: "Kernel Code", start: virt_to_phys(&_text), end: virt_to_phys(&data_start)-1,
+ flags: IORESOURCE_BUSY | IORESOURCE_MEM,
+ parent: &sysram_resource, sibling: &data_resource, child: NULL};
+
+static struct resource pdcdata_resource = {
+ name: "PDC data (Page Zero)", start: 0, end: 0x9ff,
+ flags: IORESOURCE_BUSY | IORESOURCE_MEM,
+ parent: &sysram_resource, sibling: &code_resource, child: NULL};
+
+
+
+
+struct system_cpuinfo_parisc boot_cpu_data;
+struct cpuinfo_parisc cpu_data[NR_CPUS];
+
+extern void do_inventory(void);
+extern void cache_init(void);
+extern struct hp_device * register_module(void *hpa);
+
+static int cpu_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+static struct pa_iodc_driver cpu_drivers_for[] = {
+ {HPHW_NPROC, 0x0, 0x0, 0x0, 0, 0,
+ DRIVER_CHECK_HWTYPE,
+ "CPU", "PARISC", (void *) cpu_driver_callback},
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL }
+};
+
+static long fallback_cpu_hpa[] = { 0xfffa0000L, 0xfffbe000L, 0x0 };
+
+
+/*
+** PARISC CPU driver - claim "device" and initialize CPU data structures.
+**
+** Consolidate per CPU initialization into (mostly) one module.
+** Monarch CPU will initialize boot_cpu_data which shouldn't
+** change once the system has booted.
+**
+** The callback *should* do per-instance initialization of
+** everything including the monarch. Some of the code that's
+** in setup.c:start_parisc() should migrate here and start_parisc()
+** should "register_driver(cpu_driver_for)" before calling
+** do_inventory().
+**
+** The goal of consolidating CPU initialization into one place is
+** to make sure all CPU's get initialized the same way.
+** It would be nice if the even the manarch through the exact same code path.
+** (up to rendevous at least).
+*/
+#undef ASSERT
+#define ASSERT(expr) \
+ if(!(expr)) { \
+ printk( "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \
+ panic(#expr); \
+ }
+
+static int
+cpu_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+#ifdef __LP64__
+ extern int pdc_pat; /* arch/parisc/kernel/inventory.c */
+ static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
+#endif
+ struct cpuinfo_parisc *p;
+
+#ifndef CONFIG_SMP
+ if (boot_cpu_data.cpu_count > 0) {
+ printk(KERN_INFO "CONFIG_SMP disabled - not claiming addional CPUs\n");
+ return(1);
+ }
+#endif
+
+ p = &cpu_data[boot_cpu_data.cpu_count];
+ boot_cpu_data.cpu_count++;
+
+/* TODO: Enable FP regs - done early in start_parisc() now */
+
+ /* initialize counters */
+ memset(p, 0, sizeof(struct cpuinfo_parisc));
+
+ p->hpa = (unsigned long) d->hpa; /* save CPU hpa */
+
+#ifdef __LP64__
+ if (pdc_pat) {
+ ulong status;
+ pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+
+ status = pdc_pat_cell_module(& pdc_result, d->pcell_loc,
+ d->mod_index, PA_VIEW, & pa_pdc_cell);
+
+ ASSERT(PDC_RET_OK == status);
+
+ /* verify it's the same as what do_pat_inventory() found */
+ ASSERT(d->mod_info == pa_pdc_cell.mod_info);
+ ASSERT(d->pmod_loc == pa_pdc_cell.mod_location);
+ ASSERT(d->mod_path == pa_pdc_cell.mod_path);
+
+ p->txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */
+
+ /* get the cpu number */
+ status = mem_pdc_call( PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER,
+ __pa(& pdc_result), d->hpa);
+
+ ASSERT(PDC_RET_OK == status);
+
+ p->cpuid = pdc_result[0];
+
+ } else
+#endif
+ {
+ p->txn_addr = (unsigned long) d->hpa; /* for normal parisc */
+
+ /* logical CPU ID and update global counter */
+ p->cpuid = boot_cpu_data.cpu_count - 1;
+ }
+
+ /*
+ ** itimer and ipi IRQ handlers are statically initialized in
+ ** arch/parisc/kernel/irq.c
+ */
+ p->region = irq_region[IRQ_FROM_REGION(CPU_IRQ_REGION)];
+
+ return(0);
+}
+
+
+void __xchg_called_with_bad_pointer(void)
+{
+ printk(KERN_EMERG "xchg() called with bad pointer !\n");
+}
+
+
+/* Some versions of IODC don't list the CPU, and since we don't walk
+ * the bus yet, we have to probe for processors at well known hpa
+ * addresses.
+ */
+
+void __init register_fallback_cpu (void)
+{
+ struct hp_device *d = NULL;
+ int i = 0;
+
+#ifdef CONFIG_SMP
+#error "Revisit CPU fallback addresses for SMP (Assuming bus walk hasn't been implemented)"
+#endif
+ printk ("No CPUs reported by firmware - probing...\n");
+
+ while (fallback_cpu_hpa[i]) {
+
+ d = register_module ((void *) fallback_cpu_hpa[i]);
+
+ if (d > 0) {
+ printk ("Found CPU at %lx\n", fallback_cpu_hpa[i]);
+ cpu_driver_callback (d, 0);
+ return;
+ }
+
+ i++;
+ }
+
+ panic ("No CPUs found. System halted.\n");
+ return;
+}
+
+
+/*
+ * Get CPU information and store it in the boot_cpu_data structure. */
+void __init collect_boot_cpu_data(void)
+{
+ memset(&boot_cpu_data,0,sizeof(boot_cpu_data));
+
+ boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */
+
+ /* get CPU-Model Information... */
+#define p ((unsigned long *)&boot_cpu_data.pdc.model)
+ if(pdc_model_info(&boot_cpu_data.pdc.model)==0)
+ printk("model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
+#undef p
+
+ if(pdc_model_versions(&boot_cpu_data.pdc.versions, 0)==0)
+ printk("vers %08lx\n", boot_cpu_data.pdc.versions.cpuid);
+
+ if(pdc_model_cpuid(&boot_cpu_data.pdc.cpuid)==0)
+ printk("cpuid %08lx\n", boot_cpu_data.pdc.cpuid.cpuid);
+
+ printk("CPUID vers %ld rev %ld\n",
+ (boot_cpu_data.pdc.cpuid.cpuid >> 5) & 127,
+ boot_cpu_data.pdc.cpuid.cpuid & 31);
+
+ if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name)==0)
+ printk("model %s\n",boot_cpu_data.pdc.sys_model_name);
+
+ boot_cpu_data.model_name = parisc_getHWdescription(HPHW_NPROC,
+ boot_cpu_data.pdc.model.hversion>>4,
+ boot_cpu_data.pdc.model.sversion>>8);
+
+ boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion;
+ boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion;
+
+ boot_cpu_data.cpu_type =
+ parisc_get_cpu_type(boot_cpu_data.pdc.model.hversion);
+
+ boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0];
+ boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1];
+}
+
+
+#ifdef __LP64__
+#define COMMAND_GLOBAL 0xfffffffffffe0030UL
+#else
+#define COMMAND_GLOBAL 0xfffe0030
+#endif
+
+#define CMD_RESET 5 /* reset any module */
+
+/*
+** The Wright Brothers and Gecko systems have a H/W problem
+** (Lasi...'nuf said) may cause a broadcast reset to lockup
+** the system. An HVERSION dependent PDC call was developed
+** to perform a "safe", platform specific broadcast reset instead
+** of kludging up all the code.
+**
+** Older machines which do not implement PDC_BROADCAST_RESET will
+** return (with an error) and the regular broadcast reset can be
+** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET
+** the PDC call will not return (the system will be reset).
+*/
+static int
+reset_parisc(struct notifier_block *self, unsigned long command, void *ptr)
+{
+ printk("%s: %s(cmd=%lu)\n", __FILE__, __FUNCTION__, command);
+
+ switch(command) {
+ case MACH_RESTART:
+#ifdef FASTBOOT_SELFTEST_SUPPORT
+ /*
+ ** If user has modified the Firmware Selftest Bitmap,
+ ** run the tests specified in the bitmap after the
+ ** system is rebooted w/PDC_DO_RESET.
+ **
+ ** ftc_bitmap = 0x1AUL "Skip destructive memory tests"
+ **
+ ** Using "directed resets" at each processor with the MEM_TOC
+ ** vector cleared will also avoid running destructive
+ ** memory self tests. (Not implemented yet)
+ */
+ if (ftc_bitmap) {
+ mem_pdc_call( PDC_BROADCAST_RESET,
+ PDC_DO_FIRM_TEST_RESET, PDC_FIRM_TEST_MAGIC,
+ ftc_bitmap);
+ }
+#endif
+
+ /* "Normal" system reset */
+ (void) mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET,
+ 0L, 0L, 0L);
+
+ /* Nope...box should reset with just CMD_RESET now */
+ gsc_writel(CMD_RESET, COMMAND_GLOBAL);
+
+ /* Wait for RESET to lay us to rest. */
+ while (1) ;
+
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block parisc_block = { reset_parisc, NULL, 0 };
+
+
+/* start_parisc() will be called from head.S to setup our new memory_start
+ and actually start our kernel !
+ Memory-Layout is:
+ - Kernel-Image (code+data+BSS)
+ - Stack (stack-size see below!, stack-setup-code is in head.S)
+ - memory_start at end of stack..
+*/
+
+unsigned long mem_start, mem_max;
+unsigned long start_pfn, max_pfn;
+extern asmlinkage void __init start_kernel(void);
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+
+void __init start_parisc(unsigned arg0, unsigned arg1,
+ unsigned arg2, unsigned arg3)
+{
+ register unsigned long ccr;
+ unsigned long memory_start;
+
+ /* Clear BSS */
+
+ {
+ char *p = &_edata, *q = &_end;
+
+ while (p < q) {
+ *p++ = 0;
+ }
+ }
+
+
+ pdc_console_init();
+
+#ifdef __LP64__
+ printk("The 64-bit Kernel has started...\n");
+#else
+ printk("The 32-bit Kernel has started...\n");
+#endif
+
+ /*
+ ** Enable FP coprocessor
+ **
+ ** REVISIT: ccr should be set by PDC_COPROC results to support PA1.0.
+ ** Hardcoding works for PA1.1 processors.
+ **
+ ** REVISIT: this could be done in the "code 22" trap handler.
+ ** (frowands idea - that way we know which processes need FP
+ ** registers saved on the interrupt stack.)
+ **
+ ** NEWS FLASH: wide kernels need FP coprocessor enabled to handle
+ ** formatted printing of %lx for example (double divides I think)
+ */
+ ccr = 0xc0;
+ mtctl(ccr, 10);
+ printk("Enabled FP coprocessor\n");
+
+#ifdef __LP64__
+ printk( "If this is the LAST MESSAGE YOU SEE, you're probably using\n"
+ "32-bit millicode by mistake.\n");
+#endif
+
+ memory_start = (unsigned long) &_end;
+ memory_start = (memory_start + PAGE_SIZE) & PAGE_MASK;
+ printk("Free memory starts at: 0x%lx\n", memory_start);
+
+ /* Collect stuff passed in from the boot loader */
+ printk(KERN_WARNING "%s(0x%x,0x%x,0x%x,0x%x)\n",
+ __FUNCTION__, arg0, arg1, arg2, arg3);
+
+ /* arg0 is free-mem start, arg1 is ptr to command line */
+ if (arg0 < 64) {
+ /* called from hpux boot loader */
+ saved_command_line[0] = '\0';
+ } else {
+ strcpy(saved_command_line, (char *)__va(arg1));
+ printk("PALO command line: '%s'\nPALO initrd %x-%x\n",
+ saved_command_line, arg2, arg3);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (arg2 != 0) /* did palo pass us a ramdisk? */
+ {
+ initrd_start = (unsigned long)__va(arg2);
+ initrd_end = (unsigned long)__va(arg3);
+ }
+#endif
+ }
+
+ mem_start = __pa(memory_start);
+#define MAX_MEM (512*1024*1024)
+ mem_max = (PAGE0->imm_max_mem > MAX_MEM ? MAX_MEM : PAGE0->imm_max_mem);
+
+ collect_boot_cpu_data();
+
+ /* initialize the LCD/LED after boot_cpu_data is available ! */
+ led_init(); /* LCD/LED initialization */
+
+ do_inventory(); /* probe for hardware */
+ register_driver(cpu_drivers_for); /* claim all the CPUs */
+
+ if (boot_cpu_data.cpu_count == 0)
+ register_fallback_cpu();
+
+ printk("CPU(s): %d x %s at %d.%06d MHz\n",
+ boot_cpu_data.cpu_count,
+ boot_cpu_data.cpu_name,
+ boot_cpu_data.cpu_hz / 1000000,
+ boot_cpu_data.cpu_hz % 1000000 );
+
+ switch (boot_cpu_data.cpu_type) {
+ case pcx:
+ case pcxs:
+ case pcxt:
+ hppa_dma_ops = &pcx_dma_ops;
+ break;
+ case pcxl2:
+ pa7300lc_init();
+ case pcxl: /* falls through */
+ hppa_dma_ops = &pcxl_dma_ops;
+ break;
+ default:
+ break;
+ }
+
+#if 1
+ /* KLUGE! this really belongs in kernel/resource.c! */
+ iomem_resource.end = ~0UL;
+#endif
+ sysram_resource.end = mem_max - 1;
+ notifier_chain_register(&mach_notifier, &parisc_block);
+ start_kernel(); /* now back to arch-generic code... */
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long bootmap_size;
+ unsigned long start_pfn;
+ unsigned long mem_free;
+
+ *cmdline_p = saved_command_line;
+
+ /* initialize bootmem */
+
+ start_pfn = PFN_UP(mem_start);
+ max_pfn = PFN_DOWN(mem_max);
+
+ bootmap_size = init_bootmem(start_pfn, max_pfn);
+
+ mem_start += bootmap_size;
+ mem_free = mem_max - mem_start;
+
+ /* free_bootmem handles rounding nicely */
+ printk("free_bootmem(0x%lx, 0x%lx)\n", (unsigned long)mem_start,
+ (unsigned long)mem_free);
+ free_bootmem(mem_start, mem_free);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ printk("initrd: %08x-%08x\n", (int) initrd_start, (int) initrd_end);
+
+ if (initrd_end != 0) {
+ initrd_below_start_ok = 1;
+ reserve_bootmem(__pa(initrd_start), initrd_end - initrd_start);
+ }
+#endif
+
+ cache_init();
+
+ paging_init();
+
+ if((unsigned long)&init_task_union&(INIT_TASK_SIZE - 1)) {
+ printk("init_task_union not aligned. Please recompile the kernel after changing the first line in arch/parisc/kernel/init_task.c from \n\"#define PAD 0\" to\n\"#define PAD 1\" or vice versa\n");
+ for(;;);
+ }
+
+
+#ifdef CONFIG_SERIAL_CONSOLE
+ /* nothing */
+#elif CONFIG_VT
+#if defined(CONFIG_STI_CONSOLE)
+ conswitchp = &dummy_con; /* we use take_over_console() later ! */
+#elif defined(CONFIG_IODC_CONSOLE)
+ conswitchp = &prom_con; /* it's currently really "prom_con" */
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
+#endif
+
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Get CPU information for use by procfs.
+ */
+
+int get_cpuinfo(char *buffer)
+{
+ char *p = buffer;
+ int n;
+
+ for(n=0; n<boot_cpu_data.cpu_count; n++) {
+#ifdef CONFIG_SMP
+ if (!(cpu_online_map & (1<<n)))
+ continue;
+#endif
+ p += sprintf(p, "processor\t: %d\n"
+ "cpu family\t: PA-RISC %s\n",
+ n, boot_cpu_data.family_name);
+
+ p += sprintf(p, "cpu\t\t: %s\n", boot_cpu_data.cpu_name );
+
+ /* cpu MHz */
+ p += sprintf(p, "cpu MHz\t\t: %d.%06d\n",
+ boot_cpu_data.cpu_hz / 1000000,
+ boot_cpu_data.cpu_hz % 1000000 );
+
+ p += sprintf(p, "model\t\t: %s\n"
+ "model name\t: %s\n",
+ boot_cpu_data.pdc.sys_model_name,
+ boot_cpu_data.model_name);
+
+ p += sprintf(p, "hversion\t: 0x%08x\n"
+ "sversion\t: 0x%08x\n",
+ boot_cpu_data.hversion,
+ boot_cpu_data.sversion );
+
+ p += get_cache_info(p);
+ /* print cachesize info ? */
+ p += sprintf(p, "bogomips\t: %lu.%02lu\n",
+ (loops_per_sec+2500)/500000,
+ ((loops_per_sec+2500)/5000) % 100);
+ }
+ return p - buffer;
+}
+#endif
+
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
new file mode 100644
index 000000000..fec670ab8
--- /dev/null
+++ b/arch/parisc/kernel/signal.c
@@ -0,0 +1,653 @@
+/*
+ * linux/arch/parisc/kernel/signal.c: Architecture-specific signal
+ * handling support.
+ *
+ * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
+ * Copyright (C) 2000 Linuxcare, Inc.
+ *
+ * Based on the ia64, i386, and alpha versions.
+ *
+ * Like the IA-64, we are a recent enough port (we are *starting*
+ * with glibc2.2) that we do not need to support the old non-realtime
+ * Linux signals. Therefore we don't. HP/UX signals will go in
+ * arch/parisc/hpux/signal.c when we figure out how to do them.
+ */
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern long sys_wait4 (int, int *, int, struct rusage *);
+int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
+
+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
+{
+ if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+ return -EFAULT;
+ if (from->si_code < 0)
+ return __copy_to_user(to, from, sizeof(siginfo_t));
+ else {
+ int err;
+
+ /*
+ * If you change siginfo_t structure, please be sure
+ * this code is fixed accordingly. It should never
+ * copy any pad contained in the structure to avoid
+ * security leaks, but must copy the generic 3 ints
+ * plus the relevant union member.
+ */
+ err = __put_user(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
+ err |= __put_user((short)from->si_code, &to->si_code);
+ switch (from->si_code >> 16) {
+ case __SI_FAULT >> 16:
+ /* FIXME: should we put the interruption code here? */
+ case __SI_POLL >> 16:
+ err |= __put_user(from->si_addr, &to->si_addr);
+ break;
+ case __SI_CHLD >> 16:
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
+ err |= __put_user(from->si_status, &to->si_status);
+ default:
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_pid, &to->si_pid);
+ break;
+ /* case __SI_RT: This is not generated by the kernel as of now. */
+ }
+ return err;
+ }
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+#ifdef __LP64__
+#include "sys32.h"
+#endif
+
+asmlinkage int
+sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
+{
+ sigset_t saveset, newset;
+#ifdef __LP64__
+ /* XXX FIXME -- assumes 32-bit user app! */
+ sigset_t32 newset32;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t32))
+ return -EINVAL;
+
+ if (copy_from_user(&newset32, (sigset_t32 *)unewset, sizeof(newset32)))
+ return -EFAULT;
+
+ newset.sig[0] = newset32.sig[0] | ((unsigned long)newset32.sig[1] << 32);
+#else
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+#endif
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sigmask_lock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ regs->gr[28] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, regs, 1))
+ return -EINTR;
+ }
+}
+
+/*
+ * Do a signal return - restore sigcontext.
+ */
+
+struct rt_sigframe {
+ unsigned int tramp[4];
+ struct siginfo info;
+ struct ucontext uc;
+};
+
+/* Trampoline for calling rt_sigreturn() */
+#define INSN_LDI_R25_0 0x34190000 /* ldi 0,%r25 (in_syscall=0) */
+#define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */
+#define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */
+#define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
+#define INSN_NOP 0x80000240 /* nop */
+/* For debugging */
+#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
+
+/*
+ * The 32-bit ABI wants at least 48 bytes for a function call frame:
+ * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of
+ * which Linux/parisc uses is sp-20 for the saved return pointer...)
+ * Then, the stack pointer must be rounded to a cache line (64 bytes).
+ */
+#define PARISC_RT_SIGFRAME_SIZE \
+ (((sizeof(struct rt_sigframe) + 48) + 63) & -64)
+
+static long
+restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs)
+{
+ long err = 0;
+
+ err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
+ err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
+ err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
+ err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
+ err |= __get_user(regs->sar, &sc->sc_sar);
+
+#if DEBUG_SIG
+ printk("restore_sigcontext: r28 is %ld\n", regs->gr[28]);
+#endif
+ return err;
+}
+
+void
+sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
+{
+ struct rt_sigframe *frame;
+ struct siginfo si;
+ sigset_t set;
+ unsigned long usp = regs->gr[30];
+
+ /* Unwind the user stack to get the rt_sigframe structure. */
+ frame = (struct rt_sigframe *)
+ (usp - PARISC_RT_SIGFRAME_SIZE);
+#if DEBUG_SIG
+ printk("in sys_rt_sigreturn, frame is %p\n", frame);
+#endif
+
+ /* Verify that it's a good sigcontext before using it */
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto give_sigsegv;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto give_sigsegv;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ /* Good thing we saved the old gr[30], eh? */
+ if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
+ goto give_sigsegv;
+
+#if DEBUG_SIG
+ printk("usp: %#08lx stack %p",
+ usp, &frame->uc.uc_stack);
+#endif
+
+ /* I don't know why everyone else assumes they can call this
+ with a pointer to a stack_t on the kernel stack. That
+ makes no sense. Anyway we'll do it like m68k, since we
+ also are using segmentation in the same way as them. */
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
+ goto give_sigsegv;
+
+ /* If we are on the syscall path IAOQ will not be restored, and
+ * if we are on the interrupt path we must not corrupt gr31.
+ */
+ if (in_syscall)
+ regs->gr[31] = regs->iaoq[0];
+#if DEBUG_SIG
+ printk("returning to %#lx\n", regs->iaoq[0]);
+ printk("in sys_rt_sigreturn:\n");
+ show_regs(regs);
+#endif
+ return;
+
+give_sigsegv:
+#if DEBUG_SIG
+ printk("fuckup in sys_rt_sigreturn, sending SIGSEGV\n");
+#endif
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SI_KERNEL;
+ si.si_pid = current->pid;
+ si.si_uid = current->uid;
+ si.si_addr = &frame->uc;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static inline void *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *) sp; /* Stacks grow up. Fun. */
+}
+
+static long
+setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, int in_syscall)
+
+{
+ unsigned long flags = 0;
+ long err = 0;
+
+ if (on_sig_stack((unsigned long) sc))
+ flags |= PARISC_SC_FLAG_ONSTACK;
+ if (in_syscall) {
+ flags |= PARISC_SC_FLAG_IN_SYSCALL;
+ /* regs->iaoq is undefined in the syscall return path */
+ err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
+ err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
+#if DEBUG_SIG
+ printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->gr[31], regs->gr[31]);
+#endif
+ } else {
+ err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
+ err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
+#if DEBUG_SIG
+ printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->iaoq[0], regs->iaoq[1]);
+#endif
+ }
+
+ err |= __put_user(flags, &sc->sc_flags);
+ err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
+ err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
+ err |= __put_user(regs->sar, &sc->sc_sar);
+#if DEBUG_SIG
+ printk("setup_sigcontext: r28 is %ld\n", regs->gr[28]);
+#endif
+
+ return err;
+}
+
+static long
+setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs, int in_syscall)
+{
+ struct rt_sigframe *frame;
+ unsigned long rp, usp, haddr;
+ struct siginfo si;
+ int err = 0;
+
+ usp = regs->gr[30];
+ /* access_ok is broken, so do a simplistic "are we stomping on
+ kernel space" assertion. */
+ if (usp > PAGE_OFFSET) {
+ printk("setup_rt_frame: called on kernel space (usp=%#lx), NOW YOU MUST DIE!!!\n",
+ usp);
+ show_regs(regs);
+ while(1);
+ }
+
+ frame = get_sigframe(ka, usp, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+#if DEBUG_SIG
+ printk("setup_rt_frame 1: frame %p info %p\n", frame, info);
+#endif
+
+ err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t));
+ err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= __put_user(sas_ss_flags(regs->gr[30]),
+ &frame->uc.uc_stack.ss_flags);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
+ &frame->tramp[0]);
+ err |= __put_user(INSN_LDI_R20, &frame->tramp[1]);
+ err |= __put_user(INSN_BLE_SR2_R0, &frame->tramp[2]);
+ err |= __put_user(INSN_NOP, &frame->tramp[3]);
+
+#if DEBUG_SIG
+ /* Assert that we're flushing in the correct space... */
+ {
+ int sid;
+ asm ("mfsp %%sr3,%0" : "=r" (sid));
+ printk("flushing 64 bytes at space %#x offset %p\n",
+ sid, frame->tramp);
+ }
+#endif
+
+#if CACHE_FLUSHING_IS_NOT_BROKEN
+ flush_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[4]);
+#else
+ /* It should *always* be cache line-aligned, but the compiler
+ sometimes screws up. */
+ asm volatile("fdc 0(%%sr3,%0)\n\t"
+ "fdc %1(%%sr3,%0)\n\t"
+ "sync\n\t"
+ "fic 0(%%sr3,%0)\n\t"
+ "fic %1(%%sr3,%0)\n\t"
+ "sync\n\t"
+ : : "r" (frame->tramp), "r" (L1_CACHE_BYTES));
+#endif
+ rp = (unsigned long) frame->tramp;
+
+ if (err)
+ goto give_sigsegv;
+
+#ifdef __LP64__
+/* Much more has to happen with signals than this -- but it'll at least */
+/* provide a pointer to some places which definitely need a look. */
+#define HACK unsigned int
+#else
+#define HACK unsigned long
+#endif
+ haddr = (HACK) ka->sa.sa_handler;
+ /* ARGH! Fucking brain damage. You don't want to know. */
+ if (haddr & 2) {
+ HACK *plabel;
+ HACK ltp;
+
+ plabel = (HACK *) (haddr & ~3);
+ err |= __get_user(haddr, plabel);
+ err |= __get_user(ltp, plabel + 1);
+ if (err)
+ goto give_sigsegv;
+ regs->gr[19] = ltp;
+ }
+
+ /* The syscall return path will create IAOQ values from r31.
+ */
+ if (in_syscall)
+ regs->gr[31] = (HACK) haddr;
+ else {
+ regs->iaoq[0] = (HACK) haddr | 3;
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ }
+
+ regs->gr[2] = rp; /* userland return pointer */
+ regs->gr[26] = sig; /* signal number */
+ regs->gr[25] = (HACK) &frame->info; /* siginfo pointer */
+ regs->gr[24] = (HACK) &frame->uc; /* ucontext pointer */
+#if DEBUG_SIG
+ printk("making sigreturn frame: %#lx + %#lx = %#lx\n",
+ regs->gr[30], PARISC_RT_SIGFRAME_SIZE,
+ regs->gr[30] + PARISC_RT_SIGFRAME_SIZE);
+#endif
+ /* Raise the user stack pointer to make a proper call frame. */
+ regs->gr[30] = ((HACK) frame + PARISC_RT_SIGFRAME_SIZE);
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
+ current->comm, current->pid, frame, regs->gr[30],
+ regs->iaoq[0], regs->iaoq[1], rp);
+#endif
+
+ return 1;
+
+give_sigsegv:
+#if DEBUG_SIG
+ printk("fuckup in setup_rt_frame, sending SIGSEGV\n");
+#endif
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SI_KERNEL;
+ si.si_pid = current->pid;
+ si.si_uid = current->uid;
+ si.si_addr = frame;
+ force_sig_info(SIGSEGV, &si, current);
+ return 0;
+}
+
+/*
+ * OK, we're invoking a handler.
+ */
+
+static long
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset,
+ struct pt_regs *regs, int in_syscall)
+{
+#if DEBUG_SIG
+ printk("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n",
+ sig, ka, info, oldset, regs);
+#endif
+ /* Set up the stack frame */
+ if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
+ return 0;
+
+ if (ka->sa.sa_flags & SA_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(&current->sigmask_lock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+ }
+ return 1;
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * We need to be able to restore the syscall arguments (r21-r26) to
+ * restart syscalls. Thus, the syscall path should save them in the
+ * pt_regs structure (it's okay to do so since they are caller-save
+ * registers). As noted below, the syscall number gets restored for
+ * us due to the magic of delayed branching.
+ */
+asmlinkage int
+do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
+{
+ siginfo_t info;
+ struct k_sigaction *ka;
+
+#if DEBUG_SIG
+ printk("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n",
+ oldset, regs, regs->sr[7], current->sigpending, in_syscall);
+#endif
+ /* Everyone else checks to see if they are in kernel mode at
+ this point and exits if that's the case. I'm not sure why
+ we would be called in that case, but for some reason we
+ are. */
+
+ if (!oldset)
+ oldset = &current->blocked;
+
+#if DEBUG_SIG
+ printk("do_signal: oldset %08lx:%08lx\n", oldset->sig[0], oldset->sig[1]);
+#endif
+
+ for (;;) {
+ unsigned long signr;
+
+ spin_lock_irq(&current->sigmask_lock);
+ signr = dequeue_signal(&current->blocked, &info);
+ spin_unlock_irq(&current->sigmask_lock);
+#if DEBUG_SIG
+ printk("do_signal: signr=%ld, pid=%d\n", signr, current->pid);
+#endif
+
+ if (!signr)
+ break;
+
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
+ /* Let the debugger run. */
+ current->exit_code = signr;
+ set_current_state(TASK_STOPPED);
+ notify_parent(current, SIGCHLD);
+ schedule();
+
+ /* We're back. Did the debugger cancel the sig? */
+ if (!(signr = current->exit_code))
+ continue;
+ current->exit_code = 0;
+
+ /* The debugger continued. Ignore SIGSTOP. */
+ if (signr == SIGSTOP)
+ continue;
+
+ /* Update the siginfo structure. Is this good? */
+ if (signr != info.si_signo) {
+ info.si_signo = signr;
+ info.si_errno = 0;
+ info.si_code = SI_USER;
+ info.si_pid = current->p_pptr->pid;
+ info.si_uid = current->p_pptr->uid;
+ }
+
+ /* If the (new) signal is now blocked, requeue it. */
+ if (sigismember(&current->blocked, signr)) {
+ send_sig_info(signr, &info, current);
+ continue;
+ }
+ }
+
+ ka = &current->sig->action[signr-1];
+#if DEBUG_SIG
+ printk("sa_handler is %lx\n", ka->sa.sa_handler);
+#endif
+ if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_IGN) {
+ if (signr != SIGCHLD)
+ continue;
+ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+ /* nothing */;
+ continue;
+ }
+
+ if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_DFL) {
+ int exit_code = signr;
+
+ /* Init gets no signals it doesn't want. */
+ if (current->pid == 1)
+ continue;
+
+ switch (signr) {
+ case SIGCONT: case SIGCHLD: case SIGWINCH:
+ continue;
+
+ case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ if (is_orphaned_pgrp(current->pgrp))
+ continue;
+ /* FALLTHRU */
+
+ case SIGSTOP:
+ set_current_state(TASK_STOPPED);
+ current->exit_code = signr;
+ if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+ notify_parent(current, SIGCHLD);
+ schedule();
+ continue;
+
+ case SIGQUIT: case SIGILL: case SIGTRAP:
+ case SIGABRT: case SIGFPE: case SIGSEGV:
+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
+ if (signr == SIGQUIT) /* Userspace debugging */
+ show_regs(regs);
+ if (do_coredump(signr, regs))
+ exit_code |= 0x80;
+ /* FALLTHRU */
+
+ default:
+ lock_kernel();
+ sigaddset(&current->pending.signal, signr);
+ recalc_sigpending(current);
+ current->flags |= PF_SIGNALED;
+ do_exit(exit_code);
+ /* NOTREACHED */
+ }
+ }
+
+ /* Restart a system call if necessary. */
+ if (in_syscall) {
+ /* Check the return code */
+ switch (regs->gr[28]) {
+ case -ERESTARTNOHAND:
+#if DEBUG_SIG
+ printk("ERESTARTNOHAND: returning -EINTR\n");
+#endif
+ regs->gr[28] = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (!(ka->sa.sa_flags & SA_RESTART)) {
+#if DEBUG_SIG
+ printk("ERESTARTSYS: putting -EINTR\n");
+#endif
+ regs->gr[28] = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ /* A syscall is just a branch, so all
+ we have to do is fiddle the return
+ pointer. */
+ regs->gr[31] -= 8; /* delayed branching */
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+ break;
+ }
+ }
+ /* Whee! Actually deliver the signal. If the
+ delivery failed, we need to continue to iterate in
+ this loop so we can deliver the SIGSEGV... */
+ if (handle_signal(signr, ka, &info, oldset, regs, in_syscall)) {
+#if DEBUG_SIG
+ printk("Exiting do_signal (success), regs->gr[28] = %ld\n", regs->gr[28]);
+#endif
+ return 1;
+ }
+ }
+
+ /* Did we come from a system call? */
+ if (in_syscall) {
+ /* Restart the system call - no handlers present */
+ if (regs->gr[28] == -ERESTARTNOHAND ||
+ regs->gr[28] == -ERESTARTSYS ||
+ regs->gr[28] == -ERESTARTNOINTR) {
+ /* Hooray for delayed branching. We don't
+ have to restore %r20 (the system call
+ number) because it gets loaded in the delay
+ slot of the branch external instruction. */
+ regs->gr[31] -= 8;
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+ }
+ }
+#if DEBUG_SIG
+ printk("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", regs->gr[28]);
+#endif
+ return 0;
+}
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
new file mode 100644
index 000000000..85aca70af
--- /dev/null
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -0,0 +1,88 @@
+/*
+ * linux/arch/parisc/kernel/sys_parisc.c
+ *
+ * this implements the missing syscalls.
+ */
+
+#include <asm/uaccess.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/smp_lock.h>
+
+/* for some reason, "old_readdir" is the only syscall which does not begin
+ * with "sys_", which breaks the ENTRY_* macros in syscall.S so I "fixed"
+ * it here.
+ */
+
+int sys_old_readdir(unsigned int fd, void *dirent, unsigned int count)
+{
+ return old_readdir(fd, dirent, count);
+}
+
+int sys_pipe(int *fildes)
+{
+ int fd[2];
+ int error;
+
+ lock_kernel();
+ error = do_pipe(fd);
+ unlock_kernel();
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2*sizeof(int)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+int sys_pause(void)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ return -ERESTARTNOHAND;
+}
+
+int sys_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags, unsigned long fd,
+ unsigned long offset)
+{
+ struct file * file = NULL;
+ int error;
+
+ down(&current->mm->mmap_sem);
+ lock_kernel();
+ if (!(flags & MAP_ANONYMOUS)) {
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ error = do_mmap(file, addr, len, prot, flags, offset);
+ if (file != NULL)
+ fput(file);
+out:
+ unlock_kernel();
+ up(&current->mm->mmap_sem);
+ return error;
+}
+
+int sys_ioperm(unsigned long from, unsigned long num, int on)
+{
+ return -ENOSYS;
+}
+
+long sys_shmat_wrapper(int shmid, void *shmaddr, int shmflag)
+{
+ extern int sys_shmat(int shmid, char *shmaddr, int shmflg,
+ unsigned long * raddr);
+ unsigned long raddr;
+ int r;
+
+ r = sys_shmat(shmid, shmaddr, shmflag, &raddr);
+ if (r < 0)
+ return r;
+ return raddr;
+}
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
new file mode 100644
index 000000000..bfa757471
--- /dev/null
+++ b/arch/parisc/kernel/syscall.S
@@ -0,0 +1,563 @@
+/*
+ * Linux/PARISC Project (http://www.thepuffingroup.com/parisc)
+ *
+ * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
+ * Licensed under the GNU GPL.
+ * thanks to Philipp Rumpf, Mike Shaver and various others
+ * sorry about the wall, puffin..
+ */
+
+#include <asm/offset.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/psw.h>
+
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/processor.h>
+#include <linux/version.h>
+
+#ifdef __LP64__
+ .level 2.0w
+#else
+ .level 1.1
+#endif
+ .text
+
+ .import syscall_exit,code
+ .import syscall_exit_rfi,code
+ .export linux_gateway_page
+
+ /* Linux gateway page is aliased to virtual page 0 in the kernel
+ * address space. Since it is a gateway page it cannot be
+ * dereferenced, so null pointers will still fault. We start
+ * the actual entry point at 0x100. We put break instructions
+ * at the beginning of the page to trap null indirect function
+ * pointers.
+ */
+
+ .align 4096
+linux_gateway_page:
+
+ break 0,0
+
+ .align 256
+linux_gateway_entry:
+ mfsp %sr7,%r1 /* we must set sr3 to the space */
+ mtsp %r1,%sr3 /* of the user before the gate */
+ gate .+8, %r0 /* become privileged */
+ mtsp %r0,%sr4 /* get kernel space into sr4 */
+ mtsp %r0,%sr5 /* get kernel space into sr5 */
+ mtsp %r0,%sr6 /* get kernel space into sr6 */
+ mtsp %r0,%sr7 /* get kernel space into sr7 */
+#ifdef __LP64__
+ /* for now we can *always* set the W bit on entry to the syscall
+ * since we don't support wide userland processes. We could
+ * also save the current SM other than in r0 and restore it on
+ * exit from the syscall, and also use that value to know
+ * whether to do narrow or wide syscalls. -PB
+ */
+ ssm PSW_SM_W, %r0
+#endif
+ mtctl %r28,%cr27
+ rsm PSW_I, %r28 /* no ints for a bit */
+ mfctl %cr30,%r1 /* get the kernel task ptr */
+ mtctl %r0,%cr30 /* zero it (flag) */
+
+ /* Save some registers for sigcontext and potential task
+ switch (see entry.S for the details of which ones are
+ saved/restored) */
+ STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
+ STREG %r19, TASK_PT_GR19(%r1)
+ STREG %r20, TASK_PT_GR20(%r1)
+ STREG %r21, TASK_PT_GR21(%r1)
+ STREG %r22, TASK_PT_GR22(%r1)
+ STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */
+ STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */
+ STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */
+ STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
+ STREG %r27, TASK_PT_GR27(%r1) /* user dp */
+ mfctl %cr27,%r19
+ STREG %r19, TASK_PT_GR28(%r1) /* return value 0 */
+ STREG %r19, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */
+ STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */
+ STREG %r30, TASK_PT_GR30(%r1) /* preserve userspace sp */
+ STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
+
+ ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */
+ save_fp %r27 /* or potential task switch */
+
+ mfctl %cr11, %r27 /* i.e. SAR */
+ STREG %r27, TASK_PT_SAR(%r1)
+
+ loadgp
+
+ ldo TASK_SZ_ALGN+64(%r1),%r30 /* set up kernel stack */
+
+#ifndef __LP64__
+ /* no need to save these on stack because in wide mode the first 8
+ * args are passed in registers */
+ stw %r22, -52(%r30) /* 5th argument */
+ stw %r21, -56(%r30) /* 6th argument */
+#endif
+
+ /* for some unknown reason, task_struct.ptrace is an unsigned long so use LDREG */
+ LDREG TASK_PTRACE(%r1), %r19 /* Are we being ptraced? */
+ mtsm %r28 /* irqs back */
+
+ bb,<,n %r19, 31, .Ltracesys /* must match PT_PTRACE bit */
+
+ /* Note! We cannot use the syscall table that is mapped
+ nearby since the gateway page is mapped execute-only. */
+
+ ldil L%sys_call_table, %r1
+ ldo R%sys_call_table(%r1), %r19
+ LDIL_FIXUP(%r19)
+
+ comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+ b,n .Lsyscall_nosys
+
+#ifdef __LP64__
+ ldd,s %r20(%r19), %r19
+#else
+ ldwx,s %r20(%r19), %r19
+#endif
+ /* If this is a sys_rt_sigreturn call, and the signal was received
+ * when not in_syscall, then we want to return via syscall_exit_rfi,
+ * not syscall_exit. Signal no. in r20, in_syscall in r25 (see
+ * trampoline code in signal.c).
+ */
+ ldi __NR_rt_sigreturn,%r2
+ comb,= %r2,%r20,.Lrt_sigreturn
+.Lin_syscall:
+ ldil L%syscall_exit,%r2
+ LDIL_FIXUP(%r2)
+ be 0(%sr7,%r19)
+ ldo R%syscall_exit(%r2),%r2
+.Lrt_sigreturn:
+ comib,<> 0,%r25,.Lin_syscall
+ ldil L%syscall_exit_rfi,%r2
+ LDIL_FIXUP(%r2)
+ be 0(%sr7,%r19)
+ ldo R%syscall_exit_rfi(%r2),%r2
+
+ /* Note! Because we are not running where we were linked, any
+ calls to functions external to this file must be indirect. To
+ be safe, we apply the opposite rule to functions within this
+ file, with local labels given to them to ensure correctness. */
+
+.Lsyscall_nosys:
+syscall_nosys:
+ ldil L%syscall_exit,%r1
+ LDIL_FIXUP(%r1)
+ be R%syscall_exit(%sr7,%r1)
+ ldo -ENOSYS(%r0),%r28 /* set errno */
+
+
+/* Warning! This trace code is a virtual duplicate of the code above so be
+ * sure to maintain both! */
+.Ltracesys:
+tracesys:
+ /* Need to save more registers so the debugger can see where we
+ * are.
+ */
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ ssm 0,%r2 /* Lower 8 bits only!! */
+ STREG %r2,TASK_PT_PSW(%r1)
+ STREG %r1,TASK_PT_CR30(%r1)
+ mfsp %sr0,%r2
+ STREG %r2,TASK_PT_SR0(%r1)
+ mfsp %sr1,%r2
+ STREG %r2,TASK_PT_SR1(%r1)
+ mfsp %sr2,%r2
+ STREG %r2,TASK_PT_SR2(%r1)
+ mfsp %sr3,%r2
+ STREG %r2,TASK_PT_SR3(%r1)
+ STREG %r2,TASK_PT_SR4(%r1)
+ STREG %r2,TASK_PT_SR5(%r1)
+ STREG %r2,TASK_PT_SR6(%r1)
+ STREG %r2,TASK_PT_SR7(%r1)
+ STREG %r2,TASK_PT_IASQ0(%r1)
+ STREG %r2,TASK_PT_IASQ1(%r1)
+ LDREG TASK_PT_GR31(%r1),%r2
+ STREG %r2,TASK_PT_IAOQ0(%r1)
+ ldo 4(%r2),%r2
+ STREG %r2,TASK_PT_IAOQ1(%r1)
+ ldo TASK_REGS(%r1),%r2
+ /* reg_save %r2 */
+ STREG %r3,PT_GR3(%r2)
+ STREG %r4,PT_GR4(%r2)
+ STREG %r5,PT_GR5(%r2)
+ STREG %r6,PT_GR6(%r2)
+ STREG %r7,PT_GR7(%r2)
+ STREG %r8,PT_GR8(%r2)
+ STREG %r9,PT_GR9(%r2)
+ STREG %r10,PT_GR10(%r2)
+ STREG %r11,PT_GR11(%r2)
+ STREG %r12,PT_GR12(%r2)
+ STREG %r13,PT_GR13(%r2)
+ STREG %r14,PT_GR14(%r2)
+ STREG %r15,PT_GR15(%r2)
+ STREG %r16,PT_GR16(%r2)
+ STREG %r17,PT_GR17(%r2)
+ STREG %r18,PT_GR18(%r2)
+ /* Finished saving things for the debugger */
+
+ ldil L%syscall_trace,%r1
+ LDIL_FIXUP(%r1)
+ ldil L%tracesys_next,%r2
+ LDIL_FIXUP(%r2)
+ be R%syscall_trace(%sr7,%r1)
+ ldo R%tracesys_next(%r2),%r2
+
+tracesys_next:
+ ldil L%sys_call_table,%r1
+ LDIL_FIXUP(%r1)
+ ldo R%sys_call_table(%r1), %r19
+
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ LDREG TASK_PT_GR20(%r1), %r20
+ LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */
+ LDREG TASK_PT_GR25(%r1), %r25
+ LDREG TASK_PT_GR24(%r1), %r24
+ LDREG TASK_PT_GR23(%r1), %r23
+#ifdef __LP64__
+ LDREG TASK_PT_GR22(%r1), %r22
+ LDREG TASK_PT_GR21(%r1), %r21
+#endif
+
+ comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+ b,n .Lsyscall_nosys
+
+#ifdef __LP64__
+ ldd,s %r20(%r19), %r19
+#else
+ ldwx,s %r20(%r19), %r19
+#endif
+ /* If this is a sys_rt_sigreturn call, and the signal was received
+ * when not in_syscall, then we want to return via syscall_exit_rfi,
+ * not syscall_exit. Signal no. in r20, in_syscall in r25 (see
+ * trampoline code in signal.c).
+ */
+ ldi __NR_rt_sigreturn,%r2
+ comb,= %r2,%r20,.Ltrace_rt_sigreturn
+.Ltrace_in_syscall:
+ ldil L%tracesys_exit,%r2
+ LDIL_FIXUP(%r2)
+ be 0(%sr7,%r19)
+ ldo R%tracesys_exit(%r2),%r2
+
+ /* Do *not* call this function on the gateway page, because it
+ makes a direct call to syscall_trace. */
+
+tracesys_exit:
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ bl syscall_trace, %r2
+ STREG %r28,TASK_PT_GR28(%r1) /* save return value now */
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */
+
+ ldil L%syscall_exit,%r1
+ LDIL_FIXUP(%r1)
+ be,n R%syscall_exit(%sr7,%r1)
+
+.Ltrace_rt_sigreturn:
+ comib,<> 0,%r25,.Ltrace_in_syscall
+ ldil L%tracesys_sigexit,%r2
+ LDIL_FIXUP(%r2)
+ be 0(%sr7,%r19)
+ ldo R%tracesys_sigexit(%r2),%r2
+
+tracesys_sigexit:
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ bl syscall_trace, %r2
+ nop
+
+ ldil L%syscall_exit_rfi,%r1
+ LDIL_FIXUP(%r1)
+ be,n R%syscall_exit_rfi(%sr7,%r1)
+
+#ifdef __LP64__
+/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
+ * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
+ * implementation is required on wide palinux.
+ */
+#define ENTRY_SAME(_name_) .dword sys_##_name_
+#define ENTRY_DIFF(_name_) .dword sys32_##_name_
+#define ENTRY_UHOH(_name_) .dword sys32_unimplemented
+#else
+#define ENTRY_SAME(_name_) .word sys_##_name_
+#define ENTRY_DIFF(_name_) .word sys_##_name_
+#define ENTRY_UHOH(_name_) .word sys_##_name_
+#endif
+
+ .align 8
+ .export sys_call_table
+.Lsys_call_table:
+sys_call_table:
+ ENTRY_SAME(ni_syscall) /* 0 - old "setup()" system call*/
+ ENTRY_SAME(exit)
+ ENTRY_SAME(fork_wrapper)
+ ENTRY_SAME(read)
+ ENTRY_SAME(write)
+ ENTRY_SAME(open) /* 5 */
+ ENTRY_SAME(close)
+ ENTRY_SAME(waitpid)
+ ENTRY_SAME(creat)
+ ENTRY_SAME(link)
+ ENTRY_SAME(unlink) /* 10 */
+ ENTRY_DIFF(execve_wrapper)
+ ENTRY_SAME(chdir)
+ /* See comments in kernel/time.c!!! Maybe we don't need this? */
+ ENTRY_DIFF(time)
+ ENTRY_SAME(mknod)
+ ENTRY_SAME(chmod) /* 15 */
+ ENTRY_SAME(lchown)
+ ENTRY_SAME(socket)
+ /* struct stat is MAYBE identical wide and narrow ?? */
+ ENTRY_DIFF(newstat)
+ ENTRY_SAME(lseek)
+ ENTRY_SAME(getpid) /* 20 */
+ /* the 'void * data' parameter may need re-packing in wide */
+ ENTRY_DIFF(mount)
+ /* concerned about struct sockaddr in wide/narrow */
+ /* ---> I think sockaddr is OK unless the compiler packs the struct */
+ /* differently to align the char array */
+ ENTRY_SAME(bind)
+ ENTRY_SAME(setuid)
+ ENTRY_SAME(getuid)
+ ENTRY_SAME(stime) /* 25 */
+ ENTRY_SAME(ptrace)
+ ENTRY_SAME(alarm)
+ /* see stat comment */
+ ENTRY_DIFF(newfstat)
+ ENTRY_SAME(pause)
+ /* struct utimbuf uses time_t which might vary */
+ ENTRY_DIFF(utime) /* 30 */
+ /* struct sockaddr... */
+ ENTRY_SAME(connect)
+ ENTRY_SAME(listen)
+ ENTRY_SAME(access)
+ ENTRY_SAME(nice)
+ /* struct sockaddr... */
+ ENTRY_SAME(accept) /* 35 */
+ ENTRY_SAME(sync)
+ ENTRY_SAME(kill)
+ ENTRY_SAME(rename)
+ ENTRY_SAME(mkdir)
+ ENTRY_SAME(rmdir) /* 40 */
+ ENTRY_SAME(dup)
+ ENTRY_SAME(pipe)
+ ENTRY_DIFF(times)
+ /* struct sockaddr... */
+ ENTRY_SAME(getsockname)
+ /* it seems possible brk() could return a >4G pointer... */
+ ENTRY_SAME(brk) /* 45 */
+ ENTRY_SAME(setgid)
+ ENTRY_SAME(getgid)
+ ENTRY_SAME(signal)
+ ENTRY_SAME(geteuid)
+ ENTRY_SAME(getegid) /* 50 */
+ ENTRY_SAME(acct)
+ ENTRY_SAME(umount)
+ /* struct sockaddr... */
+ ENTRY_SAME(getpeername)
+ /* This one's a huge ugly mess */
+ ENTRY_DIFF(ioctl)
+ /* struct flock? */
+ ENTRY_DIFF(fcntl) /* 55 */
+ ENTRY_SAME(socketpair)
+ ENTRY_SAME(setpgid)
+ ENTRY_SAME(send)
+ ENTRY_SAME(newuname)
+ ENTRY_SAME(umask) /* 60 */
+ ENTRY_SAME(chroot)
+ ENTRY_SAME(ustat)
+ ENTRY_SAME(dup2)
+ ENTRY_SAME(getppid)
+ ENTRY_SAME(getpgrp) /* 65 */
+ ENTRY_SAME(setsid)
+ ENTRY_SAME(pivot_root)
+ /* I don't like this */
+ ENTRY_UHOH(sgetmask)
+ ENTRY_UHOH(ssetmask)
+ ENTRY_SAME(setreuid) /* 70 */
+ ENTRY_SAME(setregid)
+ ENTRY_SAME(mincore)
+ ENTRY_DIFF(sigpending)
+ ENTRY_SAME(sethostname)
+ /* Following 3 have linux-common-code structs containing longs -( */
+ ENTRY_DIFF(setrlimit) /* 75 */
+ ENTRY_DIFF(getrlimit)
+ ENTRY_DIFF(getrusage)
+ /* struct timeval and timezone are maybe?? consistent wide and narrow */
+ ENTRY_SAME(gettimeofday)
+ ENTRY_SAME(settimeofday)
+ ENTRY_SAME(getgroups) /* 80 */
+ ENTRY_SAME(setgroups)
+ /* struct socketaddr... */
+ ENTRY_SAME(sendto)
+ ENTRY_SAME(symlink)
+ /* see stat comment */
+ ENTRY_DIFF(newlstat)
+ ENTRY_SAME(readlink) /* 85 */
+ /* suspect we'll need some work for narrow shlibs on wide kernel */
+ ENTRY_UHOH(uselib)
+ ENTRY_SAME(swapon)
+ ENTRY_SAME(reboot)
+ /* argh! struct dirent contains a long */
+ ENTRY_UHOH(old_readdir)
+ /* I'm not certain about off_t... */
+ ENTRY_SAME(mmap) /* 90 */
+ ENTRY_SAME(munmap)
+ ENTRY_SAME(truncate)
+ ENTRY_SAME(ftruncate)
+ ENTRY_SAME(fchmod)
+ ENTRY_SAME(fchown) /* 95 */
+ ENTRY_SAME(getpriority)
+ ENTRY_SAME(setpriority)
+ ENTRY_SAME(recv)
+ ENTRY_DIFF(statfs)
+ ENTRY_DIFF(fstatfs) /* 100 */
+ ENTRY_SAME(ni_syscall)
+ /* don't think hppa glibc even provides an entry pt for this
+ * so disable for now */
+ ENTRY_UHOH(socketcall)
+ ENTRY_SAME(syslog)
+ /* even though manpage says struct timeval contains longs, ours has
+ * time_t and suseconds_t -- both of which are safe wide/narrow */
+ ENTRY_SAME(setitimer)
+ ENTRY_SAME(getitimer) /* 105 */
+ ENTRY_SAME(capget)
+ ENTRY_SAME(capset)
+ ENTRY_SAME(pread)
+ ENTRY_SAME(pwrite)
+ ENTRY_SAME(getcwd) /* 110 */
+ ENTRY_SAME(vhangup)
+ ENTRY_SAME(ni_syscall)
+ ENTRY_SAME(vfork_wrapper)
+ /* struct rusage contains longs... */
+ ENTRY_DIFF(wait4)
+ ENTRY_SAME(swapoff) /* 115 */
+ /* struct sysinfo contains longs */
+ ENTRY_SAME(sysinfo)
+ ENTRY_SAME(shutdown)
+ ENTRY_SAME(fsync)
+ ENTRY_SAME(madvise)
+ ENTRY_SAME(clone_wrapper) /* 120 */
+ ENTRY_SAME(setdomainname)
+ ENTRY_SAME(sendfile)
+ /* struct sockaddr... */
+ ENTRY_SAME(recvfrom)
+ /* struct timex contains longs */
+ ENTRY_UHOH(adjtimex)
+ ENTRY_SAME(mprotect) /* 125 */
+ /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
+ ENTRY_DIFF(sigprocmask)
+ ENTRY_SAME(create_module)
+ /* struct module contains longs, but insmod builds a 64 bit struct
+ * if running under a 64 bit kernel */
+ ENTRY_SAME(init_module)
+ ENTRY_SAME(delete_module)
+ /* struct kernel_sym contains a long. Linus never heard of size_t? */
+ ENTRY_DIFF(get_kernel_syms) /* 130 */
+ ENTRY_SAME(quotactl)
+ ENTRY_SAME(getpgid)
+ ENTRY_SAME(fchdir)
+ /* bdflush(func, addr) where func has least-significant-bit set means
+ * addr is a pointer to long :-( */
+ ENTRY_UHOH(bdflush)
+ ENTRY_SAME(sysfs) /* 135 */
+ ENTRY_SAME(personality)
+ ENTRY_SAME(ni_syscall) /* for afs_syscall */
+ ENTRY_SAME(setfsuid)
+ ENTRY_SAME(setfsgid)
+ /* I think this might work */
+ ENTRY_SAME(llseek) /* 140 */
+ /* struct linux_dirent has longs, like 'unsigned long d_ino' which
+ * almost definitely should be 'ino_t d_ino' but it's too late now */
+ ENTRY_DIFF(getdents)
+ /* it is POSSIBLE that select will be OK because even though fd_set
+ * contains longs, the macros and sizes are clever. */
+ ENTRY_SAME(select)
+ ENTRY_SAME(flock)
+ ENTRY_SAME(msync)
+ /* struct iovec contains pointers */
+ ENTRY_UHOH(readv) /* 145 */
+ ENTRY_UHOH(writev)
+ ENTRY_SAME(getsid)
+ ENTRY_SAME(fdatasync)
+ /* struct __sysctl_args is a mess */
+ ENTRY_DIFF(sysctl)
+ ENTRY_SAME(mlock) /* 150 */
+ ENTRY_SAME(munlock)
+ ENTRY_SAME(mlockall)
+ ENTRY_SAME(munlockall)
+ /* struct sched_param is ok for now */
+ ENTRY_SAME(sched_setparam)
+ ENTRY_SAME(sched_getparam) /* 155 */
+ ENTRY_SAME(sched_setscheduler)
+ ENTRY_SAME(sched_getscheduler)
+ ENTRY_SAME(sched_yield)
+ ENTRY_SAME(sched_get_priority_max)
+ ENTRY_SAME(sched_get_priority_min) /* 160 */
+ /* These 2 would've worked if someone had defined struct timespec
+ * carefully, like timeval for example (which is about the same).
+ * Unfortunately it contains a long :-( */
+ ENTRY_DIFF(sched_rr_get_interval)
+ ENTRY_DIFF(nanosleep)
+ ENTRY_SAME(mremap)
+ ENTRY_SAME(setresuid)
+ ENTRY_SAME(getresuid) /* 165 */
+ /* might work, but in general signals need a thorough review */
+ ENTRY_UHOH(sigaltstack_wrapper)
+ /* struct passed back to user can contain long symbol values */
+ ENTRY_DIFF(query_module)
+ ENTRY_SAME(poll)
+ /* structs contain pointers and an in_addr... */
+ ENTRY_UHOH(nfsservctl)
+ ENTRY_SAME(setresgid) /* 170 */
+ ENTRY_SAME(getresgid)
+ ENTRY_SAME(prctl)
+ /* signals need a careful review */
+ ENTRY_SAME(rt_sigreturn_wrapper)
+ ENTRY_DIFF(rt_sigaction)
+ ENTRY_DIFF(rt_sigprocmask) /* 175 */
+ ENTRY_DIFF(rt_sigpending)
+ ENTRY_UHOH(rt_sigtimedwait)
+ ENTRY_UHOH(rt_sigqueueinfo)
+ ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
+ ENTRY_SAME(chown) /* 180 */
+ /* *sockopt() might work... */
+ ENTRY_SAME(setsockopt)
+ ENTRY_SAME(getsockopt)
+ /* struct msghdr contains pointers... */
+ ENTRY_UHOH(sendmsg)
+ ENTRY_UHOH(recvmsg)
+ ENTRY_SAME(semop) /* 185 */
+ ENTRY_SAME(semget)
+ /* needs a more careful review */
+ ENTRY_UHOH(semctl)
+ /* struct msgbuf contains a long */
+ ENTRY_UHOH(msgsnd)
+ ENTRY_UHOH(msgrcv)
+ ENTRY_SAME(msgget) /* 190 */
+ /* struct msqid_ds contains pointers */
+ ENTRY_UHOH(msgctl)
+ ENTRY_SAME(shmat_wrapper)
+ ENTRY_SAME(shmdt)
+ ENTRY_SAME(shmget)
+ /***************/
+ /* struct shmid_ds contains pointers */
+ ENTRY_UHOH(shmctl) /* 195 */
+ ENTRY_SAME(ni_syscall) /* streams1 */
+ ENTRY_SAME(ni_syscall) /* streams2 */
+
+.end
+
+ /* Make sure nothing else is placed on this page */
+
+ .align 4096
+ .export end_linux_gateway_page
+end_linux_gateway_page:
+
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
new file mode 100644
index 000000000..7b3de0e0a
--- /dev/null
+++ b/arch/parisc/kernel/time.c
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/arm/kernel/time.c
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King
+ * Copyright (C) 1999 SuSE GmbH, (Philipp Rumpf, prumpf@tux.org)
+ *
+ * 1994-07-02 Alan Modra
+ * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
+ * 1998-12-20 Updated NTP code according to technical memorandum Jan '96
+ * "A Kernel Model for Precision Timekeeping" by Dave Mills
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.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 <asm/param.h>
+#include <asm/pdc.h>
+#include <asm/led.h>
+
+#include <linux/timex.h>
+
+extern rwlock_t xtime_lock;
+
+static int timer_value;
+static int timer_delta;
+static struct pdc_tod tod_data __attribute__((aligned(8)));
+
+void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int old;
+ int lost = 0;
+ int cr16;
+
+ old = timer_value;
+
+ cr16 = mfctl(16);
+ while((timer_value - cr16) < (timer_delta / 2)) {
+ timer_value += timer_delta;
+ lost++;
+ }
+
+ mtctl(timer_value ,16);
+
+ do_timer(regs);
+
+ led_interrupt_func();
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long flags;
+
+ read_lock_irqsave(&xtime_lock, flags);
+ tv->tv_sec = xtime.tv_sec;
+ tv->tv_usec = xtime.tv_usec;
+ read_unlock_irqrestore(&xtime_lock, flags);
+
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+ write_lock_irq(&xtime_lock);
+ xtime.tv_sec = tv->tv_sec;
+ xtime.tv_usec = tv->tv_usec;
+ write_unlock_irq(&xtime_lock);
+}
+
+void __init time_init(void)
+{
+ timer_delta = (100 * PAGE0->mem_10msec) / HZ;
+
+ /* make the first timer interrupt go off in one second */
+ timer_value = mfctl(16) + (HZ * timer_delta);
+ mtctl(timer_value, 16);
+
+
+ if(pdc_tod_read(&tod_data) == 0) {
+ xtime.tv_sec = tod_data.tod_sec;
+ xtime.tv_usec = tod_data.tod_usec;
+ } else {
+ printk(KERN_ERR "Error reading tod clock\n");
+ xtime.tv_sec = 0;
+ xtime.tv_usec = 0;
+ }
+
+}
+
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
new file mode 100644
index 000000000..d85553702
--- /dev/null
+++ b/arch/parisc/kernel/traps.c
@@ -0,0 +1,895 @@
+/*
+ * linux/arch/parisc/traps.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org>
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+
+#include <asm/smp.h>
+#include <asm/pdc.h>
+
+#ifdef CONFIG_KWDB
+#include <kdb/break.h> /* for BI2_KGDB_GDB */
+#include <kdb/kgdb_types.h> /* for __() */
+#include <kdb/save_state.h> /* for struct save_state */
+#include <kdb/kgdb_machine.h> /* for pt_regs_to_ssp and ssp_to_pt_regs */
+#include <kdb/trap.h> /* for I_BRK_INST */
+#endif /* CONFIG_KWDB */
+
+
+static inline void console_verbose(void)
+{
+ extern int console_loglevel;
+ console_loglevel = 15;
+}
+
+
+void page_exception(void);
+
+/*
+ * 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)
+
+int kstack_depth_to_print = 24;
+
+static void printbinary(unsigned long x, int nbits)
+{
+ unsigned long mask = 1UL << (nbits - 1);
+ while (mask != 0) {
+ printk(mask & x ? "1" : "0");
+ mask >>= 1;
+ }
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+#ifdef __LP64__
+#define RFMT " %016lx"
+#else
+#define RFMT " %08lx"
+#endif
+
+ printk("\n"); /* don't want to have that pretty register dump messed up */
+
+ printk(" YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\nPSW: ");
+ printbinary(regs->gr[0], 32);
+ printk("\n");
+
+ for (i = 0; i < 32; i += 4) {
+ int j;
+ printk("r%d-%d\t", i, i + 3);
+ for (j = 0; j < 4; j++) {
+ printk(RFMT, i + j == 0 ? 0 : regs->gr[i + j]);
+ }
+ printk("\n");
+ }
+
+ for (i = 0; i < 8; i += 4) {
+ int j;
+ printk("sr%d-%d\t", i, i + 4);
+ for (j = 0; j < 4; j++) {
+ printk(RFMT, regs->sr[i + j]);
+ }
+ printk("\n");
+ }
+
+#if REDICULOUSLY_VERBOSE
+ for (i = 0; i < 32; i++) {
+ printk("FR%2d : %016lx ", i, regs->fr[i]);
+ if ((i & 1) == 1)
+ printk("\n");
+ }
+#endif
+
+ printk("\nIASQ:" RFMT RFMT " IAOQ:" RFMT RFMT "\n",
+ regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
+ printk(" IIR: %08lx ISR:" RFMT " IOR:" RFMT "\nORIG_R28:" RFMT
+ "\n", regs->iir, regs->isr, regs->ior, regs->orig_r28);
+}
+
+void
+die_if_kernel (char *str, struct pt_regs *regs, long err)
+{
+ if (user_mode(regs)) {
+#if 1
+ if (err == 0)
+ return; /* STFU */
+
+ /* XXX for debugging only */
+ printk ("!!die_if_kernel: %s(%d): %s %ld\n",
+ current->comm, current->pid, str, err);
+ show_regs(regs);
+#endif
+ return;
+ }
+
+ printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);
+
+ show_regs(regs);
+
+ /* Wot's wrong wif bein' racy? */
+ if (current->thread.flags & PARISC_KERNEL_DEATH) {
+ printk("die_if_kernel recursion detected.\n");
+ sti();
+ while (1);
+ }
+ current->thread.flags |= PARISC_KERNEL_DEATH;
+ do_exit(SIGSEGV);
+}
+
+asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code)
+{
+}
+
+asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
+{
+}
+
+#ifndef CONFIG_MATH_EMULATION
+
+asmlinkage void math_emulate(long arg)
+{
+}
+
+#endif /* CONFIG_MATH_EMULATION */
+
+int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
+{
+ return syscall(regs);
+}
+
+struct {
+ int retval;
+
+ int (*func) (void *, struct pt_regs *);
+ void * data;
+} ipi_action[NR_CPUS];
+
+void ipi_interrupt(int irq, void *unused, struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+
+ if(!ipi_action[cpu].func)
+ BUG();
+
+ ipi_action[cpu].retval =
+ ipi_action[cpu].func(ipi_action[cpu].data, regs);
+}
+
+/* gdb uses break 4,8 */
+#define GDB_BREAK_INSN 0x10004
+void handle_gdb_break(struct pt_regs *regs, int wot)
+{
+ struct siginfo si;
+
+ si.si_code = wot;
+ si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ si.si_errno = 0;
+ force_sig_info(SIGTRAP, &si, current);
+}
+
+void handle_break(unsigned iir, struct pt_regs *regs)
+{
+ struct siginfo si;
+#ifdef CONFIG_KWDB
+ struct save_state ssp;
+#endif /* CONFIG_KWDB */
+
+ flush_all_caches();
+ switch(iir) {
+ case 0x00:
+ /* show registers, halt */
+ cli();
+ printk("break 0,0: pid=%d command='%s'\n",
+ current->pid, current->comm);
+ die_if_kernel("Breakpoint", regs, 0);
+ show_regs(regs);
+ si.si_code = TRAP_BRKPT;
+ si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ force_sig_info(SIGTRAP, &si, current);
+ break;
+
+ case GDB_BREAK_INSN:
+ die_if_kernel("Breakpoint", regs, 0);
+ handle_gdb_break(regs, TRAP_BRKPT);
+ break;
+
+#ifdef CONFIG_KWDB
+
+ case KGDB_BREAK_INSN:
+ mtctl(0, 15);
+ pt_regs_to_ssp(regs, &ssp);
+ kgdb_trap(I_BRK_INST, &ssp, 1);
+ ssp_to_pt_regs(&ssp, regs);
+ break;
+
+ case KGDB_INIT_BREAK_INSN:
+ mtctl(0, 15);
+ pt_regs_to_ssp(regs, &ssp);
+ kgdb_trap(I_BRK_INST, &ssp, 1);
+ ssp_to_pt_regs(&ssp, regs);
+
+ /* Advance pcoq to skip break */
+ regs->iaoq[0] = regs->iaoq[1];
+ regs->iaoq[1] += 4;
+ break;
+
+#endif /* CONFIG_KWDB */
+
+ default:
+ set_eiem(0);
+ printk("break %#08x: pid=%d command='%s'\n",
+ iir, current->pid, current->comm);
+ show_regs(regs);
+ si.si_signo = SIGTRAP;
+ si.si_code = TRAP_BRKPT;
+ si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ force_sig_info(SIGTRAP, &si, current);
+ return;
+ }
+}
+
+/* Format of the floating-point exception registers. */
+struct exc_reg {
+ unsigned int exception : 6;
+ unsigned int ei : 26;
+};
+
+/* Macros for grabbing bits of the instruction format from the 'ei'
+ field above. */
+/* Major opcode 0c and 0e */
+#define FP0CE_UID(i) (((i) >> 6) & 3)
+#define FP0CE_CLASS(i) (((i) >> 9) & 3)
+#define FP0CE_SUBOP(i) (((i) >> 13) & 7)
+#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
+#define FP0C_FORMAT(i) (((i) >> 11) & 3)
+#define FP0E_FORMAT(i) (((i) >> 11) & 1)
+
+/* Major opcode 0c, uid 2 (performance monitoring) */
+#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
+
+/* Major opcode 2e (fused operations). */
+#define FP2E_SUBOP(i) (((i) >> 5) & 1)
+#define FP2E_FORMAT(i) (((i) >> 11) & 1)
+
+/* Major opcode 26 (FMPYSUB) */
+/* Major opcode 06 (FMPYADD) */
+#define FPx6_FORMAT(i) ((i) & 0x1f)
+
+/* Flags and enable bits of the status word. */
+#define FPSW_FLAGS(w) ((w) >> 27)
+#define FPSW_ENABLE(w) ((w) & 0x1f)
+#define FPSW_V (1<<4)
+#define FPSW_Z (1<<3)
+#define FPSW_O (1<<2)
+#define FPSW_U (1<<1)
+#define FPSW_I (1<<0)
+
+/* Emulate a floating point instruction if necessary and possible
+ (this will be moved elsewhere eventually). Return zero if
+ successful or if emulation was not required, -1 if the instruction
+ is actually illegal or unimplemented. The status word passed as
+ the first parameter will be modified to signal exceptions, if
+ any. */
+
+/* FIXME!!! This is really incomplete and, at the moment, most
+ illegal FP instructions will simply act as no-ops. Obviously that
+ is *not* what we want. Also we don't even try to handle exception
+ types other than the 'unimplemented' ones. */
+int
+fp_emul_insn(u32 *sw, struct exc_reg exc, struct pt_regs *regs)
+{
+ switch (exc.exception) {
+ case 0x3: /* Unimplemented, opcode 06 */
+ break;
+ case 0x9: /* Unimplemented, opcode 0c */
+ /* We do not support quadword operations, end of
+ story. There's no support for them in GCC. */
+ if (FP0C_FORMAT(exc.ei) == 3)
+ return -1; /* SIGILL */
+ /* Fall through. */
+ case 0xa: /* Unimplemented, opcode 0e */
+ if (FP0CE_CLASS(exc.ei) == 1) {
+ /* FCNV instructions of various sorts. */
+ } else {
+ if (FP0CE_CLASS(exc.ei == 0)
+ && FP0CE_SUBOP(exc.ei == 5)) {
+ /* FRND instructions should be
+ emulated, at some point, I
+ guess. */
+ return -1; /* SIGILL */
+ }
+ }
+ break;
+ case 0x23: /* Unimplemented, opcode 26 */
+ break;
+ case 0x2b: /* Unimplemented, opcode 2e */
+ break;
+ case 0x1: /* Unimplemented, opcode 0e/0c */
+ /* FIXME: How the hell are we supposed to tell which
+ opcode it is? */
+ break;
+ default:
+ return -1; /* Punt */
+ }
+
+ return 0;
+}
+
+/* Handle a floating point exception. Return zero if the faulting
+ instruction can be completed successfully. */
+int
+handle_fpe(struct pt_regs *regs)
+{
+ struct siginfo si;
+ union {
+ struct fpsw {
+ /* flag bits */
+ unsigned int fv : 1;
+ unsigned int fz : 1;
+ unsigned int fo : 1;
+ unsigned int fu : 1;
+ unsigned int fi : 1;
+
+ unsigned int c : 1;
+ unsigned int pad1 : 4;
+ unsigned int cq : 11;
+ unsigned int rm : 2;
+ unsigned int pad2 : 2;
+ unsigned int t : 1;
+ unsigned int d : 1;
+
+ /* enable bits */
+ unsigned int ev : 1;
+ unsigned int ez : 1;
+ unsigned int eo : 1;
+ unsigned int eu : 1;
+ unsigned int ei : 1;
+ } status;
+ u32 word;
+ } sw;
+ struct exc_reg excepts[7];
+ unsigned int code = 0;
+ unsigned int throw;
+
+ /* Status word = FR0L. */
+ memcpy(&sw, regs->fr, sizeof(sw));
+ /* Exception words = FR0R-FR3R. */
+ memcpy(excepts, ((char *) regs->fr) + 4, sizeof(excepts));
+
+ /* This is all CPU dependent. Since there is no public
+ documentation on the PA2.0 processors we will just assume
+ everything is like the 7100/7100LC/7300LC for now.
+
+ Specifically: All exceptions are marked as "unimplemented"
+ in the exception word, and the only exception word used is
+ excepts[1]. */
+
+ /* Try to emulate the instruction. Also determine if it is
+ really an illegal instruction in the process.
+
+ FIXME: fp_emul_insn() only checks for the "unimplemented"
+ exceptions at the moment. So this may break horribly on
+ PA2.0, where we may want to also check to see if we should
+ just send SIGFPE (or maybe not, let's see the documentation
+ first...) */
+ if (fp_emul_insn(&sw.word, excepts[1], regs) == -1)
+ goto send_sigill;
+
+ /* Take the intersection of the flag bits in the FPSW and the
+ enable bits in the FPSW. */
+ throw = FPSW_FLAGS(sw.word) & FPSW_ENABLE(sw.word);
+
+ /* Concoct an appropriate si_code. Of course we don't know
+ what to do if multiple exceptions were enabled and multiple
+ flags were set. Maybe that's why HP/UX doesn't implement
+ feenableexcept(). */
+
+ if (throw == 0)
+ goto success; /* Duh. */
+ else if (throw & FPSW_V)
+ code = FPE_FLTINV;
+ else if (throw & FPSW_Z)
+ code = FPE_FLTDIV;
+ else if (throw & FPSW_O)
+ code = FPE_FLTOVF;
+ else if (throw & FPSW_U)
+ code = FPE_FLTUND;
+ else if (throw & FPSW_I)
+ code = FPE_FLTRES;
+
+#if 1 /* Debugging... */
+ printk("Unemulated floating point exception, pid=%d (%s)\n",
+ current->pid, current->comm);
+ show_regs(regs);
+ {
+ int i;
+ printk("FP Status: %08x\n", sw.word);
+ printk("FP Exceptions:\n");
+ for (i = 0; i < 7; i++) {
+ printk("\tExcept%d: exception %03x insn %06x\n",
+ i, excepts[i].exception, excepts[i].ei);
+ }
+ }
+#endif
+
+ /* FIXME: Should we clear the flag bits, T bit, and exception
+ registers here? */
+
+ si.si_signo = SIGFPE;
+ si.si_errno = 0;
+ si.si_code = code;
+ si.si_addr = (void *) regs->iaoq[0];
+ force_sig_info(SIGFPE, &si, current);
+ return -1;
+
+ send_sigill:
+ si.si_signo = SIGILL;
+ si.si_errno = 0;
+ si.si_code = ILL_COPROC;
+ si.si_addr = (void *) regs->iaoq[0];
+ force_sig_info(SIGILL, &si, current);
+ return -1;
+
+ success:
+ /* We absolutely have to clear the T bit and exception
+ registers to allow the process to recover. Otherwise every
+ subsequent floating point instruction will trap. */
+ sw.status.t = 0;
+ memset(excepts, 0, sizeof(excepts));
+
+ memcpy(regs->fr, &sw, sizeof(sw));
+ memcpy(((char *) regs->fr) + 4,excepts , sizeof(excepts));
+ return 0;
+}
+
+int handle_toc(void)
+{
+ return 0;
+}
+
+void default_trap(int code, struct pt_regs *regs)
+{
+ printk("Trap %d on CPU %d\n", code, smp_processor_id());
+
+ show_regs(regs);
+}
+
+void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
+
+
+#ifdef CONFIG_KWDB
+int
+debug_call (void) {
+ printk ("Debug call.\n");
+ return 0;
+}
+
+int
+debug_call_leaf (void) {
+ return 0;
+}
+#endif /* CONFIG_KWDB */
+
+extern void do_page_fault(struct pt_regs *, int, unsigned long);
+extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long);
+extern void transfer_pim_to_trap_frame(struct pt_regs *);
+extern void pdc_console_restart(void);
+
+void handle_interruption(int code, struct pt_regs *regs)
+{
+ unsigned long fault_address = 0;
+ unsigned long fault_space = 0;
+ struct siginfo si;
+#ifdef CONFIG_KWDB
+ struct save_state ssp;
+#endif /* CONFIG_KWDB */
+
+ if (code == 1)
+ pdc_console_restart(); /* switch back to pdc if HPMC */
+ else
+ sti();
+
+#ifdef __LP64__
+
+ /*
+ * FIXME:
+ * For 32 bit processes we don't want the b bits (bits 0 & 1)
+ * in the ior. This is more appropriately handled in the tlb
+ * miss handlers. Changes need to be made to support addresses
+ * >32 bits for 64 bit processes.
+ */
+
+ regs->ior &= 0x3FFFFFFFFFFFFFFFUL;
+#endif
+
+#if 0
+ printk("interrupted with code %d, regs %p\n", code, regs);
+ show_regs(regs);
+#endif
+
+ switch(code) {
+ case 1:
+ parisc_terminate("High Priority Machine Check (HPMC)",regs,code,0);
+ /* NOT REACHED */
+ case 3: /* Recovery counter trap */
+ regs->gr[0] &= ~PSW_R;
+ if (regs->iasq[0])
+ handle_gdb_break(regs, TRAP_TRACE);
+ /* else this must be the start of a syscall - just let it
+ * run.
+ */
+ return;
+
+ case 5:
+ flush_all_caches();
+ cpu_lpmc(5, regs);
+ return;
+
+ case 6:
+ fault_address = regs->iaoq[0];
+ fault_space = regs->iasq[0];
+ break;
+
+ case 9: /* Break Instruction */
+ handle_break(regs->iir,regs);
+ return;
+
+ case 14:
+ /* Assist Exception Trap, i.e. floating point exception. */
+ die_if_kernel("Floating point exception", regs, 0); /* quiet */
+ handle_fpe(regs);
+ return;
+ case 15:
+ case 16: /* Non-Access TLB miss faulting address is in IOR */
+ case 17:
+ case 26:
+ fault_address = regs->ior;
+ fault_space = regs->isr;
+
+ if (code == 26 && fault_space == 0)
+ parisc_terminate("Data access rights fault in kernel",regs,code,fault_address);
+ break;
+
+ case 19:
+ regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
+ /* fall thru */
+ case 21:
+ handle_gdb_break(regs, TRAP_HWBKPT);
+ return;
+
+ case 25: /* Taken branch trap */
+ regs->gr[0] &= ~PSW_T;
+ if (regs->iasq[0])
+ handle_gdb_break(regs, TRAP_BRANCH);
+ /* else this must be the start of a syscall - just let it
+ * run.
+ */
+ return;
+
+#if 0 /* def CONFIG_KWDB */
+ case I_TAKEN_BR: /* 25 */
+ mtctl(0, 15);
+ pt_regs_to_ssp(regs, &ssp);
+ kgdb_trap(I_TAKEN_BR, &ssp, 1);
+ ssp_to_pt_regs(&ssp, regs);
+ break;
+#endif /* CONFIG_KWDB */
+
+ case 8:
+ die_if_kernel("Illegal instruction", regs, code);
+ si.si_code = ILL_ILLOPC;
+ goto give_sigill;
+
+ case 10:
+ die_if_kernel("Priviledged operation - shouldn't happen!", regs, code);
+ si.si_code = ILL_PRVOPC;
+ goto give_sigill;
+ case 11:
+ die_if_kernel("Priviledged register - shouldn't happen!", regs, code);
+ si.si_code = ILL_PRVREG;
+ give_sigill:
+ si.si_signo = SIGILL;
+ si.si_errno = 0;
+ si.si_addr = (void *) regs->iaoq[0];
+ force_sig_info(SIGILL, &si, current);
+ return;
+
+ case 28: /* Unaligned just causes SIGBUS for now */
+ die_if_kernel("Unaligned data reference", regs, code);
+ si.si_code = BUS_ADRALN;
+ si.si_signo = SIGBUS;
+ si.si_errno = 0;
+ si.si_addr = (void *) regs->ior;
+ force_sig_info(SIGBUS, &si, current);
+ return;
+
+ default:
+ if (user_mode(regs)) {
+ printk("\nhandle_interruption() pid=%d command='%s'\n",
+ current->pid, current->comm);
+ show_regs(regs);
+ /* SIGBUS, for lack of a better one. */
+ si.si_signo = SIGBUS;
+ si.si_code = BUS_OBJERR;
+ si.si_errno = 0;
+ si.si_addr = (void *) regs->ior;
+ force_sig_info(SIGBUS, &si, current);
+ return;
+ }
+ parisc_terminate("Unexpected Interruption!",regs,code,0);
+ /* NOT REACHED */
+ }
+
+ if (user_mode(regs)) {
+ if (fault_space != regs->sr[7]) {
+ if (fault_space == 0)
+ printk("User Fault on Kernel Space ");
+ else /* this case should never happen, but whatever... */
+ printk("User Fault (long pointer) ");
+ printk("pid=%d command='%s'\n", current->pid, current->comm);
+ show_regs(regs);
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SEGV_MAPERR;
+ si.si_addr = (void *) regs->ior;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+ }
+ }
+ else {
+
+ /*
+ * The kernel should never fault on its own address space.
+ */
+
+ if (fault_space == 0)
+ parisc_terminate("Kernel Fault",regs,code,fault_address);
+ }
+
+#ifdef CONFIG_KWDB
+ debug_call_leaf ();
+#endif /* CONFIG_KWDB */
+
+ do_page_fault(regs, code, fault_address);
+
+ /*
+ * This should not be necessary.
+ * However, we do not currently
+ * implement flush_page_to_ram.
+ *
+ * The problem is that if we just
+ * brought in some code through the
+ * D-cache, the I-cache may not see
+ * it since it hasn't been flushed
+ * to ram.
+ */
+
+/* flush_all_caches(); */
+
+#if 0
+ printk("returning %p\n", regs);
+/* show_regs(regs); */
+#endif
+
+ return;
+
+}
+
+void show_stack(unsigned long sp)
+{
+#if 1
+ if ((sp & 0xc0000000UL) == 0xc0000000UL) {
+
+ __u32 *stackptr;
+ __u32 *dumpptr;
+
+ /* Stack Dump! */
+
+ stackptr = (__u32 *)sp;
+ dumpptr = (__u32 *)(sp & ~(INIT_TASK_SIZE - 1));
+ printk("\nDumping Stack from %p to %p:\n",dumpptr,stackptr);
+ while (dumpptr < stackptr) {
+ printk("%04x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ ((__u32)dumpptr) & 0xffff,
+ dumpptr[0], dumpptr[1], dumpptr[2], dumpptr[3],
+ dumpptr[4], dumpptr[5], dumpptr[6], dumpptr[7]);
+ dumpptr += 8;
+ }
+ }
+#endif
+}
+
+
+void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
+{
+ set_eiem(0);
+ cli();
+
+ if (code == 1)
+ transfer_pim_to_trap_frame(regs);
+
+#if 1
+ show_stack(regs->gr[30]);
+#endif
+
+ printk("\n%s: Code=%d regs=%p (Addr=%08lx)\n",msg,code,regs,offset);
+ show_regs(regs);
+
+ for(;;)
+ ;
+}
+
+void transfer_pim_to_trap_frame(struct pt_regs *regs)
+{
+ register int i;
+ extern unsigned int hpmc_pim_data[];
+ struct pdc_hpmc_pim_11 *pim_narrow;
+ struct pdc_hpmc_pim_20 *pim_wide;
+
+ if (boot_cpu_data.cpu_type >= pcxu) {
+
+ pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
+
+ /*
+ * Note: The following code will probably generate a
+ * bunch of truncation error warnings from the compiler.
+ * Could be handled with an ifdef, but perhaps there
+ * is a better way.
+ */
+
+ regs->gr[0] = pim_wide->cr[22];
+
+ for (i = 1; i < 32; i++)
+ regs->gr[i] = pim_wide->gr[i];
+
+ for (i = 0; i < 32; i++)
+ regs->fr[i] = pim_wide->fr[i];
+
+ for (i = 0; i < 8; i++)
+ regs->sr[i] = pim_wide->sr[i];
+
+ regs->iasq[0] = pim_wide->cr[17];
+ regs->iasq[1] = pim_wide->iasq_back;
+ regs->iaoq[0] = pim_wide->cr[18];
+ regs->iaoq[1] = pim_wide->iaoq_back;
+
+ regs->cr30 = pim_wide->cr[30];
+ regs->sar = pim_wide->cr[11];
+ regs->iir = pim_wide->cr[19];
+ regs->isr = pim_wide->cr[20];
+ regs->ior = pim_wide->cr[21];
+ }
+ else {
+ pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
+
+ regs->gr[0] = pim_narrow->cr[22];
+
+ for (i = 1; i < 32; i++)
+ regs->gr[i] = pim_narrow->gr[i];
+
+ for (i = 0; i < 32; i++)
+ regs->fr[i] = pim_narrow->fr[i];
+
+ for (i = 0; i < 8; i++)
+ regs->sr[i] = pim_narrow->sr[i];
+
+ regs->iasq[0] = pim_narrow->cr[17];
+ regs->iasq[1] = pim_narrow->iasq_back;
+ regs->iaoq[0] = pim_narrow->cr[18];
+ regs->iaoq[1] = pim_narrow->iaoq_back;
+
+ regs->cr30 = pim_narrow->cr[30];
+ regs->sar = pim_narrow->cr[11];
+ regs->iir = pim_narrow->cr[19];
+ regs->isr = pim_narrow->cr[20];
+ regs->ior = pim_narrow->cr[21];
+ }
+
+ /*
+ * The following fields only have meaning if we came through
+ * another path. So just zero them here.
+ */
+
+ regs->ksp = 0;
+ regs->kpc = 0;
+ regs->orig_r28 = 0;
+}
+
+int __init check_ivt(void *iva)
+{
+ int i;
+ u32 check = 0;
+ u32 *ivap;
+ u32 *hpmcp;
+ u32 length;
+ extern void os_hpmc(void);
+ extern void os_hpmc_end(void);
+
+ if(strcmp((char *)iva, "cows can fly"))
+ return -1;
+
+ ivap = (u32 *)iva;
+
+ for (i = 0; i < 8; i++)
+ *ivap++ = 0;
+
+ /* Compute Checksum for HPMC handler */
+
+ length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);
+ ivap[7] = length;
+
+ hpmcp = (u32 *)os_hpmc;
+
+ for(i=0; i<length/4; i++)
+ check += *hpmcp++;
+
+ for(i=0; i<8; i++)
+ check += ivap[i];
+
+ ivap[5] = -check;
+
+ return 0;
+}
+
+#ifndef __LP64__
+extern const void fault_vector_11;
+#endif
+extern const void fault_vector_20;
+
+void __init trap_init(void)
+{
+ volatile long eiem;
+ void *iva;
+
+ printk("trap_init\n");
+
+ if (boot_cpu_data.cpu_type >= pcxu)
+ iva = (void *) &fault_vector_20;
+ else
+#ifdef __LP64__
+ panic("Can't boot 64-bit OS on PA1.1 processor!");
+#else
+ iva = (void *) &fault_vector_11;
+#endif
+
+ if(check_ivt(iva))
+ panic("IVT invalid");
+
+ mtctl(0, 30);
+ mtctl(90000000, 16);
+ set_eiem(-1L);
+ mtctl(-1L, 23);
+ asm volatile ("rsm 0,%0" : "=r" (eiem));
+}
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
new file mode 100644
index 000000000..9f0670667
--- /dev/null
+++ b/arch/parisc/lib/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for parisc-specific library files..
+#
+
+
+L_TARGET = lib.a
+L_OBJS = lusercopy.o bitops.o checksum.o
+
+
+.S.o:
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c
new file mode 100644
index 000000000..c275c4246
--- /dev/null
+++ b/arch/parisc/lib/bitops.c
@@ -0,0 +1,60 @@
+/* atomic.c: atomic operations which got too long to be inlined all over
+ * the place.
+ *
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#ifdef CONFIG_SMP
+spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
+ [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+};
+#endif
+
+spinlock_t __atomic_lock = SPIN_LOCK_UNLOCKED;
+
+#ifndef __LP64__
+unsigned long __xchg(unsigned long x, unsigned long *ptr, int size)
+{
+ unsigned long temp, flags;
+
+ if (size != sizeof x) {
+ printk("__xchg called with bad pointer\n");
+ }
+ spin_lock_irqsave(&__atomic_lock, flags);
+ temp = *ptr;
+ *ptr = x;
+ spin_unlock_irqrestore(&__atomic_lock, flags);
+ return temp;
+}
+#else
+unsigned long __xchg(unsigned long x, unsigned long *ptr, int size)
+{
+ unsigned long temp, flags;
+ unsigned int *ptr32;
+
+ if (size == 8) {
+try_long:
+ spin_lock_irqsave(&__atomic_lock, flags);
+ temp = *ptr;
+ *ptr = x;
+ spin_unlock_irqrestore(&__atomic_lock, flags);
+ return temp;
+ }
+ if (size == 4) {
+ ptr32 = (unsigned int *)ptr;
+ spin_lock_irqsave(&__atomic_lock, flags);
+ temp = (unsigned long)*ptr32;
+ *ptr32 = (unsigned int)x;
+ spin_unlock_irqrestore(&__atomic_lock, flags);
+ return temp;
+ }
+
+ printk("__xchg called with bad pointer\n");
+ goto try_long;
+}
+#endif
diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
new file mode 100644
index 000000000..fa02027dd
--- /dev/null
+++ b/arch/parisc/lib/checksum.c
@@ -0,0 +1,130 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * MIPS specific IP/TCP/UDP checksumming routines
+ *
+ * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * 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.
+ *
+ * $Id: checksum.c,v 1.3 1997/12/01 17:57:34 ralf Exp $
+ */
+#include <net/checksum.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+static inline unsigned short from32to16(unsigned int x)
+{
+ /* 32 bits --> 16 bits + carry */
+ x = (x & 0xffff) + (x >> 16);
+ /* 16 bits + carry --> 16 bits including carry */
+ x = (x & 0xffff) + (x >> 16);
+ return (unsigned short)x;
+}
+
+static inline unsigned int do_csum(const unsigned char * buff, int len)
+{
+ int odd, count;
+ unsigned int result = 0;
+
+ if (len <= 0)
+ goto out;
+ odd = 1 & (unsigned long) buff;
+ if (odd) {
+ result = be16_to_cpu(*buff);
+ len--;
+ buff++;
+ }
+ count = len >> 1; /* nr of 16-bit words.. */
+ if (count) {
+ if (2 & (unsigned long) buff) {
+ result += *(unsigned short *) buff;
+ count--;
+ len -= 2;
+ buff += 2;
+ }
+ count >>= 1; /* nr of 32-bit words.. */
+ if (count) {
+ unsigned int carry = 0;
+ do {
+ unsigned int w = *(unsigned int *) buff;
+ count--;
+ buff += 4;
+ result += carry;
+ result += w;
+ carry = (w > result);
+ } while (count);
+ result += carry;
+ result = (result & 0xffff) + (result >> 16);
+ }
+ if (len & 2) {
+ result += *(unsigned short *) buff;
+ buff += 2;
+ }
+ }
+ if (len & 1)
+ result += le16_to_cpu(*buff);
+ result = from32to16(result);
+ if (odd)
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+ return result;
+}
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+{
+ unsigned int result = do_csum(buff, len);
+
+ /* add in old sum, and carry.. */
+ result += sum;
+ if(sum > result)
+ result += 1;
+ return result;
+}
+
+/*
+ * copy while checksumming, otherwise like csum_partial
+ */
+unsigned int csum_partial_copy(const char *src, char *dst,
+ int len, unsigned int sum)
+{
+ /*
+ * It's 2:30 am and I don't feel like doing it real ...
+ * This is lots slower than the real thing (tm)
+ */
+ sum = csum_partial(src, len, sum);
+ memcpy(dst, src, len);
+
+ return sum;
+}
+
+/*
+ * Copy from userspace and compute checksum. If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user (const char *src, char *dst,
+ int len, unsigned int sum,
+ int *err_ptr)
+{
+ int missing;
+
+ missing = copy_from_user(dst, src, len);
+ if (missing) {
+ memset(dst + len - missing, 0, missing);
+ *err_ptr = -EFAULT;
+ }
+
+ return csum_partial(dst, len, sum);
+}
diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S
new file mode 100644
index 000000000..b4b88b53c
--- /dev/null
+++ b/arch/parisc/lib/lusercopy.S
@@ -0,0 +1,242 @@
+/*------------------------------------------------------------------------------
+ * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ *
+ * Assembly Language User Access Routines
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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.
+ */
+
+/*
+ * These routines still have plenty of room for optimization
+ * (word & doubleword load/store, dual issue, store hints, etc.).
+ */
+
+/*
+ * The following routines assume that space register 3 (sr3) contains
+ * the space id associated with the current users address space.
+ */
+
+
+ .level 1.1
+ .text
+
+#include <asm/assembly.h>
+#include <asm/errno.h>
+
+ /*
+ * get_sr gets the appropriate space value into
+ * sr1 for kernel/user space access, depending
+ * on the flag stored in the task structure.
+ */
+
+ /* FIXME! depi below has hardcoded idea of kernel stack size */
+
+ .macro get_sr
+ copy %r30,%r1 ;! Get task structure
+ depi 0,31,14,%r1 ;! into r1
+ ldw TASK_SEGMENT(%r1),%r22
+ mfsp %sr3,%r1
+ or,<> %r22,%r0,%r0
+ copy %r0,%r1
+ mtsp %r1,%sr1
+ .endm
+
+ /*
+ * unsigned long
+ * lcopy_to_user(void *to, const void *from, unsigned long n)
+ *
+ * Returns 0 for success.
+ * otherwise, returns number of bytes not transferred.
+ */
+
+ .export lcopy_to_user,code
+lcopy_to_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,=,n 0,%r24,$lctu_done
+ get_sr
+$lctu_loop:
+ ldbs,ma 1(%r25),%r1
+ addib,<> -1,%r24,$lctu_loop
+1: stbs,ma %r1,1(%sr1,%r26)
+$lctu_done:
+ bv %r0(%r2)
+ copy %r24,%r28
+ .exit
+
+2: b $lctu_done
+ ldo 1(%r24),%r24
+
+ .section __ex_table,"a"
+ .word 1b,(2b-1b)
+ .previous
+
+ .procend
+
+ /*
+ * unsigned long
+ * lcopy_from_user(void *to, const void *from, unsigned long n)
+ *
+ * Returns 0 for success.
+ * otherwise, returns number of bytes not transferred.
+ *
+ * NOTE: This routine will also zero any bytes in the
+ * destination that were not copied due to a fault.
+ *
+ */
+
+ .export lcopy_from_user,code
+lcopy_from_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,=,n 0,%r24,$lcfu_done
+ get_sr
+$lcfu_loop:
+1: ldbs,ma 1(%sr1,%r25),%r1
+ addib,<> -1,%r24,$lcfu_loop
+ stbs,ma %r1,1(%r26)
+$lcfu_done:
+ bv %r0(%r2)
+ copy %r24,%r28
+ .exit
+
+2: copy %r24,%r23
+$lcfu_zero_loop:
+ addib,<> -1,%r23,$lcfu_zero_loop
+ stbs,ma %r0,1(%r26)
+ b $lcfu_done
+ nop
+
+ .section __ex_table,"a"
+ .word 1b,(2b-1b)
+ .previous
+
+ .procend
+
+ /*
+ * long lstrncpy_from_user(char *dst, const char *src, long n)
+ *
+ * Returns -EFAULT if exception before terminator,
+ * N if the entire buffer filled,
+ * otherwise strlen + 1 (i.e. includes zero byte)
+ */
+
+ .export lstrncpy_from_user,code
+lstrncpy_from_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,= 0,%r24,$lsfu_done
+ copy %r26,%r23
+ get_sr
+1: ldbs,ma 1(%sr1,%r25),%r1
+$lsfu_loop:
+ stbs,ma %r1,1(%r26)
+ comib,=,n 0,%r1,$lsfu_done
+ addib,<>,n -1,%r24,$lsfu_loop
+2: ldbs,ma 1(%sr1,%r25),%r1
+$lsfu_done:
+ sub %r26,%r23,%r28
+$lsfu_exit:
+ bv %r0(%r2)
+ nop
+ .exit
+
+3: b $lsfu_exit
+ ldi -EFAULT,%r28
+
+ .section __ex_table,"a"
+ .word 1b,(3b-1b)
+ .word 2b,(2b-1b)
+ .previous
+
+ .procend
+
+ /*
+ * unsigned long lclear_user(void *to, unsigned long n)
+ *
+ * Returns 0 for success.
+ * otherwise, returns number of bytes not transferred.
+ */
+
+ .export lclear_user,code
+lclear_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,=,n 0,%r25,$lclu_done
+ get_sr
+$lclu_loop:
+ addib,<> -1,%r25,$lclu_loop
+1: stbs,ma %r0,1(%sr1,%r26)
+
+$lclu_done:
+ bv %r0(%r2)
+ copy %r25,%r28
+ .exit
+
+2: b $lclu_done
+ ldo 1(%r25),%r25
+
+ .section __ex_table,"a"
+ .word 1b,(2b-1b)
+ .previous
+
+ .procend
+
+ /*
+ * long lstrnlen_user(char *s, long n)
+ *
+ * Returns 0 if exception before zero byte or reaching N,
+ * N+1 if N would be exceeded,
+ * else strlen + 1 (i.e. includes zero byte).
+ */
+
+ .export lstrnlen_user,code
+lstrnlen_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,= 0,%r25,$lslen_nzero
+ copy %r26,%r24
+ get_sr
+1: ldbs,ma 1(%sr1,%r26),%r1
+$lslen_loop:
+ comib,=,n 0,%r1,$lslen_done
+ addib,<> -1,%r25,$lslen_loop
+2: ldbs,ma 1(%sr1,%r26),%r1
+$lslen_done:
+ bv %r0(%r2)
+ sub %r26,%r24,%r28
+ .exit
+
+$lslen_nzero:
+ b $lslen_done
+ ldo 1(%r26),%r26 /* special case for N == 0 */
+
+3: b $lslen_done
+ copy %r24,%r26 /* reset r26 so 0 is returned on fault */
+
+ .section __ex_table,"a"
+ .word 1b,(3b-1b)
+ .word 2b,(2b-1b)
+ .previous
+
+ .procend
+
+ .end
diff --git a/arch/parisc/mm/Makefile b/arch/parisc/mm/Makefile
new file mode 100644
index 000000000..819872a7f
--- /dev/null
+++ b/arch/parisc/mm/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the linux parisc-specific parts of the memory manager.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := mm.o
+O_OBJS := init.o fault.o kmap.o extable.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/mm/extable.c b/arch/parisc/mm/extable.c
new file mode 100644
index 000000000..705688934
--- /dev/null
+++ b/arch/parisc/mm/extable.c
@@ -0,0 +1,69 @@
+/*
+ * Kernel exception handling table support. Derived from arch/i386/mm/extable.c.
+ *
+ * Copyright (C) 2000 Hewlett-Packard Co
+ * Copyright (C) 2000 John Marvin (jsm@fc.hp.com)
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <asm/uaccess.h>
+
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline const struct exception_table_entry *
+search_one_table (const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long addr)
+{
+ /* Abort early if the search value is out of range. */
+
+ if ((addr < first->addr) || (addr > last->addr))
+ return 0;
+
+ while (first <= last) {
+ const struct exception_table_entry *mid;
+ long diff;
+
+ mid = first + ((last - first)/2);
+ diff = mid->addr - addr;
+
+ if (diff == 0)
+ return mid;
+ else if (diff < 0)
+ first = mid+1;
+ else
+ last = mid-1;
+ }
+
+ return 0;
+}
+
+const struct exception_table_entry *
+search_exception_table (unsigned long addr)
+{
+#ifndef CONFIG_MODULE
+ /* There is only the kernel to search. */
+ return search_one_table(__start___ex_table,
+ __stop___ex_table - 1,
+ addr);
+#else
+ struct exception_table_entry *ret;
+ /* The kernel is the last "module" -- no need to treat it special. */
+ struct module *mp;
+
+ for (mp = module_list; mp ; mp = mp->next) {
+ if (!mp->ex_table_start)
+ continue;
+ ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1,
+ addr);
+ if (ret)
+ return ret;
+ }
+ return 0;
+#endif
+}
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
new file mode 100644
index 000000000..68d4614ec
--- /dev/null
+++ b/arch/parisc/mm/fault.c
@@ -0,0 +1,283 @@
+/* $Id: fault.c,v 1.5 2000/01/26 16:20:29 jsm Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
+ * Copyright 1999 Hewlett Packard Co.
+ *
+ */
+
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/uaccess.h>
+
+
+/* Defines for parisc_acctyp() */
+#define READ 0
+#define WRITE 1
+
+/* Various important other fields */
+#define bit22set(x) (x & 0x00000200)
+#define bits23_25set(x) (x & 0x000001c0)
+#define isGraphicsFlushRead(x) ((x & 0xfc003fdf) == 0x04001a80)
+ /* extended opcode is 0x6a */
+
+#define BITSSET 0x1c0 /* for identifying LDCW */
+
+/*
+ * parisc_acctyp(unsigned int inst) --
+ * Given a PA-RISC memory access instruction, determine if the
+ * the instruction would perform a memory read or memory write
+ * operation.
+ *
+ * This function assumes that the given instruction is a memory access
+ * instruction (i.e. you should really only call it if you know that
+ * the instruction has generated some sort of a memory access fault).
+ *
+ * Returns:
+ * VM_READ if read operation
+ * VM_WRITE if write operation
+ * VM_EXEC if execute operation
+ */
+static unsigned long
+parisc_acctyp(unsigned long code, unsigned int inst)
+{
+ if (code == 6 || code == 16)
+ return VM_EXEC;
+
+ switch (inst & 0xf0000000) {
+ case 0x40000000: /* load */
+ case 0x50000000: /* new load */
+ return VM_READ;
+
+ case 0x60000000: /* store */
+ case 0x70000000: /* new store */
+ return VM_WRITE;
+
+ case 0x20000000: /* coproc */
+ case 0x30000000: /* coproc2 */
+ if (bit22set(inst))
+ return VM_WRITE;
+
+ case 0x0: /* indexed/memory management */
+ if (bit22set(inst)) {
+ /*
+ * Check for the 'Graphics Flush Read' instruction.
+ * It resembles an FDC instruction, except for bits
+ * 20 and 21. Any combination other than zero will
+ * utilize the block mover functionality on some
+ * older PA-RISC platforms. The case where a block
+ * move is performed from VM to graphics IO space
+ * should be treated as a READ.
+ *
+ * The significance of bits 20,21 in the FDC
+ * instruction is:
+ *
+ * 00 Flush data cache (normal instruction behavior)
+ * 01 Graphics flush write (IO space -> VM)
+ * 10 Graphics flush read (VM -> IO space)
+ * 11 Graphics flush read/write (VM <-> IO space)
+ */
+ if (isGraphicsFlushRead(inst))
+ return VM_READ;
+ return VM_WRITE;
+ } else {
+ /*
+ * Check for LDCWX and LDCWS (semaphore instructions).
+ * If bits 23 through 25 are all 1's it is one of
+ * the above two instructions and is a write.
+ *
+ * Note: With the limited bits we are looking at,
+ * this will also catch PROBEW and PROBEWI. However,
+ * these should never get in here because they don't
+ * generate exceptions of the type:
+ * Data TLB miss fault/data page fault
+ * Data memory protection trap
+ */
+ if (bits23_25set(inst) == BITSSET)
+ return VM_WRITE;
+ }
+ return VM_READ; /* Default */
+ }
+ return VM_READ; /* Default */
+}
+
+#undef bit22set
+#undef bits23_25set
+#undef isGraphicsFlushRead
+#undef BITSSET
+
+/* This is similar to expand_stack(), except that it is for stacks
+ * that grow upwards.
+ */
+
+static inline int expand_stackup(struct vm_area_struct * vma, unsigned long address)
+{
+ unsigned long grow;
+
+ address += 4 + PAGE_SIZE - 1;
+ address &= PAGE_MASK;
+ grow = (address - vma->vm_end) >> PAGE_SHIFT;
+ if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur ||
+ ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)
+ return -ENOMEM;
+ vma->vm_end = address;
+ vma->vm_mm->total_vm += grow;
+ if (vma->vm_flags & VM_LOCKED)
+ vma->vm_mm->locked_vm += grow;
+ return 0;
+}
+
+
+/* This is similar to find_vma(), except that it understands that stacks
+ * grow up rather than down.
+ * XXX Optimise by making use of cache and avl tree as per find_vma().
+ */
+
+struct vm_area_struct * pa_find_vma(struct mm_struct * mm, unsigned long addr)
+{
+ struct vm_area_struct *vma = NULL;
+
+ if (mm) {
+ vma = mm->mmap;
+ if (!vma || addr < vma->vm_start)
+ return NULL;
+ while (vma->vm_next && addr >= vma->vm_next->vm_start)
+ vma = vma->vm_next;
+ }
+ return vma;
+}
+
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long);
+
+void do_page_fault(struct pt_regs *regs, unsigned long code,
+ unsigned long address)
+{
+ struct vm_area_struct * vma;
+ struct task_struct *tsk = current;
+ struct mm_struct *mm = tsk->mm;
+ const struct exception_table_entry *fix;
+ unsigned long acc_type;
+
+ if (in_interrupt() || !mm)
+ goto no_context;
+
+ down(&mm->mmap_sem);
+ vma = pa_find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+ if (address < vma->vm_end)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSUP) || expand_stackup(vma, address))
+ goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access. We still need to
+ * check the access permissions.
+ */
+
+good_area:
+
+ acc_type = parisc_acctyp(code,regs->iir);
+
+ if ((vma->vm_flags & acc_type) != acc_type)
+ goto bad_area;
+
+ /*
+ * If for any reason at all we couldn't handle the fault, make
+ * sure we exit gracefully rather than endlessly redo the
+ * fault.
+ */
+
+ switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) {
+ case 1:
+ ++current->min_flt;
+ break;
+ case 2:
+ ++current->maj_flt;
+ break;
+ case 0:
+ /*
+ * We ran out of memory, or some other thing happened
+ * to us that made us unable to handle the page fault
+ * gracefully.
+ */
+ goto bad_area;
+ default:
+ goto out_of_memory;
+ }
+ up(&mm->mmap_sem);
+ return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ */
+bad_area:
+ up(&mm->mmap_sem);
+
+ if (user_mode(regs)) {
+ struct siginfo si;
+
+ printk("\ndo_page_fault() pid=%d command='%s'\n",
+ tsk->pid, tsk->comm);
+ show_regs(regs);
+ /* FIXME: actually we need to get the signo and code correct */
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SEGV_MAPERR;
+ si.si_addr = (void *) address;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+ }
+
+no_context:
+
+ if (!user_mode(regs)) {
+
+ fix = search_exception_table(regs->iaoq[0]);
+
+ if (fix) {
+
+ if (fix->skip & 1)
+ regs->gr[8] = -EFAULT;
+ if (fix->skip & 2)
+ regs->gr[9] = 0;
+
+ regs->iaoq[0] += ((fix->skip) & ~3);
+
+ /*
+ * NOTE: In some cases the faulting instruction
+ * may be in the delay slot of a branch. We
+ * don't want to take the branch, so we don't
+ * increment iaoq[1], instead we set it to be
+ * iaoq[0]+4, and clear the B bit in the PSW
+ */
+
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */
+
+ return;
+ }
+ }
+
+ parisc_terminate("Bad Address (null pointer deref?)",regs,code,address);
+
+ out_of_memory:
+ up(&mm->mmap_sem);
+ printk("VM: killing process %s\n", current->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ goto no_context;
+}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
new file mode 100644
index 000000000..c3e16c463
--- /dev/null
+++ b/arch/parisc/mm/init.c
@@ -0,0 +1,479 @@
+/*
+ * linux/arch/parisc/mm/init.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright 1999 SuSE GmbH
+ * changed by Philipp Rumpf
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ *
+ */
+
+#include <linux/config.h>
+
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h> /* for hppa_dma_ops and pcxl_dma_ops */
+#include <linux/swap.h>
+#include <linux/unistd.h>
+
+#include <asm/pgalloc.h>
+
+static unsigned long totalram_pages;
+extern unsigned long max_pfn, mem_max;
+
+void free_initmem(void) {
+}
+
+/*
+ * Just an arbitrary offset to serve as a "hole" between mapping areas
+ * (between top of physical memory and a potential pcxl dma mapping
+ * area, and below the vmalloc mapping area).
+ *
+ * The current 32K value just means that there will be a 32K "hole"
+ * between mapping areas. 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 VM_MAP_OFFSET (32*1024)
+#define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
+ & ~(VM_MAP_OFFSET-1)))
+
+void *vmalloc_start;
+unsigned long pcxl_dma_start;
+
+void __init mem_init(void)
+{
+ max_mapnr = num_physpages = max_low_pfn;
+ high_memory = __va(max_low_pfn * PAGE_SIZE);
+
+ totalram_pages += free_all_bootmem();
+ printk("Memory: %luk available\n", totalram_pages << (PAGE_SHIFT-10));
+
+ if (hppa_dma_ops == &pcxl_dma_ops) {
+ pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(high_memory);
+ vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE);
+ }
+ else {
+ pcxl_dma_start = 0;
+ vmalloc_start = SET_MAP_OFFSET(high_memory);
+ }
+}
+
+void __bad_pgd(pgd_t *pgd)
+{
+ printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
+ pgd_val(*pgd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+}
+
+void __bad_pmd(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+ pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+ pte_t *pte;
+
+ pte = (pte_t *) __get_free_page(GFP_KERNEL);
+
+ if (pmd_none(*pmd)) {
+ if (pte) {
+ clear_page(pte);
+ pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)pte);
+ return pte + offset;
+ }
+ pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+ return NULL;
+ }
+
+ free_page((unsigned long)pte);
+
+ if (pmd_bad(*pmd)) {
+ __bad_pmd(pmd);
+ return NULL;
+ }
+
+ return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+int do_check_pgt_cache(int low, int high)
+{
+ return 0;
+}
+
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving an inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+pte_t * __bad_pagetable(void)
+{
+ return (pte_t *) NULL;
+}
+
+unsigned long *empty_zero_page;
+unsigned long *empty_bad_page;
+
+pte_t __bad_page(void)
+{
+ return *(pte_t *)NULL;
+}
+
+void show_mem(void)
+{
+ int i,free = 0,total = 0,reserved = 0;
+ int shared = 0, cached = 0;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ else if (!atomic_read(&mem_map[i].count))
+ free++;
+ else
+ shared += atomic_read(&mem_map[i].count) - 1;
+ }
+ printk("%d pages of RAM\n",total);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
+ show_buffers();
+}
+
+void set_pte_phys (unsigned long vaddr, unsigned long phys)
+{
+}
+
+
+/*
+ * pagetable_init() sets up the page tables
+ *
+ * Note that gateway_init() places the Linux gateway page at page 0.
+ * Since gateway pages cannot be dereferenced this has the desirable
+ * side effect of trapping those pesky NULL-reference errors in the
+ * kernel.
+ */
+static void __init pagetable_init(void)
+{
+ pgd_t *pg_dir;
+ pmd_t *pmd;
+ pte_t *pg_table;
+ unsigned long tmp1;
+ unsigned long tmp2;
+ unsigned long address;
+ unsigned long ro_start;
+ unsigned long ro_end;
+ unsigned long fv_addr;
+ extern const int stext;
+ extern int data_start;
+ extern const unsigned long fault_vector_20;
+
+ ro_start = __pa((unsigned long)&stext);
+ ro_end = __pa((unsigned long)&data_start);
+ fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
+
+ printk("pagetable_init\n");
+
+ /* Map whole memory from PAGE_OFFSET */
+ pg_dir = (pgd_t *)swapper_pg_dir + USER_PGD_PTRS;
+
+ address = 0;
+ while (address < mem_max) {
+ /* XXX: BTLB should be done here */
+
+#if PTRS_PER_PMD == 1
+ pmd = (pmd_t *)__pa(pg_dir);
+#else
+ pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir));
+
+ /*
+ * pmd is physical at this point
+ */
+
+ if (!pmd) {
+ pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ pmd = (pmd_t *) __pa(pmd);
+ }
+
+ pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd;
+#endif
+ pg_dir++;
+
+ /* now change pmd to kernel virtual addresses */
+
+ pmd = (pmd_t *) __va(pmd);
+ for (tmp1 = 0 ; tmp1 < PTRS_PER_PMD ; tmp1++,pmd++) {
+
+ /*
+ * pg_table is physical at this point
+ */
+
+ pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd));
+ if (!pg_table) {
+ pg_table = (pte_t *)
+ alloc_bootmem_low_pages(PAGE_SIZE);
+ pg_table = (pte_t *) __pa(pg_table);
+ }
+
+ pmd_val(*pmd) = _PAGE_TABLE |
+ (unsigned long) pg_table;
+
+ /* now change pg_table to kernel virtual addresses */
+
+ pg_table = (pte_t *) __va(pg_table);
+ for (tmp2=0; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
+ pte_t pte;
+
+#if !defined(CONFIG_KWDB) && !defined(CONFIG_STI_CONSOLE)
+#warning STI console should explicitly allocate executable pages but does not
+/* KWDB needs to write kernel text when setting break points.
+**
+** The right thing to do seems like KWDB modify only the pte which
+** has a break point on it...otherwise we might mask worse bugs.
+*/
+ if (address >= ro_start && address < ro_end
+ && address != fv_addr)
+ pte = __mk_pte(address, PAGE_KERNEL_RO);
+ else
+#endif
+ pte = __mk_pte(address, PAGE_KERNEL);
+
+ if (address >= mem_max)
+ pte_val(pte) = 0;
+
+ set_pte(pg_table, pte);
+
+ address += PAGE_SIZE;
+ }
+
+ if (address >= mem_max)
+ break;
+ }
+ }
+
+ empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
+ memset(empty_zero_page, 0, PAGE_SIZE);
+}
+
+unsigned long gateway_pgd_offset;
+unsigned long gateway_pgd_entry;
+
+static void __init gateway_init(void)
+{
+ unsigned long hpux_gateway_page_addr;
+ unsigned long linux_gateway_page_addr;
+ pgd_t *pg_dir;
+ pmd_t *pmd_base;
+ pmd_t *pmd;
+ pte_t *pg_table_base;
+ pte_t *pg_table;
+ /* FIXME: These are 'const' in order to trick the compiler
+ into not treating them as DP-relative data. */
+ extern void * const hpux_gateway_page;
+ extern void * const linux_gateway_page;
+ pte_t pte;
+
+ hpux_gateway_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK;
+ linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK;
+
+ gateway_pgd_offset = hpux_gateway_page_addr >> PGDIR_SHIFT;
+
+ /*
+ * Setup Linux Gateway page.
+ *
+ * The Linux gateway page will reside in kernel space (on virtual
+ * page 0), so it doesn't need to be aliased into user space.
+ */
+
+ pg_dir = (pgd_t *)swapper_pg_dir;
+
+#if PTRS_PER_PMD == 1
+ pmd_base = (pmd_t *)pg_dir;
+ pmd = pmd_base +
+ ((linux_gateway_page_addr) >> PGDIR_SHIFT);
+
+#else
+ pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
+ pgd_val(*(pg_dir + (linux_gateway_page_addr >> PGDIR_SHIFT))) =
+ _PAGE_TABLE | __pa(pmd_base);
+
+ pmd = pmd_base +
+ ((linux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
+ PMD_SHIFT);
+#endif
+
+ pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+
+ pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
+
+ pte = __mk_pte(__pa(&linux_gateway_page), PAGE_GATEWAY);
+
+ pg_table = pg_table_base +
+ ((linux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
+ PAGE_SHIFT);
+
+ set_pte(pg_table,pte);
+
+ /*
+ * Setup HP-UX gateway page.
+ * This page will be aliased into each user address space.
+ */
+
+ pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+
+ pte = __mk_pte(__pa(&hpux_gateway_page), PAGE_GATEWAY);
+ pg_table = pg_table_base +
+ ((hpux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
+ PAGE_SHIFT);
+
+ set_pte(pg_table,pte);
+
+
+#if PTRS_PER_PMD == 1
+ pmd_base = (pmd_t *)pg_table_base;
+#else
+ pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
+ pmd = pmd_base +
+ ((hpux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
+ PMD_SHIFT);
+ pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
+#endif
+
+ gateway_pgd_entry = _PAGE_TABLE | __pa(pmd_base);
+
+ /*
+ * We will be aliasing the HP-UX gateway page into all HP-UX
+ * user spaces at the same address (not counting the space register
+ * value) that will be equivalently mapped as long as space register
+ * hashing is disabled. It will be a problem if anyone touches
+ * the gateway pages at its "kernel" address, since that is
+ * NOT equivalently mapped. We'll flush the caches at this
+ * point, just in case some code has touched those addresses
+ * previous to this, but all bets are off if they get touched
+ * after this point.
+ */
+
+ flush_all_caches();
+
+ return;
+}
+
+void __init paging_init(void)
+{
+ pagetable_init();
+ gateway_init();
+
+ {
+ unsigned long zones_size[MAX_NR_ZONES] = { max_pfn/2, max_pfn/2, };
+
+ free_area_init(zones_size);
+ }
+}
+
+#define NR_SPACE_IDS 8192
+
+static unsigned long space_id[NR_SPACE_IDS / (8 * sizeof(long))];
+static unsigned long space_id_index;
+static unsigned long free_space_ids = NR_SPACE_IDS;
+
+/*
+ * XXX: We should probably unfold the set_bit / test_bit / clear_bit
+ * locking out of these two functions and have a single spinlock on the
+ * space_id data structures.
+ *
+ * Don't bother. This is all going to be significantly changed in the
+ * very near future.
+ */
+
+#define SPACEID_SHIFT (PAGE_SHIFT + (PT_NLEVELS)*(PAGE_SHIFT - PT_NLEVELS) - 32)
+
+unsigned long alloc_sid(void)
+{
+ unsigned long index;
+
+ if (free_space_ids == 0)
+ BUG();
+
+ free_space_ids--;
+
+ do {
+ index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index);
+ } while(test_and_set_bit(index, space_id));
+
+ space_id_index = index;
+
+ return index << SPACEID_SHIFT;
+}
+
+void free_sid(unsigned long spaceid)
+{
+ unsigned long index = spaceid >> SPACEID_SHIFT;
+ if (index < 0)
+ BUG();
+
+ clear_bit(index, space_id);
+
+ if (space_id_index > index) {
+ space_id_index = index;
+ }
+ free_space_ids++;
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+#if 0
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(mem_map + MAP_NR(start));
+ set_page_count(mem_map+MAP_NR(start), 1);
+ free_page(start);
+ totalram_pages++;
+ }
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+#endif
+}
+#endif
+
+void si_meminfo(struct sysinfo *val)
+{
+ int i;
+
+ i = max_mapnr;
+ val->totalram = totalram_pages;
+ val->sharedram = 0;
+ val->freeram = nr_free_pages();
+ val->bufferram = atomic_read(&buffermem_pages);
+#if 0
+ while (i-- > 0) {
+ if (PageReserved(mem_map+i))
+ continue;
+ val->totalram++;
+ if (!atomic_read(&mem_map[i].count))
+ continue;
+ val->sharedram += atomic_read(&mem_map[i].count) - 1;
+ }
+ val->totalram <<= PAGE_SHIFT;
+ val->sharedram <<= PAGE_SHIFT;
+#endif
+ val->totalhigh = 0;
+ val->freehigh = 0;
+ return;
+}
diff --git a/arch/parisc/mm/kmap.c b/arch/parisc/mm/kmap.c
new file mode 100644
index 000000000..686d540d9
--- /dev/null
+++ b/arch/parisc/mm/kmap.c
@@ -0,0 +1,143 @@
+/*
+** Stolen mostly from arch/parisc/kernel/pci-dma.c
+*/
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#include <asm/io.h>
+#include <asm/page.h> /* get_order */
+
+#undef flush_cache_all
+#define flush_cache_all flush_all_caches
+
+typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg);
+
+#if 0
+/* XXX This routine could be used with iterate_page() to replace
+ * unmap_uncached_page() and save a little code space but I didn't
+ * do that since I'm not certain whether this is the right path. -PB
+ */
+static void unmap_cached_pte(pte_t * pte, unsigned long arg)
+{
+ pte_t page = *pte;
+ pte_clear(pte);
+ if (!pte_none(page)) {
+ if (pte_present(page)) {
+ unsigned long map_nr = pte_pagenr(page);
+ if (map_nr < max_mapnr)
+ __free_page(mem_map + map_nr);
+ } else {
+ printk(KERN_CRIT
+ "Whee.. Swapped out page in kernel page table\n");
+ }
+ }
+}
+#endif
+
+/* These two routines should probably check a few things... */
+static void set_uncached(pte_t * pte, unsigned long arg)
+{
+ pte_val(*pte) |= _PAGE_NO_CACHE;
+}
+
+static void set_cached(pte_t * pte, unsigned long arg)
+{
+ pte_val(*pte) &= ~_PAGE_NO_CACHE;
+}
+
+static inline void iterate_pte(pmd_t * pmd, unsigned long address,
+ unsigned long size, pte_iterator_t op,
+ unsigned long arg)
+{
+ pte_t *pte;
+ unsigned long end;
+
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = pte_offset(pmd, address);
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ op(pte, arg);
+ address += PAGE_SIZE;
+ pte++;
+ } while (address < end);
+}
+
+static inline void iterate_pmd(pgd_t * dir, unsigned long address,
+ unsigned long size, pte_iterator_t op,
+ unsigned long arg)
+{
+ pmd_t *pmd;
+ unsigned long end;
+
+ if (pgd_none(*dir))
+ return;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return;
+ }
+ pmd = pmd_offset(dir, address);
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ iterate_pte(pmd, address, end - address, op, arg);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address < end);
+}
+
+static void iterate_pages(unsigned long address, unsigned long size,
+ pte_iterator_t op, unsigned long arg)
+{
+ pgd_t *dir;
+ unsigned long end = address + size;
+
+ dir = pgd_offset_k(address);
+ flush_cache_all();
+ do {
+ iterate_pmd(dir, address, end - address, op, arg);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ flush_tlb_all();
+}
+
+void
+kernel_set_cachemode(unsigned long vaddr, unsigned long size, int what)
+{
+ switch (what) {
+ case IOMAP_FULL_CACHING:
+ iterate_pages(vaddr, size, set_cached, 0);
+ flush_tlb_range(&init_mm, vaddr, size);
+ break;
+ case IOMAP_NOCACHE_SER:
+ iterate_pages(vaddr, size, set_uncached, 0);
+ flush_tlb_range(&init_mm, vaddr, size);
+ break;
+ default:
+ printk(KERN_CRIT
+ "kernel_set_cachemode mode %d not understood\n",
+ what);
+ break;
+ }
+}
diff --git a/arch/parisc/mm/pa11.c b/arch/parisc/mm/pa11.c
new file mode 100644
index 000000000..42f0d57f6
--- /dev/null
+++ b/arch/parisc/mm/pa11.c
@@ -0,0 +1,170 @@
+/* $Id: pa11.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $
+ *
+ * pa11.c: PA 1.1 specific mmu/cache code.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+#include <asm/mmu_context.h>
+
+extern unsigned long mips_tlb_entries;
+
+/* page functions */
+void pa11_clear_page(unsigned long page)
+{
+}
+
+static void pa11_copy_page(unsigned long to, unsigned long from)
+{
+}
+
+/* Cache operations. */
+static inline void pa11_flush_cache_all(void) { }
+static void pa11_flush_cache_mm(struct mm_struct *mm) { }
+static void pa11_flush_cache_range(struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end)
+{
+}
+
+static void pa11_flush_cache_page(struct vm_area_struct *vma,
+ unsigned long page)
+{
+}
+
+static void pa11_flush_page_to_ram(unsigned long page)
+{
+}
+
+static void pa11_flush_cache_sigtramp(unsigned long page)
+{
+}
+
+/* TLB operations. */
+static inline void pa11_flush_tlb_all(void)
+{
+ unsigned long flags;
+ int entry;
+
+ save_and_cli(flags);
+/* Here we will need to flush all the TLBs */
+ restore_flags(flags);
+}
+
+static void pa11_flush_tlb_mm(struct mm_struct *mm)
+{
+/* This is what the MIPS does.. Is it the right thing for PA-RISC? */
+ if(mm == current->mm)
+ pa11_flush_tlb_all();
+}
+
+static void pa11_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ if(mm == current->mm)
+ pa11_flush_tlb_all();
+}
+
+static void pa11_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ if(vma->vm_mm == current->mm)
+ pa11_flush_tlb_all();
+}
+
+static void pa11_load_pgd(unsigned long pg_dir)
+{
+ unsigned long flags;
+ /* We need to do the right thing here */
+}
+
+/*
+ * Initialize new page directory with pointers to invalid ptes
+ */
+static void pa11_pgd_init(unsigned long page)
+{
+ unsigned long dummy1, dummy2;
+
+}
+
+static void pa11_update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+ pa11_flush_tlb_page(vma, address);
+}
+
+static void pa11_show_regs(struct pt_regs * regs)
+{
+ /*
+ * Saved main processor registers
+ */
+ printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
+ (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
+ (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
+ (unsigned long) regs->regs[7]);
+ printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
+ (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
+ (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
+ (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
+ printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
+ (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
+ (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
+ (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
+ printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
+ (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
+ (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
+
+ /*
+ * Saved cp0 registers
+ */
+ printk("epc : %08lx\nStatus: %08x\nCause : %08x\n",
+ (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
+ (unsigned int) regs->cp0_cause);
+}
+
+static int pa11_user_mode(struct pt_regs *regs)
+{
+ /* Return user mode stuff?? */
+}
+
+__initfunc(void ld_mmu_pa11(void))
+{
+
+ /* Taken directly from the MIPS arch.. Lots of bad things here */
+ clear_page = pa11_clear_page;
+ copy_page = pa11_copy_page;
+
+ flush_cache_all = pa11_flush_cache_all;
+ flush_cache_mm = pa11_flush_cache_mm;
+ flush_cache_range = pa11_flush_cache_range;
+ flush_cache_page = pa11_flush_cache_page;
+ flush_cache_sigtramp = pa11_flush_cache_sigtramp;
+ flush_page_to_ram = pa11_flush_page_to_ram;
+
+ flush_tlb_all = pa11_flush_tlb_all;
+ flush_tlb_mm = pa11_flush_tlb_mm;
+ flush_tlb_range = pa11_flush_tlb_range;
+ flush_tlb_page = pa11_flush_tlb_page;
+ pa11_asid_setup();
+
+ load_pgd = pa11_load_pgd;
+ pgd_init = pa11_pgd_init;
+ update_mmu_cache = pa11_update_mmu_cache;
+
+ show_regs = pa11_show_regs;
+
+ add_wired_entry = pa11_add_wired_entry;
+
+ user_mode = pa11_user_mode;
+ flush_tlb_all();
+}
diff --git a/arch/parisc/mm/pa20.c b/arch/parisc/mm/pa20.c
new file mode 100644
index 000000000..cbc0343a0
--- /dev/null
+++ b/arch/parisc/mm/pa20.c
@@ -0,0 +1,170 @@
+/* $Id: pa20.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $
+ *
+ * pa20.c: PA 2.0 specific mmu/cache code.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+#include <asm/mmu_context.h>
+
+extern unsigned long mips_tlb_entries;
+
+/* page functions */
+void pa20_clear_page(unsigned long page)
+{
+}
+
+static void pa20_copy_page(unsigned long to, unsigned long from)
+{
+}
+
+/* Cache operations. */
+static inline void pa20_flush_cache_all(void) { }
+static void pa20_flush_cache_mm(struct mm_struct *mm) { }
+static void pa20_flush_cache_range(struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end)
+{
+}
+
+static void pa20_flush_cache_page(struct vm_area_struct *vma,
+ unsigned long page)
+{
+}
+
+static void pa20_flush_page_to_ram(unsigned long page)
+{
+}
+
+static void pa20_flush_cache_sigtramp(unsigned long page)
+{
+}
+
+/* TLB operations. */
+static inline void pa20_flush_tlb_all(void)
+{
+ unsigned long flags;
+ int entry;
+
+ save_and_cli(flags);
+/* Here we will need to flush all the TLBs */
+ restore_flags(flags);
+}
+
+static void pa20_flush_tlb_mm(struct mm_struct *mm)
+{
+/* This is what the MIPS does.. Is it the right thing for PA-RISC? */
+ if(mm == current->mm)
+ pa20_flush_tlb_all();
+}
+
+static void pa20_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ if(mm == current->mm)
+ pa20_flush_tlb_all();
+}
+
+static void pa20_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ if(vma->vm_mm == current->mm)
+ pa20_flush_tlb_all();
+}
+
+static void pa20_load_pgd(unsigned long pg_dir)
+{
+ unsigned long flags;
+ /* We need to do the right thing here */
+}
+
+/*
+ * Initialize new page directory with pointers to invalid ptes
+ */
+static void pa20_pgd_init(unsigned long page)
+{
+ unsigned long dummy1, dummy2;
+
+}
+
+static void pa20_update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+ pa20_flush_tlb_page(vma, address);
+}
+
+static void pa20_show_regs(struct pt_regs * regs)
+{
+ /*
+ * Saved main processor registers
+ */
+ printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
+ (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
+ (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
+ (unsigned long) regs->regs[7]);
+ printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
+ (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
+ (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
+ (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
+ printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
+ (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
+ (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
+ (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
+ printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
+ (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
+ (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
+
+ /*
+ * Saved cp0 registers
+ */
+ printk("epc : %08lx\nStatus: %08x\nCause : %08x\n",
+ (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
+ (unsigned int) regs->cp0_cause);
+}
+
+static int pa20_user_mode(struct pt_regs *regs)
+{
+ /* Return user mode stuff?? */
+}
+
+__initfunc(void ld_mmu_pa20(void))
+{
+
+ /* Taken directly from the MIPS arch.. Lots of bad things here */
+ clear_page = pa20_clear_page;
+ copy_page = pa20_copy_page;
+
+ flush_cache_all = pa20_flush_cache_all;
+ flush_cache_mm = pa20_flush_cache_mm;
+ flush_cache_range = pa20_flush_cache_range;
+ flush_cache_page = pa20_flush_cache_page;
+ flush_cache_sigtramp = pa20_flush_cache_sigtramp;
+ flush_page_to_ram = pa20_flush_page_to_ram;
+
+ flush_tlb_all = pa20_flush_tlb_all;
+ flush_tlb_mm = pa20_flush_tlb_mm;
+ flush_tlb_range = pa20_flush_tlb_range;
+ flush_tlb_page = pa20_flush_tlb_page;
+ pa20_asid_setup();
+
+ load_pgd = pa20_load_pgd;
+ pgd_init = pa20_pgd_init;
+ update_mmu_cache = pa20_update_mmu_cache;
+
+ show_regs = pa20_show_regs;
+
+ add_wired_entry = pa20_add_wired_entry;
+
+ user_mode = pa20_user_mode;
+ flush_tlb_all();
+}
diff --git a/arch/parisc/tools/Makefile b/arch/parisc/tools/Makefile
new file mode 100644
index 000000000..54fad5647
--- /dev/null
+++ b/arch/parisc/tools/Makefile
@@ -0,0 +1,28 @@
+# Makefile for MIPS kernel build tools.
+#
+# Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+# Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu)
+#
+# $Id: Makefile,v 1.3 1999/09/29 05:19:56 grundler Exp $
+#
+TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h
+
+.S.s:
+ $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+ $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: $(TARGET)
+
+$(TARGET): offset.h
+ cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET))
+
+offset.h: offset.s
+ sed -n '/^@@@/s///p' $^ >$@
+
+offset.s: offset.c
+
+clean:
+ rm -f offset.[hs] $(TARGET).new
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/tools/offset.c b/arch/parisc/tools/offset.c
new file mode 100644
index 000000000..167087f7e
--- /dev/null
+++ b/arch/parisc/tools/offset.c
@@ -0,0 +1,326 @@
+/* $Id: offset.c,v 1.2 2000/01/31 13:42:59 jsm Exp $
+ *
+ * offset.c: Calculate pt_regs and task_struct offsets.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Made portable by Ralf Baechle
+ * Adapted to parisc by Philipp Rumpf, (C) 1999 SuSE GmbH Nuernberg */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/hardirq.h>
+
+#define text(t) __asm__("\n@@@" t)
+#define _offset(type, member) (&(((type *)NULL)->member))
+
+#define offset(string, ptr, member) \
+ __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member)))
+#define size(string, size) \
+ __asm__("\n@@@" string "%0" : : "i" (sizeof(size)))
+#define align(x,y) (((x)+(2*(y))-1)-(((x)+(y)-1)%(y)))
+#define size_align(string, size, algn) \
+ __asm__("\n@@@" string "%0" : : "i" \
+ align(sizeof(size),algn))
+#define linefeed text("")
+
+text("/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */");
+linefeed;
+text("#ifndef _PARISC_OFFSET_H");
+text("#define _PARISC_OFFSET_H");
+linefeed;
+
+void output_task_ptreg_defines(void)
+{
+ text("/* PA-RISC task pt_regs offsets. */");
+ offset("#define TASK_REGS ", struct task_struct, thread.regs);
+ offset("#define TASK_PT_PSW ", struct task_struct, thread.regs.gr[ 0]);
+ offset("#define TASK_PT_GR1 ", struct task_struct, thread.regs.gr[ 1]);
+ offset("#define TASK_PT_GR2 ", struct task_struct, thread.regs.gr[ 2]);
+ offset("#define TASK_PT_GR3 ", struct task_struct, thread.regs.gr[ 3]);
+ offset("#define TASK_PT_GR4 ", struct task_struct, thread.regs.gr[ 4]);
+ offset("#define TASK_PT_GR5 ", struct task_struct, thread.regs.gr[ 5]);
+ offset("#define TASK_PT_GR6 ", struct task_struct, thread.regs.gr[ 6]);
+ offset("#define TASK_PT_GR7 ", struct task_struct, thread.regs.gr[ 7]);
+ offset("#define TASK_PT_GR8 ", struct task_struct, thread.regs.gr[ 8]);
+ offset("#define TASK_PT_GR9 ", struct task_struct, thread.regs.gr[ 9]);
+ offset("#define TASK_PT_GR10 ", struct task_struct, thread.regs.gr[10]);
+ offset("#define TASK_PT_GR11 ", struct task_struct, thread.regs.gr[11]);
+ offset("#define TASK_PT_GR12 ", struct task_struct, thread.regs.gr[12]);
+ offset("#define TASK_PT_GR13 ", struct task_struct, thread.regs.gr[13]);
+ offset("#define TASK_PT_GR14 ", struct task_struct, thread.regs.gr[14]);
+ offset("#define TASK_PT_GR15 ", struct task_struct, thread.regs.gr[15]);
+ offset("#define TASK_PT_GR16 ", struct task_struct, thread.regs.gr[16]);
+ offset("#define TASK_PT_GR17 ", struct task_struct, thread.regs.gr[17]);
+ offset("#define TASK_PT_GR18 ", struct task_struct, thread.regs.gr[18]);
+ offset("#define TASK_PT_GR19 ", struct task_struct, thread.regs.gr[19]);
+ offset("#define TASK_PT_GR20 ", struct task_struct, thread.regs.gr[20]);
+ offset("#define TASK_PT_GR21 ", struct task_struct, thread.regs.gr[21]);
+ offset("#define TASK_PT_GR22 ", struct task_struct, thread.regs.gr[22]);
+ offset("#define TASK_PT_GR23 ", struct task_struct, thread.regs.gr[23]);
+ offset("#define TASK_PT_GR24 ", struct task_struct, thread.regs.gr[24]);
+ offset("#define TASK_PT_GR25 ", struct task_struct, thread.regs.gr[25]);
+ offset("#define TASK_PT_GR26 ", struct task_struct, thread.regs.gr[26]);
+ offset("#define TASK_PT_GR27 ", struct task_struct, thread.regs.gr[27]);
+ offset("#define TASK_PT_GR28 ", struct task_struct, thread.regs.gr[28]);
+ offset("#define TASK_PT_GR29 ", struct task_struct, thread.regs.gr[29]);
+ offset("#define TASK_PT_GR30 ", struct task_struct, thread.regs.gr[30]);
+ offset("#define TASK_PT_GR31 ", struct task_struct, thread.regs.gr[31]);
+ offset("#define TASK_PT_FR0 ", struct task_struct, thread.regs.fr[ 0]);
+ offset("#define TASK_PT_FR1 ", struct task_struct, thread.regs.fr[ 1]);
+ offset("#define TASK_PT_FR2 ", struct task_struct, thread.regs.fr[ 2]);
+ offset("#define TASK_PT_FR3 ", struct task_struct, thread.regs.fr[ 3]);
+ offset("#define TASK_PT_FR4 ", struct task_struct, thread.regs.fr[ 4]);
+ offset("#define TASK_PT_FR5 ", struct task_struct, thread.regs.fr[ 5]);
+ offset("#define TASK_PT_FR6 ", struct task_struct, thread.regs.fr[ 6]);
+ offset("#define TASK_PT_FR7 ", struct task_struct, thread.regs.fr[ 7]);
+ offset("#define TASK_PT_FR8 ", struct task_struct, thread.regs.fr[ 8]);
+ offset("#define TASK_PT_FR9 ", struct task_struct, thread.regs.fr[ 9]);
+ offset("#define TASK_PT_FR10 ", struct task_struct, thread.regs.fr[10]);
+ offset("#define TASK_PT_FR11 ", struct task_struct, thread.regs.fr[11]);
+ offset("#define TASK_PT_FR12 ", struct task_struct, thread.regs.fr[12]);
+ offset("#define TASK_PT_FR13 ", struct task_struct, thread.regs.fr[13]);
+ offset("#define TASK_PT_FR14 ", struct task_struct, thread.regs.fr[14]);
+ offset("#define TASK_PT_FR15 ", struct task_struct, thread.regs.fr[15]);
+ offset("#define TASK_PT_FR16 ", struct task_struct, thread.regs.fr[16]);
+ offset("#define TASK_PT_FR17 ", struct task_struct, thread.regs.fr[17]);
+ offset("#define TASK_PT_FR18 ", struct task_struct, thread.regs.fr[18]);
+ offset("#define TASK_PT_FR19 ", struct task_struct, thread.regs.fr[19]);
+ offset("#define TASK_PT_FR20 ", struct task_struct, thread.regs.fr[20]);
+ offset("#define TASK_PT_FR21 ", struct task_struct, thread.regs.fr[21]);
+ offset("#define TASK_PT_FR22 ", struct task_struct, thread.regs.fr[22]);
+ offset("#define TASK_PT_FR23 ", struct task_struct, thread.regs.fr[23]);
+ offset("#define TASK_PT_FR24 ", struct task_struct, thread.regs.fr[24]);
+ offset("#define TASK_PT_FR25 ", struct task_struct, thread.regs.fr[25]);
+ offset("#define TASK_PT_FR26 ", struct task_struct, thread.regs.fr[26]);
+ offset("#define TASK_PT_FR27 ", struct task_struct, thread.regs.fr[27]);
+ offset("#define TASK_PT_FR28 ", struct task_struct, thread.regs.fr[28]);
+ offset("#define TASK_PT_FR29 ", struct task_struct, thread.regs.fr[29]);
+ offset("#define TASK_PT_FR30 ", struct task_struct, thread.regs.fr[30]);
+ offset("#define TASK_PT_FR31 ", struct task_struct, thread.regs.fr[31]);
+ offset("#define TASK_PT_SR0 ", struct task_struct, thread.regs.sr[ 0]);
+ offset("#define TASK_PT_SR1 ", struct task_struct, thread.regs.sr[ 1]);
+ offset("#define TASK_PT_SR2 ", struct task_struct, thread.regs.sr[ 2]);
+ offset("#define TASK_PT_SR3 ", struct task_struct, thread.regs.sr[ 3]);
+ offset("#define TASK_PT_SR4 ", struct task_struct, thread.regs.sr[ 4]);
+ offset("#define TASK_PT_SR5 ", struct task_struct, thread.regs.sr[ 5]);
+ offset("#define TASK_PT_SR6 ", struct task_struct, thread.regs.sr[ 6]);
+ offset("#define TASK_PT_SR7 ", struct task_struct, thread.regs.sr[ 7]);
+ offset("#define TASK_PT_IASQ0 ", struct task_struct, thread.regs.iasq[0]);
+ offset("#define TASK_PT_IASQ1 ", struct task_struct, thread.regs.iasq[1]);
+ offset("#define TASK_PT_IAOQ0 ", struct task_struct, thread.regs.iaoq[0]);
+ offset("#define TASK_PT_IAOQ1 ", struct task_struct, thread.regs.iaoq[1]);
+ offset("#define TASK_PT_CR24 ", struct task_struct, thread.regs.cr24);
+ offset("#define TASK_PT_CR25 ", struct task_struct, thread.regs.cr25);
+ offset("#define TASK_PT_CR26 ", struct task_struct, thread.regs.cr26);
+ offset("#define TASK_PT_CR27 ", struct task_struct, thread.regs.cr27);
+ offset("#define TASK_PT_CR30 ", struct task_struct, thread.regs.cr30);
+ offset("#define TASK_PT_ORIG_R28 ", struct task_struct, thread.regs.orig_r28);
+ offset("#define TASK_PT_KSP ", struct task_struct, thread.regs.ksp);
+ offset("#define TASK_PT_KPC ", struct task_struct, thread.regs.kpc);
+ offset("#define TASK_PT_SAR ", struct task_struct, thread.regs.sar);
+ offset("#define TASK_PT_CR11 ", struct task_struct, thread.regs.sar);
+ offset("#define TASK_PT_IIR ", struct task_struct, thread.regs.iir);
+ offset("#define TASK_PT_ISR ", struct task_struct, thread.regs.isr);
+ offset("#define TASK_PT_IOR ", struct task_struct, thread.regs.ior);
+ offset("#define TASK_PT_CR_PID0 ", struct task_struct, thread.regs.cr_pid[0]);
+ offset("#define TASK_PT_CR_PID1 ", struct task_struct, thread.regs.cr_pid[1]);
+ offset("#define TASK_PT_CR_PID2 ", struct task_struct, thread.regs.cr_pid[2]);
+ offset("#define TASK_PT_CR_PID3 ", struct task_struct, thread.regs.cr_pid[3]);
+ size("#define TASK_SZ ", struct task_struct);
+ size_align("#define TASK_SZ_ALGN ", struct task_struct, 64);
+ linefeed;
+}
+
+void output_ptreg_defines(void)
+{
+ text("/* PA-RISC pt_regs offsets. */");
+ offset("#define PT_PSW ", struct pt_regs, gr[ 0]);
+ offset("#define PT_GR1 ", struct pt_regs, gr[ 1]);
+ offset("#define PT_GR2 ", struct pt_regs, gr[ 2]);
+ offset("#define PT_GR3 ", struct pt_regs, gr[ 3]);
+ offset("#define PT_GR4 ", struct pt_regs, gr[ 4]);
+ offset("#define PT_GR5 ", struct pt_regs, gr[ 5]);
+ offset("#define PT_GR6 ", struct pt_regs, gr[ 6]);
+ offset("#define PT_GR7 ", struct pt_regs, gr[ 7]);
+ offset("#define PT_GR8 ", struct pt_regs, gr[ 8]);
+ offset("#define PT_GR9 ", struct pt_regs, gr[ 9]);
+ offset("#define PT_GR10 ", struct pt_regs, gr[10]);
+ offset("#define PT_GR11 ", struct pt_regs, gr[11]);
+ offset("#define PT_GR12 ", struct pt_regs, gr[12]);
+ offset("#define PT_GR13 ", struct pt_regs, gr[13]);
+ offset("#define PT_GR14 ", struct pt_regs, gr[14]);
+ offset("#define PT_GR15 ", struct pt_regs, gr[15]);
+ offset("#define PT_GR16 ", struct pt_regs, gr[16]);
+ offset("#define PT_GR17 ", struct pt_regs, gr[17]);
+ offset("#define PT_GR18 ", struct pt_regs, gr[18]);
+ offset("#define PT_GR19 ", struct pt_regs, gr[19]);
+ offset("#define PT_GR20 ", struct pt_regs, gr[20]);
+ offset("#define PT_GR21 ", struct pt_regs, gr[21]);
+ offset("#define PT_GR22 ", struct pt_regs, gr[22]);
+ offset("#define PT_GR23 ", struct pt_regs, gr[23]);
+ offset("#define PT_GR24 ", struct pt_regs, gr[24]);
+ offset("#define PT_GR25 ", struct pt_regs, gr[25]);
+ offset("#define PT_GR26 ", struct pt_regs, gr[26]);
+ offset("#define PT_GR27 ", struct pt_regs, gr[27]);
+ offset("#define PT_GR28 ", struct pt_regs, gr[28]);
+ offset("#define PT_GR29 ", struct pt_regs, gr[29]);
+ offset("#define PT_GR30 ", struct pt_regs, gr[30]);
+ offset("#define PT_GR31 ", struct pt_regs, gr[31]);
+ offset("#define PT_FR0 ", struct pt_regs, fr[ 0]);
+ offset("#define PT_FR1 ", struct pt_regs, fr[ 1]);
+ offset("#define PT_FR2 ", struct pt_regs, fr[ 2]);
+ offset("#define PT_FR3 ", struct pt_regs, fr[ 3]);
+ offset("#define PT_FR4 ", struct pt_regs, fr[ 4]);
+ offset("#define PT_FR5 ", struct pt_regs, fr[ 5]);
+ offset("#define PT_FR6 ", struct pt_regs, fr[ 6]);
+ offset("#define PT_FR7 ", struct pt_regs, fr[ 7]);
+ offset("#define PT_FR8 ", struct pt_regs, fr[ 8]);
+ offset("#define PT_FR9 ", struct pt_regs, fr[ 9]);
+ offset("#define PT_FR10 ", struct pt_regs, fr[10]);
+ offset("#define PT_FR11 ", struct pt_regs, fr[11]);
+ offset("#define PT_FR12 ", struct pt_regs, fr[12]);
+ offset("#define PT_FR13 ", struct pt_regs, fr[13]);
+ offset("#define PT_FR14 ", struct pt_regs, fr[14]);
+ offset("#define PT_FR15 ", struct pt_regs, fr[15]);
+ offset("#define PT_FR16 ", struct pt_regs, fr[16]);
+ offset("#define PT_FR17 ", struct pt_regs, fr[17]);
+ offset("#define PT_FR18 ", struct pt_regs, fr[18]);
+ offset("#define PT_FR19 ", struct pt_regs, fr[19]);
+ offset("#define PT_FR20 ", struct pt_regs, fr[20]);
+ offset("#define PT_FR21 ", struct pt_regs, fr[21]);
+ offset("#define PT_FR22 ", struct pt_regs, fr[22]);
+ offset("#define PT_FR23 ", struct pt_regs, fr[23]);
+ offset("#define PT_FR24 ", struct pt_regs, fr[24]);
+ offset("#define PT_FR25 ", struct pt_regs, fr[25]);
+ offset("#define PT_FR26 ", struct pt_regs, fr[26]);
+ offset("#define PT_FR27 ", struct pt_regs, fr[27]);
+ offset("#define PT_FR28 ", struct pt_regs, fr[28]);
+ offset("#define PT_FR29 ", struct pt_regs, fr[29]);
+ offset("#define PT_FR30 ", struct pt_regs, fr[30]);
+ offset("#define PT_FR31 ", struct pt_regs, fr[31]);
+ offset("#define PT_SR0 ", struct pt_regs, sr[ 0]);
+ offset("#define PT_SR1 ", struct pt_regs, sr[ 1]);
+ offset("#define PT_SR2 ", struct pt_regs, sr[ 2]);
+ offset("#define PT_SR3 ", struct pt_regs, sr[ 3]);
+ offset("#define PT_SR4 ", struct pt_regs, sr[ 4]);
+ offset("#define PT_SR5 ", struct pt_regs, sr[ 5]);
+ offset("#define PT_SR6 ", struct pt_regs, sr[ 6]);
+ offset("#define PT_SR7 ", struct pt_regs, sr[ 7]);
+ offset("#define PT_IASQ0 ", struct pt_regs, iasq[0]);
+ offset("#define PT_IASQ1 ", struct pt_regs, iasq[1]);
+ offset("#define PT_IAOQ0 ", struct pt_regs, iaoq[0]);
+ offset("#define PT_IAOQ1 ", struct pt_regs, iaoq[1]);
+ offset("#define PT_CR24 ", struct pt_regs, cr24);
+ offset("#define PT_CR25 ", struct pt_regs, cr25);
+ offset("#define PT_CR26 ", struct pt_regs, cr26);
+ offset("#define PT_CR27 ", struct pt_regs, cr27);
+ offset("#define PT_CR30 ", struct pt_regs, cr30);
+ offset("#define PT_ORIG_R28 ", struct pt_regs, orig_r28);
+ offset("#define PT_KSP ", struct pt_regs, ksp);
+ offset("#define PT_KPC ", struct pt_regs, kpc);
+ offset("#define PT_SAR ", struct pt_regs, sar);
+ offset("#define PT_CR11 ", struct pt_regs, sar);
+ offset("#define PT_IIR ", struct pt_regs, iir);
+ offset("#define PT_ISR ", struct pt_regs, isr);
+ offset("#define PT_IOR ", struct pt_regs, ior);
+ offset("#define PT_CR_PID0 ", struct pt_regs, cr_pid[0]);
+ offset("#define PT_CR_PID1 ", struct pt_regs, cr_pid[1]);
+ offset("#define PT_CR_PID2 ", struct pt_regs, cr_pid[2]);
+ offset("#define PT_CR_PID3 ", struct pt_regs, cr_pid[3]);
+ size("#define PT_SIZE ", struct pt_regs);
+ size_align("#define PT_SZ_ALGN ", struct pt_regs, 64);
+ linefeed;
+}
+
+void output_task_defines(void)
+{
+ text("/* PARISC task_struct offsets. */");
+ offset("#define TASK_STATE ", struct task_struct, state);
+ offset("#define TASK_FLAGS ", struct task_struct, flags);
+ offset("#define TASK_SIGPENDING ", struct task_struct, sigpending);
+ offset("#define TASK_SEGMENT ", struct task_struct, addr_limit);
+ offset("#define TASK_NEED_RESCHED ", struct task_struct, need_resched);
+ offset("#define TASK_COUNTER ", struct task_struct, counter);
+ offset("#define TASK_PTRACE ", struct task_struct, ptrace);
+ offset("#define TASK_NICE ", struct task_struct, nice);
+ offset("#define TASK_MM ", struct task_struct, mm);
+ offset("#define TASK_PROCESSOR ", struct task_struct, processor);
+ size ("#define TASK_SZ ", struct task_struct);
+ size_align("#define TASK_SZ_ALGN ", struct task_struct, 64);
+ linefeed;
+}
+
+void output_irq_stat_defines(void)
+{
+ text("/* PARISC irq_cpustat_t offsets. */");
+ offset("#define IRQSTAT_SI_ACTIVE ", irq_cpustat_t, __softirq_active);
+ offset("#define IRQSTAT_SI_MASK ", irq_cpustat_t, __softirq_mask);
+ size ("#define IRQSTAT_SZ ", irq_cpustat_t);
+ linefeed;
+}
+
+#ifdef PRUMPF_HAD_MORE_TIME
+void output_thread_defines(void)
+{
+ text("/* PARISC specific thread_struct offsets. */");
+ offset("#define THREAD_REG16 ", struct task_struct, thread.reg16);
+ offset("#define THREAD_REG17 ", struct task_struct, thread.reg17);
+ offset("#define THREAD_REG18 ", struct task_struct, thread.reg18);
+ offset("#define THREAD_REG19 ", struct task_struct, thread.reg19);
+ offset("#define THREAD_REG20 ", struct task_struct, thread.reg20);
+ offset("#define THREAD_REG21 ", struct task_struct, thread.reg21);
+ offset("#define THREAD_REG22 ", struct task_struct, thread.reg22);
+ offset("#define THREAD_REG23 ", struct task_struct, thread.reg23);
+ offset("#define THREAD_REG29 ", struct task_struct, thread.reg29);
+ offset("#define THREAD_REG30 ", struct task_struct, thread.reg30);
+ offset("#define THREAD_REG31 ", struct task_struct, thread.reg31);
+ offset("#define THREAD_STATUS ", struct task_struct, thread.cp0_status);
+ offset("#define THREAD_FPU ", struct task_struct, thread.fpu);
+ offset("#define THREAD_BVADDR ", struct task_struct, thread.cp0_badvaddr);
+ offset("#define THREAD_BUADDR ", struct task_struct, thread.cp0_baduaddr);
+ offset("#define THREAD_ECODE ", struct task_struct, thread.error_code);
+ offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no);
+ offset("#define THREAD_PGDIR ", struct task_struct, thread.pg_dir);
+ offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags);
+ offset("#define THREAD_CURDS ", struct task_struct, thread.current_ds);
+ offset("#define THREAD_TRAMP ", struct task_struct, thread.irix_trampoline);
+ offset("#define THREAD_OLDCTX ", struct task_struct, thread.irix_oldctx);
+ linefeed;
+}
+
+void output_mm_defines(void)
+{
+ text("/* Linux mm_struct offsets. */");
+ offset("#define MM_COUNT ", struct mm_struct, count);
+ offset("#define MM_PGD ", struct mm_struct, pgd);
+ offset("#define MM_CONTEXT ", struct mm_struct, context);
+ linefeed;
+}
+
+void output_sc_defines(void)
+{
+ text("/* Linux sigcontext offsets. */");
+ offset("#define SC_REGMASK ", struct sigcontext, sc_regmask);
+ offset("#define SC_STATUS ", struct sigcontext, sc_status);
+ offset("#define SC_PC ", struct sigcontext, sc_pc);
+ offset("#define SC_REGS ", struct sigcontext, sc_regs);
+ offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
+ offset("#define SC_OWNEDFP ", struct sigcontext, sc_ownedfp);
+ offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
+ offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
+ offset("#define SC_SSFLAGS ", struct sigcontext, sc_ssflags);
+ offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
+ offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
+ offset("#define SC_CAUSE ", struct sigcontext, sc_cause);
+ offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr);
+ offset("#define SC_SIGSET ", struct sigcontext, sc_sigset);
+ linefeed;
+}
+
+#endif
+
+text("#endif /* !(_PARISC_OFFSET_H) */");
diff --git a/arch/parisc/vmlinux.lds b/arch/parisc/vmlinux.lds
new file mode 100644
index 000000000..268fc59ce
--- /dev/null
+++ b/arch/parisc/vmlinux.lds
@@ -0,0 +1,79 @@
+/* ld script to make hppa Linux kernel */
+OUTPUT_FORMAT("elf32-hppa")
+OUTPUT_ARCH(hppa)
+ENTRY(_stext)
+SECTIONS
+{
+
+/* right now use 0x10000/0x11000, later when we don't use Console and
+ * Boot-Device IODC, we will change this to 0x8000 !!!
+ */
+
+ . = 0xc0100000;
+/* . = 0x10000; */
+
+ _text = .; /* Text and read-only data */
+ .text BLOCK(16) : {
+ *(.text*)
+ *(.PARISC.unwind)
+ *(.fixup)
+ *(.lock.text) /* out-of-line lock text */
+ *(.gnu.warning)
+ } = 0
+
+ . = ALIGN(16);
+ .rodata : { *(.rodata) }
+ .kstrtab : { *(.kstrtab) }
+
+ _etext = .; /* End of text section */
+
+ .data BLOCK(8192) : { /* Data without special */
+ data_start = .;
+ *(.data)
+ }
+
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ __start___ksymtab = .; /* Kernel symbol table */
+ __ksymtab : { *(__ksymtab) }
+ __stop___ksymtab = .;
+
+
+ . = ALIGN(16384);
+ __init_begin = .;
+ .init.text : { *(.init.text) }
+ .init.data : { *(.init.data) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup.init : { *(.setup.init) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : { *(.initcall.init) }
+ __initcall_end = .;
+ __init_end = .;
+
+
+ init_task BLOCK(16384) : { *(init_task) } /* The initial task and kernel stack */
+
+ _edata = .; /* End of data section */
+
+
+ .bss : { *(.bss) *(COMMON) } /* BSS */
+
+
+ _end = . ;
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .note 0 : { *(.note) }
+
+}
diff --git a/arch/ppc/8260_io/uart.c b/arch/ppc/8260_io/uart.c
index f7ce9da03..e6e223b61 100644
--- a/arch/ppc/8260_io/uart.c
+++ b/arch/ppc/8260_io/uart.c
@@ -496,8 +496,9 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
- queue_task(&info->tqueue_hangup,
- &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&info->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
}
}
if (info->flags & ASYNC_CTS_FLOW) {
@@ -624,10 +625,9 @@ static void do_serial_hangup(void *private_)
struct tty_struct *tty;
tty = info->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty);
+ MOD_DEC_USE_COUNT;
}
/*static void rs_8xx_timer(void)
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
index 45f10b635..659576e8c 100644
--- a/arch/ppc/8xx_io/fec.c
+++ b/arch/ppc/8xx_io/fec.c
@@ -1214,7 +1214,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
fep->phy_task.routine = (void *)mii_relink;
fep->phy_task.data = dev;
- queue_task(&fep->phy_task, &tq_scheduler);
+ schedule_task(&fep->phy_task);
}
static void mii_queue_config(uint mii_reg, struct net_device *dev)
@@ -1223,7 +1223,7 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
fep->phy_task.routine = (void *)mii_display_config;
fep->phy_task.data = dev;
- queue_task(&fep->phy_task, &tq_scheduler);
+ schedule_task(&fep->phy_task);
}
diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
index 7c05954c2..598e13ac0 100644
--- a/arch/ppc/8xx_io/uart.c
+++ b/arch/ppc/8xx_io/uart.c
@@ -514,8 +514,9 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
- queue_task(&info->tqueue_hangup,
- &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&info->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
}
}
if (info->flags & ASYNC_CTS_FLOW) {
@@ -645,10 +646,9 @@ static void do_serial_hangup(void *private_)
struct tty_struct *tty;
tty = info->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty);
+ MOD_DEC_USE_COUNT;
}
/*static void rs_8xx_timer(void)
diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
index 83e33e17b..4586d8abe 100644
--- a/arch/ppc/amiga/config.c
+++ b/arch/ppc/amiga/config.c
@@ -49,11 +49,28 @@ unsigned char amiga_vblank;
unsigned char amiga_psfreq;
struct amiga_hw_present amiga_hw_present;
-static const char *amiga_models[] = {
- "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000",
- "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco"
+static const char s_a500[] __initdata = "A500";
+static const char s_a500p[] __initdata = "A500+";
+static const char s_a600[] __initdata = "A600";
+static const char s_a1000[] __initdata = "A1000";
+static const char s_a1200[] __initdata = "A1200";
+static const char s_a2000[] __initdata = "A2000";
+static const char s_a2500[] __initdata = "A2500";
+static const char s_a3000[] __initdata = "A3000";
+static const char s_a3000t[] __initdata = "A3000T";
+static const char s_a3000p[] __initdata = "A3000+";
+static const char s_a4000[] __initdata = "A4000";
+static const char s_a4000t[] __initdata = "A4000T";
+static const char s_cdtv[] __initdata = "CDTV";
+static const char s_cd32[] __initdata = "CD32";
+static const char s_draco[] __initdata = "Draco";
+static const char *amiga_models[] __initdata = {
+ s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000,
+ s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco,
};
+static char amiga_model_name[13] = "Amiga ";
+
extern char m68k_debug_device[];
static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
@@ -117,6 +134,26 @@ static char amiga_sysrq_xlate[128] =
extern void (*kd_mksound)(unsigned int, unsigned int);
+
+ /*
+ * Motherboard Resources present in all Amiga models
+ */
+
+static struct resource mb_res[] = {
+ { "Ranger Memory", 0x00c00000, 0x00c7ffff },
+ { "CIA B", 0x00bfd000, 0x00bfdfff },
+ { "CIA A", 0x00bfe000, 0x00bfefff },
+ { "Custom I/O", 0x00dff000, 0x00dfffff },
+ { "Kickstart ROM", 0x00f80000, 0x00ffffff }
+};
+
+static struct resource rtc_resource = {
+ "A2000 RTC", 0x00dc0000, 0x00dcffff
+};
+
+static struct resource ram_resource[NUM_MEMINFO];
+
+
/*
* Parse an Amiga-specific record in the bootinfo
*/
@@ -157,11 +194,15 @@ int amiga_parse_bootinfo(const struct bi_record *record)
break;
case BI_AMIGA_AUTOCON:
- if (zorro_num_autocon < ZORRO_NUM_AUTO)
- memcpy(&zorro_autocon[zorro_num_autocon++],
- (const struct ConfigDev *)data,
- sizeof(struct ConfigDev));
- else
+ if (zorro_num_autocon < ZORRO_NUM_AUTO) {
+ const struct ConfigDev *cd = (struct ConfigDev *)data;
+ struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
+ dev->rom = cd->cd_Rom;
+ dev->slotaddr = cd->cd_SlotAddr;
+ dev->slotsize = cd->cd_SlotSize;
+ dev->resource.start = (unsigned long)cd->cd_BoardAddr;
+ dev->resource.end = dev->resource.start+cd->cd_BoardSize-1;
+ } else
printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
break;
@@ -188,8 +229,10 @@ static void __init amiga_identify(void)
memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
printk("Amiga hardware found: ");
- if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+ strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
+ }
switch(amiga_model) {
case AMI_UNKNOWN:
@@ -342,9 +385,19 @@ static void __init amiga_identify(void)
void __init config_amiga(void)
{
+ int i;
+
amiga_debug_init();
amiga_identify();
+ /* Some APUS boxes may have PCI memory, but ... */
+ iomem_resource.name = "Memory";
+ request_resource(&iomem_resource, &ranger_resource);
+ request_resource(&iomem_resource, &ciab_resource);
+ request_resource(&iomem_resource, &ciaa_resource);
+ request_resource(&iomem_resource, &custom_chips_resource);
+ request_resource(&iomem_resource, &kickstart_resource);
+
mach_sched_init = amiga_sched_init;
mach_keyb_init = amiga_keyb_init;
mach_kbdrate = amiga_kbdrate;
@@ -362,9 +415,12 @@ void __init config_amiga(void)
mach_gettimeoffset = amiga_gettimeoffset;
if (AMIGAHW_PRESENT(A3000_CLK)){
mach_gettod = a3000_gettod;
+ rtc_resource.name[1] = '3';
+ request_resource(&iomem_resource, &rtc_resource);
}
else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
mach_gettod = a2000_gettod;
+ request_resource(&iomem_resource, &rtc_resource);
}
mach_max_dma_address = 0xffffffff; /*
@@ -404,6 +460,17 @@ void __init config_amiga(void)
/* ensure that the DMA master bit is set */
custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+ /* request all RAM */
+ for (i = 0; i < m68k_num_memory; i++) {
+ ram_resource[i].name =
+ (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
+ (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
+ "16-bit Slow RAM";
+ ram_resource[i].start = m68k_memory[i].addr;
+ ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
+ request_resource(&iomem_resource, &ram_resource[i]);
+ }
+
/* initialize chipram allocator */
amiga_chip_init ();
@@ -437,6 +504,8 @@ static void __init amiga_sched_init(void (*timer_routine)(int, void *,
{
jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
+ if (!request_mem_region(CIAB_PHYSADDR+0x400, 0x200, "timer"))
+ printk("Cannot allocate ciab.ta{lo,hi}\n");
ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */
ciab.talo = jiffy_ticks % 256;
ciab.tahi = jiffy_ticks / 256;
@@ -727,7 +796,7 @@ static void amiga_mem_console_write(struct console *co, const char *s,
static void amiga_savekmsg_init(void)
{
- savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM);
+ savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM, "Debug");
savekmsg->magic1 = SAVEKMSG_MAGIC1;
savekmsg->magic2 = SAVEKMSG_MAGIC2;
savekmsg->magicptr = virt_to_phys(savekmsg);
@@ -840,9 +909,7 @@ static void amiga_heartbeat(int on)
static void amiga_get_model(char *model)
{
- strcpy(model, "Amiga ");
- if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
- strcat(model, amiga_models[amiga_model-AMI_500]);
+ strcpy(model, amiga_model_name);
}
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 2c17e7bcb..c3d77a67e 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -293,7 +293,7 @@ void show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!atomic_read(&mem_map[i].count))
+ else if (!page_count(mem_map+i))
free++;
else
shared += atomic_read(&mem_map[i].count) - 1;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 71fbe4665..4af4f6565 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -47,12 +47,6 @@ extern pgm_check_handler_t do_page_fault;
asmlinkage int system_call(void);
-static inline void console_verbose(void)
-{
- extern int console_loglevel;
- console_loglevel = 15;
-}
-
#define DO_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void name(struct pt_regs * regs, long error_code) \
{ \
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 1a22e429b..177e5e8f2 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -192,7 +192,7 @@ int do_check_pgt_cache(int low, int high)
void show_mem(void)
{
- int i,free = 0,total = 0,reserved = 0;
+ int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
printk("Mem-info:\n");
@@ -205,9 +205,7 @@ void show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!atomic_read(&mem_map[i].count))
- free++;
- else
+ else if (page_count(mem_map+i))
shared += atomic_read(&mem_map[i].count) - 1;
}
printk("%d pages of RAM\n",total);
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index db11c1247..4aeaf8efa 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -28,12 +28,6 @@
#include <asm/atomic.h>
#include <asm/processor.h>
-static inline void console_verbose(void)
-{
- extern int console_loglevel;
- console_loglevel = 15;
-}
-
#define DO_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
unsigned long r6, unsigned long r7, \
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 5a0ac1f10..e03dba90a 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -150,7 +150,7 @@ int do_check_pgt_cache(int low, int high)
void show_mem(void)
{
- int i,free = 0,total = 0,reserved = 0;
+ int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
printk("Mem-info:\n");
@@ -163,9 +163,7 @@ void show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!page_count(mem_map+i))
- free++;
- else
+ else if (page_count(mem_map+i))
shared += page_count(mem_map+i) - 1;
}
printk("%d pages of RAM\n",total);
diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c
index 04049be7a..6962cc68e 100644
--- a/arch/sparc/boot/piggyback.c
+++ b/arch/sparc/boot/piggyback.c
@@ -1,9 +1,10 @@
-/* $Id: piggyback.c,v 1.3 2000/03/11 00:22:26 zaitcev Exp $
+/* $Id: piggyback.c,v 1.4 2000/12/05 00:48:57 anton Exp $
Simple utility to make a single-image install kernel with initial ramdisk
for Sparc tftpbooting without need to set up nfs.
-
+
Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
-
+ Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000.
+
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
@@ -34,6 +35,24 @@
* as PROM looks for a.out image only.
*/
+unsigned short ld2(char *p)
+{
+ return (p[0] << 8) | p[1];
+}
+
+unsigned int ld4(char *p)
+{
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+}
+
+void st4(char *p, unsigned int x)
+{
+ p[0] = x >> 24;
+ p[1] = x >> 16;
+ p[2] = x >> 8;
+ p[3] = x;
+}
+
void usage(void)
{
/* fs_img.gz is an image of initial ramdisk. */
@@ -50,7 +69,8 @@ void die(char *str)
int main(int argc,char **argv)
{
- char buffer [1024], *q, *r;
+ static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
+ unsigned char buffer[1024], *q, *r;
unsigned int i, j, k, start, end, offset;
FILE *map;
struct stat s;
@@ -74,21 +94,20 @@ int main(int argc,char **argv)
}
if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]);
if (read(image,buffer,512) != 512) die(argv[1]);
- if (!memcmp (buffer, "\177ELF", 4)) {
- unsigned int *p = (unsigned int *)(buffer + *(unsigned int *)(buffer + 28));
-
- i = p[1] + *(unsigned int *)(buffer + 24) - p[2];
+ if (memcmp (buffer, "\177ELF", 4) == 0) {
+ q = buffer + ld4(buffer + 28);
+ i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8);
if (lseek(image,i,0) < 0) die("lseek");
if (read(image,buffer,512) != 512) die(argv[1]);
j = 0;
- } else if (*(unsigned int *)buffer == 0x01030107) {
+ } else if (memcmp(buffer, aout_magic, 4) == 0) {
i = j = 32;
} else {
fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n");
exit(1);
}
k = i;
- i += ((*(unsigned short *)(buffer + j + 2))<<2) - 512;
+ i += (ld2(buffer + j + 2)<<2) - 512;
if (lseek(image,i,0) < 0) die("lseek");
if (read(image,buffer,1024) != 1024) die(argv[1]);
for (q = buffer, r = q + 512; q < r; q += 4) {
@@ -101,10 +120,12 @@ int main(int argc,char **argv)
}
offset = i + (q - buffer) + 10;
if (lseek(image, offset, 0) < 0) die ("lseek");
- *(unsigned *)buffer = 0;
- *(unsigned *)(buffer + 4) = 0x01000000;
- *(unsigned *)(buffer + 8) = ((end + 32 + 4095) & ~4095);
- *(unsigned *)(buffer + 12) = s.st_size;
+
+ st4(buffer, 0);
+ st4(buffer + 4, 0x01000000);
+ st4(buffer + 8, (end + 32 + 4095) & ~4095);
+ st4(buffer + 12, s.st_size);
+
if (write(image,buffer+2,14) != 14) die (argv[1]);
if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek");
if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]);
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index 1a75cdf17..dbe1d1fb2 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.105 2000/11/12 10:01:41 davem Exp $
+# $Id: config.in,v 1.106 2000/11/17 04:27:52 davem Exp $
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index e0be43e08..41ef9737e 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.40 2000/10/10 09:44:46 anton Exp $
+/* $Id: ioport.c,v 1.42 2000/12/05 00:56:36 anton Exp $
* ioport.c: Simple io mapping allocator.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -447,6 +447,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int dir
*/
void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size, int direction)
{
+#if 0
unsigned long va;
struct resource *res;
@@ -461,6 +462,7 @@ void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size, int directio
* to a kernel near you. - Anton
*/
/* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */
+#endif
}
void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction)
@@ -584,7 +586,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
* Once the device is given the dma address, the device owns this memory
* until either pci_unmap_single or pci_dma_sync_single is performed.
*/
-dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size,
+ int direction)
{
if (direction == PCI_DMA_NONE)
BUG();
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index e7b4e96de..c9ba85b27 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.19 2000/11/08 04:49:17 davem Exp $
+/* $Id: pcic.c,v 1.20 2000/12/05 00:56:36 anton Exp $
* pcic.c: Sparc/PCI controller support
*
* Copyright (C) 1998 V. Roganov and G. Raiko
@@ -556,8 +556,8 @@ static void pcic_map_pci_device(struct linux_pcic *pcic,
*/
printk("PCIC: Skipping I/O space at 0x%lx,"
"this will Oops if a driver attaches;"
- "device '%s' (%x,%x)\n", address, namebuf,
- dev->device, dev->vendor);
+ "device '%s' at %02x:%02x)\n", address,
+ namebuf, dev->bus->number, dev->devfn);
}
}
}
@@ -568,12 +568,12 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
{
struct pcic_ca2irq *p;
int i, ivec;
- char namebuf[64]; /* P3 remove */
+ char namebuf[64];
if (node == 0 || node == -1) {
strcpy(namebuf, "???");
} else {
- prom_getstring(node, "name", namebuf, sizeof(namebuf)); /* P3 remove */
+ prom_getstring(node, "name", namebuf, sizeof(namebuf));
}
if ((p = pcic->pcic_imap) == 0) {
@@ -612,8 +612,8 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */
printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {}
}
- printk("PCIC: setting irq %x for device (%x,%x)\n",
- p->irq, dev->device, dev->vendor);
+ printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n",
+ p->irq, p->pin, dev->bus->number, dev->devfn);
dev->irq = p->irq;
i = p->pin;
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 414dfd076..90b305a8c 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -26,7 +26,6 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
-#include <asm/atops.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 997e4d0ce..d9883654e 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.104 2000/09/06 05:43:00 anton Exp $
+/* $Id: sparc_ksyms.c,v 1.105 2000/12/11 05:24:25 anton Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -111,6 +111,11 @@ EXPORT_SYMBOL_PRIVATE(_rw_read_enter);
EXPORT_SYMBOL_PRIVATE(_rw_read_exit);
EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
#endif
+/* semaphores */
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__down_interruptible);
/* rw semaphores */
EXPORT_SYMBOL_NOVERS(___down_read);
EXPORT_SYMBOL_NOVERS(___down_write);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 280392629..d14dbc2ac 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -28,7 +28,6 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
-#include <asm/atops.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/sbus.h>
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index d6c126d00..230a95e6b 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -25,7 +25,6 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
-#include <asm/atops.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index dd011c143..498fdb26f 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.66 2000/07/10 20:57:35 davem Exp $
+/* $Id: sys_sparc.c,v 1.67 2000/11/30 08:37:31 anton Exp $
* linux/arch/sparc/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -34,6 +34,8 @@ asmlinkage unsigned long sys_getpagesize(void)
return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
}
+#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
+
unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
{
struct vm_area_struct * vmm;
@@ -45,7 +47,11 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
return 0;
if (!addr)
addr = TASK_UNMAPPED_BASE;
- addr = PAGE_ALIGN(addr);
+
+ if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ addr = COLOUR_ALIGN(addr);
+ else
+ addr = PAGE_ALIGN(addr);
for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
@@ -58,6 +64,8 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
if (!vmm || addr + len <= vmm->vm_start)
return addr;
addr = vmm->vm_end;
+ if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ addr = COLOUR_ALIGN(addr);
}
}
@@ -224,10 +232,16 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len,
goto out_putf;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ if (flags & MAP_SHARED)
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+
down(&current->mm->mmap_sem);
retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up(&current->mm->mmap_sem);
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
+
out_putf:
if (file)
fput(file);
@@ -259,6 +273,7 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, unsigned long new_addr)
{
+ struct vm_area_struct *vma;
unsigned long ret = -EINVAL;
if (ARCH_SUN4C_SUN4) {
if (old_len > 0x20000000 || new_len > 0x20000000)
@@ -270,6 +285,9 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
new_len > TASK_SIZE - PAGE_SIZE)
goto out;
down(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, addr);
+ if (vma && (vma->vm_flags & VM_SHARED))
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
if (flags & MREMAP_FIXED) {
if (ARCH_SUN4C_SUN4 &&
new_addr < 0xe0000000 &&
@@ -290,6 +308,7 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(&current->mm->mmap_sem);
out:
return ret;
@@ -302,12 +321,10 @@ c_sys_nis_syscall (struct pt_regs *regs)
static int count = 0;
if (count++ > 5) return -ENOSYS;
- lock_kernel();
printk ("%s[%d]: Unimplemented SPARC system call %d\n", current->comm, current->pid, (int)regs->u_regs[1]);
#ifdef DEBUG_UNIMP_SYSCALL
show_regs (regs);
#endif
- unlock_kernel();
return -ENOSYS;
}
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 85161a3a6..d27495bd6 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.95 2000/11/10 04:49:56 davem Exp $
+/* $Id: init.c,v 1.96 2000/11/30 08:51:50 anton Exp $
* linux/arch/sparc/mm/init.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -579,7 +579,8 @@ void si_meminfo(struct sysinfo *val)
void flush_page_to_ram(struct page *page)
{
- unsigned long vaddr = (unsigned long) kmap(page);
- __flush_page_to_ram(vaddr);
- kunmap(page);
+ unsigned long vaddr = (unsigned long)page_address(page);
+
+ if (vaddr)
+ __flush_page_to_ram(vaddr);
}
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index b32199c13..0dba7d0a3 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.224 2000/11/09 22:40:05 davem Exp $
+/* $Id: srmmu.c,v 1.225 2000/11/30 08:37:31 anton Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -51,7 +51,6 @@ enum mbus_module srmmu_modtype;
unsigned int hwbug_bitmask;
int vac_cache_size;
int vac_line_size;
-int vac_badbits;
extern struct resource sparc_iomap;
@@ -1286,75 +1285,6 @@ static void srmmu_destroy_context(struct mm_struct *mm)
}
}
-static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
- unsigned long address, pte_t pte)
-{
- if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) {
- struct vm_area_struct *vmaring;
- struct file *file;
- struct address_space *mapping;
- unsigned long flags, offset, vaddr, start;
- int alias_found = 0;
- pgd_t *pgdp;
- pmd_t *pmdp;
- pte_t *ptep;
-
- __save_and_cli(flags);
-
- file = vma->vm_file;
- if (!file)
- goto done;
- mapping = file->f_dentry->d_inode->i_mapping;
- offset = (address & PAGE_MASK) - vma->vm_start;
- spin_lock(&mapping->i_shared_lock);
- vmaring = mapping->i_mmap_shared;
- if (vmaring != NULL) do {
- /* Do not mistake ourselves as another mapping. */
- if(vmaring == vma)
- continue;
-
- vaddr = vmaring->vm_start + offset;
- if ((vaddr ^ address) & vac_badbits) {
- alias_found++;
- start = vmaring->vm_start;
- while (start < vmaring->vm_end) {
- pgdp = srmmu_pgd_offset(vmaring->vm_mm, start);
- if(!pgdp) goto next;
- pmdp = srmmu_pmd_offset(pgdp, start);
- if(!pmdp) goto next;
- ptep = srmmu_pte_offset(pmdp, start);
- if(!ptep) goto next;
-
- if((pte_val(*ptep) & SRMMU_ET_MASK) == SRMMU_VALID) {
-#if 0
- printk("Fixing USER/USER alias [%ld:%08lx]\n",
- vmaring->vm_mm->context, start);
-#endif
- flush_cache_page(vmaring, start);
- srmmu_set_pte(ptep, __pte((pte_val(*ptep) &
- ~SRMMU_CACHE)));
- flush_tlb_page(vmaring, start);
- }
- next:
- start += PAGE_SIZE;
- }
- }
- } while ((vmaring = vmaring->vm_next_share) != NULL);
- spin_unlock(&mapping->i_shared_lock);
-
- if(alias_found && ((pte_val(pte) & SRMMU_CACHE) != 0)) {
- pgdp = srmmu_pgd_offset(vma->vm_mm, address);
- pmdp = srmmu_pmd_offset(pgdp, address);
- ptep = srmmu_pte_offset(pmdp, address);
- flush_cache_page(vma, address);
- srmmu_set_pte(ptep, __pte((pte_val(*ptep) & ~SRMMU_CACHE)));
- flush_tlb_page(vma, address);
- }
- done:
- __restore_flags(flags);
- }
-}
-
/* Init various srmmu chip types. */
static void __init srmmu_is_bad(void)
{
@@ -1389,7 +1319,6 @@ static void __init init_vac_layout(void)
}
vac_cache_size = cache_lines * vac_line_size;
- vac_badbits = (vac_cache_size - 1) & PAGE_MASK;
#ifdef CONFIG_SMP
if(vac_cache_size > max_size)
max_size = vac_cache_size;
@@ -1410,7 +1339,6 @@ static void __init init_vac_layout(void)
#ifdef CONFIG_SMP
vac_cache_size = max_size;
vac_line_size = min_line_size;
- vac_badbits = (vac_cache_size - 1) & PAGE_MASK;
#endif
printk("SRMMU: Using VAC size of %d bytes, line size %d bytes.\n",
(int)vac_cache_size, (int)vac_line_size);
@@ -1465,7 +1393,6 @@ static void __init init_hypersparc(void)
BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM);
poke_srmmu = poke_hypersparc;
hypersparc_setup_blockops();
@@ -1532,7 +1459,6 @@ static void __init init_cypress_common(void)
BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP);
BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM);
poke_srmmu = poke_cypress;
}
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index edba89672..1b32dd8ef 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.201 2000/11/09 22:39:36 davem Exp $
+/* $Id: sun4c.c,v 1.202 2000/12/01 03:17:31 anton Exp $
* sun4c.c: Doing in software what should be done in hardware.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -2373,78 +2373,6 @@ static int sun4c_check_pgt_cache(int low, int high)
return freed;
}
-/* There are really two cases of aliases to watch out for, and these
- * are:
- *
- * 1) A user's page which can be aliased with the kernels virtual
- * mapping of the physical page.
- *
- * 2) Multiple user mappings of the same inode/anonymous object
- * such that two copies of the same data for the same phys page
- * can live (writable) in the cache at the same time.
- *
- * We handle number 1 by flushing the kernel copy of the page always
- * after COW page operations.
- *
- * NOTE: We are a bit slowed down now because the VMA arg is indeed used
- * now, so our ref/mod bit tracking quick userfaults eat a few more
- * cycles than they used to.
- */
-static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long address, pte_t pte)
-{
- pgd_t *pgdp;
- pte_t *ptep;
-
- if (vma->vm_file) {
- struct address_space *mapping;
- unsigned long offset = (address & PAGE_MASK) - vma->vm_start;
- struct vm_area_struct *vmaring;
- int alias_found = 0;
-
- mapping = vma->vm_file->f_dentry->d_inode->i_mapping;
- spin_lock(&mapping->i_shared_lock);
- vmaring = mapping->i_mmap_shared;
- if (vmaring != NULL) do {
- unsigned long vaddr = vmaring->vm_start + offset;
- unsigned long start;
-
- /* Do not mistake ourselves as another mapping. */
- if (vmaring == vma)
- continue;
-
- if (S4CVAC_BADALIAS(vaddr, address)) {
- alias_found++;
- start = vmaring->vm_start;
- while (start < vmaring->vm_end) {
- pgdp = sun4c_pgd_offset(vmaring->vm_mm, start);
- if (!pgdp)
- goto next;
- ptep = sun4c_pte_offset((pmd_t *) pgdp, start);
- if (!ptep)
- goto next;
-
- if (pte_val(*ptep) & _SUN4C_PAGE_PRESENT) {
- flush_cache_page(vmaring, start);
- *ptep = __pte(pte_val(*ptep) |
- _SUN4C_PAGE_NOCACHE);
- flush_tlb_page(vmaring, start);
- }
- next:
- start += PAGE_SIZE;
- }
- }
- } while ((vmaring = vmaring->vm_next_share) != NULL);
- spin_unlock(&mapping->i_shared_lock);
-
- if (alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) {
- pgdp = sun4c_pgd_offset(vma->vm_mm, address);
- ptep = sun4c_pte_offset((pmd_t *) pgdp, address);
- *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_NOCACHE);
- pte = *ptep;
- }
- }
-}
-
/* An experiment, turn off by default for now... -DaveM */
#define SUN4C_PRELOAD_PSEG
@@ -2486,8 +2414,6 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p
#endif
start += PAGE_SIZE;
}
- if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))
- sun4c_vac_alias_fixup(vma, address, pte);
#ifndef SUN4C_PRELOAD_PSEG
sun4c_put_pte(address, pte_val(pte));
#endif
@@ -2500,9 +2426,6 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p
add_lru(entry);
}
- if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))
- sun4c_vac_alias_fixup(vma, address, pte);
-
sun4c_put_pte(address, pte_val(pte));
restore_flags(flags);
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index e1ae982bf..a0311626e 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.98 2000/11/13 10:03:32 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.99 2000/12/09 04:15:24 anton Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -179,6 +179,7 @@ EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(__flushw_user);
+EXPORT_SYMBOL(flush_icache_range);
EXPORT_SYMBOL(__flush_dcache_page);
EXPORT_SYMBOL(mstk48t02_regs);
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 235d34889..391979c87 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.46 2000/08/29 07:01:54 davem Exp $
+/* $Id: sys_sparc.c,v 1.47 2000/11/29 05:56:12 anton Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -40,6 +40,8 @@ asmlinkage unsigned long sys_getpagesize(void)
return PAGE_SIZE;
}
+#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
+
unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
{
struct vm_area_struct * vmm;
@@ -51,7 +53,11 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
return 0;
if (!addr)
addr = TASK_UNMAPPED_BASE;
- addr = PAGE_ALIGN(addr);
+
+ if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ addr = COLOUR_ALIGN(addr);
+ else
+ addr = PAGE_ALIGN(addr);
task_size -= len;
@@ -66,6 +72,8 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
if (!vmm || addr + len <= vmm->vm_start)
return addr;
addr = vmm->vm_end;
+ if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ addr = COLOUR_ALIGN(addr);
}
}
@@ -232,10 +240,15 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
goto out_putf;
}
+ if (flags & MAP_SHARED)
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+
down(&current->mm->mmap_sem);
retval = do_mmap(file, addr, len, prot, flags, off);
up(&current->mm->mmap_sem);
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
+
out_putf:
if (file)
fput(file);
@@ -264,6 +277,7 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, unsigned long new_addr)
{
+ struct vm_area_struct *vma;
unsigned long ret = -EINVAL;
if (current->thread.flags & SPARC_FLAG_32BIT)
goto out;
@@ -272,6 +286,9 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
if (addr < PAGE_OFFSET && addr + old_len > -PAGE_OFFSET)
goto out;
down(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, addr);
+ if (vma && (vma->vm_flags & VM_SHARED))
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
if (flags & MREMAP_FIXED) {
if (new_addr < PAGE_OFFSET &&
new_addr + new_len > -PAGE_OFFSET)
@@ -280,13 +297,14 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
ret = -ENOMEM;
if (!(flags & MREMAP_MAYMOVE))
goto out_sem;
- new_addr = get_unmapped_area (addr, new_len);
+ new_addr = get_unmapped_area(addr, new_len);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(&current->mm->mmap_sem);
out:
return ret;
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 9b211d86d..0964409c9 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.166 2000/11/10 04:49:56 davem Exp $
+/* $Id: sys_sparc32.c,v 1.168 2000/12/11 18:59:35 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -2966,6 +2966,7 @@ static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
err = copy_from_user(kaddr + offset, (char *)A(str),
bytes_to_copy);
+ flush_dcache_page(page);
flush_page_to_ram(page);
kunmap(page);
@@ -4133,6 +4134,7 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, u32 __new_addr)
{
+ struct vm_area_struct *vma;
unsigned long ret = -EINVAL;
unsigned long new_addr = AA(__new_addr);
@@ -4141,6 +4143,9 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
if (addr > 0xf0000000UL - old_len)
goto out;
down(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, addr);
+ if (vma && (vma->vm_flags & VM_SHARED))
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
if (flags & MREMAP_FIXED) {
if (new_addr > 0xf0000000UL - new_len)
goto out_sem;
@@ -4148,13 +4153,14 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
ret = -ENOMEM;
if (!(flags & MREMAP_MAYMOVE))
goto out_sem;
- new_addr = get_unmapped_area (addr, new_len);
+ new_addr = get_unmapped_area(addr, new_len);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(&current->mm->mmap_sem);
out:
return ret;
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index a5f5411f5..a9d143759 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.54 2000/08/12 13:25:41 davem Exp $
+/* $Id: sys_sunos32.c,v 1.55 2000/11/18 02:10:59 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index de4968ac4..2562df1f3 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.67 2000/07/30 23:12:24 davem Exp $
+/* $Id: traps.c,v 1.68 2000/11/22 06:50:37 davem Exp $
* arch/sparc64/kernel/traps.c
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -551,7 +551,7 @@ void do_fpe_common(struct pt_regs *regs)
else if (fsr & 0x01)
info.si_code = FPE_FLTRES;
}
- send_sig_info(SIGFPE, &info, current);
+ force_sig_info(SIGFPE, &info, current);
}
}
@@ -594,7 +594,7 @@ void do_tof(struct pt_regs *regs)
info.si_code = EMT_TAGOVF;
info.si_addr = (void *)regs->tpc;
info.si_trapno = 0;
- send_sig_info(SIGEMT, &info, current);
+ force_sig_info(SIGEMT, &info, current);
}
void do_div0(struct pt_regs *regs)
@@ -606,7 +606,7 @@ void do_div0(struct pt_regs *regs)
info.si_code = FPE_INTDIV;
info.si_addr = (void *)regs->tpc;
info.si_trapno = 0;
- send_sig_info(SIGFPE, &info, current);
+ force_sig_info(SIGFPE, &info, current);
}
void instruction_dump (unsigned int *pc)
@@ -715,7 +715,7 @@ void do_illegal_instruction(struct pt_regs *regs)
info.si_code = ILL_ILLOPC;
info.si_addr = (void *)pc;
info.si_trapno = 0;
- send_sig_info(SIGILL, &info, current);
+ force_sig_info(SIGILL, &info, current);
}
void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
@@ -734,7 +734,7 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
info.si_code = BUS_ADRALN;
info.si_addr = (void *)sfar;
info.si_trapno = 0;
- send_sig_info(SIGBUS, &info, current);
+ force_sig_info(SIGBUS, &info, current);
}
void do_privop(struct pt_regs *regs)
@@ -746,7 +746,7 @@ void do_privop(struct pt_regs *regs)
info.si_code = ILL_PRVOPC;
info.si_addr = (void *)regs->tpc;
info.si_trapno = 0;
- send_sig_info(SIGILL, &info, current);
+ force_sig_info(SIGILL, &info, current);
}
void do_privact(struct pt_regs *regs)
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 6da2d0b85..289092756 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.159 2000/11/06 06:59:04 davem Exp $
+/* $Id: init.c,v 1.161 2000/12/09 20:16:58 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -113,6 +113,17 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p
__update_mmu_cache(vma, address, pte);
}
+/* In arch/sparc64/mm/ultra.S */
+extern void __flush_icache_page(unsigned long);
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned long kaddr;
+
+ for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE)
+ __flush_icache_page(__get_phys(kaddr));
+}
+
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
index 4a10c1b4c..72c8f3405 100644
--- a/arch/sparc64/solaris/ioctl.c
+++ b/arch/sparc64/solaris/ioctl.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl.c,v 1.15 2000/07/28 12:15:02 davem Exp $
+/* $Id: ioctl.c,v 1.16 2000/11/18 02:10:59 davem Exp $
* ioctl.c: Solaris ioctl emulation.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
index 9b910a633..e016e4b1a 100644
--- a/arch/sparc64/solaris/socket.c
+++ b/arch/sparc64/solaris/socket.c
@@ -1,4 +1,4 @@
-/* $Id: socket.c,v 1.3 2000/08/14 23:50:31 anton Exp $
+/* $Id: socket.c,v 1.4 2000/11/18 02:11:00 davem Exp $
* socket.c: Socket syscall emulation for Solaris 2.6+
*
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
diff --git a/drivers/acpi/driver.c b/drivers/acpi/driver.c
index 411e07fcb..5015551eb 100644
--- a/drivers/acpi/driver.c
+++ b/drivers/acpi/driver.c
@@ -336,9 +336,7 @@ acpi_thread(void *context)
interruptible_sleep_on(&acpi_thread_wait);
if (signal_pending(current))
break;
- do {
- run_task_queue(&acpi_thread_run);
- } while (acpi_thread_run);
+ run_task_queue(&acpi_thread_run);
}
/*
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index b860253d3..8a24cfb66 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -2397,7 +2397,7 @@ static int __init amb_probe (void) {
#ifdef FILL_RX_POOLS_IN_BH
// initialise bottom half
- dev->bh.next = 0;
+ INIT_LIST_HEAD(&dev->bh.list);
dev->bh.sync = 0;
dev->bh.routine = (void (*)(void *)) fill_rx_pools;
dev->bh.data = dev;
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index dba6b5adf..5e8dc19f9 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -19,8 +19,8 @@
*/
-#define DAC960_DriverVersion "2.4.8"
-#define DAC960_DriverDate "19 August 2000"
+#define DAC960_DriverVersion "2.4.9"
+#define DAC960_DriverDate "7 September 2000"
#include <linux/version.h>
@@ -300,13 +300,8 @@ static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
{
- DECLARE_WAITQUEUE(WaitQueueEntry, current);
- add_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry);
- current->state = TASK_UNINTERRUPTIBLE;
- spin_unlock(&io_request_lock);
- schedule();
- current->state = TASK_RUNNING;
- remove_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry);
+ spin_unlock_irq(&io_request_lock);
+ __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands);
spin_lock_irq(&io_request_lock);
}
@@ -4957,7 +4952,8 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File,
}
Geometry.start =
Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].start_sect;
- return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T));
+ return (copy_to_user(UserGeometry, &Geometry,
+ sizeof(DiskGeometry_T)) ? -EFAULT : 0);
case BLKGETSIZE:
/* Get Device Size. */
if ((long *) Argument == NULL) return -EINVAL;
@@ -5078,8 +5074,8 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
ControllerInfo.PCI_Address = Controller->PCI_Address;
strcpy(ControllerInfo.ModelName, Controller->ModelName);
strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion);
- return copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
- sizeof(DAC960_ControllerInfo_T));
+ return (copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
+ sizeof(DAC960_ControllerInfo_T)) ? -EFAULT : 0);
}
case DAC960_IOCTL_V1_EXECUTE_COMMAND:
{
@@ -6401,7 +6397,7 @@ static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer,
unsigned char CommandBuffer[80];
int Length;
if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
- copy_from_user(CommandBuffer, Buffer, Count);
+ if (copy_from_user(CommandBuffer, Buffer, Count)) return -EFAULT;
CommandBuffer[Count] = '\0';
Length = strlen(CommandBuffer);
if (CommandBuffer[Length-1] == '\n')
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index f2a102cf2..53261f815 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -1785,7 +1785,7 @@ int acsi_init( void )
return -EBUSY;
}
if (!(acsi_buffer =
- (char *)atari_stram_alloc( ACSI_BUFFER_SIZE, NULL, "acsi" ))) {
+ (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) {
printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );
devfs_unregister_blkdev( MAJOR_NR, "ad" );
return -ENOMEM;
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 33dd5b896..0ae7379a9 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -317,7 +317,7 @@ static volatile int fdc_busy = 0;
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
static DECLARE_WAIT_QUEUE_HEAD(format_wait);
-static unsigned int changed_floppies = 0xff, fake_change = 0;
+static unsigned long changed_floppies = 0xff, fake_change = 0;
#define CHECK_CHANGE_DELAY HZ/2
#define FD_MOTOR_OFF_DELAY (3*HZ)
@@ -1990,7 +1990,7 @@ int __init atari_floppy_init (void)
SelectedDrive = -1;
BufferDrive = -1;
- DMABuffer = atari_stram_alloc( BUFFER_SIZE+512, NULL, "ataflop" );
+ DMABuffer = atari_stram_alloc(BUFFER_SIZE+512, "ataflop");
if (!DMABuffer) {
printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n");
unregister_blkdev(MAJOR_NR, "fd");
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index ad370bcb7..20e363b8e 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -176,14 +176,15 @@ static int __blk_cleanup_queue(struct list_head *head)
* blk_cleanup_queue: - release a &request_queue_t when it is no longer needed
* @q: the request queue to be released
*
- * Description: blk_cleanup_queue is the pair to blk_init_queue(). It should
- * be called when a request queue is being released; typically when a block
- * device is being de-registered.
- * Currently, its primary task it to free all the &struct request structures
- * that were allocated to the queue.
- * Caveat:
- * Hopefully the low level driver will have finished any outstanding
- * requests first...
+ * Description:
+ * blk_cleanup_queue is the pair to blk_init_queue(). It should
+ * be called when a request queue is being released; typically
+ * when a block device is being de-registered. Currently, its
+ * primary task it to free all the &struct request structures that
+ * were allocated to the queue.
+ * Caveat:
+ * Hopefully the low level driver will have finished any
+ * outstanding requests first...
**/
void blk_cleanup_queue(request_queue_t * q)
{
@@ -234,19 +235,21 @@ void blk_queue_headactive(request_queue_t * q, int active)
* @plug: the function to be called to plug a queue
*
* Description:
- * A request queue will be "plugged" if a request is added to it while it
- * is empty. This allows a number of requests to be added before any are
- * processed, thus providing an opportunity for these requests to be merged
- * or re-ordered.
- * The default plugging function (generic_plug_device()) sets the "plugged"
- * flag for the queue and adds a task to the $tq_disk task queue to unplug
- * the queue and call the request function at a later time.
+ * A request queue will be "plugged" if a request is added to it
+ * while it is empty. This allows a number of requests to be added
+ * before any are processed, thus providing an opportunity for these
+ * requests to be merged or re-ordered.
+ * The default plugging function (generic_plug_device()) sets the
+ * "plugged" flag for the queue and adds a task to the $tq_disk task
+ * queue to unplug the queue and call the request function at a
+ * later time.
*
- * A device driver may provide an alternate plugging function by passing it to
- * blk_queue_pluggable(). This function should set the "plugged" flag if it
- * want calls to the request_function to be blocked, and should place a
- * task on $tq_disk which will unplug the queue. Alternately it can simply
- * do nothing and there-by disable plugging of the device.
+ * A device driver may provide an alternate plugging function by
+ * passing it to blk_queue_pluggable(). This function should set
+ * the "plugged" flag if it want calls to the request_function to be
+ * blocked, and should place a task on $tq_disk which will unplug
+ * the queue. Alternately it can simply do nothing and there-by
+ * disable plugging of the device.
**/
void blk_queue_pluggable (request_queue_t * q, plug_device_fn *plug)
@@ -261,14 +264,21 @@ void blk_queue_pluggable (request_queue_t * q, plug_device_fn *plug)
* @mfn: the alternate make_request function
*
* Description:
- * The normal way for &struct buffer_heads to be passed to a device driver
- * it to collect into requests on a request queue, and allow the device
- * driver to select requests off that queue when it is ready. This works
- * well for many block devices. However some block devices (typically
- * virtual devices such as md or lvm) do not benefit from the processes on
- * the request queue, and are served best by having the requests passed
- * directly to them. This can be achieved by providing a function to
- * blk_queue_make_request().
+ * The normal way for &struct buffer_heads to be passed to a device
+ * driver is for them to be collected into requests on a request
+ * queue, and then to allow the device driver to select requests
+ * off that queue when it is ready. This works well for many block
+ * devices. However some block devices (typically virtual devices
+ * such as md or lvm) do not benefit from the processing on the
+ * request queue, and are served best by having the requests passed
+ * directly to them. This can be achieved by providing a function
+ * to blk_queue_make_request().
+ *
+ * Caveat:
+ * The driver that does this *must* be able to deal appropriately
+ * with buffers in "highmemory", either by calling bh_kmap() to get
+ * a kernel mapping, to by calling create_bounce() to create a
+ * buffer in normal memory.
**/
void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
@@ -347,9 +357,10 @@ static void generic_plug_device(request_queue_t *q, kdev_t dev)
*/
static inline void __generic_unplug_device(request_queue_t *q)
{
- if (!list_empty(&q->queue_head)) {
+ if (q->plugged) {
q->plugged = 0;
- q->request_fn(q);
+ if (!list_empty(&q->queue_head))
+ q->request_fn(q);
}
}
@@ -383,6 +394,8 @@ static void blk_init_free_list(request_queue_t *q)
spin_lock_init(&q->request_lock);
}
+static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh);
+
/**
* blk_init_queue - prepare a request queue for use with a block device
* @q: The &request_queue_t to be initialised
@@ -416,7 +429,6 @@ static void blk_init_free_list(request_queue_t *q)
* blk_init_queue() must be paired with a blk_cleanup-queue() call
* when the block device is deactivated (such as at module unload).
**/
-static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh);
void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
{
INIT_LIST_HEAD(&q->queue_head);
@@ -635,7 +647,10 @@ static void attempt_merge(request_queue_t * q,
next = blkdev_next_request(req);
if (req->sector + req->nr_sectors != next->sector)
return;
- if (req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors > max_sectors || next->sem)
+ if (req->cmd != next->cmd
+ || req->rq_dev != next->rq_dev
+ || req->nr_sectors + next->nr_sectors > max_sectors
+ || next->sem)
return;
/*
* If we are not allowed to merge these requests, then
@@ -684,7 +699,7 @@ static int __make_request(request_queue_t * q, int rw,
int max_segments = MAX_SEGMENTS;
struct request * req = NULL, *freereq = NULL;
int rw_ahead, max_sectors, el_ret;
- struct list_head *head = &q->queue_head;
+ struct list_head *head;
int latency;
elevator_t *elevator = &q->elevator;
@@ -738,6 +753,7 @@ again:
/*
* skip first entry, for devices with active queue head
*/
+ head = &q->queue_head;
if (q->head_active && !q->plugged)
head = head->next;
@@ -746,7 +762,8 @@ again:
goto get_rq;
}
- el_ret = elevator->elevator_merge_fn(q, &req, bh, rw, &max_sectors, &max_segments);
+ el_ret = elevator->elevator_merge_fn(q, &req, bh, rw,
+ &max_sectors, &max_segments);
switch (el_ret) {
case ELEVATOR_BACK_MERGE:
@@ -830,6 +847,40 @@ end_io:
return 0;
}
+/**
+ * generic_make_request: hand a buffer head to it's device driver for I/O
+ * @rw: READ, WRITE, or READA - what sort of I/O is desired.
+ * @bh: The buffer head describing the location in memory and on the device.
+ *
+ * generic_make_request() is used to make I/O requests of block
+ * devices. It is passed a &struct buffer_head and a &rw value. The
+ * %READ and %WRITE options are (hopefully) obvious in meaning. The
+ * %READA value means that a read is required, but that the driver is
+ * free to fail the request if, for example, it cannot get needed
+ * resources immediately.
+ *
+ * generic_make_request() does not return any status. The
+ * success/failure status of the request, along with notification of
+ * completion, is delivered asynchronously through the bh->b_end_io
+ * function described (one day) else where.
+ *
+ * The caller of generic_make_request must make sure that b_page,
+ * b_addr, b_size are set to describe the memory buffer, that b_rdev
+ * and b_rsector are set to describe the device address, and the
+ * b_end_io and optionally b_private are set to describe how
+ * completion notification should be signaled. BH_Mapped should also
+ * be set (to confirm that b_dev and b_blocknr are valid).
+ *
+ * generic_make_request and the drivers it calls may use b_reqnext,
+ * and may change b_rdev and b_rsector. So the values of these fields
+ * should NOT be depended on after the call to generic_make_request.
+ * Because of this, the caller should record the device address
+ * information in b_dev and b_blocknr.
+ *
+ * Apart from those fields mentioned above, no other fields, and in
+ * particular, no other flags, are changed by generic_make_request or
+ * any lower level drivers.
+ * */
void generic_make_request (int rw, struct buffer_head * bh)
{
int major = MAJOR(bh->b_rdev);
@@ -882,9 +933,76 @@ void generic_make_request (int rw, struct buffer_head * bh)
while (q->make_request_fn(q, rw, bh));
}
-/* This function can be used to request a number of buffers from a block
- device. Currently the only restriction is that all buffers must belong to
- the same device */
+
+/**
+ * submit_bh: submit a buffer_head to the block device later for I/O
+ * @rw: whether to %READ or %WRITE, or mayve to %READA (read ahead)
+ * @bh: The &struct buffer_head which describes the I/O
+ *
+ * submit_bh() is very similar in purpose to generic_make_request(), and
+ * uses that function to do most of the work.
+ *
+ * The extra functionality provided by submit_bh is to determine
+ * b_rsector from b_blocknr and b_size, and to set b_rdev from b_dev.
+ * This is is appropriate for IO requests that come from the buffer
+ * cache and page cache which (currently) always use aligned blocks.
+ */
+void submit_bh(int rw, struct buffer_head * bh)
+{
+ if (!test_bit(BH_Lock, &bh->b_state))
+ BUG();
+
+ set_bit(BH_Req, &bh->b_state);
+
+ /*
+ * First step, 'identity mapping' - RAID or LVM might
+ * further remap this.
+ */
+ bh->b_rdev = bh->b_dev;
+ bh->b_rsector = bh->b_blocknr * (bh->b_size>>9);
+
+ generic_make_request(rw, bh);
+}
+
+/*
+ * Default IO end handler, used by "ll_rw_block()".
+ */
+static void end_buffer_io_sync(struct buffer_head *bh, int uptodate)
+{
+ mark_buffer_uptodate(bh, uptodate);
+ unlock_buffer(bh);
+}
+
+/**
+ * ll_rw_block: low-level access to block devices
+ * @rw: whether to %READ or %WRITE or maybe %READA (readahead)
+ * @nr: number of &struct buffer_heads in the array
+ * @bhs: array of pointers to &struct buffer_head
+ *
+ * ll_rw_block() takes an array of pointers to &struct buffer_heads,
+ * and requests an I/O operation on them, either a %READ or a %WRITE.
+ * The third %READA option is described in the documentation for
+ * generic_make_request() which ll_rw_block() calls.
+ *
+ * This function provides extra functionality that is not in
+ * generic_make_request() that is relevant to buffers in the buffer
+ * cache or page cache. In particular it drops any buffer that it
+ * cannot get a lock on (with the BH_Lock state bit), any buffer that
+ * appears to be clean when doing a write request, and any buffer that
+ * appears to be up-to-date when doing read request. Further it marks
+ * as clean buffers that are processed for writing (the buffer cache
+ * wont assume that they are actually clean until the buffer gets
+ * unlocked).
+ *
+ * ll_rw_block sets b_end_io to simple completion handler that marks
+ * the buffer up-to-date (if approriate), unlocks the buffer and wakes
+ * any waiters. As client that needs a more interesting completion
+ * routine should call submit_bh() (or generic_make_request())
+ * directly.
+ *
+ * Caveat:
+ * All of the buffers must be for the same device, and must also be
+ * of the current approved size for the device. */
void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
{
@@ -928,7 +1046,8 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
if (test_and_set_bit(BH_Lock, &bh->b_state))
continue;
- set_bit(BH_Req, &bh->b_state);
+ /* We have the buffer lock */
+ bh->b_end_io = end_buffer_io_sync;
switch(rw) {
case WRITE:
@@ -951,17 +1070,9 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
end_io:
bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
continue;
-
}
- /*
- * First step, 'identity mapping' - RAID or LVM might
- * further remap this.
- */
- bh->b_rdev = bh->b_dev;
- bh->b_rsector = bh->b_blocknr * (bh->b_size>>9);
-
- generic_make_request(rw, bh);
+ submit_bh(rw, bh);
}
return;
@@ -970,7 +1081,6 @@ sorry:
buffer_IO_error(bhs[i]);
}
-
#ifdef CONFIG_STRAM_SWAP
extern int stram_device_init (void);
#endif
diff --git a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h
index 35ca3f458..0e1a8d2e5 100644
--- a/drivers/block/paride/pseudo.h
+++ b/drivers/block/paride/pseudo.h
@@ -50,7 +50,7 @@ static int ps_nice = 0;
static spinlock_t ps_spinlock __attribute__((unused)) = SPIN_LOCK_UNLOCKED;
static struct timer_list ps_timer = { function: ps_timer_int };
-static struct tq_struct ps_tq = {0,0,ps_tq_int,NULL};
+static struct tq_struct ps_tq = { routine: ps_tq_int };
static void ps_set_intr( void (*continuation)(void),
int (*ready)(void),
@@ -71,7 +71,7 @@ static void ps_set_intr( void (*continuation)(void),
disable_hlt();
#endif
ps_tq_active = 1;
- queue_task(&ps_tq,&tq_scheduler);
+ schedule_task(&ps_tq);
}
if (!ps_timer_active) {
@@ -114,7 +114,7 @@ static void ps_tq_int( void *data )
#endif
ps_tq_active = 1;
- queue_task(&ps_tq,&tq_scheduler);
+ schedule_task(&ps_tq);
spin_unlock_irqrestore(&ps_spinlock,flags);
}
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 88764463a..5aedc2543 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -29,6 +29,7 @@
#include <linux/major.h>
#include <linux/malloc.h>
+#include <linux/vmalloc.h>
#include <linux/blk.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -201,8 +202,6 @@ z2_open( struct inode *inode, struct file *filp )
#ifdef __powerpc__
/* FIXME: ioremap doesn't build correct memory tables. */
{
- extern void* vmalloc (unsigned long);
- extern void vfree (void*);
vfree(vmalloc (size));
}
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 055c42fe8..3001f35d0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -138,6 +138,9 @@ obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX) += sx.o generic_serial.o
obj-$(CONFIG_RIO) += rio/rio.o generic_serial.o
obj-$(CONFIG_SH_SCI) += sh-sci.o generic_serial.o
+obj-$(CONFIG_SERIAL167) += serial167.o
+obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o
+obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o
ifeq ($(CONFIG_RIO),y)
SUB_DIRS += rio
diff --git a/drivers/char/README.epca b/drivers/char/README.epca
index d95ff1fed..83dadc4ce 100644
--- a/drivers/char/README.epca
+++ b/drivers/char/README.epca
@@ -495,7 +495,7 @@ Release version : 1.1.0
Programmer : Daniel Taylor
Date : April 25, 1997
Description (Verbose) : Updated driver:
- 1. Fixed DCD bug. (&tq_scheduler)
+ 1. Fixed DCD bug. (&tq scheduler)
2. Removed BH handler code, as it was only handling
hangups, and not being called for that.
3. Namespace cleanup (DIGI_TIMER2 => DIGI_TIMER)
diff --git a/drivers/char/adbmouse.c b/drivers/char/adbmouse.c
index a4108cf0e..f3c098b43 100644
--- a/drivers/char/adbmouse.c
+++ b/drivers/char/adbmouse.c
@@ -53,7 +53,6 @@ extern void (*adb_mouse_interrupt_hook)(unsigned char *, int);
extern int adb_emulate_buttons;
extern int adb_button2_keycode;
extern int adb_button3_keycode;
-extern int console_loglevel;
/*
* XXX: need to figure out what ADB mouse packets mean ...
diff --git a/drivers/char/amigamouse.c b/drivers/char/amigamouse.c
index b7b6c3cc2..f3eecc13f 100644
--- a/drivers/char/amigamouse.c
+++ b/drivers/char/amigamouse.c
@@ -47,6 +47,7 @@
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <linux/logibusmouse.h>
#include <asm/setup.h>
@@ -185,6 +186,8 @@ static int __init amiga_mouse_init(void)
{
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
return -ENODEV;
+ if (!request_mem_region(CUSTOM_PHYSADDR+10, 2, "amigamouse [Denise]"))
+ return -EBUSY;
custom.joytest = 0; /* reset counters */
#if AMIGA_OLD_INT
@@ -201,6 +204,7 @@ static int __init amiga_mouse_init(void)
static void __exit amiga_mouse_exit(void)
{
unregister_busmouse(msedev);
+ release_mem_region(CUSTOM_PHYSADDR+10, 2);
}
module_init(amiga_mouse_init);
diff --git a/drivers/char/amikeyb.c b/drivers/char/amikeyb.c
index 73b8fecd2..a81a4c0b3 100644
--- a/drivers/char/amikeyb.c
+++ b/drivers/char/amikeyb.c
@@ -12,6 +12,7 @@
* Amiga support by Hamish Macdonald
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
@@ -23,6 +24,7 @@
#include <linux/timer.h>
#include <linux/random.h>
#include <linux/kernel.h>
+#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/kbd_kern.h>
@@ -186,7 +188,6 @@ static void amikeyb_rep(unsigned long ignore)
kbd_pt_regs = NULL;
- init_timer(&amikeyb_rep_timer);
amikeyb_rep_timer.expires = jiffies + key_repeat_rate;
add_timer(&amikeyb_rep_timer);
handle_scancode(rep_scancode, 1);
@@ -254,7 +255,6 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
} else {
del_timer(&amikeyb_rep_timer);
rep_scancode = keycode;
- init_timer(&amikeyb_rep_timer);
amikeyb_rep_timer.expires = jiffies + key_repeat_delay;
add_timer(&amikeyb_rep_timer);
}
@@ -300,6 +300,8 @@ int __init amiga_keyb_init(void)
{
if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
return -EIO;
+ if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
+ return -EBUSY;
/* setup key map */
memcpy(key_maps[0], amiplain_map, sizeof(plain_map));
@@ -342,3 +344,16 @@ int amiga_kbdrate( struct kbd_repeat *k )
return( 0 );
}
+
+int amiga_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+ /* SHIFT+ALTGR+HELP pressed? */
+ if ((keycode == 0x5f) && ((shift_state & 0xff) == 3))
+ *keycodep = 0xff;
+ else
+#endif
+ *keycodep = keycode;
+ return 1;
+}
+
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index c109c5965..63f26cc0f 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -63,8 +63,8 @@
#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
-#define MAX_PCI_DEVICE_NUM 3
#endif
+#define MAX_PCI_DEVICE_NUM 3
static char *applicom_pci_devnames[] = {
"PCI board",
diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c
index 4ab67281c..4854c56d5 100644
--- a/drivers/char/drm/gamma_dma.c
+++ b/drivers/char/drm/gamma_dma.c
@@ -651,7 +651,7 @@ int gamma_irq_install(drm_device_t *dev, int irq)
dev->dma->next_queue = NULL;
dev->dma->this_buffer = NULL;
- dev->tq.next = NULL;
+ INIT_LIST_HEAD(&dev->tq.list);
dev->tq.sync = 0;
dev->tq.routine = gamma_dma_schedule_tq_wrapper;
dev->tq.data = dev;
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 26fe0c1c1..aa824a79c 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -924,7 +924,7 @@ int i810_irq_install(drm_device_t *dev, int irq)
dev->dma->next_queue = NULL;
dev->dma->this_buffer = NULL;
- dev->tq.next = NULL;
+ INIT_LIST_HEAD(&dev->tq.list);
dev->tq.sync = 0;
dev->tq.routine = i810_dma_task_queue;
dev->tq.data = dev;
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index 6adffb8a9..356376ca9 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -143,7 +143,7 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
unsigned long end;
int i;
- DRM_DEBUG("dispatch_status = 0x%02x\n", dev_priv->dispatch_status);
+ DRM_DEBUG("dispatch_status = 0x%02lx\n", dev_priv->dispatch_status);
end = jiffies + (HZ*3);
while(1) {
if(!test_and_set_bit(MGA_IN_DISPATCH,
@@ -154,7 +154,7 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
DRM_ERROR("irqs: %d wanted %d\n",
atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
- DRM_ERROR("lockup: dispatch_status = 0x%02x,"
+ DRM_ERROR("lockup: dispatch_status = 0x%02lx,"
" jiffies = %lu, end = %lu\n",
dev_priv->dispatch_status, jiffies, end);
return;
@@ -177,7 +177,7 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
sarea_priv->dirty |= MGA_DMA_FLUSH;
clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
- DRM_DEBUG("exit, dispatch_status = 0x%02x\n",
+ DRM_DEBUG("exit, dispatch_status = 0x%02lx\n",
dev_priv->dispatch_status);
}
@@ -818,7 +818,7 @@ int mga_irq_install(drm_device_t *dev, int irq)
dev->dma->next_buffer = NULL;
dev->dma->next_queue = NULL;
dev->dma->this_buffer = NULL;
- dev->tq.next = NULL;
+ INIT_LIST_HEAD(&dev->tq.list);
dev->tq.sync = 0;
dev->tq.routine = mga_dma_task_queue;
dev->tq.data = dev;
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 883eb75ca..3937d9717 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -502,7 +502,7 @@ int mga_release(struct inode *inode, struct file *filp)
if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
&& dev->lock.pid == current->pid) {
mga_reclaim_buffers(dev, priv->pid);
- DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02x)\n",
+ DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02lx)\n",
current->pid,
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock),
dev->dev_private ?
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index e37cc2ef4..59bb9c247 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -38,7 +38,7 @@
#define MGA_BUF_NEEDS_OVERFLOW 3
typedef struct {
- u32 buffer_status;
+ long buffer_status; /* long req'd for set_bit() --RR */
int num_dwords;
int max_dwords;
u32 *current_dma_ptr;
@@ -62,7 +62,7 @@ typedef struct _drm_mga_freelist {
#define MGA_IN_GETBUF 3
typedef struct _drm_mga_private {
- u32 dispatch_status;
+ long dispatch_status; /* long req'd for set_bit() --RR */
unsigned int next_prim_age;
__volatile__ unsigned int last_prim_age;
int reserved_map_idx;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 8991f65bb..7a1d5471d 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -483,7 +483,9 @@ static inline void pc_sched_event(struct channel *ch, int event)
-------------------------------------------------------------------------*/
ch->event |= 1 << event;
- queue_task(&ch->tqueue, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&ch->tqueue) == 0)
+ MOD_DEC_USE_COUNT;
} /* End pc_sched_event */
@@ -3435,7 +3437,7 @@ static void do_softint(void *private_)
if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event))
{ /* Begin if clear_bit */
- tty_hangup(tty);
+ tty_hangup(tty); /* FIXME: module removal race here - AKPM */
wake_up_interruptible(&ch->open_wait);
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
@@ -3443,7 +3445,7 @@ static void do_softint(void *private_)
}
} /* End EPCA_MAGIC */
-
+ MOD_DEC_USE_COUNT;
} /* End do_softint */
/* ------------------------------------------------------------
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 478b05aa5..6e575c3dd 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -640,7 +640,9 @@ static _INLINE_ void check_modem_status(struct esp_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
- queue_task(&info->tqueue_hangup, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&info->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
}
}
}
@@ -802,10 +804,9 @@ static void do_serial_hangup(void *private_)
struct tty_struct *tty;
tty = info->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty);
+ MOD_DEC_USE_COUNT;
}
/*
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 52c6b5f19..5f5a94fbc 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -582,9 +582,11 @@ static void isicom_interrupt(int irq, void * dev_id, struct pt_regs * regs)
#endif
port->status &= ~ISI_DCD;
if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
- (port->flags & ASYNC_CALLOUT_NOHUP)))
- queue_task(&port->hangup_tq,
- &tq_scheduler);
+ (port->flags & ASYNC_CALLOUT_NOHUP))) {
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&port->hangup_tq) == 0)
+ MOD_DEC_USE_COUNT;
+ }
}
}
else {
@@ -1630,10 +1632,9 @@ static void do_isicom_hangup(void * data)
struct tty_struct * tty;
tty = port->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty); /* FIXME: module removal race here - AKPM */
+ MOD_DEC_USE_COUNT;
}
static void isicom_hangup(struct tty_struct * tty)
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 0bcc63a43..bd6caa775 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -2363,12 +2363,18 @@ static void stli_dohangup(void *arg)
printk("stli_dohangup(portp=%x)\n", (int) arg);
#endif
+ /*
+ * FIXME: There's a module removal race here: tty_hangup
+ * calls schedule_task which will call into this
+ * driver later.
+ */
portp = (stliport_t *) arg;
- if (portp == (stliport_t *) NULL)
- return;
- if (portp->tty == (struct tty_struct *) NULL)
- return;
- tty_hangup(portp->tty);
+ if (portp != (stliport_t *) NULL) {
+ if (portp->tty != (struct tty_struct *) NULL) {
+ tty_hangup(portp->tty);
+ }
+ }
+ MOD_DEC_USE_COUNT;
}
/*****************************************************************************/
@@ -2999,8 +3005,11 @@ static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
if (portp->flags & ASYNC_CHECK_CD) {
if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) &&
(portp->flags & ASYNC_CALLOUT_NOHUP))) {
- if (tty != (struct tty_struct *) NULL)
- queue_task(&portp->tqhangup, &tq_scheduler);
+ if (tty != (struct tty_struct *) NULL) {
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&portp->tqhangup) == 0)
+ MOD_DEC_USE_COUNT;
+ }
}
}
}
diff --git a/drivers/char/mixcomwd.c b/drivers/char/mixcomwd.c
index 90f16ca35..8b156f69c 100644
--- a/drivers/char/mixcomwd.c
+++ b/drivers/char/mixcomwd.c
@@ -54,7 +54,7 @@ static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 };
#define FLASHCOM_WATCHDOG_OFFSET 0x4
#define FLASHCOM_ID 0x18
-static int mixcomwd_opened;
+static long mixcomwd_opened; /* long req'd for setbit --RR */
static int watchdog_port;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index b2d959f36..d002c2e44 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -152,7 +152,7 @@ struct moxa_str {
unsigned short closing_wait;
int count;
int blocked_open;
- int event;
+ long event; /* long req'd for set_bit --RR */
int asyncflags;
long session;
long pgrp;
@@ -540,13 +540,14 @@ static void do_moxa_softint(void *private_)
struct moxa_str *ch = (struct moxa_str *) private_;
struct tty_struct *tty;
- if (!ch || !(tty = ch->tty))
- return;
- if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) {
- tty_hangup(tty);
- wake_up_interruptible(&ch->open_wait);
- ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
+ if (ch && (tty = ch->tty)) {
+ if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) {
+ tty_hangup(tty); /* FIXME: module removal race here - AKPM */
+ wake_up_interruptible(&ch->open_wait);
+ ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
+ }
}
+ MOD_DEC_USE_COUNT;
}
static int moxa_open(struct tty_struct *tty, struct file *filp)
@@ -1013,7 +1014,9 @@ static void moxa_poll(unsigned long ignored)
wake_up_interruptible(&ch->open_wait);
else {
set_bit(MOXA_EVENT_HANGUP, &ch->event);
- queue_task(&ch->tqueue, &tq_scheduler);
+ MOD_DEC_USE_COUNT;
+ if (schedule_task(&ch->tqueue) == 0)
+ MOD_INC_USE_COUNT;
}
}
}
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 2ab0563c2..c0eeab2f0 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -690,17 +690,18 @@ static void mxser_do_softint(void *private_)
struct tty_struct *tty;
tty = info->tty;
- if (!tty)
- return;
- if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup) (tty);
- wake_up_interruptible(&tty->write_wait);
- }
- if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {
- tty_hangup(tty);
+ if (tty) {
+ if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup) (tty);
+ wake_up_interruptible(&tty->write_wait);
+ }
+ if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {
+ tty_hangup(tty); /* FIXME: module removal race here - AKPM */
+ }
}
+ MOD_DEC_USE_COUNT;
}
/*
@@ -1456,7 +1457,7 @@ static inline void mxser_transmit_chars(struct mxser_struct *info)
if (info->xmit_cnt < WAKEUP_CHARS) {
set_bit(MXSER_EVENT_TXLOW, &info->event);
- queue_task(&info->tqueue, &tq_scheduler);
+ schedule_task(&info->tqueue);
}
if (info->xmit_cnt <= 0) {
info->IER &= ~UART_IER_THRI;
@@ -1485,7 +1486,7 @@ static inline void mxser_check_modem_status(struct mxser_struct *info,
else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
(info->flags & ASYNC_CALLOUT_NOHUP)))
set_bit(MXSER_EVENT_HANGUP, &info->event);
- queue_task(&info->tqueue, &tq_scheduler);
+ schedule_task(&info->tqueue);
}
if (info->flags & ASYNC_CTS_FLOW) {
@@ -1496,7 +1497,9 @@ static inline void mxser_check_modem_status(struct mxser_struct *info,
outb(info->IER, info->base + UART_IER);
set_bit(MXSER_EVENT_TXLOW, &info->event);
- queue_task(&info->tqueue, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&info->tqueue) == 0)
+ MOD_DEC_USE_COUNT;
}
} else {
if (!(status & UART_MSR_CTS)) {
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index d91689800..8a825753a 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1157,12 +1157,12 @@ static int r3964_open(struct tty_struct *tty)
* Add 'on_timer' to timer task queue
* (will be called from timer bh)
*/
- pInfo->bh_1.next = NULL;
+ INIT_LIST_HEAD(&pInfo->bh_1.list);
pInfo->bh_1.sync = 0;
pInfo->bh_1.routine = &on_timer_1;
pInfo->bh_1.data = pInfo;
- pInfo->bh_2.next = NULL;
+ INIT_LIST_HEAD(&pInfo->bh_2.list);
pInfo->bh_2.sync = 0;
pInfo->bh_2.routine = &on_timer_2;
pInfo->bh_2.data = pInfo;
@@ -1174,7 +1174,6 @@ static int r3964_open(struct tty_struct *tty)
static void r3964_close(struct tty_struct *tty)
{
- struct tq_struct *tq, *prev;
struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
struct r3964_client_info *pClient, *pNext;
struct r3964_message *pMsg;
@@ -1187,19 +1186,12 @@ static void r3964_close(struct tty_struct *tty)
* Make sure that our task queue isn't activated. If it
* is, take it out of the linked list.
*/
- save_flags(flags);
- cli();
-
- for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) {
- if ((tq == &pInfo->bh_1) || (tq==&pInfo->bh_2)) {
- if (prev)
- prev->next = tq->next;
- else
- tq_timer = tq->next;
- break;
- }
- }
- restore_flags(flags);
+ spin_lock_irqsave(&tqueue_lock, flags);
+ if (pInfo->bh_1.sync)
+ list_del(&pInfo->bh_1.list);
+ if (pInfo->bh_2.sync)
+ list_del(&pInfo->bh_2.list);
+ spin_unlock_irqrestore(&tqueue_lock, flags);
/* Remove client-structs and message queues: */
pClient=pInfo->firstClient;
diff --git a/drivers/char/q40_keyb.c b/drivers/char/q40_keyb.c
index a0e41b189..22c981b79 100644
--- a/drivers/char/q40_keyb.c
+++ b/drivers/char/q40_keyb.c
@@ -10,10 +10,12 @@
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/mm.h>
+#include <linux/keyboard.h>
#include <linux/signal.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/kbd_ll.h>
+#include <linux/kbd_kern.h>
#include <linux/delay.h>
#include <linux/sysrq.h>
#include <linux/random.h>
@@ -342,7 +344,6 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char status;
- disable_keyboard();
spin_lock(&kbd_controller_lock);
kbd_pt_regs = regs;
@@ -378,8 +379,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
handle_scancode(scancode, ! keyup );
keyup=0;
- mark_bh(KEYBOARD_BH);
-
+ tasklet_schedule(&keyboard_tasklet);
}
else
keyup=1;
@@ -387,20 +387,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
exit:
spin_unlock(&kbd_controller_lock);
master_outb(-1,KEYBOARD_UNLOCK_REG); /* keyb ints reenabled herewith */
- enable_keyboard();
-}
-
-
-
-
-#ifdef CONFIG_MAGIC_SYSRQ
-int kbd_is_sysrq(unsigned char keycode)
-{
- return( keycode == SYSRQ_KEY );
}
-#endif /* CONFIG_MAGIC_SYSRQ */
-
-
#define KBD_NO_DATA (-1) /* No data */
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
index 12c47eae2..4c6596387 100644
--- a/drivers/char/rio/host.h
+++ b/drivers/char/rio/host.h
@@ -110,7 +110,7 @@ struct Host
struct UnixRup UnixRups[MAX_RUP+LINKS_PER_UNIT];
int timeout_id; /* For calling 100 ms delays */
int timeout_sem;/* For calling 100 ms delays */
- int locks;
+ long locks; /* long req'd for set_bit --RR */
char ____end_marker____;
};
#define Control CardP->DpControl
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index d00e3c4fe..b60df303b 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -77,7 +77,7 @@
#define RS_EVENT_WRITE_WAKEUP 0
-DECLARE_TASK_QUEUE(tq_riscom);
+static DECLARE_TASK_QUEUE(tq_riscom);
#define RISCOM_TYPE_NORMAL 1
#define RISCOM_TYPE_CALLOUT 2
@@ -146,38 +146,38 @@ static inline int rc_paranoia_check(struct riscom_port const * port,
*/
/* Get board number from pointer */
-extern inline int board_No (struct riscom_board const * bp)
+static inline int board_No (struct riscom_board const * bp)
{
return bp - rc_board;
}
/* Get port number from pointer */
-extern inline int port_No (struct riscom_port const * port)
+static inline int port_No (struct riscom_port const * port)
{
return RC_PORT(port - rc_port);
}
/* Get pointer to board from pointer to port */
-extern inline struct riscom_board * port_Board(struct riscom_port const * port)
+static inline struct riscom_board * port_Board(struct riscom_port const * port)
{
return &rc_board[RC_BOARD(port - rc_port)];
}
/* Input Byte from CL CD180 register */
-extern inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg)
+static inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg)
{
return inb(bp->base + RC_TO_ISA(reg));
}
/* Output Byte to CL CD180 register */
-extern inline void rc_out(struct riscom_board const * bp, unsigned short reg,
+static inline void rc_out(struct riscom_board const * bp, unsigned short reg,
unsigned char val)
{
outb(val, bp->base + RC_TO_ISA(reg));
}
/* Wait for Channel Command Register ready */
-extern inline void rc_wait_CCR(struct riscom_board const * bp)
+static inline void rc_wait_CCR(struct riscom_board const * bp)
{
unsigned long delay;
@@ -193,7 +193,7 @@ extern inline void rc_wait_CCR(struct riscom_board const * bp)
* RISCom/8 probe functions.
*/
-extern inline int rc_check_io_range(struct riscom_board * const bp)
+static inline int rc_check_io_range(struct riscom_board * const bp)
{
int i;
@@ -206,7 +206,7 @@ extern inline int rc_check_io_range(struct riscom_board * const bp)
return 0;
}
-extern inline void rc_request_io_range(struct riscom_board * const bp)
+static inline void rc_request_io_range(struct riscom_board * const bp)
{
int i;
@@ -214,7 +214,7 @@ extern inline void rc_request_io_range(struct riscom_board * const bp)
request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1, "RISCom/8" );
}
-extern inline void rc_release_io_range(struct riscom_board * const bp)
+static inline void rc_release_io_range(struct riscom_board * const bp)
{
int i;
@@ -224,7 +224,7 @@ extern inline void rc_release_io_range(struct riscom_board * const bp)
/* Must be called with enabled interrupts */
-extern inline void rc_long_delay(unsigned long delay)
+static inline void rc_long_delay(unsigned long delay)
{
unsigned long i;
@@ -326,7 +326,7 @@ static int __init rc_probe(struct riscom_board *bp)
*
*/
-extern inline void rc_mark_event(struct riscom_port * port, int event)
+static inline void rc_mark_event(struct riscom_port * port, int event)
{
/*
* I'm not quite happy with current scheme all serial
@@ -341,7 +341,7 @@ extern inline void rc_mark_event(struct riscom_port * port, int event)
mark_bh(RISCOM8_BH);
}
-extern inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
+static inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
unsigned char const * what)
{
unsigned char channel;
@@ -359,7 +359,7 @@ extern inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
return NULL;
}
-extern inline void rc_receive_exc(struct riscom_board const * bp)
+static inline void rc_receive_exc(struct riscom_board const * bp)
{
struct riscom_port *port;
struct tty_struct *tty;
@@ -422,7 +422,7 @@ extern inline void rc_receive_exc(struct riscom_board const * bp)
queue_task(&tty->flip.tqueue, &tq_timer);
}
-extern inline void rc_receive(struct riscom_board const * bp)
+static inline void rc_receive(struct riscom_board const * bp)
{
struct riscom_port *port;
struct tty_struct *tty;
@@ -452,7 +452,7 @@ extern inline void rc_receive(struct riscom_board const * bp)
queue_task(&tty->flip.tqueue, &tq_timer);
}
-extern inline void rc_transmit(struct riscom_board const * bp)
+static inline void rc_transmit(struct riscom_board const * bp)
{
struct riscom_port *port;
struct tty_struct *tty;
@@ -521,7 +521,7 @@ extern inline void rc_transmit(struct riscom_board const * bp)
rc_mark_event(port, RS_EVENT_WRITE_WAKEUP);
}
-extern inline void rc_check_modem(struct riscom_board const * bp)
+static inline void rc_check_modem(struct riscom_board const * bp)
{
struct riscom_port *port;
struct tty_struct *tty;
@@ -537,8 +537,11 @@ extern inline void rc_check_modem(struct riscom_board const * bp)
if (rc_in(bp, CD180_MSVR) & MSVR_CD)
wake_up_interruptible(&port->open_wait);
else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
- (port->flags & ASYNC_CALLOUT_NOHUP)))
- queue_task(&port->tqueue_hangup, &tq_scheduler);
+ (port->flags & ASYNC_CALLOUT_NOHUP))) {
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&port->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
+ }
}
#ifdef RISCOM_BRAIN_DAMAGED_CTS
@@ -634,7 +637,7 @@ static void rc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
*/
/* Called with disabled interrupts */
-extern inline int rc_setup_board(struct riscom_board * bp)
+static inline int rc_setup_board(struct riscom_board * bp)
{
int error;
@@ -657,7 +660,7 @@ extern inline int rc_setup_board(struct riscom_board * bp)
}
/* Called with disabled interrupts */
-extern inline void rc_shutdown_board(struct riscom_board *bp)
+static inline void rc_shutdown_board(struct riscom_board *bp)
{
if (!(bp->flags & RC_BOARD_ACTIVE))
return;
@@ -1399,7 +1402,7 @@ static int rc_set_modem_info(struct riscom_port * port, unsigned int cmd,
return 0;
}
-extern inline void rc_send_break(struct riscom_port * port, unsigned long length)
+static inline void rc_send_break(struct riscom_port * port, unsigned long length)
{
struct riscom_board *bp = port_Board(port);
unsigned long flags;
@@ -1417,7 +1420,7 @@ extern inline void rc_send_break(struct riscom_port * port, unsigned long length
restore_flags(flags);
}
-extern inline int rc_set_serial_info(struct riscom_port * port,
+static inline int rc_set_serial_info(struct riscom_port * port,
struct serial_struct * newinfo)
{
struct serial_struct tmp;
@@ -1467,7 +1470,7 @@ extern inline int rc_set_serial_info(struct riscom_port * port,
return 0;
}
-extern inline int rc_get_serial_info(struct riscom_port * port,
+static inline int rc_get_serial_info(struct riscom_port * port,
struct serial_struct * retinfo)
{
struct serial_struct tmp;
@@ -1648,10 +1651,9 @@ static void do_rc_hangup(void *private_)
struct tty_struct *tty;
tty = port->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty); /* FIXME: module removal race still here */
+ MOD_DEC_USE_COUNT;
}
static void rc_hangup(struct tty_struct * tty)
@@ -1820,7 +1822,7 @@ static void rc_release_drivers(void)
* addresses in this case.
*
*/
-void __init riscom8_setup(char *str, int * ints)
+static void __init riscom8_setup(char *str, int * ints)
{
int i;
@@ -1831,12 +1833,14 @@ void __init riscom8_setup(char *str, int * ints)
rc_board[i].base = 0;
}
}
+
+__setup("riscom8=", riscom8_setup);
#endif
/*
* This routine must be called by kernel at boot time
*/
-int __init riscom8_init(void)
+static int __init riscom8_init(void)
{
int i;
int found = 0;
@@ -1859,22 +1863,24 @@ int __init riscom8_init(void)
}
#ifdef MODULE
-int iobase = 0;
-int iobase1 = 0;
-int iobase2 = 0;
-int iobase3 = 0;
+static int iobase;
+static int iobase1;
+static int iobase2;
+static int iobase3;
MODULE_PARM(iobase, "i");
MODULE_PARM(iobase1, "i");
MODULE_PARM(iobase2, "i");
MODULE_PARM(iobase3, "i");
+#endif /* MODULE */
/*
* You can setup up to 4 boards (current value of RC_NBOARD)
* by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
*
*/
-int init_module(void)
+static int __init riscom8_init_module (void)
{
+#ifdef MODULE
int i;
if (iobase || iobase1 || iobase2 || iobase3) {
@@ -1890,11 +1896,12 @@ int init_module(void)
rc_board[2].base = iobase2;
if (iobase3)
rc_board[3].base = iobase3;
-
+#endif /* MODULE */
+
return riscom8_init();
}
-void cleanup_module(void)
+static void __exit riscom8_exit_module (void)
{
int i;
@@ -1904,4 +1911,7 @@ void cleanup_module(void)
rc_release_io_range(&rc_board[i]);
}
-#endif /* MODULE */
+
+module_init(riscom8_init_module);
+module_exit(riscom8_exit_module);
+
diff --git a/drivers/char/riscom8.h b/drivers/char/riscom8.h
index 3b2b9e78d..da6a8b1b6 100644
--- a/drivers/char/riscom8.h
+++ b/drivers/char/riscom8.h
@@ -71,7 +71,7 @@ struct riscom_port {
struct tty_struct * tty;
int count;
int blocked_open;
- int event;
+ long event; /* long req'd for set_bit --RR */
int timeout;
int close_delay;
long session;
diff --git a/drivers/char/scan_keyb.c b/drivers/char/scan_keyb.c
index f2435e9ec..6ba861be2 100644
--- a/drivers/char/scan_keyb.c
+++ b/drivers/char/scan_keyb.c
@@ -120,7 +120,7 @@ int register_scan_keyboard(void (*scan)(unsigned char *buffer),
void __init scan_kbd_init(void)
{
- task_scan_kbd.next=NULL;
+ INIT_LIST_HEAD(task_scan_kbd.list);
task_scan_kbd.sync=0;
task_scan_kbd.routine=scan_kbd;
task_scan_kbd.data=NULL;
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index 65912962b..59d0a4379 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -701,7 +701,7 @@ static _INLINE_ void receive_chars(struct async_struct *info,
#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
tty_flip_buffer_push(tty);
#else
- queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+ queue_task(&tty->flip.tqueue, &tq_timer);
#endif
}
@@ -4018,7 +4018,7 @@ pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable)
if (dev->vendor == PCI_VENDOR_ID_PANACOM)
irq_config = 0x43;
if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
- (dev->device == PCI_VENDOR_ID_PLX_ROMULUS)) {
+ (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
/*
* As the megawolf cards have the int pins active
* high, and have 2 UART chips, both ints must be
@@ -4352,7 +4352,7 @@ static struct pci_board pci_boards[] __devinitdata = {
SPCI_FL_BASE2, 8, 460800 },
/* Megawolf Romulus PCI Serial Card, from Mike Hudson */
/* (Exoray@isys.ca) */
- { PCI_VENDOR_ID_PLX, PCI_VENDOR_ID_PLX_ROMULUS,
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
0x10b5, 0x106a,
SPCI_FL_BASE2, 4, 921600,
0x20, 2, pci_plx9050_fn, 0x03 },
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 3496229c6..a7ccb1d75 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -31,8 +31,18 @@
* Revision 1.36.1.4 1995/03/29 06:14:14 bentson
* disambiguate between Cyclom-16Y and Cyclom-32Ye;
*
+ * Changes:
+ *
* 200 lines of changes record removed - RGH 11-10-95, starting work on
* converting this to drive serial ports on mvme166 (cd2401).
+ *
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25
+ * - get rid of verify_area
+ * - use get_user to access memory from userspace in set_threshold,
+ * set_default_threshold and set_timeout
+ * - don't use the panic function in serial167_init
+ * - do resource release on failure on serial167_init
+ * - include missing restore_flags in mvme167_serial_console_setup
*/
#include <linux/config.h>
@@ -68,17 +78,6 @@
#include <asm/uaccess.h>
#include <linux/init.h>
-#define cy_put_user put_user
-
-static unsigned long cy_get_user(unsigned long *addr)
-{
- unsigned long result = 0;
- int error = get_user (result, addr);
- if (error)
- printk ("serial167: cy_get_user: error == %d\n", error);
- return result;
-}
-
#define SERIAL_PARANOIA_CHECK
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_THROTTLE
@@ -1259,7 +1258,11 @@ cy_write(struct tty_struct * tty, int from_user,
if (from_user) {
down(&tmp_buf_sem);
- copy_from_user(tmp_buf, buf, c);
+ if (copy_from_user(tmp_buf, buf, c)) {
+ up(&tmp_buf_sem);
+ restore_flags(flags);
+ return 0;
+ }
c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head));
memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
@@ -1435,8 +1438,7 @@ get_serial_info(struct cyclades_port * info,
tmp.close_delay = info->close_delay;
tmp.custom_divisor = 0; /*!!!*/
tmp.hub6 = 0; /*!!!*/
- copy_to_user(retinfo,&tmp,sizeof(*retinfo));
- return 0;
+ return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0;
} /* get_serial_info */
static int
@@ -1449,7 +1451,8 @@ set_serial_info(struct cyclades_port * info,
/* CP('s'); */
if (!new_info)
return -EFAULT;
- copy_from_user(&new_serial,new_info,sizeof(new_serial));
+ if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+ return -EFAULT;
old_info = *info;
if (!suser()) {
@@ -1503,8 +1506,7 @@ get_modem_info(struct cyclades_port * info, unsigned int *value)
| ((status & CyDCD) ? TIOCM_CAR : 0)
| ((status & CyDSR) ? TIOCM_DSR : 0)
| ((status & CyCTS) ? TIOCM_CTS : 0);
- cy_put_user(result,(unsigned int *) value);
- return 0;
+ return put_user(result,(unsigned int *) value);
} /* get_modem_info */
static int
@@ -1514,8 +1516,10 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
int channel;
volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
unsigned long flags;
- unsigned int arg = cy_get_user((unsigned long *) value);
-
+ unsigned int arg;
+
+ if (get_user(arg, (unsigned long *) value))
+ return -EFAULT;
channel = info->line;
switch (cmd) {
@@ -1612,7 +1616,8 @@ static int
get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
{
- copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor));
+ if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
+ return -EFAULT;
info->mon.int_count = 0;
info->mon.char_count = 0;
info->mon.char_max = 0;
@@ -1621,13 +1626,16 @@ get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
}
static int
-set_threshold(struct cyclades_port * info, unsigned long value)
+set_threshold(struct cyclades_port * info, unsigned long *arg)
{
volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
+ unsigned long value;
int channel;
- channel = info->line;
+ if (get_user(value, arg))
+ return -EFAULT;
+ channel = info->line;
info->cor4 &= ~CyREC_FIFO;
info->cor4 |= value & CyREC_FIFO;
base_addr[CyCOR4] = info->cor4;
@@ -1644,13 +1652,17 @@ get_threshold(struct cyclades_port * info, unsigned long *value)
channel = info->line;
tmp = base_addr[CyCOR4] & CyREC_FIFO;
- cy_put_user(tmp,value);
- return 0;
+ return put_user(tmp,value);
}
static int
-set_default_threshold(struct cyclades_port * info, unsigned long value)
+set_default_threshold(struct cyclades_port * info, unsigned long *arg)
{
+ unsigned long value;
+
+ if (get_user(value, arg))
+ return -EFAULT;
+
info->default_threshold = value & 0x0f;
return 0;
}
@@ -1658,15 +1670,18 @@ set_default_threshold(struct cyclades_port * info, unsigned long value)
static int
get_default_threshold(struct cyclades_port * info, unsigned long *value)
{
- cy_put_user(info->default_threshold,value);
- return 0;
+ return put_user(info->default_threshold,value);
}
static int
-set_timeout(struct cyclades_port * info, unsigned long value)
+set_timeout(struct cyclades_port * info, unsigned long *arg)
{
volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
int channel;
+ unsigned long value;
+
+ if (get_user(value, arg))
+ return -EFAULT;
channel = info->line;
@@ -1685,8 +1700,7 @@ get_timeout(struct cyclades_port * info, unsigned long *value)
channel = info->line;
tmp = base_addr[CyRTPRL];
- cy_put_user(tmp,value);
- return 0;
+ return put_user(tmp,value);
}
static int
@@ -1699,15 +1713,14 @@ set_default_timeout(struct cyclades_port * info, unsigned long value)
static int
get_default_timeout(struct cyclades_port * info, unsigned long *value)
{
- cy_put_user(info->default_timeout,value);
- return 0;
+ return put_user(info->default_timeout,value);
}
static int
cy_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- int error;
+ unsigned long val;
struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
int ret_val = 0;
@@ -1717,57 +1730,27 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
switch (cmd) {
case CYGETMON:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(struct cyclades_monitor));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
break;
case CYGETTHRESH:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned long));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_threshold(info, (unsigned long *)arg);
break;
case CYSETTHRESH:
- ret_val = set_threshold(info, (unsigned long)arg);
+ ret_val = set_threshold(info, (unsigned long *)arg);
break;
case CYGETDEFTHRESH:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned long));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_default_threshold(info, (unsigned long *)arg);
break;
case CYSETDEFTHRESH:
- ret_val = set_default_threshold(info, (unsigned long)arg);
+ ret_val = set_default_threshold(info, (unsigned long *)arg);
break;
case CYGETTIMEOUT:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned long));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_timeout(info, (unsigned long *)arg);
break;
case CYSETTIMEOUT:
- ret_val = set_timeout(info, (unsigned long)arg);
+ ret_val = set_timeout(info, (unsigned long *)arg);
break;
case CYGETDEFTIMEOUT:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned long));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_default_timeout(info, (unsigned long *)arg);
break;
case CYSETDEFTIMEOUT:
@@ -1776,7 +1759,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
case TCSBRK: /* SVID version: non-zero arg --> no break */
ret_val = tty_check_change(tty);
if (ret_val)
- return ret_val;
+ break;
tty_wait_until_sent(tty,0);
if (!arg)
send_break(info, HZ/4); /* 1/4 second */
@@ -1784,7 +1767,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
case TCSBRKP: /* support for POSIX tcsendbreak() */
ret_val = tty_check_change(tty);
if (ret_val)
- return ret_val;
+ break;
tty_wait_until_sent(tty,0);
send_break(info, arg ? arg*(HZ/10) : HZ/4);
break;
@@ -1796,46 +1779,20 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
/* The following commands are incompletely implemented!!! */
case TIOCGSOFTCAR:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned int *));
- if (error){
- ret_val = error;
- break;
- }
- cy_put_user(C_CLOCAL(tty) ? 1 : 0,
- (unsigned long *) arg);
+ ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
break;
case TIOCSSOFTCAR:
- error = verify_area(VERIFY_READ, (void *) arg
- ,sizeof(unsigned long *));
- if (error){
- ret_val = error;
- break;
- }
-
- arg = cy_get_user((unsigned long *) arg);
+ ret_val = get_user(val, (unsigned long *) arg);
+ if (ret_val)
+ break;
tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
+ ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
break;
case TIOCMGET:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(unsigned int *));
- if (error){
- ret_val = error;
- break;
- }
ret_val = get_modem_info(info, (unsigned int *) arg);
break;
case TIOCGSERIAL:
- error = verify_area(VERIFY_WRITE, (void *) arg
- ,sizeof(struct serial_struct));
- if (error){
- ret_val = error;
- break;
- }
- ret_val = get_serial_info(info,
- (struct serial_struct *) arg);
+ ret_val = get_serial_info(info, (struct serial_struct *) arg);
break;
case TIOCSSERIAL:
ret_val = set_serial_info(info,
@@ -2288,6 +2245,7 @@ mvme167_serial_console_setup(int cflag)
my_udelay(20000L); /* Allow time for any active o/p to complete */
if(base_addr[CyCCR] != 0x00){
+ restore_flags(flags);
/* printk(" chip is never idle (CCR != 0)\n"); */
return;
}
@@ -2296,6 +2254,7 @@ mvme167_serial_console_setup(int cflag)
my_udelay(1000L);
if(base_addr[CyGFRCR] == 0x00){
+ restore_flags(flags);
/* printk(" chip is not responding (GFRCR stayed 0)\n"); */
return;
}
@@ -2384,6 +2343,7 @@ int
serial167_init(void)
{
struct cyclades_port *info;
+ int ret = 0;
int good_ports = 0;
int port_num = 0;
int index;
@@ -2456,10 +2416,16 @@ scrn[1] = '\0';
cy_callout_driver.major = TTYAUX_MAJOR;
cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
- if (tty_register_driver(&cy_serial_driver))
- panic("Couldn't register Cyclom serial driver\n");
- if (tty_register_driver(&cy_callout_driver))
- panic("Couldn't register Cyclom callout driver\n");
+ ret = tty_register_driver(&cy_serial_driver);
+ if (ret) {
+ printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
+ return ret;
+ }
+ ret = tty_register_driver(&cy_callout_driver);
+ if (ret) {
+ printk(KERN_ERR "Couldn't register MVME166/7 callout driver\n");
+ goto cleanup_serial_driver;
+ }
init_bh(CYCLADES_BH, do_cyclades_bh);
@@ -2529,16 +2495,32 @@ scrn[1] = '\0';
#ifdef CONFIG_REMOTE_DEBUG
debug_setup();
#endif
- if (request_irq (MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
- "cd2401_errors", cd2401_rxerr_interrupt) ||
- request_irq (MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
- "cd2401_modem", cd2401_modem_interrupt) ||
- request_irq (MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
- "cd2401_txints", cd2401_tx_interrupt) ||
- request_irq (MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
- "cd2401_rxints", cd2401_rx_interrupt))
- {
- panic ("Couldn't get serial IRQs");
+ ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
+ "cd2401_errors", cd2401_rxerr_interrupt);
+ if (ret) {
+ printk(KERN_ERR "Could't get cd2401_errors IRQ");
+ goto cleanup_callout_driver;
+ }
+
+ ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
+ "cd2401_modem", cd2401_modem_interrupt);
+ if (ret) {
+ printk(KERN_ERR "Could't get cd2401_modem IRQ");
+ goto cleanup_irq_cd2401_errors;
+ }
+
+ ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
+ "cd2401_txints", cd2401_tx_interrupt);
+ if (ret) {
+ printk(KERN_ERR "Could't get cd2401_txints IRQ");
+ goto cleanup_irq_cd2401_modem;
+ }
+
+ ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
+ "cd2401_rxints", cd2401_rx_interrupt);
+ if (ret) {
+ printk(KERN_ERR "Could't get cd2401_rxints IRQ");
+ goto cleanup_irq_cd2401_txints;
}
/* Now we have registered the interrupt handlers, allow the interrupts */
@@ -2550,6 +2532,19 @@ scrn[1] = '\0';
pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */
return 0;
+cleanup_irq_cd2401_txints:
+ free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
+cleanup_irq_cd2401_modem:
+ free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
+cleanup_irq_cd2401_errors:
+ free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
+cleanup_callout_driver:
+ if (tty_unregister_driver(&cy_callout_driver))
+ printk(KERN_ERR "Couldn't unregister MVME166/7 callout driver\n");
+cleanup_serial_driver:
+ if (tty_unregister_driver(&cy_serial_driver))
+ printk(KERN_ERR "Couldn't unregister MVME166/7 serial driver\n");
+ return ret;
} /* serial167_init */
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 6e3c6a99c..a08de5cad 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -834,8 +834,9 @@ extern inline void sx_check_modem(struct specialix_board * bp)
#ifdef SPECIALIX_DEBUG
printk ( "Sending HUP.\n");
#endif
- queue_task(&port->tqueue_hangup,
- &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&port->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
} else {
#ifdef SPECIALIX_DEBUG
printk ( "Don't need to send HUP.\n");
@@ -2121,10 +2122,9 @@ static void do_sx_hangup(void *private_)
struct tty_struct *tty;
tty = port->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty); /* FIXME: module removal race here */
+ MOD_DEC_USE_COUNT;
}
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 8907fdeab..dbd51e51a 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -2231,11 +2231,11 @@ static void stl_offintr(void *private)
#endif
if (portp == (stlport_t *) NULL)
- return;
+ goto out;
tty = portp->tty;
if (tty == (struct tty_struct *) NULL)
- return;
+ goto out;
lock_kernel();
if (test_bit(ASYI_TXLOW, &portp->istate)) {
@@ -2254,12 +2254,14 @@ static void stl_offintr(void *private)
if (portp->flags & ASYNC_CHECK_CD) {
if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) &&
(portp->flags & ASYNC_CALLOUT_NOHUP))) {
- tty_hangup(tty);
+ tty_hangup(tty); /* FIXME: module removal race here - AKPM */
}
}
}
}
unlock_kernel();
+out:
+ MOD_DEC_USE_COUNT;
}
/*****************************************************************************/
@@ -4108,7 +4110,9 @@ static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr)
if ((len == 0) || ((len < STL_TXBUFLOW) &&
(test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
set_bit(ASYI_TXLOW, &portp->istate);
- queue_task(&portp->tqueue, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&portp->tqueue) == 0)
+ MOD_DEC_USE_COUNT;
}
if (len == 0) {
@@ -4288,7 +4292,9 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
misr = inb(ioaddr + EREG_DATA);
if (misr & MISR_DCD) {
set_bit(ASYI_DCDCHANGE, &portp->istate);
- queue_task(&portp->tqueue, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&portp->tqueue) == 0)
+ MOD_DEC_USE_COUNT;
portp->stats.modem++;
}
@@ -5085,7 +5091,9 @@ static void stl_sc26198txisr(stlport_t *portp)
if ((len == 0) || ((len < STL_TXBUFLOW) &&
(test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
set_bit(ASYI_TXLOW, &portp->istate);
- queue_task(&portp->tqueue, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&portp->tqueue) == 0)
+ MOD_DEC_USE_COUNT;
}
if (len == 0) {
@@ -5302,7 +5310,9 @@ static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack)
ipr = stl_sc26198getreg(portp, IPR);
if (ipr & IPR_DCDCHANGE) {
set_bit(ASYI_DCDCHANGE, &portp->istate);
- queue_task(&portp->tqueue, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&portp->tqueue) == 0)
+ MOD_DEC_USE_COUNT;
portp->stats.modem++;
}
break;
diff --git a/drivers/char/sx.h b/drivers/char/sx.h
index 662b27ca2..8d77c3c77 100644
--- a/drivers/char/sx.h
+++ b/drivers/char/sx.h
@@ -31,7 +31,7 @@ struct sx_port {
int c_dcd;
struct sx_board *board;
int line;
- int locks;
+ long locks;
};
struct sx_board {
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 3c05aa042..71773fa6c 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -27,7 +27,6 @@
extern void wakeup_bdflush(int);
extern void reset_vc(unsigned int);
-extern int console_loglevel;
extern struct list_head super_blocks;
/* Whether we react on sysrq keys or just ignore them */
diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
index cf521edfe..536942f41 100644
--- a/drivers/char/tpqic02.c
+++ b/drivers/char/tpqic02.c
@@ -760,7 +760,7 @@ static int rdstatus(char *stp, unsigned size, char qcmd)
static int get_status(volatile struct tpstatus *stp)
{
int stat = rdstatus((char *) stp, TPSTATSIZE, QCMD_RD_STAT);
-#if defined(i386) || defined(i486)
+#ifdef __i386__
byte_swap_w(&(stp->dec));
byte_swap_w(&(stp->urc));
#else
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 50e03a103..fe7da9e04 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -425,11 +425,9 @@ static struct file_operations hung_up_tty_fops = {
};
/*
- * This can be called through the "tq_scheduler"
- * task-list. That is process synchronous, but
- * doesn't hold any locks, so we need to make
- * sure we have the appropriate locks for what
- * we're doing..
+ * This can be called by the "eventd" kernel thread. That is process synchronous,
+ * but doesn't hold any locks, so we need to make sure we have the appropriate
+ * locks for what we're doing..
*/
void do_tty_hangup(void *data)
{
@@ -541,7 +539,7 @@ void tty_hangup(struct tty_struct * tty)
printk("%s hangup...\n", tty_name(tty, buf));
#endif
- queue_task(&tty->tq_hangup, &tq_scheduler);
+ schedule_task(&tty->tq_hangup);
}
void tty_vhangup(struct tty_struct * tty)
@@ -1264,7 +1262,7 @@ static void release_dev(struct file * filp)
* Make sure that the tty's task queue isn't activated.
*/
run_task_queue(&tq_timer);
- run_task_queue(&tq_scheduler);
+ flush_scheduled_tasks();
/*
* The release_mem function takes care of the details of clearing
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index ecf7cf05e..d6bc4e63b 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -48,7 +48,7 @@
#include <asm/bvme6000hw.h>
#endif
-#include "generic_serial.h"
+#include <linux/generic_serial.h>
#include "scc.h"
@@ -75,7 +75,7 @@ static void scc_disable_rx_interrupts(void * ptr);
static void scc_enable_rx_interrupts(void * ptr);
static int scc_get_CD(void * ptr);
static void scc_shutdown_port(void * ptr);
-static void scc_set_real_termios(void *ptr);
+static int scc_set_real_termios(void *ptr);
static void scc_hungup(void *ptr);
static void scc_close(void *ptr);
static int scc_chars_in_buffer(void * ptr);
@@ -688,7 +688,7 @@ static void scc_shutdown_port(void *ptr)
}
-static void scc_set_real_termios (void *ptr)
+static int scc_set_real_termios (void *ptr)
{
/* the SCC has char sizes 5,7,6,8 in that order! */
static int chsize_map[4] = { 0, 2, 1, 3 };
@@ -697,12 +697,12 @@ static void scc_set_real_termios (void *ptr)
struct scc_port *port = ptr;
SCC_ACCESS_INIT(port);
- if (!port->gs.tty || !port->gs.tty->termios) return;
+ if (!port->gs.tty || !port->gs.tty->termios) return 0;
channel = port->channel;
if (channel == CHANNEL_A)
- return; /* Settings controlled by boot PROM */
+ return 0; /* Settings controlled by boot PROM */
cflag = port->gs.tty->termios->c_cflag;
baud = port->gs.baud;
@@ -714,13 +714,13 @@ static void scc_set_real_termios (void *ptr)
cli();
SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
restore_flags(flags);
- return;
+ return 0;
}
else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
(MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
(MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
printk("SCC: Bad speed requested, %d\n", baud);
- return;
+ return 0;
}
if (cflag & CLOCAL)
@@ -769,6 +769,8 @@ static void scc_set_real_termios (void *ptr)
SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
restore_flags(flags);
+
+ return 0;
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 4328bbaeb..e50d98cd6 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -62,7 +62,7 @@ struct vt_struct *vt_cons[MAX_NR_CONSOLES];
*/
unsigned char keyboard_type = KB_101;
-#if !defined(__alpha__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__)
+#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__)
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
#endif
@@ -472,7 +472,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
ucval = keyboard_type;
goto setchar;
-#if !defined(__alpha__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__)
+#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__)
/*
* These cannot be implemented on any machine that implements
* ioperm() in user level (such as Alpha PCs).
diff --git a/drivers/i2o/i2o_lan.c b/drivers/i2o/i2o_lan.c
index 9bc7d825f..8b9e4c448 100644
--- a/drivers/i2o/i2o_lan.c
+++ b/drivers/i2o/i2o_lan.c
@@ -112,8 +112,10 @@ static struct i2o_handler i2o_lan_handler = {
};
static int lan_context;
-static struct tq_struct i2o_post_buckets_task = {
- 0, 0, (void (*)(void *))i2o_lan_receive_post, (void *) 0
+DECLARE_TASK_QUEUE(i2o_post_buckets_task);
+struct tq_struct run_i2o_post_buckets_task = {
+ routine: (void (*)(void *)) run_task_queue,
+ data: (void *) 0
};
/* Functions to handle message failures and transaction errors:
@@ -379,8 +381,8 @@ static void i2o_lan_receive_post_reply(struct i2o_handler *h,
/* If DDM has already consumed bucket_thresh buckets, post new ones */
if (atomic_read(&priv->buckets_out) <= priv->max_buckets_out - priv->bucket_thresh) {
- i2o_post_buckets_task.data = (void *)dev;
- queue_task(&i2o_post_buckets_task, &tq_immediate);
+ run_i2o_post_buckets_task.data = (void *)dev;
+ queue_task(&run_i2o_post_buckets_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
@@ -846,6 +848,7 @@ static void i2o_lan_batch_send(struct net_device *dev)
}
priv->send_active = 0;
spin_unlock_irq(&priv->tx_lock);
+ MOD_DEC_USE_COUNT;
}
#ifdef CONFIG_NET_FC
@@ -900,7 +903,9 @@ static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
if ((priv->tx_batch_mode & 0x01) && !priv->send_active) {
priv->send_active = 1;
- queue_task(&priv->i2o_batch_send_task, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&priv->i2o_batch_send_task) == 0)
+ MOD_DEC_USE_COUNT;
}
} else { /* Add new SGL element to the previous message frame */
@@ -986,7 +991,9 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
if ((priv->tx_batch_mode & 0x01) && !priv->send_active) {
priv->send_active = 1;
- queue_task(&priv->i2o_batch_send_task, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&priv->i2o_batch_send_task) == 0)
+ MOD_DEC_USE_COUNT;
}
} else { /* Add new SGL element to the previous message frame */
@@ -1396,7 +1403,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
atomic_set(&priv->tx_out, 0);
priv->tx_count = 0;
- priv->i2o_batch_send_task.next = NULL;
+ INIT_LIST_HEAD(&priv->i2o_batch_send_task.list);
priv->i2o_batch_send_task.sync = 0;
priv->i2o_batch_send_task.routine = (void *)i2o_lan_batch_send;
priv->i2o_batch_send_task.data = (void *)dev;
diff --git a/drivers/ide/buddha.c b/drivers/ide/buddha.c
index 7ef6f645a..4de01ad9c 100644
--- a/drivers/ide/buddha.c
+++ b/drivers/ide/buddha.c
@@ -43,7 +43,7 @@
#define BUDDHA_BASE2 0xa00
#define BUDDHA_BASE3 0xc00
-static const u_int __init buddha_bases[CATWEASEL_NUM_HWIFS] = {
+static const u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = {
BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
};
@@ -62,7 +62,7 @@ static const u_int __init buddha_bases[CATWEASEL_NUM_HWIFS] = {
#define BUDDHA_STATUS 0x1e /* see status-bits */
#define BUDDHA_CONTROL 0x11a
-static int __init buddha_offsets[IDE_NR_PORTS] = {
+static int buddha_offsets[IDE_NR_PORTS] __initdata = {
BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL
};
@@ -76,7 +76,7 @@ static int __init buddha_offsets[IDE_NR_PORTS] = {
#define BUDDHA_IRQ2 0xf40 /* interrupt */
#define BUDDHA_IRQ3 0xf80
-static const int __init buddha_irqports[CATWEASEL_NUM_HWIFS] = {
+static const int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = {
BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
};
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c
index 2011b6a26..5a5e8c04d 100644
--- a/drivers/ide/gayle.c
+++ b/drivers/ide/gayle.c
@@ -17,8 +17,10 @@
#include <linux/ide.h>
#include <linux/init.h>
+#include <asm/setup.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
+#include <asm/amigayle.h>
/*
@@ -42,7 +44,7 @@
#define GAYLE_STATUS 0x1e /* see status-bits */
#define GAYLE_CONTROL 0x101a
-static int __init gayle_offsets[IDE_NR_PORTS] = {
+static int gayle_offsets[IDE_NR_PORTS] __initdata = {
GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
};
@@ -87,7 +89,7 @@ static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
unsigned char ch;
ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
- if (!(ch & 0x80))
+ if (!(ch & GAYLE_IRQ_IDE))
return 0;
return 1;
}
@@ -97,10 +99,10 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
unsigned char ch;
ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
- if (!(ch & 0x80))
+ if (!(ch & GAYLE_IRQ_IDE))
return 0;
(void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
- outb(0x7c | (ch & 0x03), hwif->io_ports[IDE_IRQ_OFFSET]);
+ outb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]);
return 1;
}
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index d2a5ae37e..f00c68ed4 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1841,9 +1841,9 @@ static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
memset(&pc, 0, sizeof (pc));
pc.sense = &sense;
- pc.c[0] = GPCMD_PLAY_AUDIO_10;
- put_unaligned(cpu_to_be32(lba_start), (unsigned int *) &pc.c[2]);
- put_unaligned(cpu_to_be16(lba_end - lba_start), (unsigned int *) &pc.c[7]);
+ pc.c[0] = GPCMD_PLAY_AUDIO_MSF;
+ lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
+ lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
return cdrom_queue_packet_command(drive, &pc);
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 32205cccc..95640895a 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1324,7 +1324,7 @@ static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
mod_timer(&hwgroup->timer, sleep);
/* we purposely leave hwgroup->busy==1 while sleeping */
} else {
- /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
+ /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_disk? */
ide_release_lock(&ide_lock); /* for atari only */
hwgroup->busy = 0;
}
@@ -3241,6 +3241,12 @@ static void __init probe_for_hwifs (void)
macide_init();
}
#endif /* CONFIG_BLK_DEV_MAC_IDE */
+#ifdef CONFIG_BLK_DEV_Q40IDE
+ {
+ extern void q40ide_init(void);
+ q40ide_init();
+ }
+#endif /* CONFIG_BLK_DEV_Q40IDE */
#ifdef CONFIG_BLK_DEV_BUDDHA
{
extern void buddha_init(void);
diff --git a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c
index 41d4277d2..cbc99d25f 100644
--- a/drivers/ide/q40ide.c
+++ b/drivers/ide/q40ide.c
@@ -1,18 +1,12 @@
/*
* linux/drivers/ide/q40ide.c -- Q40 I/O port IDE Driver
*
- * original file created 12 Jul 1997 by Geert Uytterhoeven
+ * (c) Richard Zidlicky
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
- * RZ:
- * almost identical with pcide.c, maybe we can merge it later.
- * Differences:
- * max 2 HWIFS for now
- * translate portaddresses to q40 native addresses (not yet...) instead rely on in/out[bw]
- * address translation
*
*/
@@ -28,7 +22,7 @@
* Bases of the IDE interfaces
*/
-#define PCIDE_NUM_HWIFS 2
+#define Q40IDE_NUM_HWIFS 2
#define PCIDE_BASE1 0x1f0
#define PCIDE_BASE2 0x170
@@ -37,7 +31,7 @@
#define PCIDE_BASE5 0x1e0
#define PCIDE_BASE6 0x160
-static const q40ide_ioreg_t pcide_bases[PCIDE_NUM_HWIFS] = {
+static const q40ide_ioreg_t pcide_bases[Q40IDE_NUM_HWIFS] = {
PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5,
PCIDE_BASE6 */
};
@@ -58,7 +52,7 @@ static const int pcide_offsets[IDE_NR_PORTS] = {
PCIDE_REG(CMD)
};
-int q40ide_default_irq(q40ide_ioreg_t base)
+static int q40ide_default_irq(q40ide_ioreg_t base)
{
switch (base) {
case 0x1f0: return 14;
@@ -69,41 +63,26 @@ int q40ide_default_irq(q40ide_ioreg_t base)
}
}
-void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq)
-{
- q40ide_ioreg_t port = base;
- int i = 8;
-
- while (i--)
- *p++ = port++;
- *p++ = base + 0x206;
- if (irq != NULL)
- *irq = 0;
-}
/*
- * Probe for PC IDE interfaces
+ * Probe for Q40 IDE interfaces
*/
-int q40ide_probe_hwif(int index, ide_hwif_t *hwif)
+void q40ide_init(void)
{
- static int pcide_index[PCIDE_NUM_HWIFS] = { 0, };
int i;
if (!MACH_IS_Q40)
- return 0;
-
- for (i = 0; i < PCIDE_NUM_HWIFS; i++) {
- if (!pcide_index[i]) {
- /*printk("ide%d: Q40 IDE interface\n", index);*/
- pcide_index[i] = index+1;
- }
- if (pcide_index[i] == index+1) {
- ide_setup_ports(hwif,(ide_ioreg_t) pcide_bases[i], pcide_offsets, 0, /*q40_ack_intr???*/ NULL);
- hwif->irq = ide_default_irq((ide_ioreg_t)pcide_bases[i]); /*q40_ide_irq[i]; */ /* 14 */
- return 1;
- }
+ return ;
+
+ for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
+ hw_regs_t hw;
+
+ ide_setup_ports(&hw,(ide_ioreg_t) pcide_bases[i], (int *)pcide_offsets,
+ pcide_bases[i]+0x206,
+ 0, NULL, q40ide_default_irq(pcide_bases[i]));
+ ide_register_hw(&hw, NULL);
}
- return 0;
}
+
diff --git a/drivers/ieee1394/guid.c b/drivers/ieee1394/guid.c
index 1aa453292..6745222f3 100644
--- a/drivers/ieee1394/guid.c
+++ b/drivers/ieee1394/guid.c
@@ -163,7 +163,7 @@ static void host_reset(struct hpsb_host *host)
return;
}
- greq->tq.next = NULL;
+ INIT_LIST_HEAD(&greq->tq.list);
greq->tq.sync = 0;
greq->tq.routine = (void (*)(void*))pkt_complete;
greq->tq.data = greq;
diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h
index 8175fa8f9..c55f7e66b 100644
--- a/drivers/ieee1394/ieee1394_types.h
+++ b/drivers/ieee1394/ieee1394_types.h
@@ -10,186 +10,12 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-
-#include <linux/wait.h>
-#define DECLARE_WAITQUEUE(name, task) struct wait_queue name = { task, NULL }
-
-typedef struct wait_queue *wait_queue_head_t;
-typedef struct wait_queue wait_queue_t;
-
-inline static void init_waitqueue_head(wait_queue_head_t *wh)
-{
- *wh = NULL;
-}
-
-inline static void init_waitqueue_entry(wait_queue_t *wq, struct task_struct *p)
-{
- wq->task = p;
- wq->next = NULL;
-}
-
-static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-#define __constant_cpu_to_be32(x) __constant_htonl((x))
-
-#define set_current_state(state_value) \
- do { current->state = (state_value); } while (0)
-
-
-#include <asm/page.h>
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int order;
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
-#include <linux/mm.h>
-#include <linux/pci.h>
-inline static int pci_enable_device(struct pci_dev *dev)
-{
- u16 cmd;
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY);
- return 0;
-}
-
-#define PCI_DMA_BIDIRECTIONAL 0
-#define PCI_DMA_TODEVICE 1
-#define PCI_DMA_FROMDEVICE 2
-#define PCI_DMA_NONE 3
-#define PCI_ROM_RESOURCE 6
-#define pci_resource_start(dev, bar) ((bar) == PCI_ROM_RESOURCE \
- ? (dev)->rom_address \
- : (dev)->base_address[(bar)])
-#define BUG() *(int *)0 = 0
-
-#include <asm/io.h>
-typedef u32 dma_addr_t;
-
-extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
-{
- return 1;
-}
-
-extern inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle)
-{
- void *ret;
- ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
- if (ret) {
- memset(ret, 0, size);
- *dma_handle = virt_to_bus(ret);
- }
- return ret;
-}
-
-extern inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- free_pages((unsigned long)vaddr, get_order(size));
-}
-
-extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
- size_t size, int direction)
-{
- if (direction == PCI_DMA_NONE)
- BUG();
- return virt_to_bus(ptr);
-}
-
-extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
- size_t size, int direction)
-{
- if (direction == PCI_DMA_NONE)
- BUG();
-}
-
-#include <asm/scatterlist.h>
-extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, int direction)
-{
- if (direction == PCI_DMA_NONE)
- BUG();
- return nents;
-}
-
-extern inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, int direction)
-{
- if (direction == PCI_DMA_NONE)
- BUG();
-}
-
-extern inline void pci_dma_sync_single(struct pci_dev *hwdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
-{
- if (direction == PCI_DMA_NONE)
- BUG();
-}
-
-extern inline void pci_dma_sync_sg(struct pci_dev *hwdev,
- struct scatterlist *sg,
- int nelems, int direction)
-{
- if (direction == PCI_DMA_NONE)
- BUG();
-}
-
-
-#ifndef _LINUX_DEVFS_FS_KERNEL_H
-typedef struct devfs_entry * devfs_handle_t;
-#define DEVFS_FL_NONE 0
-
-static inline devfs_handle_t devfs_register (devfs_handle_t dir,
- const char *name,
- unsigned int flags,
- unsigned int major,
- unsigned int minor,
- umode_t mode,
- void *ops, void *info)
-{
- return NULL;
-}
-static inline void devfs_unregister (devfs_handle_t de)
-{
- return;
-}
-static inline int devfs_register_chrdev (unsigned int major, const char *name,
- struct file_operations *fops)
-{
- return register_chrdev (major, name, fops);
-}
-static inline int devfs_unregister_chrdev (unsigned int major,const char *name)
-{
- return unregister_chrdev (major, name);
-}
-#endif /* _LINUX_DEVFS_FS_KERNEL_H */
-
-
-#define V22_COMPAT_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
-#define V22_COMPAT_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
-#define OWNER_THIS_MODULE
-
-#else /* Linux version < 2.3 */
-
+#include "linux22compat.h"
+#else
#define V22_COMPAT_MOD_INC_USE_COUNT do {} while (0)
#define V22_COMPAT_MOD_DEC_USE_COUNT do {} while (0)
#define OWNER_THIS_MODULE owner: THIS_MODULE,
-
-#endif /* Linux version < 2.3 */
-
-
+#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
#include <asm/spinlock.h>
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 6dc42555d..3b41afb55 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -1585,7 +1585,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
/* initialize bottom handler */
d->task.sync = 0;
- d->task.next = NULL;
+ INIT_LIST_HEAD(&d->task.list);
d->task.routine = dma_rcv_bh;
d->task.data = (void*)d;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 352f85408..9943c255c 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1457,9 +1457,9 @@ static void remove_card(struct ti_lynx *lynx)
switch (lynx->state) {
case have_intr:
+ reg_write(lynx, PCI_INT_ENABLE, 0);
free_irq(lynx->dev->irq, lynx);
case have_iomappings:
- reg_write(lynx, PCI_INT_ENABLE, 0);
reg_write(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
iounmap(lynx->registers);
iounmap(lynx->local_rom);
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 8b4aa7244..16399b347 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -786,6 +786,10 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
req->req.length = 0;
queue_task(&req->tq, &packet->complete_tq);
+ spin_lock_irq(&fi->reqlists_lock);
+ list_add_tail(&req->list, &fi->req_pending);
+ spin_unlock_irq(&fi->reqlists_lock);
+
if (!hpsb_send_packet(packet)) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
queue_complete_req(req);
diff --git a/drivers/isdn/avmb1/Makefile b/drivers/isdn/avmb1/Makefile
index 56f7ac4be..a076ef7c3 100644
--- a/drivers/isdn/avmb1/Makefile
+++ b/drivers/isdn/avmb1/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.21 2000/11/01 14:05:02 calle Exp $
+# $Id: Makefile,v 1.22 2000/11/23 20:45:14 kai Exp $
#
# Makefile for the CAPI and AVM-B1 device drivers.
#
@@ -11,6 +11,10 @@
# parent makes..
#
# $Log: Makefile,v $
+# Revision 1.22 2000/11/23 20:45:14 kai
+# fixed module_init/exit stuff
+# Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+#
# Revision 1.21 2000/11/01 14:05:02 calle
# - use module_init/module_exit from linux/init.h.
# - all static struct variables are initialized with "membername:" now.
@@ -150,19 +154,19 @@ ifeq ($(CONFIG_ISDN_CAPI),y)
OX_OBJS += kcapi.o
O_OBJS += capi.o
ifdef CONFIG_ISDN_CAPIFS
- OX_OBJS += capifs.o
+ OX_OBJS += capifs.o
endif
ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
- O_OBJS += b1isa.o
+ O_OBJS += b1isa.o
endif
ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
- O_OBJS += b1pci.o
+ O_OBJS += b1pci.o
endif
ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
- O_OBJS += t1isa.o
+ O_OBJS += t1isa.o
endif
ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
- OX_OBJS += b1pcmcia.o
+ OX_OBJS += b1pcmcia.o
ifeq ($(CONFIG_HOTPLUG),y)
ifneq ($(CONFIG_PCMCIA),n)
M_OBJS += avm_cs.o
@@ -170,44 +174,44 @@ ifeq ($(CONFIG_ISDN_CAPI),y)
endif
endif
ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
- O_OBJS += t1pci.o
+ O_OBJS += t1pci.o
endif
ifdef CONFIG_ISDN_DRV_AVMB1_C4
- O_OBJS += c4.o
+ O_OBJS += c4.o
endif
OX_OBJS += capiutil.o capidrv.o b1.o b1dma.o
else
ifeq ($(CONFIG_ISDN_CAPI),m)
- O_TARGET += kernelcapi.o
- OX_OBJS += kcapi.o
- M_OBJS += capi.o kernelcapi.o
- ifdef CONFIG_ISDN_CAPIFS
- MX_OBJS += capifs.o
- endif
- ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
- M_OBJS += b1isa.o
- endif
- ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
- M_OBJS += b1pci.o
- endif
- ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
- M_OBJS += t1isa.o
- endif
- ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
- MX_OBJS += b1pcmcia.o
+ O_TARGET += kernelcapi.o
+ OX_OBJS += kcapi.o
+ M_OBJS += capi.o kernelcapi.o
+ ifdef CONFIG_ISDN_CAPIFS
+ MX_OBJS += capifs.o
+ endif
+ ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
+ M_OBJS += b1isa.o
+ endif
+ ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
+ M_OBJS += b1pci.o
+ endif
+ ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
+ M_OBJS += t1isa.o
+ endif
+ ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+ MX_OBJS += b1pcmcia.o
ifeq ($(CONFIG_HOTPLUG),y)
ifneq ($(CONFIG_PCMCIA),n)
- M_OBJS += avm_cs.o
+ M_OBJS += avm_cs.o
endif
endif
- endif
- ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
- M_OBJS += t1pci.o
- endif
- ifdef CONFIG_ISDN_DRV_AVMB1_C4
- M_OBJS += c4.o
- endif
- MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o
+ endif
+ ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
+ M_OBJS += t1pci.o
+ endif
+ ifdef CONFIG_ISDN_DRV_AVMB1_C4
+ M_OBJS += c4.o
+ endif
+ MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o
endif
endif
diff --git a/drivers/isdn/avmb1/avm_cs.c b/drivers/isdn/avmb1/avm_cs.c
index f1538b44f..3b184c54e 100644
--- a/drivers/isdn/avmb1/avm_cs.c
+++ b/drivers/isdn/avmb1/avm_cs.c
@@ -145,9 +145,7 @@ static dev_link_t *avmcs_attach(void)
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.NumPorts2 = 16;
- link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
- link->io.IOAddrLines = 5;
+ link->io.NumPorts2 = 0;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
@@ -329,9 +327,10 @@ static void avmcs_config(dev_link_t *link)
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.NumPorts1 = cf->io.win[0].len;
+ link->io.NumPorts2 = 0;
printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
link->io.BasePort1,
- link->io.BasePort1+link->io.NumPorts1);
+ link->io.BasePort1+link->io.NumPorts1-1);
i = CardServices(RequestIO, link->handle, &link->io);
if (i == CS_SUCCESS) goto found_port;
}
@@ -504,7 +503,7 @@ static int avmcs_event(event_t event, int priority,
/*====================================================================*/
-int init_module(void)
+static int __init avmcs_init(void)
{
servinfo_t serv;
CardServices(GetCardServicesInfo, &serv);
@@ -517,7 +516,7 @@ int init_module(void)
return 0;
}
-void cleanup_module(void)
+static void __exit avmcs_exit(void)
{
unregister_pccard_driver(&dev_info);
while (dev_list != NULL) {
@@ -526,3 +525,6 @@ void cleanup_module(void)
avmcs_detach(dev_list);
}
}
+
+module_init(avmcs_init);
+module_exit(avmcs_exit);
diff --git a/drivers/isdn/avmb1/b1.c b/drivers/isdn/avmb1/b1.c
index 747b5ea7f..3feb65ce9 100644
--- a/drivers/isdn/avmb1/b1.c
+++ b/drivers/isdn/avmb1/b1.c
@@ -1,11 +1,26 @@
/*
- * $Id: b1.c,v 1.16 2000/08/04 15:36:31 calle Exp $
+ * $Id: b1.c,v 1.20 2000/11/23 20:45:14 kai Exp $
*
* Common module for AVM B1 cards.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1.c,v $
+ * Revision 1.20 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.19 2000/11/19 17:02:47 kai
+ * compatibility cleanup - part 3
+ *
+ * Revision 1.18 2000/11/19 17:01:53 kai
+ * compatibility cleanup - part 2
+ *
+ * Revision 1.17 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
* Revision 1.16 2000/08/04 15:36:31 calle
* copied wrong from file to file :-(
*
@@ -94,6 +109,7 @@
#include <linux/ioport.h>
#include <linux/capi.h>
#include <asm/io.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include "capilli.h"
@@ -101,7 +117,7 @@
#include "capicmd.h"
#include "capiutil.h"
-static char *revision = "$Revision: 1.16 $";
+static char *revision = "$Revision: 1.20 $";
/* ------------------------------------------------------------- */
@@ -728,12 +744,7 @@ EXPORT_SYMBOL(b1_handle_interrupt);
EXPORT_SYMBOL(b1ctl_read_proc);
-#ifdef MODULE
-#define b1_init init_module
-void cleanup_module(void);
-#endif
-
-int b1_init(void)
+static int __init b1_init(void)
{
char *p;
char rev[10];
@@ -750,8 +761,9 @@ int b1_init(void)
return 0;
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit b1_exit(void)
{
}
-#endif
+
+module_init(b1_init);
+module_exit(b1_exit);
diff --git a/drivers/isdn/avmb1/b1capi.c b/drivers/isdn/avmb1/b1capi.c
index ea4aeb369..117701a90 100644
--- a/drivers/isdn/avmb1/b1capi.c
+++ b/drivers/isdn/avmb1/b1capi.c
@@ -468,6 +468,7 @@ static void notify_handler(void *dummy)
for (contr=1; VALID_CARD(contr); contr++)
if (test_and_clear_bit(contr, &notify_down_set))
notify_down(contr);
+ MOD_DEC_USE_COUNT;
}
/* -------- card ready callback ------------------------------- */
@@ -508,7 +509,9 @@ void avmb1_card_ready(avmb1_card * card)
}
set_bit(CARDNR(card), &notify_up_set);
- queue_task(&tq_state_notify, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&tq_state_notify) == 0)
+ MOD_DEC_USE_COUNT;
flag = ((__u8 *)(profp->manu))[1];
switch (flag) {
@@ -568,7 +571,9 @@ static void avmb1_card_down(avmb1_card * card, int notify)
}
}
set_bit(CARDNR(card), &notify_down_set);
- queue_task(&tq_state_notify, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&tq_state_notify) == 0)
+ MOD_DEC_USE_COUNT;
printk(KERN_NOTICE "b1capi: card %d down.\n", CARDNR(card));
}
diff --git a/drivers/isdn/avmb1/b1dma.c b/drivers/isdn/avmb1/b1dma.c
index 6cdc6c5a4..78cec8c9a 100644
--- a/drivers/isdn/avmb1/b1dma.c
+++ b/drivers/isdn/avmb1/b1dma.c
@@ -1,11 +1,17 @@
/*
- * $Id: b1dma.c,v 1.9 2000/11/01 14:05:02 calle Exp $
+ * $Id: b1dma.c,v 1.11 2000/11/19 17:02:47 kai Exp $
*
* Common module for AVM B1 cards that support dma with AMCC
*
* (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1dma.c,v $
+ * Revision 1.11 2000/11/19 17:02:47 kai
+ * compatibility cleanup - part 3
+ *
+ * Revision 1.10 2000/11/19 17:01:53 kai
+ * compatibility cleanup - part 2
+ *
* Revision 1.9 2000/11/01 14:05:02 calle
* - use module_init/module_exit from linux/init.h.
* - all static struct variables are initialized with "membername:" now.
@@ -48,6 +54,7 @@
#include <linux/ioport.h>
#include <linux/capi.h>
#include <asm/io.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include "capilli.h"
@@ -55,7 +62,7 @@
#include "capicmd.h"
#include "capiutil.h"
-static char *revision = "$Revision: 1.9 $";
+static char *revision = "$Revision: 1.11 $";
/* ------------------------------------------------------------- */
@@ -978,11 +985,6 @@ EXPORT_SYMBOL(b1dma_release_appl);
EXPORT_SYMBOL(b1dma_send_message);
EXPORT_SYMBOL(b1dmactl_read_proc);
-#ifdef MODULE
-#define b1dma_init init_module
-void cleanup_module(void);
-#endif
-
int b1dma_init(void)
{
char *p;
@@ -1000,8 +1002,9 @@ int b1dma_init(void)
return 0;
}
-#ifdef MODULE
-void cleanup_module(void)
+void b1dma_exit(void)
{
}
-#endif
+
+module_init(b1dma_init);
+module_exit(b1dma_exit);
diff --git a/drivers/isdn/avmb1/b1isa.c b/drivers/isdn/avmb1/b1isa.c
index 486a0f28d..76e1faed3 100644
--- a/drivers/isdn/avmb1/b1isa.c
+++ b/drivers/isdn/avmb1/b1isa.c
@@ -1,11 +1,20 @@
/*
- * $Id: b1isa.c,v 1.8 2000/04/03 13:29:24 calle Exp $
+ * $Id: b1isa.c,v 1.10 2000/11/23 20:45:14 kai Exp $
*
* Module for AVM B1 ISA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1isa.c,v $
+ * Revision 1.10 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.9 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
* Revision 1.8 2000/04/03 13:29:24 calle
* make Tim Waugh happy (module unload races in 2.3.99-pre3).
* no real problem there, but now it is much cleaner ...
@@ -67,13 +76,14 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/capi.h>
+#include <linux/init.h>
#include <asm/io.h>
#include "capicmd.h"
#include "capiutil.h"
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.8 $";
+static char *revision = "$Revision: 1.10 $";
/* ------------------------------------------------------------- */
@@ -260,12 +270,7 @@ static struct capi_driver b1isa_driver = {
add_card: b1isa_add_card,
};
-#ifdef MODULE
-#define b1isa_init init_module
-void cleanup_module(void);
-#endif
-
-int b1isa_init(void)
+static int __init b1isa_init(void)
{
struct capi_driver *driver = &b1isa_driver;
char *p;
@@ -292,9 +297,10 @@ int b1isa_init(void)
return retval;
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit b1isa_exit(void)
{
detach_capi_driver(&b1isa_driver);
}
-#endif
+
+module_init(b1isa_init);
+module_exit(b1isa_exit);
diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c
index 27af2e27b..6d7ac7af4 100644
--- a/drivers/isdn/avmb1/b1pci.c
+++ b/drivers/isdn/avmb1/b1pci.c
@@ -1,11 +1,30 @@
/*
- * $Id: b1pci.c,v 1.27 2000/08/08 09:24:19 calle Exp $
+ * $Id: b1pci.c,v 1.29.6.1 2000/11/28 12:02:45 kai Exp $
*
* Module for AVM B1 PCI-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1pci.c,v $
+ * Revision 1.29.6.1 2000/11/28 12:02:45 kai
+ * MODULE_DEVICE_TABLE for 2.4
+ *
+ * Revision 1.29.2.2 2000/11/26 17:47:53 kai
+ * added PCI_DEV_TABLE for 2.4
+ *
+ * Revision 1.29.2.1 2000/11/26 17:14:19 kai
+ * fix device ids
+ * also needs patches to include/linux/pci_ids.h
+ *
+ * Revision 1.29 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.28 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
* Revision 1.27 2000/08/08 09:24:19 calle
* calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI
*
@@ -94,25 +113,22 @@
#include <linux/pci.h>
#include <linux/capi.h>
#include <asm/io.h>
+#include <linux/init.h>
#include "capicmd.h"
#include "capiutil.h"
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.27 $";
+static char *revision = "$Revision: 1.29.6.1 $";
/* ------------------------------------------------------------- */
-#ifndef PCI_VENDOR_ID_AVM
-#define PCI_VENDOR_ID_AVM 0x1244
-#endif
-
-#ifndef PCI_DEVICE_ID_AVM_B1
-#define PCI_DEVICE_ID_AVM_B1 0x700
-#endif
-
-/* ------------------------------------------------------------- */
+static struct pci_device_id b1pci_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl);
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
/* ------------------------------------------------------------- */
@@ -481,11 +497,6 @@ static struct capi_driver b1pciv4_driver = {
#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
-#ifdef MODULE
-#define b1pci_init init_module
-void cleanup_module(void);
-#endif
-
static int ncards = 0;
static int add_card(struct pci_dev *dev)
@@ -548,7 +559,7 @@ static int add_card(struct pci_dev *dev)
return retval;
}
-int b1pci_init(void)
+static int __init b1pci_init(void)
{
struct capi_driver *driver = &b1pci_driver;
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
@@ -640,12 +651,13 @@ int b1pci_init(void)
#endif
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit b1pci_exit(void)
{
detach_capi_driver(&b1pci_driver);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
detach_capi_driver(&b1pciv4_driver);
#endif
}
-#endif
+
+module_init(b1pci_init);
+module_exit(b1pci_exit);
diff --git a/drivers/isdn/avmb1/b1pcmcia.c b/drivers/isdn/avmb1/b1pcmcia.c
index 20b851548..bc4a27bd2 100644
--- a/drivers/isdn/avmb1/b1pcmcia.c
+++ b/drivers/isdn/avmb1/b1pcmcia.c
@@ -1,11 +1,20 @@
/*
- * $Id: b1pcmcia.c,v 1.10 2000/05/06 00:52:36 kai Exp $
+ * $Id: b1pcmcia.c,v 1.12 2000/11/23 20:45:14 kai Exp $
*
* Module for AVM B1/M1/M2 PCMCIA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1pcmcia.c,v $
+ * Revision 1.12 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.11 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
* Revision 1.10 2000/05/06 00:52:36 kai
* merged changes from kernel tree
* fixed timer and net_device->name breakage
@@ -75,6 +84,7 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <linux/capi.h>
#include <linux/b1pcmcia.h>
@@ -83,7 +93,7 @@
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.10 $";
+static char *revision = "$Revision: 1.12 $";
/* ------------------------------------------------------------- */
@@ -300,12 +310,7 @@ EXPORT_SYMBOL(b1pcmcia_delcard);
/* ------------------------------------------------------------- */
-#ifdef MODULE
-#define b1pcmcia_init init_module
-void cleanup_module(void);
-#endif
-
-int b1pcmcia_init(void)
+static int __init b1pcmcia_init(void)
{
struct capi_driver *driver = &b1pcmcia_driver;
char *p;
@@ -332,9 +337,10 @@ int b1pcmcia_init(void)
return retval;
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit b1pcmcia_exit(void)
{
detach_capi_driver(&b1pcmcia_driver);
}
-#endif
+
+module_init(b1pcmcia_init);
+module_exit(b1pcmcia_exit);
diff --git a/drivers/isdn/avmb1/c4.c b/drivers/isdn/avmb1/c4.c
index 7f1340001..4c0b5f0eb 100644
--- a/drivers/isdn/avmb1/c4.c
+++ b/drivers/isdn/avmb1/c4.c
@@ -1,11 +1,28 @@
/*
- * $Id: c4.c,v 1.18 2000/11/01 14:05:02 calle Exp $
+ * $Id: c4.c,v 1.20.6.1 2000/11/28 12:02:45 kai Exp $
*
* Module for AVM C4 card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: c4.c,v $
+ * Revision 1.20.6.1 2000/11/28 12:02:45 kai
+ * MODULE_DEVICE_TABLE for 2.4
+ *
+ * Revision 1.20.2.2 2000/11/26 17:47:53 kai
+ * added PCI_DEV_TABLE for 2.4
+ *
+ * Revision 1.20.2.1 2000/11/26 17:14:19 kai
+ * fix device ids
+ * also needs patches to include/linux/pci_ids.h
+ *
+ * Revision 1.20 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.19 2000/11/19 17:02:47 kai
+ * compatibility cleanup - part 3
+ *
* Revision 1.18 2000/11/01 14:05:02 calle
* - use module_init/module_exit from linux/init.h.
* - all static struct variables are initialized with "membername:" now.
@@ -80,6 +97,7 @@
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/capi.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h>
@@ -88,35 +106,22 @@
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.18 $";
+static char *revision = "$Revision: 1.20.6.1 $";
#undef CONFIG_C4_DEBUG
#undef CONFIG_C4_POLLDEBUG
/* ------------------------------------------------------------- */
-#ifndef PCI_VENDOR_ID_DEC
-#define PCI_VENDOR_ID_DEC 0x1011
-#endif
+static int suppress_pollack;
-#ifndef PCI_DEVICE_ID_DEC_21285
-#define PCI_DEVICE_ID_DEC_21285 0x1065
-#endif
-
-#ifndef PCI_VENDOR_ID_AVM
-#define PCI_VENDOR_ID_AVM 0x1244
-#endif
-
-#ifndef PCI_DEVICE_ID_AVM_C4
-#define PCI_DEVICE_ID_AVM_C4 0x0800
-#endif
-
-/* ------------------------------------------------------------- */
-
-static int suppress_pollack = 0;
+static struct pci_device_id c4_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4 },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, c4_pci_tbl);
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
-
MODULE_PARM(suppress_pollack, "0-1i");
/* ------------------------------------------------------------- */
@@ -1327,15 +1332,9 @@ static struct capi_driver c4_driver = {
};
-#ifdef MODULE
-#define c4_init init_module
-void cleanup_module(void);
-#endif
-
-
static int ncards = 0;
-int c4_init(void)
+static int __init c4_init(void)
{
struct capi_driver *driver = &c4_driver;
struct pci_dev *dev = NULL;
@@ -1419,9 +1418,10 @@ int c4_init(void)
#endif
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit c4_exit(void)
{
detach_capi_driver(&c4_driver);
}
-#endif
+
+module_init(c4_init);
+module_exit(c4_exit);
diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c
index 69385b4df..73846f660 100644
--- a/drivers/isdn/avmb1/capi.c
+++ b/drivers/isdn/avmb1/capi.c
@@ -1,11 +1,32 @@
/*
- * $Id: capi.c,v 1.39 2000/07/24 13:42:50 calle Exp $
+ * $Id: capi.c,v 1.44 2000/11/25 17:00:59 kai Exp $
*
* CAPI 2.0 Interface for Linux
*
* Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capi.c,v $
+ * Revision 1.44 2000/11/25 17:00:59 kai
+ * compatibility cleanup - final part for the time being
+ *
+ * Revision 1.43 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.42 2000/11/19 17:03:55 kai
+ * compatibility cleanup - part 5
+ *
+ * Revision 1.41 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
+ * Revision 1.40 2000/10/24 15:15:04 calle
+ * Workaround: pppd calls restoretty before reseting the ldisc and
+ * ldisc "ppp_sync" didn't support this. So we call n_tty_ioctl
+ * in the driver ioctl function. (remember: driver ioctl function is
+ * only called if ldisc ioctl function did not handle the call)
+ *
* Revision 1.39 2000/07/24 13:42:50 calle
* - lock_kernel/unlock_kernel for _release functions. (from 2.4)
*
@@ -211,8 +232,8 @@
#include <linux/poll.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
+#include <linux/devfs_fs_kernel.h>
#include "capiutil.h"
#include "capicmd.h"
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -220,7 +241,7 @@
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
#include <linux/slab.h>
-static char *revision = "$Revision: 1.39 $";
+static char *revision = "$Revision: 1.44 $";
MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)");
@@ -1667,7 +1688,13 @@ int capinc_tty_chars_in_buffer(struct tty_struct *tty)
int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- return -ENOIOCTLCMD;
+ int error = 0;
+ switch (cmd) {
+ default:
+ error = n_tty_ioctl (tty, file, cmd, arg);
+ break;
+ }
+ return error;
}
void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
@@ -1960,7 +1987,7 @@ static void __exit proc_exit(void)
/* -------- init function and module interface ---------------------- */
-static void alloc_exit(void)
+static void __exit alloc_exit(void)
{
if (capidev_cachep) {
(void)kmem_cache_destroy(capidev_cachep);
@@ -2060,7 +2087,7 @@ static struct capi_interface_user cuser = {
static char rev[10];
-int __init capi_init(void)
+static int __init capi_init(void)
{
char *p;
@@ -2173,8 +2200,5 @@ static void __exit capi_exit(void)
printk(KERN_NOTICE "capi: Rev%s: unloaded\n", rev);
}
-#ifdef MODULE
module_init(capi_init);
-#endif
module_exit(capi_exit);
-
diff --git a/drivers/isdn/avmb1/capidev.h b/drivers/isdn/avmb1/capidev.h
index 6f1d9a42a..722178485 100644
--- a/drivers/isdn/avmb1/capidev.h
+++ b/drivers/isdn/avmb1/capidev.h
@@ -1,11 +1,14 @@
/*
- * $Id: capidev.h,v 1.5 2000/03/03 15:50:42 calle Exp $
+ * $Id: capidev.h,v 1.6 2000/11/25 17:00:59 kai Exp $
*
* CAPI 2.0 Interface for Linux
*
* (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capidev.h,v $
+ * Revision 1.6 2000/11/25 17:00:59 kai
+ * compatibility cleanup - final part for the time being
+ *
* Revision 1.5 2000/03/03 15:50:42 calle
* - kernel CAPI:
* - Changed parameter "param" in capi_signal from __u32 to void *.
diff --git a/drivers/isdn/avmb1/capidrv.c b/drivers/isdn/avmb1/capidrv.c
index e512c8672..24eeb3739 100644
--- a/drivers/isdn/avmb1/capidrv.c
+++ b/drivers/isdn/avmb1/capidrv.c
@@ -1,11 +1,23 @@
/*
- * $Id: capidrv.c,v 1.36 2000/06/26 15:13:41 keil Exp $
+ * $Id: capidrv.c,v 1.39 2000/11/23 20:45:14 kai Exp $
*
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
*
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capidrv.c,v $
+ * Revision 1.39 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.38 2000/11/14 08:43:07 calle
+ * Bugfix for v110. Connectparamters where setup for sync ...
+ *
+ * Revision 1.37 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
* Revision 1.36 2000/06/26 15:13:41 keil
* features should be or'ed
*
@@ -207,7 +219,7 @@
#include "capicmd.h"
#include "capidrv.h"
-static char *revision = "$Revision: 1.36 $";
+static char *revision = "$Revision: 1.39 $";
static int debugmode = 0;
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
@@ -2468,7 +2480,7 @@ static struct capi_interface_user cuser = {
callback: lower_callback
};
-int __init capidrv_init(void)
+static int __init capidrv_init(void)
{
struct capi_register_params rparam;
capi_profile profile;
@@ -2550,8 +2562,5 @@ static void __exit capidrv_exit(void)
printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);
}
-#ifdef MODULE
module_init(capidrv_init);
-#endif
module_exit(capidrv_exit);
-
diff --git a/drivers/isdn/avmb1/capifs.c b/drivers/isdn/avmb1/capifs.c
index b932c17e0..268ddfc4e 100644
--- a/drivers/isdn/avmb1/capifs.c
+++ b/drivers/isdn/avmb1/capifs.c
@@ -1,11 +1,32 @@
/*
- * $Id: capifs.c,v 1.10 2000/10/12 10:12:35 calle Exp $
+ * $Id: capifs.c,v 1.14.6.1 2000/11/28 12:02:45 kai Exp $
*
* (c) Copyright 2000 by Carsten Paeth (calle@calle.de)
*
* Heavily based on devpts filesystem from H. Peter Anvin
*
* $Log: capifs.c,v $
+ * Revision 1.14.6.1 2000/11/28 12:02:45 kai
+ * MODULE_DEVICE_TABLE for 2.4
+ *
+ * Revision 1.14.2.1 2000/11/26 17:47:53 kai
+ * added PCI_DEV_TABLE for 2.4
+ *
+ * Revision 1.14 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.13 2000/11/18 16:17:25 kai
+ * change from 2.4 tree
+ *
+ * Revision 1.12 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
+ * Revision 1.11 2000/10/24 15:08:47 calle
+ * Too much includes.
+ *
* Revision 1.10 2000/10/12 10:12:35 calle
* Bugfix: second iput(inode) on umount, destroies a foreign inode.
*
@@ -72,7 +93,7 @@
MODULE_AUTHOR("Carsten Paeth <calle@calle.de>");
-static char *revision = "$Revision: 1.10 $";
+static char *revision = "$Revision: 1.14.6.1 $";
struct capifs_ncci {
struct inode *inode;
@@ -558,7 +579,7 @@ void capifs_free_ncci(char type, unsigned int num)
}
}
-int __init capifs_init(void)
+static int __init capifs_init(void)
{
char rev[10];
char *p;
@@ -587,7 +608,7 @@ int __init capifs_init(void)
return 0;
}
-void capifs_exit(void)
+static void __exit capifs_exit(void)
{
unregister_filesystem(&capifs_fs_type);
}
@@ -595,16 +616,5 @@ void capifs_exit(void)
EXPORT_SYMBOL(capifs_new_ncci);
EXPORT_SYMBOL(capifs_free_ncci);
-#ifdef MODULE
-
-int init_module(void)
-{
- return capifs_init();
-}
-
-void cleanup_module(void)
-{
- capifs_exit();
-}
-
-#endif
+module_init(capifs_init);
+module_exit(capifs_exit);
diff --git a/drivers/isdn/avmb1/capiutil.c b/drivers/isdn/avmb1/capiutil.c
index 6f10025f5..321212ecc 100644
--- a/drivers/isdn/avmb1/capiutil.c
+++ b/drivers/isdn/avmb1/capiutil.c
@@ -1,5 +1,5 @@
/*
- * $Id: capiutil.c,v 1.11 2000/03/03 15:50:42 calle Exp $
+ * $Id: capiutil.c,v 1.13 2000/11/23 20:45:14 kai Exp $
*
* CAPI 2.0 convert capi message to capi message struct
*
@@ -7,6 +7,15 @@
* Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capiutil.c,v $
+ * Revision 1.13 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.12 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
* Revision 1.11 2000/03/03 15:50:42 calle
* - kernel CAPI:
* - Changed parameter "param" in capi_signal from __u32 to void *.
@@ -81,6 +90,7 @@
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/init.h>
#include <asm/segment.h>
#include <linux/config.h>
@@ -978,7 +988,6 @@ char *capi_cmsg2str(_cmsg * cmsg)
return buf;
}
-
EXPORT_SYMBOL(capi_cmsg2message);
EXPORT_SYMBOL(capi_message2cmsg);
EXPORT_SYMBOL(capi_cmsg_header);
@@ -987,15 +996,14 @@ EXPORT_SYMBOL(capi_cmsg2str);
EXPORT_SYMBOL(capi_message2str);
EXPORT_SYMBOL(capi_info2str);
-#ifdef MODULE
-
-int init_module(void)
-{
- return 0;
+static int __init capiutil_init(void)
+{
+ return 0;
}
-void cleanup_module(void)
+static void __exit capiutil_exit(void)
{
}
-#endif
+module_init(capiutil_init);
+module_exit(capiutil_exit);
diff --git a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c
index fd18bf93c..bf6571856 100644
--- a/drivers/isdn/avmb1/kcapi.c
+++ b/drivers/isdn/avmb1/kcapi.c
@@ -1,11 +1,23 @@
/*
- * $Id: kcapi.c,v 1.18 2000/07/20 10:22:27 calle Exp $
+ * $Id: kcapi.c,v 1.21 2000/11/23 20:45:14 kai Exp $
*
* Kernel CAPI 2.0 Module
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: kcapi.c,v $
+ * Revision 1.21 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.20 2000/11/19 17:01:53 kai
+ * compatibility cleanup - part 2
+ *
+ * Revision 1.19 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
* Revision 1.18 2000/07/20 10:22:27 calle
* - Made procfs function cleaner and removed variable "begin".
*
@@ -18,7 +30,7 @@
* Revision 1.15 2000/04/06 15:01:25 calle
* Bugfix: crash in capidrv.c when reseting a capi controller.
* - changed code order on remove of controller.
- * - using tq_schedule for notifier in kcapi.c.
+ * - using tq schedule for notifier in kcapi.c.
* - now using spin_lock_irqsave() and spin_unlock_irqrestore().
* strange: sometimes even MP hang on unload of isdn.o ...
*
@@ -110,6 +122,7 @@
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <linux/locks.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include "capicmd.h"
#include "capiutil.h"
@@ -118,7 +131,7 @@
#include <linux/b1lli.h>
#endif
-static char *revision = "$Revision: 1.18 $";
+static char *revision = "$Revision: 1.21 $";
/* ------------------------------------------------------------- */
@@ -617,7 +630,9 @@ static int notify_push(unsigned int cmd, __u32 controller,
* of devices. Devices can only removed in
* user process, not in bh.
*/
- queue_task(&tq_state_notify, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&tq_state_notify) == 0)
+ MOD_DEC_USE_COUNT;
return 0;
}
@@ -713,6 +728,7 @@ static void notify_handler(void *dummy)
kfree(np);
MOD_DEC_USE_COUNT;
}
+ MOD_DEC_USE_COUNT;
}
/* -------- NCCI Handling ------------------------------------- */
@@ -1724,36 +1740,11 @@ EXPORT_SYMBOL(detach_capi_interface);
EXPORT_SYMBOL(attach_capi_driver);
EXPORT_SYMBOL(detach_capi_driver);
-#ifndef MODULE
-#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
-extern int b1isa_init(void);
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
-extern int b1pci_init(void);
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
-extern int t1isa_init(void);
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
-extern int b1pcmcia_init(void);
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
-extern int t1pci_init(void);
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_C4
-extern int c4_init(void);
-#endif
-#endif
-
/*
* init / exit functions
*/
-#ifdef MODULE
-#define kcapi_init init_module
-#endif
-
-int kcapi_init(void)
+static int __init kcapi_init(void)
{
char *p;
char rev[10];
@@ -1761,7 +1752,6 @@ int kcapi_init(void)
MOD_INC_USE_COUNT;
skb_queue_head_init(&recv_queue);
- /* init_bh(CAPI_BH, do_capi_bh); */
tq_state_notify.routine = notify_handler;
tq_state_notify.data = 0;
@@ -1782,31 +1772,12 @@ int kcapi_init(void)
printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev);
#else
printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev);
-#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
- (void)b1isa_init();
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
- (void)b1pci_init();
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
- (void)t1isa_init();
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
- (void)b1pcmcia_init();
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
- (void)t1pci_init();
-#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1_C4
- (void)c4_init();
-#endif
#endif
MOD_DEC_USE_COUNT;
return 0;
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit kcapi_exit(void)
{
char rev[10];
char *p;
@@ -1822,4 +1793,6 @@ void cleanup_module(void)
proc_capi_exit();
printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev);
}
-#endif
+
+module_init(kcapi_init);
+module_exit(kcapi_exit);
diff --git a/drivers/isdn/avmb1/t1isa.c b/drivers/isdn/avmb1/t1isa.c
index ff77c5f20..5676dc911 100644
--- a/drivers/isdn/avmb1/t1isa.c
+++ b/drivers/isdn/avmb1/t1isa.c
@@ -1,11 +1,15 @@
/*
- * $Id: t1isa.c,v 1.15 2000/11/01 14:05:02 calle Exp $
+ * $Id: t1isa.c,v 1.16 2000/11/23 20:45:14 kai Exp $
*
* Module for AVM T1 HEMA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: t1isa.c,v $
+ * Revision 1.16 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
* Revision 1.15 2000/11/01 14:05:02 calle
* - use module_init/module_exit from linux/init.h.
* - all static struct variables are initialized with "membername:" now.
@@ -100,7 +104,7 @@
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.15 $";
+static char *revision = "$Revision: 1.16 $";
/* ------------------------------------------------------------- */
@@ -613,12 +617,7 @@ static struct capi_driver t1isa_driver = {
add_card: t1isa_add_card,
};
-#ifdef MODULE
-#define t1isa_init init_module
-void cleanup_module(void);
-#endif
-
-int t1isa_init(void)
+static int __init t1isa_init(void)
{
struct capi_driver *driver = &t1isa_driver;
char *p;
@@ -646,9 +645,10 @@ int t1isa_init(void)
return retval;
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit t1isa_exit(void)
{
detach_capi_driver(&t1isa_driver);
}
-#endif
+
+module_init(t1isa_init);
+module_exit(t1isa_exit);
diff --git a/drivers/isdn/avmb1/t1pci.c b/drivers/isdn/avmb1/t1pci.c
index 50ecc729d..ac2f93994 100644
--- a/drivers/isdn/avmb1/t1pci.c
+++ b/drivers/isdn/avmb1/t1pci.c
@@ -1,11 +1,30 @@
/*
- * $Id: t1pci.c,v 1.11 2000/08/08 09:24:19 calle Exp $
+ * $Id: t1pci.c,v 1.13.6.1 2000/11/28 12:02:45 kai Exp $
*
* Module for AVM T1 PCI-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: t1pci.c,v $
+ * Revision 1.13.6.1 2000/11/28 12:02:45 kai
+ * MODULE_DEVICE_TABLE for 2.4
+ *
+ * Revision 1.13.2.2 2000/11/26 17:47:53 kai
+ * added PCI_DEV_TABLE for 2.4
+ *
+ * Revision 1.13.2.1 2000/11/26 17:14:19 kai
+ * fix device ids
+ * also needs patches to include/linux/pci_ids.h
+ *
+ * Revision 1.13 2000/11/23 20:45:14 kai
+ * fixed module_init/exit stuff
+ * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
+ *
+ * Revision 1.12 2000/11/01 14:05:02 calle
+ * - use module_init/module_exit from linux/init.h.
+ * - all static struct variables are initialized with "membername:" now.
+ * - avm_cs.c, let it work with newer pcmcia-cs.
+ *
* Revision 1.11 2000/08/08 09:24:19 calle
* calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI
*
@@ -62,29 +81,26 @@
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/capi.h>
+#include <linux/init.h>
#include <asm/io.h>
#include "capicmd.h"
#include "capiutil.h"
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.11 $";
+static char *revision = "$Revision: 1.13.6.1 $";
#undef CONFIG_T1PCI_DEBUG
#undef CONFIG_T1PCI_POLLDEBUG
/* ------------------------------------------------------------- */
-#ifndef PCI_VENDOR_ID_AVM
-#define PCI_VENDOR_ID_AVM 0x1244
-#endif
-
-#ifndef PCI_DEVICE_ID_AVM_T1
-#define PCI_DEVICE_ID_AVM_T1 0x1200
-#endif
-
-/* ------------------------------------------------------------- */
+static struct pci_device_id t1pci_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl);
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
/* ------------------------------------------------------------- */
@@ -275,14 +291,9 @@ static struct capi_driver t1pci_driver = {
add_card: 0, /* no add_card function */
};
-#ifdef MODULE
-#define t1pci_init init_module
-void cleanup_module(void);
-#endif
-
static int ncards = 0;
-int t1pci_init(void)
+static int __init t1pci_init(void)
{
struct capi_driver *driver = &t1pci_driver;
struct pci_dev *dev = NULL;
@@ -320,7 +331,7 @@ int t1pci_init(void)
struct capicardparams param;
param.port = pci_resource_start(dev, 1);
- param.irq = dev->irq;
+ param.irq = dev->irq;
param.membase = pci_resource_start(dev, 0);
retval = pci_enable_device (dev);
@@ -364,9 +375,10 @@ int t1pci_init(void)
#endif
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit t1pci_exit(void)
{
detach_capi_driver(&t1pci_driver);
}
-#endif
+
+module_init(t1pci_init);
+module_exit(t1pci_exit);
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 8cff1683a..492f8f53c 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -1,5 +1,5 @@
/*
- * $Id: divert_procfs.c,v 1.10 2000/11/13 22:51:47 kai Exp $
+ * $Id: divert_procfs.c,v 1.11 2000/11/25 17:01:00 kai Exp $
*
* Filesystem handling for the diversion supplementary services.
*
diff --git a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c
index d4fb0452a..1a8c75ace 100644
--- a/drivers/isdn/hisax/amd7930.c
+++ b/drivers/isdn/hisax/amd7930.c
@@ -1,4 +1,4 @@
-/* $Id: amd7930.c,v 1.4 2000/06/26 08:59:12 keil Exp $
+/* $Id: amd7930.c,v 1.5 2000/11/24 17:05:37 kai Exp $
*
* HiSax ISDN driver - chip specific routines for AMD 7930
*
@@ -94,7 +94,7 @@
#include "rawhdlc.h"
#include <linux/interrupt.h>
-static const char *amd7930_revision = "$Revision: 1.4 $";
+static const char *amd7930_revision = "$Revision: 1.5 $";
#define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */
#define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into
@@ -734,8 +734,8 @@ amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_amd7930(struct IsdnCard *card))
+int __init
+setup_amd7930(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c
index 7708afdb6..4ff4d7a4f 100644
--- a/drivers/isdn/hisax/arcofi.c
+++ b/drivers/isdn/hisax/arcofi.c
@@ -1,4 +1,4 @@
-/* $Id: arcofi.c,v 1.11 2000/06/26 08:59:12 keil Exp $
+/* $Id: arcofi.c,v 1.12 2000/11/25 17:01:00 kai Exp $
*
* arcofi.c Ansteuerung ARCOFI 2165
*
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
index b86f5db6a..01b668d8e 100644
--- a/drivers/isdn/hisax/asuscom.c
+++ b/drivers/isdn/hisax/asuscom.c
@@ -1,4 +1,4 @@
-/* $Id: asuscom.c,v 1.10 2000/06/26 08:59:12 keil Exp $
+/* $Id: asuscom.c,v 1.11 2000/11/24 17:05:37 kai Exp $
*
* asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
*
@@ -11,6 +11,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "ipac.h"
@@ -19,7 +20,7 @@
extern const char *CardType[];
-const char *Asuscom_revision = "$Revision: 1.10 $";
+const char *Asuscom_revision = "$Revision: 1.11 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -306,8 +307,8 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_asuscom(struct IsdnCard *card))
+int __init
+setup_asuscom(struct IsdnCard *card)
{
int bytecnt;
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
index cc3ce4490..e2765970e 100644
--- a/drivers/isdn/hisax/avm_a1.c
+++ b/drivers/isdn/hisax/avm_a1.c
@@ -1,4 +1,4 @@
-/* $Id: avm_a1.c,v 2.12 2000/06/26 08:59:12 keil Exp $
+/* $Id: avm_a1.c,v 2.13 2000/11/24 17:05:37 kai Exp $
*
* avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards
*
@@ -8,13 +8,14 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
#include "isdnl1.h"
extern const char *CardType[];
-static const char *avm_revision = "$Revision: 2.12 $";
+static const char *avm_revision = "$Revision: 2.13 $";
#define AVM_A1_STAT_ISAC 0x01
#define AVM_A1_STAT_HSCX 0x02
@@ -171,8 +172,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_avm_a1(struct IsdnCard *card))
+int __init
+setup_avm_a1(struct IsdnCard *card)
{
u_char val;
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
index a9a132b98..2f813402f 100644
--- a/drivers/isdn/hisax/avm_a1p.c
+++ b/drivers/isdn/hisax/avm_a1p.c
@@ -1,4 +1,4 @@
-/* $Id: avm_a1p.c,v 2.6 2000/06/26 08:59:12 keil Exp $
+/* $Id: avm_a1p.c,v 2.7 2000/11/24 17:05:37 kai Exp $
*
* avm_a1p.c low level stuff for the following AVM cards:
* A1 PCMCIA
@@ -10,6 +10,7 @@
* This file is (c) under GNU PUBLIC LICENSE
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
@@ -52,7 +53,7 @@
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
-static const char *avm_revision = "$Revision: 2.6 $";
+static const char *avm_revision = "$Revision: 2.7 $";
static inline u_char
ReadISAC(struct IsdnCardState *cs, u_char offset)
@@ -244,8 +245,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return 0;
}
-__initfunc(int
-setup_avm_a1_pcmcia(struct IsdnCard *card))
+int __devinit
+setup_avm_a1_pcmcia(struct IsdnCard *card)
{
u_char model, vers;
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 4302585dc..79f96fe18 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -1,4 +1,4 @@
-/* $Id: avm_pci.c,v 1.18 2000/08/20 07:34:04 keil Exp $
+/* $Id: avm_pci.c,v 1.22.6.2 2000/11/29 16:00:14 kai Exp $
*
* avm_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
* Thanks to AVM, Berlin for informations
@@ -10,6 +10,7 @@
*/
#define __NO_VERSION__
#include <linux/config.h>
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "isdnl1.h"
@@ -17,18 +18,11 @@
#include <linux/interrupt.h>
extern const char *CardType[];
-static const char *avm_pci_rev = "$Revision: 1.18 $";
+static const char *avm_pci_rev = "$Revision: 1.22.6.2 $";
#define AVM_FRITZ_PCI 1
#define AVM_FRITZ_PNP 2
-#ifndef PCI_VENDOR_ID_AVM
-#define PCI_VENDOR_ID_AVM 0x1244
-#endif
-#ifndef PCI_DEVICE_ID_AVM_FRITZ
-#define PCI_DEVICE_ID_AVM_FRITZ 0xa00
-#endif
-
#define HDLC_FIFO 0x0
#define HDLC_STATUS 0x4
@@ -649,8 +643,8 @@ setstack_hdlc(struct PStack *st, struct BCState *bcs)
return (0);
}
-HISAX_INITFUNC(void
-clear_pending_hdlc_ints(struct IsdnCardState *cs))
+void __init
+clear_pending_hdlc_ints(struct IsdnCardState *cs)
{
u_int val;
@@ -679,8 +673,8 @@ clear_pending_hdlc_ints(struct IsdnCardState *cs))
}
}
-HISAX_INITFUNC(void
-inithdlc(struct IsdnCardState *cs))
+void __init
+inithdlc(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_hdlc;
cs->bcs[1].BC_SetStack = setstack_hdlc;
@@ -764,10 +758,10 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_avm __initdata = NULL;
+static struct pci_dev *dev_avm __initdata = NULL;
-__initfunc(int
-setup_avm_pcipnp(struct IsdnCard *card))
+int __init
+setup_avm_pcipnp(struct IsdnCard *card)
{
u_int val, ver;
struct IsdnCardState *cs = card->cs;
@@ -788,7 +782,7 @@ setup_avm_pcipnp(struct IsdnCard *card))
return(0);
}
if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
- PCI_DEVICE_ID_AVM_FRITZ, dev_avm))) {
+ PCI_DEVICE_ID_AVM_A1, dev_avm))) {
cs->irq = dev_avm->irq;
if (!cs->irq) {
printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index 75729c282..c8a4896a9 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -1,4 +1,4 @@
-/* $Id: bkm_a4t.c,v 1.11 2000/06/26 08:59:12 keil Exp $
+/* $Id: bkm_a4t.c,v 1.13.6.2 2000/11/29 16:00:14 kai Exp $
* bkm_a4t.c low level stuff for T-Berkom A4T
* derived from the original file sedlbauer.c
* derived from the original file niccy.c
@@ -13,6 +13,7 @@
#define __NO_VERSION__
#include <linux/config.h>
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
@@ -23,7 +24,7 @@
extern const char *CardType[];
-const char *bkm_a4t_revision = "$Revision: 1.11 $";
+const char *bkm_a4t_revision = "$Revision: 1.13.6.2 $";
static inline u_char
@@ -265,8 +266,8 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
static struct pci_dev *dev_a4t __initdata = NULL;
-__initfunc(int
- setup_bkm_a4t(struct IsdnCard *card))
+int __init
+setup_bkm_a4t(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
@@ -294,7 +295,7 @@ __initfunc(int
sub_vendor = dev_a4t->subsystem_vendor;
sub_sys = dev_a4t->subsystem_device;
- if ((sub_sys == A4T_SUBSYS_ID) && (sub_vendor == A4T_SUBVEN_ID)) {
+ if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
if (pci_enable_device(dev_a4t))
return(0);
found = 1;
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index 6f00073c6..45011d356 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -1,4 +1,4 @@
-/* $Id: bkm_a8.c,v 1.12 2000/06/26 08:59:12 keil Exp $
+/* $Id: bkm_a8.c,v 1.14.6.2 2000/11/29 16:00:14 kai Exp $
* bkm_a8.c low level stuff for Scitel Quadro (4*S0, passive)
* derived from the original file sedlbauer.c
* derived from the original file niccy.c
@@ -12,6 +12,7 @@
#define __NO_VERSION__
#include <linux/config.h>
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "ipac.h"
@@ -26,7 +27,7 @@
extern const char *CardType[];
-const char sct_quadro_revision[] = "$Revision: 1.12 $";
+const char sct_quadro_revision[] = "$Revision: 1.14.6.2 $";
static const char *sct_quadro_subtypes[] =
{
@@ -268,8 +269,8 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return (0);
}
-__initfunc(int
-sct_alloc_io(u_int adr, u_int len))
+int __init
+sct_alloc_io(u_int adr, u_int len)
{
if (check_region(adr, len)) {
printk(KERN_WARNING
@@ -291,8 +292,8 @@ static u_char pci_irq __initdata = 0;
#endif /* CONFIG_PCI */
-__initfunc(int
-setup_sct_quadro(struct IsdnCard *card))
+int __init
+setup_sct_quadro(struct IsdnCard *card)
{
#if CONFIG_PCI
struct IsdnCardState *cs = card->cs;
@@ -316,8 +317,8 @@ setup_sct_quadro(struct IsdnCard *card))
CardType[card->typ]);
return (0);
}
- if ((cs->subtyp != SCT_1) && ((sub_sys_id != SCT_SUBSYS_ID) ||
- (sub_vendor_id != SCT_SUBVEN_ID)))
+ if ((cs->subtyp != SCT_1) && ((sub_sys_id != PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) ||
+ (sub_vendor_id != PCI_VENDOR_ID_BERKOM)))
return (0);
if (cs->subtyp == SCT_1) {
if (!pci_present()) {
@@ -329,8 +330,8 @@ setup_sct_quadro(struct IsdnCard *card))
sub_vendor_id = dev_a8->subsystem_vendor;
sub_sys_id = dev_a8->subsystem_device;
- if ((sub_sys_id == SCT_SUBSYS_ID) &&
- (sub_vendor_id == SCT_SUBVEN_ID)) {
+ if ((sub_sys_id == PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) &&
+ (sub_vendor_id == PCI_VENDOR_ID_BERKOM)) {
if (pci_enable_device(dev_a8))
return(0);
pci_ioaddr1 = pci_resource_start(dev_a8, 1);
diff --git a/drivers/isdn/hisax/bkm_ax.h b/drivers/isdn/hisax/bkm_ax.h
index e513c81a6..921698784 100644
--- a/drivers/isdn/hisax/bkm_ax.h
+++ b/drivers/isdn/hisax/bkm_ax.h
@@ -1,4 +1,4 @@
-/* $Id: bkm_ax.h,v 1.4 2000/06/26 08:59:12 keil Exp $
+/* $Id: bkm_ax.h,v 1.5.6.1 2000/11/28 12:02:46 kai Exp $
* bkm_ax.h low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive)
*
* Author Roland Klabunde (R.Klabunde@Berkom.de)
@@ -17,27 +17,6 @@
#define SCT_4 4
#define BKM_A4T 5
-
-/* A4T */
-#ifndef PCI_VENDOR_ID_ZORAN
-#define PCI_VENDOR_ID_ZORAN 0x11DE
-#endif
-#ifndef PCI_DEVICE_ID_ZORAN_36120
-#define PCI_DEVICE_ID_ZORAN_36120 0x6120
-#endif
-#define A4T_SUBVEN_ID 0x0871
-#define A4T_SUBSYS_ID 0xFFA4
-/* Scitel Quadro */
-#ifndef PCI_VENDOR_ID_PLX
-#define PCI_VENDOR_ID_PLX 0x10B5
-#endif
-#ifndef PCI_DEVICE_ID_PLX_9050
-#define PCI_DEVICE_ID_PLX_9050 0x9050
-#endif
-#define SCT_SUBVEN_ID 0x0871
-#define SCT_SUBSYS_ID 0xFFA8
-
-
#define PLX_ADDR_PLX 0x14 /* Addr PLX configuration */
#define PLX_ADDR_ISAC 0x18 /* Addr ISAC */
#define PLX_ADDR_HSCX 0x1C /* Addr HSCX */
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 4d3290392..ced19e429 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -1,4 +1,4 @@
-/* $Id: callc.c,v 2.47 2000/06/26 08:59:12 keil Exp $
+/* $Id: callc.c,v 2.51 2000/11/24 17:05:37 kai Exp $
*
* Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
@@ -11,8 +11,8 @@
* Fritz Elfert
*
*/
-
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "../avmb1/capicmd.h" /* this should be moved in a common place */
@@ -20,7 +20,7 @@
#define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
#endif /* MODULE */
-const char *lli_revision = "$Revision: 2.47 $";
+const char *lli_revision = "$Revision: 2.51 $";
extern struct IsdnCard cards[];
extern int nrcards;
@@ -30,10 +30,8 @@ extern void HiSax_mod_inc_use_count(void);
static int init_b_st(struct Channel *chanp, int incoming);
static void release_b_st(struct Channel *chanp);
-static struct Fsm callcfsm =
-{NULL, 0, 0, NULL, NULL};
-
-static int chancount = 0;
+static struct Fsm callcfsm;
+static int chancount;
/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
#define ALERT_REJECT 0
@@ -782,7 +780,7 @@ lli_failure_a(struct FsmInst *fi, int event, void *arg)
}
/* *INDENT-OFF* */
-static struct FsmNode fnlist[] HISAX_INITDATA =
+static struct FsmNode fnlist[] __initdata =
{
{ST_NULL, EV_DIAL, lli_prep_dialout},
{ST_NULL, EV_RESUME, lli_resume},
@@ -852,8 +850,8 @@ static struct FsmNode fnlist[] HISAX_INITDATA =
#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
-HISAX_INITFUNC(void
-CallcNew(void))
+void __init
+CallcNew(void)
{
callcfsm.state_count = STATE_COUNT;
callcfsm.event_count = EVENT_COUNT;
@@ -880,6 +878,7 @@ release_b_st(struct Channel *chanp)
releasestack_isdnl2(st);
break;
case (ISDN_PROTO_L2_HDLC):
+ case (ISDN_PROTO_L2_HDLC_56K):
case (ISDN_PROTO_L2_TRANS):
case (ISDN_PROTO_L2_MODEM):
case (ISDN_PROTO_L2_FAX):
@@ -1273,6 +1272,9 @@ init_b_st(struct Channel *chanp, int incoming)
case (ISDN_PROTO_L2_HDLC):
st->l1.mode = L1_MODE_HDLC;
break;
+ case (ISDN_PROTO_L2_HDLC_56K):
+ st->l1.mode = L1_MODE_HDLC_56K;
+ break;
case (ISDN_PROTO_L2_TRANS):
st->l1.mode = L1_MODE_TRANS;
break;
@@ -1309,6 +1311,7 @@ init_b_st(struct Channel *chanp, int incoming)
st->l2.debug = chanp->debug & 64;
break;
case (ISDN_PROTO_L2_HDLC):
+ case (ISDN_PROTO_L2_HDLC_56K):
case (ISDN_PROTO_L2_TRANS):
case (ISDN_PROTO_L2_MODEM):
case (ISDN_PROTO_L2_FAX):
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 614f145cb..f25e2a159 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1,4 +1,4 @@
-/* $Id: config.c,v 2.50 2000/07/04 10:24:32 keil Exp $
+/* $Id: config.c,v 2.57.6.3 2000/11/29 17:48:59 kai Exp $
*
* Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
@@ -11,6 +11,7 @@
#include <linux/timer.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/pci.h>
#include "hisax.h"
#include <linux/module.h>
#include <linux/kernel_stat.h>
@@ -66,6 +67,7 @@
* 36 Winbond 6692 PCI none
* 37 HFC 2BDS0 S+/SP p0=irq p1=iobase
* 38 Travers Technologies NETspider-U PCI card
+ * 39 HFC 2BDS0-SP PCMCIA p0=irq p1=iobase
*
* protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
*
@@ -81,7 +83,7 @@ const char *CardType[] =
"AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
"Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir",
"Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
- "HFC 2BDS0 SX", "NETspider-U",
+ "HFC 2BDS0 SX", "NETspider-U", "HFC-2BDS0-SP PCMCIA",
};
void HiSax_closecard(int cardnr);
@@ -221,6 +223,8 @@ EXPORT_SYMBOL(sedl_init_pcmcia);
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_HFC_SX
#define DEFAULT_CFG {5,0x2E0,0,0}
+int hfc_init_pcmcia(void*, int, int*, int);
+EXPORT_SYMBOL(hfc_init_pcmcia);
#endif
@@ -336,18 +340,14 @@ struct IsdnCard cards[] =
EMPTY_CARD,
};
-static char HiSaxID[64] HISAX_INITDATA = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
-"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
-"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-char *HiSax_id HISAX_INITDATA = HiSaxID;
+static char HiSaxID[64] __devinitdata = { 0, };
+
+char *HiSax_id __devinitdata = HiSaxID;
#ifdef MODULE
/* Variables for insmod */
-static int type[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0};
-static int protocol[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0};
-static int io[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0};
+static int type[8] __devinitdata = { 0, };
+static int protocol[8] __devinitdata = { 0, };
+static int io[8] __devinitdata = { 0, };
#undef IO0_IO1
#ifdef CONFIG_HISAX_16_3
#define IO0_IO1
@@ -357,16 +357,12 @@ static int io[] HISAX_INITDATA =
#define IO0_IO1
#endif
#ifdef IO0_IO1
-static int io0[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0};
-static int io1[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0};
+static int io0[8] __devinitdata = { 0, };
+static int io1[8] __devinitdata = { 0, };
#endif
-static int irq[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0};
-static int mem[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0};
-static char *id HISAX_INITDATA = HiSaxID;
+static int irq[8] __devinitdata = { 0, };
+static int mem[8] __devinitdata = { 0, };
+static char *id __devinitdata = HiSaxID;
MODULE_AUTHOR("Karsten Keil");
MODULE_PARM(type, "1-8i");
@@ -389,8 +385,8 @@ extern char *l3_revision;
extern char *lli_revision;
extern char *tei_revision;
-HISAX_INITFUNC(char *
-HiSax_getrev(const char *revision))
+char *
+HiSax_getrev(const char *revision)
{
char *rev;
char *p;
@@ -404,8 +400,8 @@ HiSax_getrev(const char *revision))
return rev;
}
-HISAX_INITFUNC(void
-HiSaxVersion(void))
+void __init
+HiSaxVersion(void)
{
char tmp[64];
@@ -440,9 +436,7 @@ HiSax_mod_inc_use_count(void)
MOD_INC_USE_COUNT;
}
-#ifdef MODULE
-#define HiSax_init init_module
-#else
+#ifndef MODULE
#define MAX_ARG (HISAX_MAX_CARDS*5)
static int __init
HiSax_setup(char *line)
@@ -863,7 +857,8 @@ closecard(int cardnr)
ll_unload(csta);
}
-HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs))
+static int __devinit
+init_card(struct IsdnCardState *cs)
{
int irq_cnt, cnt = 3;
long flags;
@@ -910,8 +905,8 @@ HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs))
return(3);
}
-HISAX_INITFUNC(static int
-checkcard(int cardnr, char *id, int *busy_flag))
+static int __devinit
+checkcard(int cardnr, char *id, int *busy_flag)
{
long flags;
int ret = 0;
@@ -973,6 +968,7 @@ checkcard(int cardnr, char *id, int *busy_flag))
cs->iif.features =
ISDN_FEATURE_L2_X75I |
ISDN_FEATURE_L2_HDLC |
+ ISDN_FEATURE_L2_HDLC_56K |
ISDN_FEATURE_L2_TRANS |
ISDN_FEATURE_L3_TRANS |
#ifdef CONFIG_HISAX_1TR6
@@ -1184,7 +1180,7 @@ checkcard(int cardnr, char *id, int *busy_flag))
cs->tx_skb = NULL;
cs->tx_cnt = 0;
cs->event = 0;
- cs->tqueue.next = 0;
+ INIT_LIST_HEAD(&cs->tqueue.list);
cs->tqueue.sync = 0;
cs->tqueue.data = cs;
@@ -1208,8 +1204,8 @@ checkcard(int cardnr, char *id, int *busy_flag))
return (1);
}
-HISAX_INITFUNC(void
-HiSax_shiftcards(int idx))
+void __devinit
+HiSax_shiftcards(int idx)
{
int i;
@@ -1217,8 +1213,8 @@ HiSax_shiftcards(int idx))
memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
}
-HISAX_INITFUNC(int
-HiSax_inithardware(int *busy_flag))
+int __devinit
+HiSax_inithardware(int *busy_flag)
{
int foundcards = 0;
int i = 0;
@@ -1302,7 +1298,7 @@ HiSax_reportcard(int cardnr, int sel)
printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
(ulong) & HiSax_reportcard);
printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
- printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc1 flg %x\n",
+ printk(KERN_DEBUG "HiSax: HW_Flags %lx bc0 flg %lx bc1 flg %lx\n",
cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag);
printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n",
cs->bcs[0].mode, cs->bcs[0].channel);
@@ -1331,21 +1327,22 @@ HiSax_reportcard(int cardnr, int sel)
#endif
}
-
-__initfunc(int
-HiSax_init(void))
+int __init
+HiSax_init(void)
{
int i,j;
+ int nzproto = 0;
+
+ HiSaxVersion();
+ CallcNew();
+ Isdnl3New();
+ Isdnl2New();
+ TeiNew();
+ Isdnl1New();
#ifdef MODULE
- int nzproto = 0;
if (!type[0]) {
/* We 'll register drivers later, but init basic functions*/
- CallcNew();
- Isdnl3New();
- Isdnl2New();
- TeiNew();
- Isdnl1New();
return 0;
}
#ifdef CONFIG_HISAX_ELSA
@@ -1366,9 +1363,14 @@ HiSax_init(void))
return 0;
}
#endif
+#ifdef CONFIG_HISAX_HFC_SX
+ if (type[0] == ISDN_CTYPE_HFC_SP_PCMCIA) {
+ /* we have to export and return in this case */
+ return 0;
+ }
+#endif
#endif
nrcards = 0;
- HiSaxVersion();
#ifdef MODULE
if (id) /* If id= string used */
HiSax_id = id;
@@ -1430,6 +1432,7 @@ HiSax_init(void))
case ISDN_CTYPE_HSTSAPHIR:
case ISDN_CTYPE_GAZEL:
case ISDN_CTYPE_HFC_SX:
+ case ISDN_CTYPE_HFC_SP_PCMCIA:
cards[j].para[0] = irq[i];
cards[j].para[1] = io[i];
break;
@@ -1469,7 +1472,6 @@ HiSax_init(void))
}
if (!nzproto) {
printk(KERN_WARNING "HiSax: Warning - no protocol specified\n");
- printk(KERN_WARNING "HiSax: Note! module load syntax has changed.\n");
printk(KERN_WARNING "HiSax: using protocol %s\n", DEFAULT_PROTO_NAME);
}
#endif
@@ -1483,15 +1485,8 @@ HiSax_init(void))
printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
nrcards, (nrcards > 1) ? "s" : "");
- CallcNew();
- Isdnl3New();
- Isdnl2New();
- TeiNew();
- Isdnl1New();
if (HiSax_inithardware(NULL)) {
/* Install only, if at least one card found */
-#ifdef MODULE
-#endif /* MODULE */
return (0);
} else {
Isdnl1Free();
@@ -1504,6 +1499,8 @@ HiSax_init(void))
}
#ifdef MODULE
+int init_module(void) { return HiSax_init(); }
+
void
cleanup_module(void)
{
@@ -1529,10 +1526,49 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
#ifdef MODULE
int i;
+
+ nrcards = 0;
+ /* Initialize all structs, even though we only accept
+ two pcmcia cards
+ */
+ for (i = 0; i < HISAX_MAX_CARDS; i++) {
+ cards[i].para[0] = irq[i];
+ cards[i].para[1] = io[i];
+ cards[i].typ = type[i];
+ if (protocol[i]) {
+ cards[i].protocol = protocol[i];
+ }
+ }
+ cards[0].para[0] = pcm_irq;
+ cards[0].para[1] = (int)pcm_iob;
+ cards[0].protocol = prot;
+ cards[0].typ = ISDN_CTYPE_ELSA_PCMCIA;
+
+ if (!HiSax_id)
+ HiSax_id = HiSaxID;
+ if (!HiSaxID[0])
+ strcpy(HiSaxID, "HiSax");
+ for (i = 0; i < HISAX_MAX_CARDS; i++)
+ if (cards[i].typ > 0)
+ nrcards++;
+ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+ nrcards, (nrcards > 1) ? "s" : "");
+
+ HiSax_inithardware(busy_flag);
+ printk(KERN_NOTICE "HiSax: module installed\n");
+#endif
+ return (0);
+}
+#endif
+
+#ifdef CONFIG_HISAX_HFC_SX
+int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
+{
+#ifdef MODULE
+ int i;
int nzproto = 0;
nrcards = 0;
- HiSaxVersion();
/* Initialize all structs, even though we only accept
two pcmcia cards
*/
@@ -1548,7 +1584,7 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
cards[0].para[0] = pcm_irq;
cards[0].para[1] = (int)pcm_iob;
cards[0].protocol = prot;
- cards[0].typ = 10;
+ cards[0].typ = ISDN_CTYPE_HFC_SP_PCMCIA;
nzproto = 1;
if (!HiSax_id)
@@ -1561,11 +1597,6 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
nrcards, (nrcards > 1) ? "s" : "");
- Isdnl1New();
- CallcNew();
- Isdnl3New();
- Isdnl2New();
- TeiNew();
HiSax_inithardware(busy_flag);
printk(KERN_NOTICE "HiSax: module installed\n");
#endif
@@ -1581,7 +1612,6 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
int nzproto = 0;
nrcards = 0;
- HiSaxVersion();
/* Initialize all structs, even though we only accept
two pcmcia cards
*/
@@ -1610,11 +1640,6 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
nrcards, (nrcards > 1) ? "s" : "");
- CallcNew();
- Isdnl3New();
- Isdnl2New();
- Isdnl1New();
- TeiNew();
HiSax_inithardware(busy_flag);
printk(KERN_NOTICE "HiSax: module installed\n");
#endif
@@ -1630,7 +1655,6 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
int nzproto = 0;
nrcards = 0;
- HiSaxVersion();
/* Initialize all structs, even though we only accept
two pcmcia cards
*/
@@ -1659,11 +1683,6 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
nrcards, (nrcards > 1) ? "s" : "");
- Isdnl1New();
- CallcNew();
- Isdnl3New();
- Isdnl2New();
- TeiNew();
HiSax_inithardware(busy_flag);
printk(KERN_NOTICE "HiSax: module installed\n");
#endif
@@ -1671,7 +1690,7 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
}
#endif
-int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
+int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
{
u_char ids[16];
int ret = -1;
@@ -1688,3 +1707,66 @@ int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
nrcards++;
return (ret);
}
+
+static struct pci_device_id hisax_pci_tbl[] __initdata = {
+#ifdef CONFIG_HISAX_FRTIZPCI
+ {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_FRITZ, PCI_ANY_ID, PCI_ANY_ID},
+#endif
+#ifdef CONFIG_HISAX_DIEHLDIVA
+ {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, PCI_ANY_ID, PCI_ANY_ID},
+#endif
+#ifdef CONFIG_HISAX_ELSA
+ {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, PCI_ANY_ID, PCI_ANY_ID},
+#endif
+#ifdef CONFIG_HISAX_GAZEL
+ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R685, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R753, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO, PCI_ANY_ID, PCI_ANY_ID},
+#endif
+#ifdef CONFIG_HISAX_QUADRO
+ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_ANY_ID, PCI_ANY_ID},
+#endif
+#ifdef CONFIG_HISAX_NICCY
+ {PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, PCI_ANY_ID,PCI_ANY_ID},
+#endif
+#ifdef CONFIG_HISAX_SEDLBAUER
+ {PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_ANY_ID,PCI_ANY_ID},
+#endif
+#if defined(CONFIG_HISAX_NETJET) || defined(CONFIG_HISAX_NETJET_U)
+ {PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, PCI_ANY_ID,PCI_ANY_ID},
+#endif
+#if defined(CONFIG_HISAX_TELESPCI) || defined(CONFIG_HISAX_SCT_QUADRO)
+ {PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, PCI_ANY_ID,PCI_ANY_ID},
+#endif
+#ifdef CONFIG_HISAX_W6692
+ {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, PCI_ANY_ID,PCI_ANY_ID},
+ {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, PCI_ANY_ID,PCI_ANY_ID},
+#endif
+#ifdef CONFIG_HISAX_HFC_PCI
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A, PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A, PCI_ANY_ID, PCI_ANY_ID},
+#endif
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(pci, hisax_pci_tbl);
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index f39dd7558..8967accde 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -1,4 +1,4 @@
-/* $Id: diva.c,v 1.21 2000/06/26 08:59:12 keil Exp $
+/* $Id: diva.c,v 1.25.6.2 2000/11/29 16:00:14 kai Exp $
*
* diva.c low level stuff for Eicon.Diehl Diva Family ISDN cards
*
@@ -13,6 +13,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include <linux/config.h>
#include "hisax.h"
#include "isac.h"
@@ -23,7 +24,7 @@
extern const char *CardType[];
-const char *Diva_revision = "$Revision: 1.21 $";
+const char *Diva_revision = "$Revision: 1.25.6.2 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -46,20 +47,6 @@ const char *Diva_revision = "$Revision: 1.21 $";
#define DIVA_IPAC_ISA 3
#define DIVA_IPAC_PCI 4
-/* PCI stuff */
-#ifndef PCI_VENDOR_ID_EICON
-#define PCI_VENDOR_ID_EICON 0x1133
-#endif
-#ifndef PCI_DEVICE_ID_EICON_DIVA20
-#define PCI_DEVICE_ID_EICON_DIVA20 0xe002
-#endif
-#ifndef PCI_DEVICE_ID_EICON_DIVA20_U
-#define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004
-#endif
-#ifndef PCI_DEVICE_ID_EICON_DIVA201
-#define PCI_DEVICE_ID_EICON_DIVA201 0xe005
-#endif
-
/* CTRL (Read) */
#define DIVA_IRQ_STAT 0x01
#define DIVA_EEPROM_SDA 0x02
@@ -833,12 +820,12 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_diva __initdata = NULL;
-static struct pci_dev *dev_diva_u __initdata = NULL;
-static struct pci_dev *dev_diva201 __initdata = NULL;
+static struct pci_dev *dev_diva __initdata = NULL;
+static struct pci_dev *dev_diva_u __initdata = NULL;
+static struct pci_dev *dev_diva201 __initdata = NULL;
-__initfunc(int
-setup_diva(struct IsdnCard *card))
+int __init
+setup_diva(struct IsdnCard *card)
{
int bytecnt;
u_char val;
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index f2357cc4b..ff20606df 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -1,4 +1,4 @@
-/* $Id: elsa.c,v 2.23 2000/06/26 08:59:12 keil Exp $
+/* $Id: elsa.c,v 2.26.6.1 2000/11/28 12:02:46 kai Exp $
*
* elsa.c low level stuff for Elsa isdn cards
*
@@ -16,6 +16,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include <linux/config.h>
#include "hisax.h"
#include "arcofi.h"
@@ -29,7 +30,7 @@
extern const char *CardType[];
-const char *Elsa_revision = "$Revision: 2.23 $";
+const char *Elsa_revision = "$Revision: 2.26.6.1 $";
const char *Elsa_Types[] =
{"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
"PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI",
@@ -66,15 +67,6 @@ const char *ITACVer[] =
#define ELSA_PCMCIA_IPAC 11
/* PCI stuff */
-#ifndef PCI_VENDOR_ID_ELSA
-#define PCI_VENDOR_ID_ELSA 0x1048
-#endif
-#ifndef PCI_DEVICE_ID_ELSA_MIRCOLINK
-#define PCI_DEVICE_ID_ELSA_MIRCOLINK 0x1000
-#endif
-#ifndef PCI_DEVICE_ID_ELSA_QS3000
-#define PCI_DEVICE_ID_ELSA_QS3000 0x3000
-#endif
#define ELSA_PCI_IRQ_MASK 0x04
/* ITAC Registeradressen (only Microlink PC) */
@@ -865,10 +857,10 @@ probe_elsa(struct IsdnCardState *cs)
return (CARD_portlist[i]);
}
-static struct pci_dev *dev_qs1000 __initdata = NULL;
-static struct pci_dev *dev_qs3000 __initdata = NULL;
+static struct pci_dev *dev_qs1000 __devinitdata = NULL;
+static struct pci_dev *dev_qs3000 __devinitdata = NULL;
-int
+int __devinit
setup_elsa(struct IsdnCard *card)
{
long flags;
@@ -990,7 +982,7 @@ setup_elsa(struct IsdnCard *card)
}
cs->subtyp = 0;
if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
- PCI_DEVICE_ID_ELSA_MIRCOLINK, dev_qs1000))) {
+ PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
if (pci_enable_device(dev_qs1000))
return(0);
cs->subtyp = ELSA_QS1000PCI;
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index 7f439e1a2..74bedf8f6 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -1,4 +1,4 @@
-/* $Id: elsa_ser.c,v 2.9 2000/06/26 08:59:12 keil Exp $
+/* $Id: elsa_ser.c,v 2.10 2000/11/19 17:02:47 kai Exp $
*
* stuff for the serial modem on ELSA cards
*
diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c
index a483b5824..28a759230 100644
--- a/drivers/isdn/hisax/fsm.c
+++ b/drivers/isdn/hisax/fsm.c
@@ -1,4 +1,4 @@
-/* $Id: fsm.c,v 1.13 2000/06/26 08:59:12 keil Exp $
+/* $Id: fsm.c,v 1.14 2000/11/24 17:05:37 kai Exp $
*
* Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
@@ -10,13 +10,13 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#define FSM_TIMER_DEBUG 0
-HISAX_INITFUNC(void
-FsmNew(struct Fsm *fsm,
- struct FsmNode *fnlist, int fncount))
+void __init
+FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
{
int i;
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
index eb777b184..11db6b9ee 100644
--- a/drivers/isdn/hisax/gazel.c
+++ b/drivers/isdn/hisax/gazel.c
@@ -1,4 +1,4 @@
-/* $Id: gazel.c,v 2.8 2000/06/26 08:59:12 keil Exp $
+/* $Id: gazel.c,v 2.11.6.2 2000/11/29 16:00:14 kai Exp $
*
* gazel.c low level stuff for Gazel isdn cards
*
@@ -9,6 +9,7 @@
*
*/
#include <linux/config.h>
+#include <linux/init.h>
#define __NO_VERSION__
#include "hisax.h"
#include "isac.h"
@@ -18,27 +19,13 @@
#include <linux/pci.h>
extern const char *CardType[];
-const char *gazel_revision = "$Revision: 2.8 $";
+const char *gazel_revision = "$Revision: 2.11.6.2 $";
#define R647 1
#define R685 2
#define R753 3
#define R742 4
-/* Gazel R685 stuff */
-#ifndef PCI_VENDOR_ID_PLX
-#define PCI_VENDOR_ID_PLX 0x10b5
-#endif
-#ifndef PCI_DEVICE_ID_PLX_R685
-#define PCI_DEVICE_ID_PLX_R685 0x1030
-#endif
-#ifndef PCI_DEVICE_ID_PLX_R753
-#define PCI_DEVICE_ID_PLX_R753 0x1152
-#endif
-#ifndef PCI_DEVICE_ID_PLX_DJINN_ITOO
-#define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151
-#endif
-
#define PLX_CNTRL 0x50 /* registre de controle PLX */
#define RESET_GAZEL 0x4
#define RESET_9050 0x40000000
@@ -645,8 +632,8 @@ setup_gazelpci(struct IsdnCardState *cs)
return (0);
}
-__initfunc(int
- setup_gazel(struct IsdnCard *card))
+int __init
+setup_gazel(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index 9e03c111e..73c6fb448 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.c,v 1.13 2000/06/26 08:59:12 keil Exp $
+/* $Id: hfc_2bds0.c,v 1.15 2000/11/24 17:05:37 kai Exp $
*
* specific routines for CCD's HFC 2BDS0
*
@@ -8,6 +8,7 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "hfc_2bds0.h"
#include "isdnl1.h"
@@ -1104,8 +1105,8 @@ hfc_dbusy_timer(struct IsdnCardState *cs)
{
}
-__initfunc(unsigned int
-*init_send_hfcd(int cnt))
+unsigned int __init
+*init_send_hfcd(int cnt)
{
int i, *send;
@@ -1119,8 +1120,8 @@ __initfunc(unsigned int
return(send);
}
-__initfunc(void
-init2bds0(struct IsdnCardState *cs))
+void __init
+init2bds0(struct IsdnCardState *cs)
{
cs->setstack_d = setstack_hfcd;
cs->dbusytimer.function = (void *) hfc_dbusy_timer;
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
index bd1442046..22e94c074 100644
--- a/drivers/isdn/hisax/hfc_2bs0.c
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bs0.c,v 1.15 2000/07/26 20:46:47 keil Exp $
+/* $Id: hfc_2bs0.c,v 1.17 2000/11/24 17:05:37 kai Exp $
*
* specific routines for CCD's HFC 2BS0
*
@@ -9,6 +9,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "hfc_2bs0.h"
#include "isac.h"
@@ -570,8 +571,8 @@ setstack_hfc(struct PStack *st, struct BCState *bcs)
return (0);
}
-__initfunc(void
-init_send(struct BCState *bcs))
+void __init
+init_send(struct BCState *bcs)
{
int i;
@@ -584,8 +585,8 @@ init_send(struct BCState *bcs))
bcs->hw.hfc.send[i] = 0x1fff;
}
-__initfunc(void
-inithfc(struct IsdnCardState *cs))
+void __init
+inithfc(struct IsdnCardState *cs)
{
init_send(&cs->bcs[0]);
init_send(&cs->bcs[1]);
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index ac0392251..c32525e7d 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.31 2000/08/20 07:32:55 keil Exp $
+/* $Id: hfc_pci.c,v 1.34.6.2 2000/11/28 12:02:46 kai Exp $
* hfc_pci.c low level driver for CCD´s hfc-pci based cards
*
@@ -24,6 +24,7 @@
*
*/
+#include <linux/init.h>
#include <linux/config.h>
#define __NO_VERSION__
#include "hisax.h"
@@ -31,11 +32,10 @@
#include "isdnl1.h"
#include <linux/pci.h>
#include <linux/interrupt.h>
-#include <linux/init.h>
extern const char *CardType[];
-static const char *hfcpci_revision = "$Revision: 1.31 $";
+static const char *hfcpci_revision = "$Revision: 1.34.6.2 $";
/* table entry in the PCI devices list */
typedef struct {
@@ -51,25 +51,25 @@ typedef struct {
static const PCI_ENTRY id_list[] =
{
- {0x1397, 0x2BD0, "CCD/Billion/Asuscom", "2BD0"},
- {0x1397, 0xB000, "Billion", "B000"},
- {0x1397, 0xB006, "Billion", "B006"},
- {0x1397, 0xB007, "Billion", "B007"},
- {0x1397, 0xB008, "Billion", "B008"},
- {0x1397, 0xB009, "Billion", "B009"},
- {0x1397, 0xB00A, "Billion", "B00A"},
- {0x1397, 0xB00B, "Billion", "B00B"},
- {0x1397, 0xB00C, "Billion", "B00C"},
- {0x1043, 0x0675, "Asuscom/Askey", "675"},
- {0x0871, 0xFFA2, "German telekom", "T-Concept"},
- {0x0871, 0xFFA1, "German telekom", "A1T"},
- {0x1051, 0x0100, "Motorola MC145575", "MC145575"},
- {0x1397, 0xB100, "Seyeon", "B100"},
- {0x15B0, 0x2BD0, "Zoltrix", "2BD0"},
- {0x114F, 0x70,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"},
- {0x114F, 0x71,"Digi International", "Digi DataFire Micro V (Europe)"},
- {0x114F, 0x72,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
- {0x114F, 0x73,"Digi International", "Digi DataFire Micro V (North America)"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, "CCD/Billion/Asuscom", "2BD0"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, "Billion", "B000"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, "Billion", "B006"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, "Billion", "B007"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, "Billion", "B008"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, "Billion", "B009"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, "Billion", "B00A"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"},
+ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"},
+ {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"},
+ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"},
+ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, "German telekom", "A1T"},
+ {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, "Motorola MC145575", "MC145575"},
+ {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, "Zoltrix", "2BD0"},
+ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"},
+ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
+ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
+ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
{0, 0, NULL, NULL},
};
@@ -1571,8 +1571,8 @@ hfcpci_bh(struct IsdnCardState *cs)
/********************************/
/* called for card init message */
/********************************/
-__initfunc(void
- inithfcpci(struct IsdnCardState *cs))
+void __init
+inithfcpci(struct IsdnCardState *cs)
{
cs->setstack_d = setstack_hfcpci;
cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index 36c26cb36..ef8ed461a 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_sx.c,v 1.6 2000/06/26 08:59:13 keil Exp $
+/* $Id: hfc_sx.c,v 1.9 2000/11/24 17:05:37 kai Exp $
* hfc_sx.c low level driver for CCD´s hfc-s+/sp based cards
*
@@ -24,6 +24,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "hfc_sx.h"
#include "isdnl1.h"
@@ -31,7 +32,7 @@
extern const char *CardType[];
-static const char *hfcsx_revision = "$Revision: 1.6 $";
+static const char *hfcsx_revision = "$Revision: 1.9 $";
/***************************************/
/* IRQ-table for CCDs demo board */
@@ -1415,8 +1416,8 @@ hfcsx_bh(struct IsdnCardState *cs)
/********************************/
/* called for card init message */
/********************************/
-__initfunc(void
- inithfcsx(struct IsdnCardState *cs))
+void __devinit
+inithfcsx(struct IsdnCardState *cs)
{
cs->setstack_d = setstack_hfcsx;
cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
@@ -1472,8 +1473,8 @@ hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-__initfunc(int
- setup_hfcsx(struct IsdnCard *card))
+int __devinit
+setup_hfcsx(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
@@ -1486,7 +1487,8 @@ __initfunc(int
cs->hw.hfcsx.int_s1 = 0;
cs->dc.hfcsx.ph_state = 0;
cs->hw.hfcsx.fifo = 255;
- if (cs->typ == ISDN_CTYPE_HFC_SX) {
+ if ((cs->typ == ISDN_CTYPE_HFC_SX) ||
+ (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) {
if ((!cs->hw.hfcsx.base) ||
check_region((cs->hw.hfcsx.base), 2)) {
printk(KERN_WARNING
diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
index 18993bf0d..6c06186ae 100644
--- a/drivers/isdn/hisax/hfcscard.c
+++ b/drivers/isdn/hisax/hfcscard.c
@@ -1,4 +1,4 @@
-/* $Id: hfcscard.c,v 1.7 2000/06/26 08:59:13 keil Exp $
+/* $Id: hfcscard.c,v 1.8 2000/11/24 17:05:37 kai Exp $
*
* hfcscard.c low level stuff for hfcs based cards (Teles3c, ACER P10)
*
@@ -9,13 +9,14 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "hfc_2bds0.h"
#include "isdnl1.h"
extern const char *CardType[];
-static const char *hfcs_revision = "$Revision: 1.7 $";
+static const char *hfcs_revision = "$Revision: 1.8 $";
static void
hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
@@ -136,8 +137,8 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_hfcs(struct IsdnCard *card))
+int __init
+setup_hfcs(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index abc215f87..22cf911b3 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1,4 +1,4 @@
-/* $Id: hisax.h,v 2.48 2000/07/04 10:24:32 keil Exp $
+/* $Id: hisax.h,v 2.52 2000/11/25 17:01:00 kai Exp $
*
* Basic declarations, defines and prototypes
*
@@ -202,7 +202,7 @@ struct Layer1 {
void *hardware;
struct BCState *bcs;
struct PStack **stlistp;
- int Flags;
+ long Flags;
struct FsmInst l1m;
struct FsmTimer timer;
void (*l1l2) (struct PStack *, int, void *);
@@ -241,7 +241,7 @@ struct Layer2 {
int tei;
int sap;
int maxlen;
- unsigned int flag;
+ unsigned long flag;
unsigned int vs, va, vr;
int rc;
unsigned int window;
@@ -366,7 +366,7 @@ struct w6692B_hw {
};
struct isar_reg {
- unsigned int Flags;
+ unsigned long Flags;
volatile u_char bstat;
volatile u_char iis;
volatile u_char cmsb;
@@ -476,6 +476,7 @@ struct amd7930_hw {
#define L1_MODE_TRANS 1
#define L1_MODE_HDLC 2
#define L1_MODE_EXTRN 3
+#define L1_MODE_HDLC_56K 4
#define L1_MODE_MODEM 7
#define L1_MODE_V32 8
#define L1_MODE_FAX 9
@@ -483,7 +484,7 @@ struct amd7930_hw {
struct BCState {
int channel;
int mode;
- int Flag;
+ long Flag; /* long req'd for set_bit --RR */
struct IsdnCardState *cs;
int tx_cnt; /* B-Channel transmit counter */
struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
@@ -528,7 +529,8 @@ struct Channel {
int data_open;
struct l3_process *proc;
setup_parm setup; /* from isdnif.h numbers and Serviceindicator */
- int Flags; /* for remembering action done in l4 */
+ long Flags; /* for remembering action done in l4 */
+ /* long req'd for set_bit --RR */
int leased;
};
@@ -865,7 +867,7 @@ struct IsdnCardState {
int protocol;
unsigned int irq;
unsigned long irq_flags;
- int HW_Flags;
+ long HW_Flags;
int *busy_flag;
int chanlimit; /* limited number of B-chans to use */
int logecho; /* log echo if supported by card */
@@ -932,7 +934,7 @@ struct IsdnCardState {
int rcvidx;
struct sk_buff *tx_skb;
int tx_cnt;
- int event;
+ long event;
struct tq_struct tqueue;
struct timer_list dbusytimer;
#ifdef ERROR_STATISTIC
@@ -987,24 +989,14 @@ struct IsdnCardState {
#define ISDN_CTYPE_W6692 36
#define ISDN_CTYPE_HFC_SX 37
#define ISDN_CTYPE_NETJET_U 38
-#define ISDN_CTYPE_COUNT 38
+#define ISDN_CTYPE_HFC_SP_PCMCIA 39
+#define ISDN_CTYPE_COUNT 39
#ifdef ISDN_CHIP_ISAC
#undef ISDN_CHIP_ISAC
#endif
-#ifndef __initfunc
-#define __initfunc(__arginit) __arginit
-#endif
-
-#ifndef __initdata
-#define __initdata
-#endif
-
-#define HISAX_INITFUNC(__arginit) __initfunc(__arginit)
-#define HISAX_INITDATA __initdata
-
#ifdef CONFIG_HISAX_16_0
#define CARD_TELES0 1
#ifndef ISDN_CHIP_ISAC
@@ -1064,10 +1056,6 @@ struct IsdnCardState {
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
-#undef HISAX_INITFUNC
-#define HISAX_INITFUNC(__arginit) __arginit
-#undef HISAX_INITDATA
-#define HISAX_INITDATA
#else
#define CARD_ELSA 0
#endif
diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
index 6cae36eef..d8338bc26 100644
--- a/drivers/isdn/hisax/hscx.c
+++ b/drivers/isdn/hisax/hscx.c
@@ -1,4 +1,4 @@
-/* $Id: hscx.c,v 1.19 2000/06/26 08:59:13 keil Exp $
+/* $Id: hscx.c,v 1.21 2000/11/24 17:05:37 kai Exp $
*
* hscx.c HSCX specific routines
*
@@ -9,18 +9,19 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "hscx.h"
#include "isac.h"
#include "isdnl1.h"
#include <linux/interrupt.h>
-static char *HSCXVer[] HISAX_INITDATA =
+static char *HSCXVer[] __initdata =
{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
"?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
-HISAX_INITFUNC(int
-HscxVersion(struct IsdnCardState *cs, char *s))
+int __init
+HscxVersion(struct IsdnCardState *cs, char *s)
{
int verA, verB;
@@ -218,8 +219,8 @@ setstack_hscx(struct PStack *st, struct BCState *bcs)
return (0);
}
-HISAX_INITFUNC(void
-clear_pending_hscx_ints(struct IsdnCardState *cs))
+void __init
+clear_pending_hscx_ints(struct IsdnCardState *cs)
{
int val, eval;
@@ -244,8 +245,8 @@ clear_pending_hscx_ints(struct IsdnCardState *cs))
cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
}
-HISAX_INITFUNC(void
-inithscx(struct IsdnCardState *cs))
+void __init
+inithscx(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_hscx;
cs->bcs[1].BC_SetStack = setstack_hscx;
@@ -261,8 +262,8 @@ inithscx(struct IsdnCardState *cs))
modehscx(cs->bcs + 1, 0, 0);
}
-HISAX_INITFUNC(void
-inithscxisac(struct IsdnCardState *cs, int part))
+void __init
+inithscxisac(struct IsdnCardState *cs, int part)
{
if (part & 1) {
clear_pending_isac_ints(cs);
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
index 581cf9213..c28f070e2 100644
--- a/drivers/isdn/hisax/hscx_irq.c
+++ b/drivers/isdn/hisax/hscx_irq.c
@@ -1,4 +1,4 @@
-/* $Id: hscx_irq.c,v 1.15 2000/06/26 08:59:13 keil Exp $
+/* $Id: hscx_irq.c,v 1.16 2000/11/19 17:02:47 kai Exp $
*
* hscx_irq.c low level b-channel stuff for Siemens HSCX
*
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index 5f2740e9e..fb449592a 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -1,4 +1,4 @@
-// $Id: icc.c,v 1.3 2000/08/20 07:34:04 keil Exp $
+// $Id: icc.c,v 1.5 2000/11/24 17:05:37 kai Exp $
//-----------------------------------------------------------------------------
//
// ICC specific routines
@@ -15,6 +15,7 @@
//-----------------------------------------------------------------------------
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "icc.h"
// #include "arcofi.h"
@@ -24,7 +25,7 @@
#define DBUSY_TIMER_VALUE 80
#define ARCOFI_USE 0
-static char *ICCVer[] HISAX_INITDATA =
+static char *ICCVer[] __initdata =
{"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"};
void
@@ -622,8 +623,8 @@ dbusy_timer_handler(struct IsdnCardState *cs)
}
}
-HISAX_INITFUNC(void
-initicc(struct IsdnCardState *cs))
+void __init
+initicc(struct IsdnCardState *cs)
{
cs->tqueue.routine = (void *) (void *) icc_bh;
cs->setstack_d = setstack_icc;
@@ -659,8 +660,8 @@ initicc(struct IsdnCardState *cs))
ph_command(cs, ICC_CMD_DI);
}
-HISAX_INITFUNC(void
-clear_pending_icc_ints(struct IsdnCardState *cs))
+void __init
+clear_pending_icc_ints(struct IsdnCardState *cs)
{
int val, eval;
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 363408ab0..ae68aea1b 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -1,4 +1,4 @@
-/* $Id: isac.c,v 1.26 2000/06/26 08:59:13 keil Exp $
+/* $Id: isac.c,v 1.28 2000/11/24 17:05:37 kai Exp $
*
* isac.c ISAC specific routines
*
@@ -15,11 +15,12 @@
#include "arcofi.h"
#include "isdnl1.h"
#include <linux/interrupt.h>
+#include <linux/init.h>
#define DBUSY_TIMER_VALUE 80
#define ARCOFI_USE 1
-static char *ISACVer[] HISAX_INITDATA =
+static char *ISACVer[] __devinitdata =
{"2086/2186 V1.1", "2085 B1", "2085 B2",
"2085 V2.3"};
@@ -620,8 +621,8 @@ dbusy_timer_handler(struct IsdnCardState *cs)
}
}
-HISAX_INITFUNC(void
-initisac(struct IsdnCardState *cs))
+void __devinit
+initisac(struct IsdnCardState *cs)
{
cs->tqueue.routine = (void *) (void *) isac_bh;
cs->setstack_d = setstack_isac;
@@ -656,8 +657,8 @@ initisac(struct IsdnCardState *cs))
cs->writeisac(cs, ISAC_MASK, 0x0);
}
-HISAX_INITFUNC(void
-clear_pending_isac_ints(struct IsdnCardState *cs))
+void __devinit
+clear_pending_isac_ints(struct IsdnCardState *cs)
{
int val, eval;
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index d91f86f02..27987e2c1 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -1,4 +1,4 @@
-/* $Id: isar.c,v 1.15 2000/06/26 08:59:13 keil Exp $
+/* $Id: isar.c,v 1.17 2000/11/24 17:05:37 kai Exp $
*
* isar.c ISAR (Siemens PSB 7110) specific routines
*
@@ -9,6 +9,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isar.h"
#include "isdnl1.h"
@@ -1782,8 +1783,8 @@ isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
return(0);
}
-HISAX_INITFUNC(void
-initisar(struct IsdnCardState *cs))
+void __devinit
+initisar(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_isar;
cs->bcs[1].BC_SetStack = setstack_isar;
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
index f523f378d..cda9e422c 100644
--- a/drivers/isdn/hisax/isdnl1.c
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -1,4 +1,4 @@
-/* $Id: isdnl1.c,v 2.39 2000/06/26 08:59:13 keil Exp $
+/* $Id: isdnl1.c,v 2.41 2000/11/24 17:05:37 kai Exp $
*
* isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards
* based on the teles driver from Jan den Ouden
@@ -15,21 +15,17 @@
*
*/
-const char *l1_revision = "$Revision: 2.39 $";
+const char *l1_revision = "$Revision: 2.41 $";
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isdnl1.h"
#define TIMER3_VALUE 7000
-static
-struct Fsm l1fsm_b =
-{NULL, 0, 0, NULL, NULL};
-
-static
-struct Fsm l1fsm_s =
-{NULL, 0, 0, NULL, NULL};
+static struct Fsm l1fsm_b;
+static struct Fsm l1fsm_s;
enum {
ST_L1_F2,
@@ -347,7 +343,7 @@ init_bcstate(struct IsdnCardState *cs,
bcs->cs = cs;
bcs->channel = bc;
- bcs->tqueue.next = 0;
+ INIT_LIST_HEAD(&bcs->tqueue.list);
bcs->tqueue.sync = 0;
bcs->tqueue.routine = (void *) (void *) BChannel_bh;
bcs->tqueue.data = bcs;
@@ -584,7 +580,7 @@ l1_activate_no(struct FsmInst *fi, int event, void *arg)
}
}
-static struct FsmNode L1SFnList[] HISAX_INITDATA =
+static struct FsmNode L1SFnList[] __initdata =
{
{ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},
{ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
@@ -669,7 +665,7 @@ l1_activate_u(struct FsmInst *fi, int event, void *arg)
st->l1.l1hw(st, HW_INFO1 | REQUEST, NULL);
}
-static struct FsmNode L1UFnList[] HISAX_INITDATA =
+static struct FsmNode L1UFnList[] __initdata =
{
{ST_L1_RESET, EV_DEACT_IND, l1_deact_req_u},
{ST_L1_DEACT, EV_DEACT_IND, l1_deact_req_u},
@@ -731,7 +727,7 @@ l1b_timer_deact(struct FsmInst *fi, int event, void *arg)
st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
}
-static struct FsmNode L1BFnList[] HISAX_INITDATA =
+static struct FsmNode L1BFnList[] __initdata =
{
{ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate},
{ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act},
@@ -741,7 +737,8 @@ static struct FsmNode L1BFnList[] HISAX_INITDATA =
#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
-HISAX_INITFUNC(void Isdnl1New(void))
+void __init
+Isdnl1New(void)
{
#ifdef HISAX_UINTERFACE
l1fsm_u.state_count = L1U_STATE_COUNT;
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index c20d0d21f..59d461c0b 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -1,4 +1,4 @@
-/* $Id: isdnl2.c,v 2.23 2000/06/26 08:59:13 keil Exp $
+/* $Id: isdnl2.c,v 2.25 2000/11/24 17:05:38 kai Exp $
*
* Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
@@ -12,16 +12,15 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isdnl2.h"
-const char *l2_revision = "$Revision: 2.23 $";
+const char *l2_revision = "$Revision: 2.25 $";
static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
-static
-struct Fsm l2fsm =
-{NULL, 0, 0, NULL, NULL};
+static struct Fsm l2fsm;
enum {
ST_L2_1,
@@ -1535,7 +1534,7 @@ l2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
}
-static struct FsmNode L2FnList[] HISAX_INITDATA =
+static struct FsmNode L2FnList[] __initdata =
{
{ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
{ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
@@ -1832,8 +1831,8 @@ releasestack_transl2(struct PStack *st)
{
}
-HISAX_INITFUNC(void
-Isdnl2New(void))
+void __init
+Isdnl2New(void)
{
l2fsm.state_count = L2_STATE_COUNT;
l2fsm.event_count = L2_EVENT_COUNT;
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index b4e473670..b484635f1 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -1,4 +1,4 @@
-/* $Id: isdnl3.c,v 2.14 2000/06/26 08:59:13 keil Exp $
+/* $Id: isdnl3.c,v 2.17 2000/11/24 17:05:38 kai Exp $
*
* Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
@@ -11,16 +11,16 @@
* Fritz Elfert
*
*/
+
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isdnl3.h"
#include <linux/config.h>
-const char *l3_revision = "$Revision: 2.14 $";
+const char *l3_revision = "$Revision: 2.17 $";
-static
-struct Fsm l3fsm =
-{NULL, 0, 0, NULL, NULL};
+static struct Fsm l3fsm;
enum {
ST_L3_LC_REL,
@@ -303,7 +303,10 @@ release_l3_process(struct l3_process *p)
if (!skb_queue_len(&p->st->l3.squeue)) {
if (p->debug)
l3_debug(p->st, "release_l3_process: release link");
- FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL);
+ if (p->st->protocol != ISDN_PTYPE_NI1)
+ FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL);
+ else
+ FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL);
} else {
if (p->debug)
l3_debug(p->st, "release_l3_process: not release link");
@@ -483,6 +486,18 @@ lc_start_delay(struct FsmInst *fi, int event, void *arg)
}
static void
+lc_start_delay_check(struct FsmInst *fi, int event, void *arg)
+/* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */
+{
+ struct PStack *st = fi->userdata;
+
+ FsmChangeState(fi, ST_L3_LC_REL_DELAY);
+ /* 19/09/00 - GE timer not user for NI-1 */
+ if (st->protocol != ISDN_PTYPE_NI1)
+ FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
+}
+
+static void
lc_release_req(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
@@ -521,7 +536,7 @@ lc_release_cnf(struct FsmInst *fi, int event, void *arg)
/* *INDENT-OFF* */
-static struct FsmNode L3FnList[] HISAX_INITDATA =
+static struct FsmNode L3FnList[] __initdata =
{
{ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate},
{ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect},
@@ -530,7 +545,7 @@ static struct FsmNode L3FnList[] HISAX_INITDATA =
{ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay},
{ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind},
{ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind},
- {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay},
+ {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay_check},
{ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind},
{ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected},
{ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req},
@@ -576,8 +591,8 @@ l3_msg(struct PStack *st, int pr, void *arg)
}
}
-HISAX_INITFUNC(void
-Isdnl3New(void))
+void __init
+Isdnl3New(void)
{
l3fsm.state_count = L3_STATE_COUNT;
l3fsm.event_count = L3_EVENT_COUNT;
diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
index bc08dafd8..e703ecf66 100644
--- a/drivers/isdn/hisax/isurf.c
+++ b/drivers/isdn/hisax/isurf.c
@@ -1,4 +1,4 @@
-/* $Id: isurf.c,v 1.9 2000/06/26 08:59:13 keil Exp $
+/* $Id: isurf.c,v 1.10 2000/11/24 17:05:38 kai Exp $
*
* isurf.c low level stuff for Siemens I-Surf/I-Talk cards
*
@@ -9,6 +9,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "isar.h"
@@ -16,7 +17,7 @@
extern const char *CardType[];
-static const char *ISurf_revision = "$Revision: 1.9 $";
+static const char *ISurf_revision = "$Revision: 1.10 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -190,8 +191,8 @@ isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
return(isar_auxcmd(cs, ic));
}
-__initfunc(int
-setup_isurf(struct IsdnCard *card))
+int __init
+setup_isurf(struct IsdnCard *card)
{
int ver;
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
index 01976b82f..11e5bd316 100644
--- a/drivers/isdn/hisax/ix1_micro.c
+++ b/drivers/isdn/hisax/ix1_micro.c
@@ -1,4 +1,4 @@
-/* $Id: ix1_micro.c,v 2.9 2000/06/26 08:59:13 keil Exp $
+/* $Id: ix1_micro.c,v 2.10 2000/11/24 17:05:38 kai Exp $
*
* ix1_micro.c low level stuff for ITK ix1-micro Rev.2 isdn cards
* derived from the original file teles3.c from Karsten Keil
@@ -43,13 +43,14 @@
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
#include "isdnl1.h"
extern const char *CardType[];
-const char *ix1_revision = "$Revision: 2.9 $";
+const char *ix1_revision = "$Revision: 2.10 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -243,8 +244,8 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
-__initfunc(int
-setup_ix1micro(struct IsdnCard *card))
+int __init
+setup_ix1micro(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
index b2586ebda..fc96b6e2e 100644
--- a/drivers/isdn/hisax/jade.c
+++ b/drivers/isdn/hisax/jade.c
@@ -1,4 +1,4 @@
-/* $Id: jade.c,v 1.4 2000/06/26 08:59:14 keil Exp $
+/* $Id: jade.c,v 1.6 2000/11/24 17:05:38 kai Exp $
*
* jade.c JADE stuff (derived from original hscx.c)
*
@@ -10,6 +10,7 @@
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "hscx.h"
#include "jade.h"
@@ -17,8 +18,8 @@
#include <linux/interrupt.h>
-HISAX_INITFUNC(int
-JadeVersion(struct IsdnCardState *cs, char *s))
+int __init
+JadeVersion(struct IsdnCardState *cs, char *s)
{
int ver,i;
int to = 50;
@@ -262,8 +263,8 @@ setstack_jade(struct PStack *st, struct BCState *bcs)
return (0);
}
-HISAX_INITFUNC(void
-clear_pending_jade_ints(struct IsdnCardState *cs))
+void __init
+clear_pending_jade_ints(struct IsdnCardState *cs)
{
int val;
char tmp[64];
@@ -288,8 +289,8 @@ clear_pending_jade_ints(struct IsdnCardState *cs))
cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
}
-HISAX_INITFUNC(void
-initjade(struct IsdnCardState *cs))
+void __init
+initjade(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_jade;
cs->bcs[1].BC_SetStack = setstack_jade;
diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
index beb10d20a..d9d289886 100644
--- a/drivers/isdn/hisax/jade_irq.c
+++ b/drivers/isdn/hisax/jade_irq.c
@@ -1,4 +1,4 @@
-/* $Id: jade_irq.c,v 1.4 2000/06/26 08:59:14 keil Exp $
+/* $Id: jade_irq.c,v 1.5 2000/11/19 17:02:48 kai Exp $
*
* jade_irq.c Low level JADE IRQ stuff (derived from original hscx_irq.c)
*
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index 831d788b5..fcb34f415 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -1,4 +1,4 @@
-/* $Id: l3_1tr6.c,v 2.12 2000/08/20 07:31:30 keil Exp $
+/* $Id: l3_1tr6.c,v 2.13 2000/11/19 17:02:48 kai Exp $
*
* German 1TR6 D-channel protocol
*
@@ -17,7 +17,7 @@
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.12 $";
+const char *l3_1tr6_revision = "$Revision: 2.13 $";
#define MsgHead(ptr, cref, mty, dis) \
*ptr++ = dis; \
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index 8778bf3a0..cc714ce3d 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -1,4 +1,4 @@
-/* $Id: l3dss1.c,v 2.29 2000/06/26 08:59:14 keil Exp $
+/* $Id: l3dss1.c,v 2.30 2000/11/19 17:02:48 kai Exp $
*
* EURO/DSS1 D-channel protocol
*
@@ -22,7 +22,7 @@
#include <linux/config.h>
extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.29 $";
+const char *dss1_revision = "$Revision: 2.30 $";
#define EXT_BEARER_CAPS 1
diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c
index ec28539a7..8f4ccf421 100644
--- a/drivers/isdn/hisax/l3ni1.c
+++ b/drivers/isdn/hisax/l3ni1.c
@@ -1,20 +1,24 @@
-// $Id: l3ni1.c,v 2.3 2000/06/26 08:59:14 keil Exp $
+// $Id: l3ni1.c,v 2.5 2000/11/19 17:02:48 kai Exp $
+//
//-----------------------------------------------------------------------------
//
// NI1 D-channel protocol
//
-// Author Matt Henderson & Guy Ellis - Traverse Tecnologies Pty Ltd
-// www.traverse.com.au
+// Authors:
+// Matt Henderson & Guy Ellis - Traverse Tecnologies Pty Ltd
+// www.traverse.com.au
//
// 2000.6.6 Initial implementation of routines for US NI1
// Layer 3 protocol based on the EURO/DSS1 D-channel protocol
-// driver written by Karsten Keil et al. Thanks also for the
-// code provided by Ragnar Paulson and Will Scales.
+// driver written by Karsten Keil et al.
+// NI-1 Hall of Fame - Thanks to....
+// Ragnar Paulson - for some handy code fragments
+// Will Scales - beta tester extraordinaire
+// Brett Whittacre - beta tester and remote devel system in Vegas
//
// This file is (c) under GNU PUBLIC LICENSE
//
//-----------------------------------------------------------------------------
-
#define __NO_VERSION__
#include "hisax.h"
#include "isdnl3.h"
@@ -22,7 +26,7 @@
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *ni1_revision = "$Revision: 2.3 $";
+const char *ni1_revision = "$Revision: 2.5 $";
#define EXT_BEARER_CAPS 1
@@ -443,6 +447,27 @@ l3ni1_message(struct l3_process *pc, u_char mt)
}
static void
+l3ni1_message_plus_chid(struct l3_process *pc, u_char mt)
+/* sends an l3 messages plus channel id - added GE 05/09/00 */
+{
+ struct sk_buff *skb;
+ u_char tmp[16];
+ u_char *p = tmp;
+ u_char chid;
+
+ chid = (u_char)(pc->para.bchannel & 0x03) | 0x88;
+ MsgHead(p, pc->callref, mt);
+ *p++ = IE_CHANNEL_ID;
+ *p++ = 0x01;
+ *p++ = chid;
+
+ if (!(skb = l3_alloc_skb(7)))
+ return;
+ memcpy(skb_put(skb, 7), tmp, 7);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
+}
+
+static void
l3ni1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
{
struct sk_buff *skb;
@@ -1175,9 +1200,9 @@ l3ni1_setup_req(struct l3_process *pc, u_char pr,
case 1: /* Telephony */
*p++ = IE_BEARER;
*p++ = 0x3; /* Length */
- *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
+ *p++ = 0x90; /* 3.1khz Audio */
*p++ = 0x90; /* Circuit-Mode 64kbps */
- *p++ = 0xa3; /* A-Law Audio */
+ *p++ = 0xa2; /* u-Law Audio */
break;
case 5: /* Datatransmission 64k, BTX */
case 7: /* Datatransmission 64k */
@@ -1240,7 +1265,7 @@ l3ni1_setup_req(struct l3_process *pc, u_char pr,
*p++ = 0x3; /* Length */
*p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
*p++ = 0x90; /* Circuit-Mode 64kbps */
- *p++ = 0xa3; /* A-Law Audio */
+ *p++ = 0xa2; /* u-Law Audio */
break;
case 5: /* Datatransmission 64k, BTX */
case 7: /* Datatransmission 64k */
@@ -1641,7 +1666,9 @@ l3ni1_setup_rsp(struct l3_process *pc, u_char pr,
return;
}
newl3state(pc, 8);
- l3ni1_message(pc, MT_CONNECT);
+ if (pc->debug & L3_DEB_WARN)
+ l3_debug(pc->st, "D-chan connect for waiting call");
+ l3ni1_message_plus_chid(pc, MT_CONNECT); /* GE 05/09/00 */
L3DelTimer(&pc->timer);
L3AddTimer(&pc->timer, T313, CC_T313);
}
@@ -2544,6 +2571,7 @@ l3ni1_global_restart(struct l3_process *pc, u_char pr, void *arg)
up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
else if (up->para.bchannel == chan)
up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
+
up = up->next;
}
p = tmp;
diff --git a/drivers/isdn/hisax/l3ni1.h b/drivers/isdn/hisax/l3ni1.h
index 24c919a17..9fd7ce86a 100644
--- a/drivers/isdn/hisax/l3ni1.h
+++ b/drivers/isdn/hisax/l3ni1.h
@@ -1,4 +1,4 @@
-// $Id: l3ni1.h,v 2.2 2000/06/26 08:59:14 keil Exp $
+// $Id: l3ni1.h,v 2.3 2000/11/16 13:50:43 keil Exp $
//-----------------------------------------------------------------------------
//
// NI1 D-channel protocol
@@ -11,6 +11,7 @@
// driver written by Karsten Keil et al. Thanks also for the
// code provided by Ragnar Paulson.
//
+//
// This file is (c) under GNU PUBLIC LICENSE
//
//-----------------------------------------------------------------------------
@@ -29,7 +30,7 @@
#define T313 4000
#define T318 4000
#define T319 4000
-#define TSPID 2000
+#define TSPID 5000 /* was 2000 - Guy Ellis */
/*
* Message-Types
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
index db5d2ee46..abb544866 100644
--- a/drivers/isdn/hisax/mic.c
+++ b/drivers/isdn/hisax/mic.c
@@ -1,4 +1,4 @@
-/* $Id: mic.c,v 1.9 2000/06/26 08:59:14 keil Exp $
+/* $Id: mic.c,v 1.10 2000/11/24 17:05:38 kai Exp $
*
* mic.c low level stuff for mic cards
*
@@ -11,6 +11,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
@@ -18,7 +19,7 @@
extern const char *CardType[];
-const char *mic_revision = "$Revision: 1.9 $";
+const char *mic_revision = "$Revision: 1.10 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -198,8 +199,8 @@ mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_mic(struct IsdnCard *card))
+int __init
+setup_mic(struct IsdnCard *card)
{
int bytecnt;
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index 6be8a493d..9dede4757 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -1,4 +1,4 @@
-/* $Id: netjet.c,v 1.20 2000/06/26 08:59:14 keil Exp $
+/* $Id: netjet.c,v 1.24 2000/11/24 17:05:38 kai Exp $
*
* netjet.c low level stuff for Traverse Technologie NETJet ISDN cards
*
@@ -11,6 +11,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
@@ -28,7 +29,7 @@
#define virt_to_bus (u_int)
#endif
-const char *NETjet_revision = "$Revision: 1.20 $";
+const char *NETjet_revision = "$Revision: 1.24 $";
/* Interface functions */
@@ -161,7 +162,8 @@ mode_tiger(struct BCState *bcs, int mode, int bc)
break;
case (L1_MODE_TRANS):
break;
- case (L1_MODE_HDLC):
+ case (L1_MODE_HDLC_56K):
+ case (L1_MODE_HDLC):
fill_mem(bcs, bcs->hw.tiger.send,
NETJET_DMA_TXSIZE, bc, 0xff);
bcs->hw.tiger.r_state = HDLC_ZERO_SEARCH;
@@ -176,7 +178,8 @@ mode_tiger(struct BCState *bcs, int mode, int bc)
cs->hw.njet.dmactrl = 1;
byteout(cs->hw.njet.base + NETJET_DMACTRL,
cs->hw.njet.dmactrl);
- byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x3f);
+ byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x0f);
+ /* was 0x3f now 0x0f for TJ300 and TJ320 GE 13/07/00 */
}
bcs->hw.tiger.sendp = bcs->hw.tiger.send;
bcs->hw.tiger.free = NETJET_DMA_TXSIZE;
@@ -214,6 +217,8 @@ static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s
}
}
+// macro for 64k
+
#define MAKE_RAW_BYTE for (j=0; j<8; j++) { \
bitcnt++;\
s_val >>= 1;\
@@ -242,6 +247,7 @@ static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s
}
static int make_raw_data(struct BCState *bcs) {
+// this make_raw is for 64k
register u_int i,s_cnt=0;
register u_char j;
register u_char val;
@@ -297,6 +303,113 @@ static int make_raw_data(struct BCState *bcs) {
return(0);
}
+// macro for 56k
+
+#define MAKE_RAW_BYTE_56K for (j=0; j<8; j++) { \
+ bitcnt++;\
+ s_val >>= 1;\
+ if (val & 1) {\
+ s_one++;\
+ s_val |= 0x80;\
+ } else {\
+ s_one = 0;\
+ s_val &= 0x7f;\
+ }\
+ if (bitcnt==7) {\
+ s_val >>= 1;\
+ s_val |= 0x80;\
+ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
+ bitcnt = 0;\
+ }\
+ if (s_one == 5) {\
+ s_val >>= 1;\
+ s_val &= 0x7f;\
+ bitcnt++;\
+ s_one = 0;\
+ }\
+ if (bitcnt==7) {\
+ s_val >>= 1;\
+ s_val |= 0x80;\
+ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
+ bitcnt = 0;\
+ }\
+ val >>= 1;\
+ }
+
+static int make_raw_data_56k(struct BCState *bcs) {
+// this make_raw is for 56k
+ register u_int i,s_cnt=0;
+ register u_char j;
+ register u_char val;
+ register u_char s_one = 0;
+ register u_char s_val = 0;
+ register u_char bitcnt = 0;
+ u_int fcs;
+
+ if (!bcs->tx_skb) {
+ debugl1(bcs->cs, "tiger make_raw_56k: NULL skb");
+ return(1);
+ }
+ val = HDLC_FLAG_VALUE;
+ for (j=0; j<8; j++) {
+ bitcnt++;
+ s_val >>= 1;
+ if (val & 1)
+ s_val |= 0x80;
+ else
+ s_val &= 0x7f;
+ if (bitcnt==7) {
+ s_val >>= 1;
+ s_val |= 0x80;
+ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
+ bitcnt = 0;
+ }
+ val >>= 1;
+ };
+ fcs = PPP_INITFCS;
+ for (i=0; i<bcs->tx_skb->len; i++) {
+ val = bcs->tx_skb->data[i];
+ fcs = PPP_FCS (fcs, val);
+ MAKE_RAW_BYTE_56K;
+ }
+ fcs ^= 0xffff;
+ val = fcs & 0xff;
+ MAKE_RAW_BYTE_56K;
+ val = (fcs>>8) & 0xff;
+ MAKE_RAW_BYTE_56K;
+ val = HDLC_FLAG_VALUE;
+ for (j=0; j<8; j++) {
+ bitcnt++;
+ s_val >>= 1;
+ if (val & 1)
+ s_val |= 0x80;
+ else
+ s_val &= 0x7f;
+ if (bitcnt==7) {
+ s_val >>= 1;
+ s_val |= 0x80;
+ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
+ bitcnt = 0;
+ }
+ val >>= 1;
+ }
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger make_raw_56k: in %ld out %d.%d",
+ bcs->tx_skb->len, s_cnt, bitcnt);
+ if (bitcnt) {
+ while (8>bitcnt++) {
+ s_val >>= 1;
+ s_val |= 0x80;
+ }
+ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
+ bcs->hw.tiger.sendbuf[s_cnt++] = 0xff; // NJ<->NJ thoughput bug fix
+ }
+ bcs->hw.tiger.sendcnt = s_cnt;
+ bcs->tx_cnt -= bcs->tx_skb->len;
+ bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf;
+ return(0);
+}
+
static void got_frame(struct BCState *bcs, int count) {
struct sk_buff *skb;
@@ -326,20 +439,30 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
register u_char r_val = bcs->hw.tiger.r_val;
register u_int bitcnt = bcs->hw.tiger.r_bitcnt;
u_int *p = buf;
-
+ int bits;
+ u_char mask;
+
+ if (bcs->mode == L1_MODE_HDLC) { // it's 64k
+ mask = 0xff;
+ bits = 8;
+ }
+ else { // it's 56K
+ mask = 0x7f;
+ bits = 7;
+ };
for (i=0;i<cnt;i++) {
val = bcs->channel ? ((*p>>8) & 0xff) : (*p & 0xff);
p++;
if (p > pend)
p = bcs->hw.tiger.rec;
- if (val == 0xff) {
+ if ((val & mask) == mask) {
state = HDLC_ZERO_SEARCH;
bcs->hw.tiger.r_tot++;
bitcnt = 0;
r_one = 0;
continue;
}
- for (j=0;j<8;j++) {
+ for (j=0;j<bits;j++) {
if (state == HDLC_ZERO_SEARCH) {
if (val & 1) {
r_one++;
@@ -505,9 +628,10 @@ void read_tiger(struct IsdnCardState *cs) {
p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1;
else
p = cs->bcs[0].hw.tiger.rec + cnt - 1;
- if (cs->bcs[0].mode == L1_MODE_HDLC)
+ if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K))
read_raw(cs->bcs, p, cnt);
- if (cs->bcs[1].mode == L1_MODE_HDLC)
+
+ if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K))
read_raw(cs->bcs + 1, p, cnt);
cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ;
}
@@ -526,8 +650,14 @@ void netjet_fill_dma(struct BCState *bcs)
bcs->Flag);
if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag))
return;
- if (make_raw_data(bcs))
- return;
+ if (bcs->mode == L1_MODE_HDLC) { // it's 64k
+ if (make_raw_data(bcs))
+ return;
+ }
+ else { // it's 56k
+ if (make_raw_data_56k(bcs))
+ return;
+ };
if (bcs->cs->debug & L1_DEB_HSCX)
debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel,
bcs->Flag);
@@ -682,9 +812,9 @@ void write_tiger(struct IsdnCardState *cs) {
p = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1;
else
p = cs->bcs[0].hw.tiger.send + cnt - 1;
- if (cs->bcs[0].mode == L1_MODE_HDLC)
+ if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K))
write_raw(cs->bcs, p, cnt);
- if (cs->bcs[1].mode == L1_MODE_HDLC)
+ if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K))
write_raw(cs->bcs + 1, p, cnt);
cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE;
}
@@ -807,8 +937,8 @@ setstack_tiger(struct PStack *st, struct BCState *bcs)
}
-__initfunc(void
-inittiger(struct IsdnCardState *cs))
+void __init
+inittiger(struct IsdnCardState *cs)
{
if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int),
GFP_KERNEL | GFP_DMA))) {
diff --git a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h
index d7dede4ff..120a98d27 100644
--- a/drivers/isdn/hisax/netjet.h
+++ b/drivers/isdn/hisax/netjet.h
@@ -1,4 +1,4 @@
-// $Id: netjet.h,v 2.3 2000/06/26 08:59:14 keil Exp $
+// $Id: netjet.h,v 2.5.6.1 2000/11/28 12:02:46 kai Exp $
//-----------------------------------------------------------------------------
//
// NETjet common header file
@@ -15,13 +15,6 @@ extern const char *CardType[];
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
-/* PCI stuff */
-#ifndef PCI_VENDOR_ID_TIGERJET
-#define PCI_VENDOR_ID_TIGERJET 0xe159
-#endif
-#ifndef PCI_DEVICE_ID_TIGERJET_300
-#define PCI_DEVICE_ID_TIGERJET_300 0x0001
-#endif
#define NETJET_CTRL 0x00
#define NETJET_DMACTRL 0x01
#define NETJET_AUXCTRL 0x02
@@ -72,6 +65,6 @@ void write_tiger(struct IsdnCardState *cs);
void netjet_fill_dma(struct BCState *bcs);
void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs);
-__initfunc(void inittiger(struct IsdnCardState *cs));
+void inittiger(struct IsdnCardState *cs);
void release_io_netjet(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index 4428483b3..b22ed23e7 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -1,4 +1,4 @@
-/* $Id: niccy.c,v 1.12 2000/06/26 08:59:14 keil Exp $
+/* $Id: niccy.c,v 1.15.6.2 2000/11/29 16:00:14 kai Exp $
*
* niccy.c low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
* compatible (SAGEM cybermodem)
@@ -14,6 +14,7 @@
#define __NO_VERSION__
#include <linux/config.h>
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
@@ -21,7 +22,7 @@
#include <linux/pci.h>
extern const char *CardType[];
-const char *niccy_revision = "$Revision: 1.12 $";
+const char *niccy_revision = "$Revision: 1.15.6.2 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -38,12 +39,6 @@ const char *niccy_revision = "$Revision: 1.12 $";
#define NICCY_PCI 2
/* PCI stuff */
-#ifndef PCI_VENDOR_ID_SATSAGEM
-#define PCI_VENDOR_ID_SATSAGEM 0x1267
-#endif
-#ifndef PCI_DEVICE_ID_SATSAGEM_NICCY
-#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016
-#endif
#define PCI_IRQ_CTRL_REG 0x38
#define PCI_IRQ_ENABLE 0x1f00
#define PCI_IRQ_DISABLE 0xff0000
@@ -240,10 +235,10 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *niccy_dev __initdata = NULL;
+static struct pci_dev *niccy_dev __initdata = NULL;
-__initfunc(int
-setup_niccy(struct IsdnCard *card))
+int __init
+setup_niccy(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
index 1ff42d3b7..4aaf9e185 100644
--- a/drivers/isdn/hisax/nj_s.c
+++ b/drivers/isdn/hisax/nj_s.c
@@ -1,9 +1,11 @@
-// $Id: nj_s.c,v 2.3 2000/06/26 08:59:14 keil Exp $
+// $Id: nj_s.c,v 2.7.6.1 2000/11/29 16:00:14 kai Exp $
//
// This file is (c) under GNU PUBLIC LICENSE
//
+
#define __NO_VERSION__
#include <linux/config.h>
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "isdnl1.h"
@@ -12,7 +14,7 @@
#include <linux/ppp_defs.h>
#include "netjet.h"
-const char *NETjet_S_revision = "$Revision: 2.3 $";
+const char *NETjet_S_revision = "$Revision: 2.7.6.1 $";
static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
{
@@ -47,28 +49,37 @@ netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
save_flags(flags);
cli();
- if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) {
+ /* start new code 13/07/00 GE */
+ /* set bits in sval to indicate which page is free */
+ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
+ inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
+ /* the 2nd write page is free */
+ sval = 0x08;
+ else /* the 1st write page is free */
+ sval = 0x04;
+ if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) <
+ inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ))
+ /* the 2nd read page is free */
+ sval = sval | 0x02;
+ else /* the 1st read page is free */
+ sval = sval | 0x01;
+ if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */
+ {
if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
restore_flags(flags);
return;
}
cs->hw.njet.irqstat0 = sval;
restore_flags(flags);
-/* debugl1(cs, "tiger: ist0 %x %x %x %x/%x pulse=%d",
- sval,
- bytein(cs->hw.njet.base + NETJET_DMACTRL),
- bytein(cs->hw.njet.base + NETJET_IRQMASK0),
- inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
- inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
- bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
-*/
-/* cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30;
-*/ byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0);
-/* byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0);
-*/ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ)
+ if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) !=
+ (cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
+ /* we have a read dma int */
read_tiger(cs);
- if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE)
+ if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) !=
+ (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE))
+ /* we have a write dma int */
write_tiger(cs);
+ /* end new code 13/07/00 GE */
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
} else
restore_flags(flags);
@@ -93,7 +104,8 @@ reset_netjet_s(struct IsdnCardState *cs)
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
- cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
+ cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */
+ /* now edge triggered for TJ320 GE 13/07/00 */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
@@ -128,17 +140,16 @@ NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_netjet __initdata = NULL;
+static struct pci_dev *dev_netjet __initdata = NULL;
-__initfunc(int
-setup_netjet_s(struct IsdnCard *card))
+int __init
+setup_netjet_s(struct IsdnCard *card)
{
int bytecnt;
struct IsdnCardState *cs = card->cs;
char tmp[64];
long flags;
-#if CONFIG_PCI
-#endif
+
#ifdef __BIG_ENDIAN
#error "not running on big endian machines now"
#endif
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 57de4b44b..a98724bd1 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -1,10 +1,12 @@
-/* $Id: nj_u.c,v 2.4 2000/06/26 11:42:16 keil Exp $
+/* $Id: nj_u.c,v 2.8.6.1 2000/11/29 16:00:14 kai Exp $
*
* This file is (c) under GNU PUBLIC LICENSE
*
*/
+
#define __NO_VERSION__
#include <linux/config.h>
+#include <linux/init.h>
#include "hisax.h"
#include "icc.h"
#include "isdnl1.h"
@@ -13,7 +15,7 @@
#include <linux/ppp_defs.h>
#include "netjet.h"
-const char *NETjet_U_revision = "$Revision: 2.4 $";
+const char *NETjet_U_revision = "$Revision: 2.8.6.1 $";
static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
{
@@ -48,28 +50,37 @@ netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
save_flags(flags);
cli();
- if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) {
+ /* start new code 13/07/00 GE */
+ /* set bits in sval to indicate which page is free */
+ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
+ inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
+ /* the 2nd write page is free */
+ sval = 0x08;
+ else /* the 1st write page is free */
+ sval = 0x04;
+ if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) <
+ inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ))
+ /* the 2nd read page is free */
+ sval = sval | 0x02;
+ else /* the 1st read page is free */
+ sval = sval | 0x01;
+ if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */
+ {
if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
restore_flags(flags);
return;
}
cs->hw.njet.irqstat0 = sval;
restore_flags(flags);
-/* debugl1(cs, "tiger: ist0 %x %x %x %x/%x pulse=%d",
- sval,
- bytein(cs->hw.njet.base + NETJET_DMACTRL),
- bytein(cs->hw.njet.base + NETJET_IRQMASK0),
- inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
- inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
- bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
-*/
-/* cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30;
-*/ byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0);
-/* byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0);
-*/ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ)
+ if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) !=
+ (cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
+ /* we have a read dma int */
read_tiger(cs);
- if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE)
+ if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) !=
+ (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE))
+ /* we have a write dma int */
write_tiger(cs);
+ /* end new code 13/07/00 GE */
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
} else
restore_flags(flags);
@@ -94,7 +105,8 @@ reset_netjet_u(struct IsdnCardState *cs)
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
- cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
+ cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */
+ /* now edge triggered for TJ320 GE 13/07/00 */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
@@ -130,10 +142,10 @@ NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_netjet __initdata = NULL;
+static struct pci_dev *dev_netjet __initdata = NULL;
-__initfunc(int
-setup_netjet_u(struct IsdnCard *card))
+int __init
+setup_netjet_u(struct IsdnCard *card)
{
int bytecnt;
struct IsdnCardState *cs = card->cs;
@@ -155,7 +167,7 @@ setup_netjet_u(struct IsdnCard *card))
for ( ;; )
{
if (!pci_present()) {
- printk(KERN_ERR "NETspider-U: no PCI bus present\n");
+ printk(KERN_ERR "Netjet: no PCI bus present\n");
return(0);
}
if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
@@ -241,7 +253,7 @@ setup_netjet_u(struct IsdnCard *card))
cs->hw.njet.base + bytecnt);
return (0);
} else {
- request_region(cs->hw.njet.base, bytecnt, "netjet-u isdn");
+ request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn");
}
reset_netjet_u(cs);
cs->readisac = &NETjet_ReadIC;
diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
index 6b102bcec..c29e765e6 100644
--- a/drivers/isdn/hisax/s0box.c
+++ b/drivers/isdn/hisax/s0box.c
@@ -1,4 +1,4 @@
-/* $Id: s0box.c,v 2.3 2000/06/26 08:59:14 keil Exp $
+/* $Id: s0box.c,v 2.4 2000/11/24 17:05:38 kai Exp $
*
* s0box.c low level stuff for Creatix S0BOX
*
@@ -8,13 +8,14 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
#include "isdnl1.h"
extern const char *CardType[];
-const char *s0box_revision = "$Revision: 2.3 $";
+const char *s0box_revision = "$Revision: 2.4 $";
static inline void
writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
@@ -213,8 +214,8 @@ S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_s0box(struct IsdnCard *card))
+int __init
+setup_s0box(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
index af2023b81..8f4b7c473 100644
--- a/drivers/isdn/hisax/saphir.c
+++ b/drivers/isdn/hisax/saphir.c
@@ -1,4 +1,4 @@
-/* $Id: saphir.c,v 1.7 2000/06/26 08:59:14 keil Exp $
+/* $Id: saphir.c,v 1.8 2000/11/24 17:05:38 kai Exp $
*
* saphir.c low level stuff for HST Saphir 1
*
@@ -12,13 +12,14 @@
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
#include "isdnl1.h"
extern const char *CardType[];
-static char *saphir_rev = "$Revision: 1.7 $";
+static char *saphir_rev = "$Revision: 1.8 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -253,8 +254,8 @@ saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
-__initfunc(int
-setup_saphir(struct IsdnCard *card))
+int __init
+setup_saphir(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 192c496b0..abe4d2198 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -1,4 +1,4 @@
-/* $Id: sedlbauer.c,v 1.23 2000/06/26 08:59:14 keil Exp $
+/* $Id: sedlbauer.c,v 1.25.6.2 2000/11/29 17:48:59 kai Exp $
*
* sedlbauer.c low level stuff for Sedlbauer cards
* includes support for the Sedlbauer speed star (speed star II),
@@ -40,6 +40,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include <linux/config.h>
#include "hisax.h"
#include "isac.h"
@@ -51,19 +52,13 @@
extern const char *CardType[];
-const char *Sedlbauer_revision = "$Revision: 1.23 $";
+const char *Sedlbauer_revision = "$Revision: 1.25.6.2 $";
const char *Sedlbauer_Types[] =
{"None", "speed card/win", "speed star", "speed fax+",
"speed win II / ISDN PC/104", "speed star II", "speed pci",
"speed fax+ pyramid", "speed fax+ pci"};
-#ifndef PCI_VENDOR_ID_TIGERJET
-#define PCI_VENDOR_ID_TIGERJET 0xe159
-#endif
-#ifndef PCI_DEVICE_ID_TIGERJET_100
-#define PCI_DEVICE_ID_TIGERJET_100 0x0002
-#endif
#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
#define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53
#define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54
@@ -534,10 +529,10 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_sedl __initdata = NULL;
+static struct pci_dev *dev_sedl __devinitdata = NULL;
-__initfunc(int
-setup_sedlbauer(struct IsdnCard *card))
+int __devinit
+setup_sedlbauer(struct IsdnCard *card)
{
int bytecnt, ver, val;
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
index 6b6407796..b72ff032c 100644
--- a/drivers/isdn/hisax/sportster.c
+++ b/drivers/isdn/hisax/sportster.c
@@ -1,4 +1,4 @@
-/* $Id: sportster.c,v 1.13 2000/06/26 08:59:14 keil Exp $
+/* $Id: sportster.c,v 1.14 2000/11/24 17:05:38 kai Exp $
*
* sportster.c low level stuff for USR Sportster internal TA
*
@@ -10,13 +10,14 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
#include "isdnl1.h"
extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.13 $";
+const char *sportster_revision = "$Revision: 1.14 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -181,8 +182,8 @@ Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-get_io_range(struct IsdnCardState *cs))
+static int __init
+get_io_range(struct IsdnCardState *cs)
{
int i, j, adr;
@@ -207,8 +208,8 @@ get_io_range(struct IsdnCardState *cs))
}
}
-__initfunc(int
-setup_sportster(struct IsdnCard *card))
+int __init
+setup_sportster(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
index 2a84aa2d2..41a7446b7 100644
--- a/drivers/isdn/hisax/tei.c
+++ b/drivers/isdn/hisax/tei.c
@@ -1,4 +1,4 @@
-/* $Id: tei.c,v 2.15 2000/06/26 08:59:14 keil Exp $
+/* $Id: tei.c,v 2.17 2000/11/24 17:05:38 kai Exp $
*
* Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
@@ -14,9 +14,10 @@
#define __NO_VERSION__
#include "hisax.h"
#include "isdnl2.h"
+#include <linux/init.h>
#include <linux/random.h>
-const char *tei_revision = "$Revision: 2.15 $";
+const char *tei_revision = "$Revision: 2.17 $";
#define ID_REQUEST 1
#define ID_ASSIGNED 2
@@ -28,9 +29,7 @@ const char *tei_revision = "$Revision: 2.15 $";
#define TEI_ENTITY_ID 0xf
-static
-struct Fsm teifsm =
-{NULL, 0, 0, NULL, NULL};
+static struct Fsm teifsm;
void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb);
@@ -430,7 +429,7 @@ release_tei(struct IsdnCardState *cs)
}
}
-static struct FsmNode TeiFnList[] HISAX_INITDATA =
+static struct FsmNode TeiFnList[] __initdata =
{
{ST_TEI_NOP, EV_IDREQ, tei_id_request},
{ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
@@ -447,8 +446,8 @@ static struct FsmNode TeiFnList[] HISAX_INITDATA =
#define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
-HISAX_INITFUNC(void
-TeiNew(void))
+void __init
+TeiNew(void)
{
teifsm.state_count = TEI_STATE_COUNT;
teifsm.event_count = TEI_EVENT_COUNT;
diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
index 90e0e2ec5..eb65d3c85 100644
--- a/drivers/isdn/hisax/teleint.c
+++ b/drivers/isdn/hisax/teleint.c
@@ -1,4 +1,4 @@
-/* $Id: teleint.c,v 1.13 2000/06/26 08:59:14 keil Exp $
+/* $Id: teleint.c,v 1.14 2000/11/24 17:05:38 kai Exp $
*
* teleint.c low level stuff for TeleInt isdn cards
*
@@ -9,6 +9,7 @@
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hfc_2bs0.h"
@@ -16,7 +17,7 @@
extern const char *CardType[];
-const char *TeleInt_revision = "$Revision: 1.13 $";
+const char *TeleInt_revision = "$Revision: 1.14 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -260,8 +261,8 @@ TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_TeleInt(struct IsdnCard *card))
+int __init
+setup_TeleInt(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
index c9c5838a5..efbd15266 100644
--- a/drivers/isdn/hisax/teles0.c
+++ b/drivers/isdn/hisax/teles0.c
@@ -1,4 +1,4 @@
-/* $Id: teles0.c,v 2.12 2000/06/26 08:59:14 keil Exp $
+/* $Id: teles0.c,v 2.13 2000/11/24 17:05:38 kai Exp $
*
* teles0.c low level stuff for Teles Memory IO isdn cards
* based on the teles driver from Jan den Ouden
@@ -13,6 +13,7 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isdnl1.h"
#include "isac.h"
@@ -20,7 +21,7 @@
extern const char *CardType[];
-const char *teles0_revision = "$Revision: 2.12 $";
+const char *teles0_revision = "$Revision: 2.13 $";
#define TELES_IOMEM_SIZE 0x400
#define byteout(addr,val) outb(val,addr)
@@ -260,8 +261,8 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_teles0(struct IsdnCard *card))
+int __init
+setup_teles0(struct IsdnCard *card)
{
u_char val;
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
index 3cdbfbeb5..3fdcfb04d 100644
--- a/drivers/isdn/hisax/teles3.c
+++ b/drivers/isdn/hisax/teles3.c
@@ -1,4 +1,4 @@
-/* $Id: teles3.c,v 2.16 2000/06/26 08:59:15 keil Exp $
+/* $Id: teles3.c,v 2.17 2000/11/24 17:05:38 kai Exp $
*
* teles3.c low level stuff for Teles 16.3 & PNP isdn cards
*
@@ -14,13 +14,14 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
#include "isdnl1.h"
extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.16 $";
+const char *teles3_revision = "$Revision: 2.17 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -253,8 +254,8 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-__initfunc(int
-setup_teles3(struct IsdnCard *card))
+int __devinit
+setup_teles3(struct IsdnCard *card)
{
u_char val;
struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
index eb17ce331..83b640f8f 100644
--- a/drivers/isdn/hisax/telespci.c
+++ b/drivers/isdn/hisax/telespci.c
@@ -1,4 +1,4 @@
-/* $Id: telespci.c,v 2.13 2000/06/26 08:59:15 keil Exp $
+/* $Id: telespci.c,v 2.16.6.2 2000/11/29 16:00:14 kai Exp $
*
* telespci.c low level stuff for Teles PCI isdn cards
*
@@ -9,6 +9,7 @@
*
*/
#define __NO_VERSION__
+#include <linux/init.h>
#include <linux/config.h>
#include "hisax.h"
#include "isac.h"
@@ -17,7 +18,7 @@
#include <linux/pci.h>
extern const char *CardType[];
-const char *telespci_revision = "$Revision: 2.13 $";
+const char *telespci_revision = "$Revision: 2.16.6.2 $";
#define ZORAN_PO_RQ_PEN 0x02000000
#define ZORAN_PO_WR 0x00800000
@@ -27,12 +28,6 @@ const char *telespci_revision = "$Revision: 2.13 $";
#define ZORAN_PO_GREG1 0x00010000
#define ZORAN_PO_DMASK 0xFF
-#ifndef PCI_VENDOR_ID_ZORAN
-#define PCI_VENDOR_ID_ZORAN 0x11DE
-#endif
-#ifndef PCI_DEVICE_ID_ZORAN_36120
-#define PCI_DEVICE_ID_ZORAN_36120 0x6120
-#endif
#define WRITE_ADDR_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0)
#define READ_DATA_ISAC (ZORAN_PO_GID0 | ZORAN_PO_GREG1)
#define WRITE_DATA_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1)
@@ -280,10 +275,10 @@ TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static struct pci_dev *dev_tel __initdata = NULL;
+static struct pci_dev *dev_tel __initdata = NULL;
-__initfunc(int
-setup_telespci(struct IsdnCard *card))
+int __init
+setup_telespci(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index 0a2e1d4ec..9afb73f90 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -1,4 +1,4 @@
-/* $Id: w6692.c,v 1.8 2000/09/07 20:33:30 werner Exp $
+/* $Id: w6692.c,v 1.12.6.2 2000/11/29 16:00:14 kai Exp $
*
* w6692.c Winbond W6692 specific routines
*
@@ -10,6 +10,7 @@
*/
#include <linux/config.h>
+#include <linux/init.h>
#define __NO_VERSION__
#include "hisax.h"
#include "w6692.h"
@@ -17,18 +18,6 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
-#ifndef PCI_VENDOR_ID_ASUSCOM
-#define PCI_VENDOR_ID_ASUSCOM 0x675
-#endif
-#ifndef PCI_DEVICE_ID_ASUSCOM_TA1
-#define PCI_DEVICE_ID_ASUSCOM_TA1 0x1702
-#endif
-#ifndef PCI_VENDOR_ID_WINBOND2
-#define PCI_VENDOR_ID_WINBOND2 0x1050
-#endif
-#ifndef PCI_DEVICE_ID_WINBOND_6692
-#define PCI_DEVICE_ID_WINBOND_6692 0x6692
-#endif
/* table entry in the PCI devices list */
typedef struct {
int vendor_id;
@@ -39,18 +28,18 @@ typedef struct {
static const PCI_ENTRY id_list[] =
{
- {PCI_VENDOR_ID_ASUSCOM, PCI_DEVICE_ID_ASUSCOM_TA1, "AsusCom", "TA XXX"},
- {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND_6692, "Winbond", "W6692"},
+ {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
+ {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
{0, 0, NULL, NULL}
};
extern const char *CardType[];
-const char *w6692_revision = "$Revision: 1.8 $";
+const char *w6692_revision = "$Revision: 1.12.6.2 $";
#define DBUSY_TIMER_VALUE 80
-static char *W6692Ver[] HISAX_INITDATA =
+static char *W6692Ver[] __initdata =
{"W6692 V00", "W6692 V01", "W6692 V10",
"W6692 V11"};
@@ -869,7 +858,7 @@ setstack_w6692(struct PStack *st, struct BCState *bcs)
return (0);
}
-HISAX_INITFUNC(void initW6692(struct IsdnCardState *cs, int part))
+void __init initW6692(struct IsdnCardState *cs, int part)
{
if (part & 1) {
cs->tqueue.routine = (void *) (void *) W6692_bh;
@@ -966,11 +955,12 @@ w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return (0);
}
-static int id_idx = 0;
+static int id_idx ;
static struct pci_dev *dev_w6692 __initdata = NULL;
-__initfunc(int setup_w6692(struct IsdnCard *card))
+int __init
+setup_w6692(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c
index 17fc82ffc..941a4bfab 100644
--- a/drivers/isdn/hysdn/boardergo.c
+++ b/drivers/isdn/hysdn/boardergo.c
@@ -1,4 +1,4 @@
-/* $Id: boardergo.c,v 1.4 2000/11/13 22:51:47 kai Exp $
+/* $Id: boardergo.c,v 1.5 2000/11/22 17:13:13 kai Exp $
* Linux driver for HYSDN cards, specific routines for ergo type boards.
*
@@ -458,7 +458,7 @@ ergo_inithardware(hysdn_card * card)
card->writebootseq = ergo_writebootseq;
card->waitpofready = ergo_waitpofready;
card->set_errlog_state = ergo_set_errlog_state;
- card->irq_queue.next = 0;
+ INIT_LIST_HEAD(&card->irq_queue.list);
card->irq_queue.sync = 0;
card->irq_queue.data = card; /* init task queue for interrupt */
card->irq_queue.routine = (void *) (void *) ergo_irq_bh;
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
index f90d902e2..ddc00823f 100644
--- a/drivers/isdn/hysdn/hycapi.c
+++ b/drivers/isdn/hysdn/hycapi.c
@@ -1,4 +1,4 @@
-/* $Id: hycapi.c,v 1.7 2000/11/13 22:51:47 kai Exp $
+/* $Id: hycapi.c,v 1.8 2000/11/22 17:13:13 kai Exp $
*
* Linux driver for HYSDN cards, CAPI2.0-Interface.
* written by Ulrich Albrecht (u.albrecht@hypercope.de) for Hypercope GmbH
@@ -41,7 +41,7 @@
#include "hysdn_defs.h"
#include <linux/kernelcapi.h>
-static char hycapi_revision[]="$Revision: 1.7 $";
+static char hycapi_revision[]="$Revision: 1.8 $";
typedef struct _hycapi_appl {
unsigned int ctrl_mask;
diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h
index 0e4794c39..8bc589981 100644
--- a/drivers/isdn/hysdn/hysdn_defs.h
+++ b/drivers/isdn/hysdn/hysdn_defs.h
@@ -1,4 +1,4 @@
-/* $Id: hysdn_defs.h,v 1.4 2000/11/13 22:51:47 kai Exp $
+/* $Id: hysdn_defs.h,v 1.5.6.1 2000/11/28 12:02:47 kai Exp $
* Linux driver for HYSDN cards, global definitions and exported vars and functions.
* written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
@@ -115,21 +115,6 @@
#define PROC_CONF_BASENAME "cardconf"
#define PROC_LOG_BASENAME "cardlog"
-/************************/
-/* PCI constant defines */
-/************************/
-#define PCI_VENDOR_ID_HYPERCOPE 0x1365
-#define PCI_DEVICE_ID_PLX 0x9050 /* all DPRAM cards use the same id */
-
-/*****************************/
-/* sub ids determining cards */
-/*****************************/
-#define PCI_SUB_ID_OLD_ERGO 0x0104
-#define PCI_SUB_ID_ERGO 0x0106
-#define PCI_SUB_ID_METRO 0x0107
-#define PCI_SUB_ID_CHAMP2 0x0108
-#define PCI_SUB_ID_PLEXUS 0x0109
-
/***********************************/
/* PCI 32 bit parms for IO and MEM */
/***********************************/
diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c
index 2b3916753..c3443b74b 100644
--- a/drivers/isdn/hysdn/hysdn_init.c
+++ b/drivers/isdn/hysdn/hysdn_init.c
@@ -1,4 +1,4 @@
-/* $Id: hysdn_init.c,v 1.6 2000/11/13 22:51:47 kai Exp $
+/* $Id: hysdn_init.c,v 1.6.6.1 2000/11/28 12:02:47 kai Exp $
* Linux driver for HYSDN cards, init functions.
* written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
@@ -23,6 +23,7 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/init.h>
#include <linux/version.h>
#include <linux/poll.h>
#include <linux/vmalloc.h>
@@ -31,7 +32,7 @@
#include "hysdn_defs.h"
-static char *hysdn_init_revision = "$Revision: 1.6 $";
+static char *hysdn_init_revision = "$Revision: 1.6.6.1 $";
int cardmax; /* number of found cards */
hysdn_card *card_root = NULL; /* pointer to first card */
@@ -45,22 +46,31 @@ static struct {
} pci_subid_map[] = {
{
- PCI_SUB_ID_METRO, BD_METRO
+ PCI_SUBDEVICE_ID_HYPERCOPE_METRO, BD_METRO
},
{
- PCI_SUB_ID_CHAMP2, BD_CHAMP2
+ PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, BD_CHAMP2
},
{
- PCI_SUB_ID_ERGO, BD_ERGO
+ PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, BD_ERGO
},
{
- PCI_SUB_ID_OLD_ERGO, BD_ERGO
+ PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, BD_ERGO
},
{
0, 0
} /* terminating entry */
};
+static struct pci_device_id hysdn_pci_tbl[] __initdata = {
+ {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO},
+ {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2},
+ {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO},
+ {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO},
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl);
+
/*********************************************************************/
/* search_cards searches for available cards in the pci config data. */
/* If a card is found, the card structure is allocated and the cards */
@@ -75,7 +85,7 @@ search_cards(void)
card_root = NULL;
card_last = NULL;
- while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_PLX,
+ while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
akt_pcidev)) != NULL) {
if (pci_enable_device(akt_pcidev))
continue;
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 09c595236..19f55c070 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -1,4 +1,4 @@
-/* $Id: hysdn_proclog.c,v 1.8 2000/11/13 22:51:47 kai Exp $
+/* $Id: hysdn_proclog.c,v 1.9 2000/11/25 17:01:01 kai Exp $
* Linux driver for HYSDN cards, /proc/net filesystem log functions.
* written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c
index 3091c2bc1..276f44d24 100644
--- a/drivers/isdn/hysdn/hysdn_sched.c
+++ b/drivers/isdn/hysdn/hysdn_sched.c
@@ -1,4 +1,4 @@
-/* $Id: hysdn_sched.c,v 1.4 2000/11/13 22:51:47 kai Exp $
+/* $Id: hysdn_sched.c,v 1.5 2000/11/22 17:13:13 kai Exp $
* Linux driver for HYSDN cards, scheduler routines for handling exchange card <-> pc.
*
diff --git a/drivers/isdn/isdn_cards.c b/drivers/isdn/isdn_cards.c
index 14413285f..8c7636b46 100644
--- a/drivers/isdn/isdn_cards.c
+++ b/drivers/isdn/isdn_cards.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_cards.c,v 1.13 2000/10/28 23:03:38 kai Exp $
+/* $Id: isdn_cards.c,v 1.14 2000/11/23 20:45:14 kai Exp $
* Linux ISDN subsystem, initialization for non-modularized drivers.
*
@@ -38,11 +38,6 @@ extern void pcbit_init(void);
extern void eicon_init(void);
#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1
-extern void kcapi_init(void);
-extern void capi_init(void);
-extern void capidrv_init(void);
-#endif
#if CONFIG_ISDN_DRV_ACT2000
extern void act2000_init(void);
#endif
@@ -59,11 +54,6 @@ isdn_cards_init(void)
#if CONFIG_ISDN_DRV_PCBIT
pcbit_init();
#endif
-#ifdef CONFIG_ISDN_DRV_AVMB1
- kcapi_init();
- capi_init();
- capidrv_init();
-#endif
#if CONFIG_ISDN_DRV_ACT2000
act2000_init();
#endif
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index dc117e886..eea88399b 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.113 2000/11/01 17:54:00 detabc Exp $
+/* $Id: isdn_common.c,v 1.114 2000/11/25 17:00:59 kai Exp $
* Linux ISDN subsystem, common used functions (linklevel).
*
@@ -48,7 +48,7 @@
isdn_dev *dev;
-static char *isdn_revision = "$Revision: 1.113 $";
+static char *isdn_revision = "$Revision: 1.114 $";
extern char *isdn_net_revision;
extern char *isdn_tty_revision;
diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h
index b23506ebb..3ee692824 100644
--- a/drivers/isdn/isdn_common.h
+++ b/drivers/isdn/isdn_common.h
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.h,v 1.20 2000/06/16 13:00:27 keil Exp $
+/* $Id: isdn_common.h,v 1.21 2000/11/25 17:00:59 kai Exp $
* header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
*
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index 5ad0edc6a..3bebcdfcf 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.84 2000/11/13 22:51:46 kai Exp $
+/* $Id: isdn_ppp.c,v 1.85 2000/11/25 17:00:59 kai Exp $
*
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
@@ -83,7 +83,7 @@ static void isdn_ppp_mp_cleanup( isdn_net_local * lp );
static int isdn_ppp_bundle(struct ippp_struct *, int unit);
#endif /* CONFIG_ISDN_MPP */
-char *isdn_ppp_revision = "$Revision: 1.84 $";
+char *isdn_ppp_revision = "$Revision: 1.85 $";
static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
diff --git a/drivers/isdn/isdn_tty.c b/drivers/isdn/isdn_tty.c
index 25e1139b9..ccf9ecf35 100644
--- a/drivers/isdn/isdn_tty.c
+++ b/drivers/isdn/isdn_tty.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.93 2000/08/05 09:58:26 armin Exp $
+/* $Id: isdn_tty.c,v 1.94 2000/11/25 17:00:59 kai Exp $
* Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
*
@@ -66,7 +66,7 @@ static int bit2si[8] =
static int si2bit[8] =
{4, 1, 4, 4, 4, 4, 4, 4};
-char *isdn_tty_revision = "$Revision: 1.93 $";
+char *isdn_tty_revision = "$Revision: 1.94 $";
/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 125742e6a..4f421e75c 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -135,7 +135,7 @@ int pcbit_init_dev(int board, int mem_base, int irq)
dev->b2->id = 1;
- dev->qdelivery.next = NULL;
+ INIT_LIST_HEAD(&dev->qdelivery.list);
dev->qdelivery.sync = 0;
dev->qdelivery.routine = pcbit_deliver;
dev->qdelivery.data = dev;
diff --git a/drivers/macintosh/mac_keyb.c b/drivers/macintosh/mac_keyb.c
index 662f4a7f5..80616affa 100644
--- a/drivers/macintosh/mac_keyb.c
+++ b/drivers/macintosh/mac_keyb.c
@@ -255,8 +255,6 @@ int adb_button2_keycode = 0x7d; /* right control key */
int adb_button3_keycode = 0x7c; /* right option key */
#endif
-extern int console_loglevel;
-
extern struct kbd_struct kbd_table[];
extern wait_queue_head_t keypress_wait;
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index f4670f1db..c6e84f66f 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -125,7 +125,6 @@ static int last_status;
static int driver_running = 0;
/* debug level 10 required for ADB logging (should be && debug_adb, ideally) */
-extern int console_loglevel;
/* Check for MacII style ADB */
static int macii_probe(void)
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 69d65c2bd..c37ce84db 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -16,18 +16,26 @@ obj-m :=
obj-n :=
obj- :=
-obj-$(CONFIG_BLK_DEV_MD) += md.o
+# Note: link order is important. All raid personalities
+# and xor.o must come before md.o, as they each initialise
+# themselves, and md.o may use the personalities when it
+# auto-initialised.
+# The use of MIX_OBJS allows link order to be maintained even
+# though some are export-objs and some aren't.
+
obj-$(CONFIG_MD_LINEAR) += linear.o
obj-$(CONFIG_MD_RAID0) += raid0.o
obj-$(CONFIG_MD_RAID1) += raid1.o
obj-$(CONFIG_MD_RAID5) += raid5.o xor.o
+obj-$(CONFIG_BLK_DEV_MD) += md.o
obj-$(CONFIG_BLK_DEV_LVM) += lvm-mod.o
# Translate to Rules.make lists.
-O_OBJS := $(filter-out $(export-objs), $(obj-y))
-OX_OBJS := $(filter $(export-objs), $(obj-y))
-M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
+active-objs := $(sort $(obj-y) $(obj-m))
+
+O_OBJS := $(obj-y)
+M_OBJS := $(obj-m)
+MIX_OBJS := $(filter $(export-objs), $(active-objs))
include $(TOPDIR)/Rules.make
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 855bc44dd..e6b50b84d 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -84,21 +84,19 @@ static int linear_run (mddev_t *mddev)
dev_info_t *disk = conf->disks + j;
if (size < 0) {
- table->dev1 = disk;
- table++;
+ table[-1].dev1 = disk;
}
size += disk->size;
- while (size) {
+ while (size>0) {
table->dev0 = disk;
- size -= conf->smallest->size;
- if (size < 0)
- break;
table->dev1 = NULL;
+ size -= conf->smallest->size;
table++;
}
}
- table->dev1 = NULL;
+ if (table-conf->hash_table != nb_zone)
+ BUG();
return 0;
@@ -136,7 +134,8 @@ static int linear_make_request (mddev_t *mddev,
if (!hash->dev1) {
printk ("linear_make_request : hash->dev1==NULL for block %ld\n",
block);
- return -1;
+ buffer_IO_error(bh);
+ return 0;
}
tmp_dev = hash->dev1;
} else
@@ -145,7 +144,8 @@ static int linear_make_request (mddev_t *mddev,
if (block >= (tmp_dev->size + tmp_dev->offset)
|| block < tmp_dev->offset) {
printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
- return -1;
+ buffer_IO_error(bh);
+ return 0;
}
bh->b_rdev = tmp_dev->dev;
bh->b_rsector = bh->b_rsector - (tmp_dev->offset << 1);
@@ -190,24 +190,16 @@ static mdk_personality_t linear_personality=
status: linear_status,
};
-#ifndef MODULE
-
-void md__init linear_init (void)
+static int md__init linear_init (void)
{
- register_md_personality (LINEAR, &linear_personality);
+ return register_md_personality (LINEAR, &linear_personality);
}
-#else
-
-int init_module (void)
-{
- return (register_md_personality (LINEAR, &linear_personality));
-}
-
-void cleanup_module (void)
+static void linear_exit (void)
{
unregister_md_personality (LINEAR);
}
-#endif
+module_init(linear_init);
+module_exit(linear_exit);
diff --git a/drivers/md/lvm.c b/drivers/md/lvm.c
index 5aa88df9e..f9433232e 100644
--- a/drivers/md/lvm.c
+++ b/drivers/md/lvm.c
@@ -123,6 +123,7 @@
* - avoided inline strings functions lvm_strlen etc.
* 14/02/2000 - support for 2.3.43
* - integrated Andrea Arcangeli's snapshot code
+ * 07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown
*
*/
@@ -1488,8 +1489,10 @@ static void lvm_dummy_device_request(request_queue_t * t)
*/
static int lvm_make_request_fn(request_queue_t *q, int rw, struct buffer_head *bh)
{
- lvm_map(bh, rw);
- return 1;
+ if (lvm_map(bh, rw)<0)
+ return 0; /* failure, buffer_IO_error has been called, don't recurse */
+ else
+ return 1; /* all ok, mapping done, call lower level driver */
}
/*
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 091551597..8542bc2b0 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -179,7 +179,7 @@ static int md_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
return mddev->pers->make_request(mddev, rw, bh);
else {
buffer_IO_error(bh);
- return -1;
+ return 0;
}
}
@@ -203,6 +203,7 @@ static mddev_t * alloc_mddev (kdev_t dev)
init_MUTEX(&mddev->resync_sem);
MD_INIT_LIST_HEAD(&mddev->disks);
MD_INIT_LIST_HEAD(&mddev->all_mddevs);
+ atomic_set(&mddev->active, 0);
/*
* The 'base' mddev is the one with data NULL.
@@ -656,32 +657,25 @@ static void unbind_rdev_from_array (mdk_rdev_t * rdev)
static int lock_rdev (mdk_rdev_t *rdev)
{
int err = 0;
+ struct block_device *bdev;
- /*
- * First insert a dummy inode.
- */
- if (rdev->inode)
- MD_BUG();
- rdev->inode = get_empty_inode();
- if (!rdev->inode)
+ bdev = bdget(rdev->dev);
+ if (bdev == NULL)
return -ENOMEM;
- /*
- * we dont care about any other fields
- */
- rdev->inode->i_dev = rdev->inode->i_rdev = rdev->dev;
- insert_inode_hash(rdev->inode);
-
- memset(&rdev->filp, 0, sizeof(rdev->filp));
- rdev->filp.f_mode = 3; /* read write */
+ err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FILE);
+ if (!err) {
+ rdev->bdev = bdev;
+ }
return err;
}
static void unlock_rdev (mdk_rdev_t *rdev)
{
- if (!rdev->inode)
+ if (!rdev->bdev)
MD_BUG();
- iput(rdev->inode);
- rdev->inode = NULL;
+ blkdev_put(rdev->bdev, BDEV_FILE);
+ bdput(rdev->bdev);
+ rdev->bdev = NULL;
}
static void export_rdev (mdk_rdev_t * rdev)
@@ -1149,7 +1143,7 @@ static int md_import_device (kdev_t newdev, int on_disk)
abort_free:
if (rdev->sb) {
- if (rdev->inode)
+ if (rdev->bdev)
unlock_rdev(rdev);
free_disk_sb(rdev);
}
@@ -1718,12 +1712,20 @@ out:
#define STILL_MOUNTED KERN_WARNING \
"md: md%d still mounted.\n"
+#define STILL_IN_USE \
+"md: md%d still in use.\n"
static int do_md_stop (mddev_t * mddev, int ro)
{
int err = 0, resync_interrupted = 0;
kdev_t dev = mddev_to_kdev(mddev);
+ if (atomic_read(&mddev->active)>1) {
+ printk(STILL_IN_USE, mdidx(mddev));
+ OUT(-EBUSY);
+ }
+
+ /* this shouldn't be needed as above would have fired */
if (!ro && get_super(dev)) {
printk (STILL_MOUNTED, mdidx(mddev));
OUT(-EBUSY);
@@ -1859,8 +1861,10 @@ static void autorun_array (mddev_t *mddev)
* the 'same_array' list. Then order this list based on superblock
* update time (freshest comes first), kick out 'old' disks and
* compare superblocks. If everything's fine then run it.
+ *
+ * If "unit" is allocated, then bump its reference count
*/
-static void autorun_devices (void)
+static void autorun_devices (kdev_t countdev)
{
struct md_list_head candidates;
struct md_list_head *tmp;
@@ -1902,6 +1906,12 @@ static void autorun_devices (void)
continue;
}
mddev = alloc_mddev(md_kdev);
+ if (mddev == NULL) {
+ printk("md: cannot allocate memory for md drive.\n");
+ break;
+ }
+ if (md_kdev == countdev)
+ atomic_inc(&mddev->active);
printk("created md%d\n", mdidx(mddev));
ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) {
bind_rdev_to_array(rdev, mddev);
@@ -1945,7 +1955,7 @@ static void autorun_devices (void)
#define AUTORUNNING KERN_INFO \
"md: auto-running md%d.\n"
-static int autostart_array (kdev_t startdev)
+static int autostart_array (kdev_t startdev, kdev_t countdev)
{
int err = -EINVAL, i;
mdp_super_t *sb = NULL;
@@ -2002,7 +2012,7 @@ static int autostart_array (kdev_t startdev)
/*
* possibly return codes
*/
- autorun_devices();
+ autorun_devices(countdev);
return 0;
abort:
@@ -2077,7 +2087,7 @@ int md__init md_run_setup(void)
md_list_add(&rdev->pending, &pending_raid_disks);
}
- autorun_devices();
+ autorun_devices(-1);
}
dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */
@@ -2607,6 +2617,8 @@ static int md_ioctl (struct inode *inode, struct file *file,
err = -ENOMEM;
goto abort;
}
+ atomic_inc(&mddev->active);
+
/*
* alloc_mddev() should possibly self-lock.
*/
@@ -2640,7 +2652,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
/*
* possibly make it lock the array ...
*/
- err = autostart_array((kdev_t)arg);
+ err = autostart_array((kdev_t)arg, dev);
if (err) {
printk("autostart %s failed!\n",
partition_name((kdev_t)arg));
@@ -2820,14 +2832,26 @@ abort:
static int md_open (struct inode *inode, struct file *file)
{
/*
- * Always succeed
+ * Always succeed, but increment the usage count
*/
+ mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
+ if (mddev)
+ atomic_inc(&mddev->active);
return (0);
}
+static int md_release (struct inode *inode, struct file * file)
+{
+ mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
+ if (mddev)
+ atomic_dec(&mddev->active);
+ return 0;
+}
+
static struct block_device_operations md_fops=
{
open: md_open,
+ release: md_release,
ioctl: md_ioctl,
};
@@ -3279,7 +3303,7 @@ recheck:
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) {
- printk(KERN_INFO "md: serializing resync, md%d has overlapping physical units with md%d!\n", mdidx(mddev), mdidx(mddev2));
+ printk(KERN_INFO "md: serializing resync, md%d shares one or more physical units with md%d!\n", mdidx(mddev), mdidx(mddev2));
serialize = 1;
break;
}
@@ -3576,20 +3600,14 @@ static void md_geninit (void)
create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
#endif
}
-void hsm_init (void);
-void translucent_init (void);
-void linear_init (void);
-void raid0_init (void);
-void raid1_init (void);
-void raid5_init (void);
int md__init md_init (void)
{
static char * name = "mdrecoveryd";
- printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MAX_REAL=%d\n",
+ printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n",
MD_MAJOR_VERSION, MD_MINOR_VERSION,
- MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MAX_REAL);
+ MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops))
{
@@ -3617,18 +3635,6 @@ int md__init md_init (void)
md_register_reboot_notifier(&md_notifier);
raid_table_header = register_sysctl_table(raid_root_table, 1);
-#ifdef CONFIG_MD_LINEAR
- linear_init ();
-#endif
-#ifdef CONFIG_MD_RAID0
- raid0_init ();
-#endif
-#ifdef CONFIG_MD_RAID1
- raid1_init ();
-#endif
-#ifdef CONFIG_MD_RAID5
- raid5_init ();
-#endif
md_geninit();
return (0);
}
@@ -3639,7 +3645,7 @@ struct {
unsigned long set;
int pers[MAX_MD_BOOT_DEVS];
int chunk[MAX_MD_BOOT_DEVS];
- kdev_t devices[MAX_MD_BOOT_DEVS][MAX_REAL];
+ kdev_t devices[MAX_MD_BOOT_DEVS][MD_SB_DISKS];
} md_setup_args md__initdata = { 0, };
/*
@@ -3713,7 +3719,7 @@ static int md__init md_setup(char *str)
pername="super-block";
}
devnames = str;
- for (; i<MAX_REAL && str; i++) {
+ for (; i<MD_SB_DISKS && str; i++) {
if ((device = name_to_kdev_t(str))) {
md_setup_args.devices[minor][i] = device;
} else {
@@ -3853,7 +3859,7 @@ void cleanup_module (void)
#endif
__initcall(md_init);
-#ifdef CONFIG_AUTODETECT_RAID
+#if defined(CONFIG_AUTODETECT_RAID) || defined(CONFIG_MD_BOOT)
__initcall(md_run_setup);
#endif
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 09f3f8547..576dd3b43 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -275,16 +275,18 @@ static int raid0_make_request (mddev_t *mddev,
bad_map:
printk ("raid0_make_request bug: can't convert block across chunks or bigger than %dk %ld %d\n", chunk_size, bh->b_rsector, bh->b_size >> 10);
- return -1;
+ goto outerr;
bad_hash:
printk("raid0_make_request bug: hash==NULL for block %ld\n", block);
- return -1;
+ goto outerr;
bad_zone0:
printk ("raid0_make_request bug: hash->zone0==NULL for block %ld\n", block);
- return -1;
+ goto outerr;
bad_zone1:
printk ("raid0_make_request bug: hash->zone1==NULL for block %ld\n", block);
- return -1;
+ outerr:
+ buffer_IO_error(bh);
+ return 0;
}
static int raid0_status (char *page, mddev_t *mddev)
@@ -333,24 +335,17 @@ static mdk_personality_t raid0_personality=
status: raid0_status,
};
-#ifndef MODULE
-
-void raid0_init (void)
-{
- register_md_personality (RAID0, &raid0_personality);
-}
-
-#else
-
-int init_module (void)
+static int md__init raid0_init (void)
{
- return (register_md_personality (RAID0, &raid0_personality));
+ return register_md_personality (RAID0, &raid0_personality);
}
-void cleanup_module (void)
+static void raid0_exit (void)
{
unregister_md_personality (RAID0);
}
-#endif
+module_init(raid0_init);
+module_exit(raid0_exit);
+
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 85073b564..3a381b6a2 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -463,16 +463,12 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
if (conf->resync_mirrors)
goto rb_out;
- if (conf->working_disks < 2) {
- int i = 0;
-
- while( !conf->mirrors[new_disk].operational &&
- (i < MD_SB_DISKS) ) {
- new_disk = conf->mirrors[new_disk].next;
- i++;
- }
-
- if (i >= MD_SB_DISKS) {
+
+ /* make sure that disk is operational */
+ while( !conf->mirrors[new_disk].operational) {
+ if (new_disk <= 0) new_disk = conf->raid_disks;
+ new_disk--;
+ if (new_disk == disk) {
/*
* This means no working disk was found
* Nothing much to do, lets not change anything
@@ -480,11 +476,13 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
*/
new_disk = conf->last_used;
+
+ goto rb_out;
}
-
- goto rb_out;
}
-
+ disk = new_disk;
+ /* now disk == new_disk == starting point for search */
+
/*
* Don't touch anything for sequential reads.
*/
@@ -501,16 +499,16 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
if (conf->sect_count >= conf->mirrors[new_disk].sect_limit) {
conf->sect_count = 0;
-
- while( new_disk != conf->mirrors[new_disk].next ) {
- if ((conf->mirrors[new_disk].write_only) ||
- (!conf->mirrors[new_disk].operational) )
- continue;
-
- new_disk = conf->mirrors[new_disk].next;
- break;
- }
-
+
+ do {
+ if (new_disk<=0)
+ new_disk = conf->raid_disks;
+ new_disk--;
+ if (new_disk == disk)
+ break;
+ } while ((conf->mirrors[new_disk].write_only) ||
+ (!conf->mirrors[new_disk].operational));
+
goto rb_out;
}
@@ -519,8 +517,10 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
/* Find the disk which is closest */
- while( conf->mirrors[disk].next != conf->last_used ) {
- disk = conf->mirrors[disk].next;
+ do {
+ if (disk <= 0)
+ disk = conf->raid_disks;
+ disk--;
if ((conf->mirrors[disk].write_only) ||
(!conf->mirrors[disk].operational))
@@ -534,7 +534,7 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
current_distance = new_distance;
new_disk = disk;
}
- }
+ } while (disk != conf->last_used);
rb_out:
conf->mirrors[new_disk].head_position = this_sector + sectors;
@@ -702,16 +702,6 @@ static int raid1_status (char *page, mddev_t *mddev)
return sz;
}
-static void unlink_disk (raid1_conf_t *conf, int target)
-{
- int disks = MD_SB_DISKS;
- int i;
-
- for (i = 0; i < disks; i++)
- if (conf->mirrors[i].next == target)
- conf->mirrors[i].next = conf->mirrors[target].next;
-}
-
#define LAST_DISK KERN_ALERT \
"raid1: only one disk left and IO error.\n"
@@ -735,7 +725,6 @@ static void mark_disk_bad (mddev_t *mddev, int failed)
mdp_super_t *sb = mddev->sb;
mirror->operational = 0;
- unlink_disk(conf, failed);
mark_disk_faulty(sb->disks+mirror->number);
mark_disk_nonsync(sb->disks+mirror->number);
mark_disk_inactive(sb->disks+mirror->number);
@@ -786,25 +775,6 @@ static int raid1_error (mddev_t *mddev, kdev_t dev)
#undef DISK_FAILED
#undef START_SYNCING
-/*
- * Insert the spare disk into the drive-ring
- */
-static void link_disk(raid1_conf_t *conf, struct mirror_info *mirror)
-{
- int j, next;
- int disks = MD_SB_DISKS;
- struct mirror_info *p = conf->mirrors;
-
- for (j = 0; j < disks; j++, p++)
- if (p->operational && !p->write_only) {
- next = p->next;
- p->next = mirror->raid_disk;
- mirror->next = next;
- return;
- }
-
- printk("raid1: bug: no read-operational devices\n");
-}
static void print_raid1_conf (raid1_conf_t *conf)
{
@@ -828,6 +798,32 @@ static void print_raid1_conf (raid1_conf_t *conf)
}
}
+static void close_sync(raid1_conf_t *conf)
+{
+ mddev_t *mddev = conf->mddev;
+ /* If reconstruction was interrupted, we need to close the "active" and "pending"
+ * holes.
+ * we know that there are no active rebuild requests, os cnt_active == cnt_ready ==0
+ */
+ /* this is really needed when recovery stops too... */
+ spin_lock_irq(&conf->segment_lock);
+ conf->start_active = conf->start_pending;
+ conf->start_ready = conf->start_pending;
+ wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
+ conf->start_active =conf->start_ready = conf->start_pending = conf->start_future;
+ conf->start_future = mddev->sb->size+1;
+ conf->cnt_pending = conf->cnt_future;
+ conf->cnt_future = 0;
+ conf->phase = conf->phase ^1;
+ wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
+ conf->start_active = conf->start_ready = conf->start_pending = conf->start_future = 0;
+ conf->phase = 0;
+ conf->cnt_future = conf->cnt_done;;
+ conf->cnt_done = 0;
+ spin_unlock_irq(&conf->segment_lock);
+ wake_up(&conf->wait_done);
+}
+
static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
{
int err = 0;
@@ -940,6 +936,7 @@ static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
* Deactivate a spare disk:
*/
case DISKOP_SPARE_INACTIVE:
+ close_sync(conf);
sdisk = conf->mirrors + spare_disk;
sdisk->operational = 0;
sdisk->write_only = 0;
@@ -952,7 +949,7 @@ static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
* property)
*/
case DISKOP_SPARE_ACTIVE:
-
+ close_sync(conf);
sdisk = conf->mirrors + spare_disk;
fdisk = conf->mirrors + failed_disk;
@@ -1017,7 +1014,6 @@ static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
*/
fdisk->spare = 0;
fdisk->write_only = 0;
- link_disk(conf, fdisk);
/*
* if we activate a spare, we definitely replace a
@@ -1244,27 +1240,7 @@ static void raid1syncd (void *data)
conf->resync_mirrors = 0;
}
- /* If reconstruction was interrupted, we need to close the "active" and "pending"
- * holes.
- * we know that there are no active rebuild requests, os cnt_active == cnt_ready ==0
- */
- /* this is really needed when recovery stops too... */
- spin_lock_irq(&conf->segment_lock);
- conf->start_active = conf->start_pending;
- conf->start_ready = conf->start_pending;
- wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
- conf->start_active =conf->start_ready = conf->start_pending = conf->start_future;
- conf->start_future = mddev->sb->size+1;
- conf->cnt_pending = conf->cnt_future;
- conf->cnt_future = 0;
- conf->phase = conf->phase ^1;
- wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
- conf->start_active = conf->start_ready = conf->start_pending = conf->start_future = 0;
- conf->phase = 0;
- conf->cnt_future = conf->cnt_done;;
- conf->cnt_done = 0;
- spin_unlock_irq(&conf->segment_lock);
- wake_up(&conf->wait_done);
+ close_sync(conf);
up(&mddev->recovery_sem);
raid1_shrink_buffers(conf);
@@ -1325,6 +1301,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
struct raid1_bh *r1_bh;
struct buffer_head *bh;
int bsize;
+ int disk;
spin_lock_irq(&conf->segment_lock);
if (!block_nr) {
@@ -1377,6 +1354,16 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
* could dedicate one to rebuild and others to
* service read requests ..
*/
+ disk = conf->last_used;
+ /* make sure disk is operational */
+ while (!conf->mirrors[disk].operational) {
+ if (disk <= 0) disk = conf->raid_disks;
+ disk--;
+ if (disk == conf->last_used)
+ break;
+ }
+ conf->last_used = disk;
+
mirror = conf->mirrors+conf->last_used;
r1_bh = raid1_alloc_buf (conf);
@@ -1396,7 +1383,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
bh->b_list = BUF_LOCKED;
bh->b_dev = mirror->dev;
bh->b_rdev = mirror->dev;
- bh->b_state = (1<<BH_Req) | (1<<BH_Mapped);
+ bh->b_state = (1<<BH_Req) | (1<<BH_Mapped) | (1<<BH_Lock);
if (!bh->b_page)
BUG();
if (!bh->b_data)
@@ -1717,19 +1704,10 @@ static int raid1_run (mddev_t *mddev)
* find the first working one and use it as a starting point
* to read balancing.
*/
- for (j = 0; !conf->mirrors[j].operational; j++)
+ for (j = 0; !conf->mirrors[j].operational && j < MD_SB_DISKS; j++)
/* nothing */;
conf->last_used = j;
- /*
- * initialize the 'working disks' list.
- */
- for (i = conf->raid_disks - 1; i >= 0; i--) {
- if (conf->mirrors[i].operational) {
- conf->mirrors[i].next = j;
- j = i;
- }
- }
if (conf->working_disks != sb->raid_disks) {
printk(KERN_ALERT "raid1: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev));
@@ -1882,19 +1860,16 @@ static mdk_personality_t raid1_personality=
sync_request: raid1_sync_request
};
-int raid1_init (void)
+static int md__init raid1_init (void)
{
return register_md_personality (RAID1, &raid1_personality);
}
-#ifdef MODULE
-int init_module (void)
-{
- return raid1_init();
-}
-
-void cleanup_module (void)
+static void raid1_exit (void)
{
unregister_md_personality (RAID1);
}
-#endif
+
+module_init(raid1_init);
+module_exit(raid1_exit);
+
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 4103b0ea5..55c50c5e7 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1516,8 +1516,8 @@ static int raid5_sync_request (mddev_t *mddev, unsigned long block_nr)
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
struct stripe_head *sh;
int sectors_per_chunk = conf->chunk_size >> 9;
- unsigned long stripe = (block_nr<<2)/sectors_per_chunk;
- int chunk_offset = (block_nr<<2) % sectors_per_chunk;
+ unsigned long stripe = (block_nr<<1)/sectors_per_chunk;
+ int chunk_offset = (block_nr<<1) % sectors_per_chunk;
int dd_idx, pd_idx;
unsigned long first_sector;
int raid_disks = conf->raid_disks;
@@ -2352,19 +2352,16 @@ static mdk_personality_t raid5_personality=
sync_request: raid5_sync_request
};
-int raid5_init (void)
+static int md__init raid5_init (void)
{
return register_md_personality (RAID5, &raid5_personality);
}
-#ifdef MODULE
-int init_module (void)
-{
- return raid5_init();
-}
-
-void cleanup_module (void)
+static void raid5_exit (void)
{
unregister_md_personality (RAID5);
}
-#endif
+
+module_init(raid5_init);
+module_exit(raid5_exit);
+
diff --git a/drivers/md/xor.c b/drivers/md/xor.c
index f58463ebc..b9b1cefe9 100644
--- a/drivers/md/xor.c
+++ b/drivers/md/xor.c
@@ -16,7 +16,6 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#define BH_TRACE 0
#include <linux/module.h>
#include <linux/raid/md.h>
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index b01c1562f..64bfad320 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -338,7 +338,7 @@ static int __init rtrack_init(void)
return -EINVAL;
}
- if (check_region(io, 2))
+ if (request_region(io, 2, "rtrack"))
{
printk(KERN_ERR "rtrack: port 0x%x already in use\n", io);
return -EBUSY;
@@ -347,9 +347,10 @@ static int __init rtrack_init(void)
rtrack_radio.priv=&rtrack_unit;
if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO)==-1)
+ {
+ release_region(io, 2);
return -EINVAL;
-
- request_region(io, 2, "rtrack");
+ }
printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n");
/* Set up the I/O locking */
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 06999d806..971b62fe1 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -289,7 +289,7 @@ static int __init aztech_init(void)
return -EINVAL;
}
- if (check_region(io, 2))
+ if (request_region(io, 2, "aztech"))
{
printk(KERN_ERR "aztech: port 0x%x already in use\n", io);
return -EBUSY;
@@ -299,9 +299,11 @@ static int __init aztech_init(void)
aztech_radio.priv=&aztech_unit;
if(video_register_device(&aztech_radio, VFL_TYPE_RADIO)==-1)
+ {
+ release_region(io,2);
return -EINVAL;
+ }
- request_region(io, 2, "aztech");
printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
/* mute card - prevents noisy bootups */
outb (0, io);
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 15ec8515a..8ffe83a88 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -27,6 +27,7 @@
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/config.h> /* CONFIG_RADIO_CADET_PORT */
#include <linux/param.h>
+#include <linux/isapnp.h>
#ifndef CONFIG_RADIO_CADET_PORT
#define CONFIG_RADIO_CADET_PORT 0x330
@@ -44,16 +45,9 @@ static __u8 rdsin=0,rdsout=0,rdsstat=0;
static unsigned char rdsbuf[RDS_BUFFER];
static int cadet_lock=0;
-#ifndef MODULE
static int cadet_probe(void);
-#endif
-
-#ifdef CONFIG_ISAPNP
-#include <linux/isapnp.h>
-
-struct pci_dev *dev;
+static struct pci_dev *dev;
static int isapnp_cadet_probe(void);
-#endif
/*
* Signal Strength Threshold Values
@@ -551,7 +545,6 @@ static struct video_device cadet_radio=
ioctl: cadet_ioctl,
};
-#ifdef CONFIG_ISAPNP
static int isapnp_cadet_probe(void)
{
dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'),
@@ -574,9 +567,7 @@ static int isapnp_cadet_probe(void)
return io;
}
-#endif /* CONFIG_ISAPNP */
-#ifdef MODULE
static int cadet_probe(void)
{
static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
@@ -584,30 +575,35 @@ static int cadet_probe(void)
for(i=0;i<8;i++) {
io=iovals[i];
- if(check_region(io,2)>=0) {
+ if(request_region(io,2, "cadet-probe")>=0) {
cadet_setfreq(1410);
if(cadet_getfreq()==1410) {
+ release_region(io, 2);
return io;
}
+ release_region(io, 2);
}
}
return -1;
}
-#endif /* MODULE */
static int __init cadet_init(void)
{
-#ifdef CONFIG_ISAPNP
- io = isapnp_cadet_probe();
-
+ /*
+ * If a probe was requested then probe ISAPnP first (safest)
+ */
if (io < 0)
- return (io);
-#else
-#ifndef MODULE /* only probe on non-ISAPnP monolithic compiles */
- io = cadet_probe ();
-#endif /* MODULE */
-#endif /* CONFIG_ISAPNP */
+ io = isapnp_cadet_probe();
+ /*
+ * If that fails then probe unsafely if probe is requested
+ */
+ if(io < 0)
+ io = cadet_probe ();
+ /*
+ * Else we bail out
+ */
+
if(io < 0) {
#ifdef MODULE
printk(KERN_ERR "You must set an I/O address with io=0x???\n");
@@ -638,10 +634,8 @@ static void __exit cadet_cleanup_module(void)
video_unregister_device(&cadet_radio);
release_region(io,2);
-#ifdef CONFIG_ISAPNP
if (dev)
dev->deactivate(dev);
-#endif
}
module_init(cadet_init);
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 4bac8dcfe..32351f653 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -265,7 +265,7 @@ static int __init gemtek_init(void)
return -EINVAL;
}
- if (check_region(io, 4))
+ if (request_region(io, 4, "gemtek"))
{
printk(KERN_ERR "gemtek: port 0x%x already in use\n", io);
return -EBUSY;
@@ -274,9 +274,10 @@ static int __init gemtek_init(void)
gemtek_radio.priv=&gemtek_unit;
if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO)==-1)
+ {
+ release_region(io, 4);
return -EINVAL;
-
- request_region(io, 4, "gemtek");
+ }
printk(KERN_INFO "GemTek Radio Card driver.\n");
spin_lock_init(&lock);
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index ad479af32..d34315b2b 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -230,7 +230,7 @@ static int __init rtrack2_init(void)
printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
return -EINVAL;
}
- if (check_region(io, 4))
+ if (request_region(io, 4, "rtrack2"))
{
printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
return -EBUSY;
@@ -240,9 +240,11 @@ static int __init rtrack2_init(void)
spin_lock_init(&lock);
if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1)
+ {
+ release_region(io, 4);
return -EINVAL;
+ }
- request_region(io, 4, "rtrack2");
printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n");
/* mute card - prevents noisy bootups */
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 13a155316..e2fa902ff 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -291,7 +291,7 @@ static int __init fmi_init(void)
printk(KERN_ERR "You must set an I/O address with io=0x???\n");
return -EINVAL;
}
- if (check_region(io, 2))
+ if (request_region(io, 2, "fmi"))
{
printk(KERN_ERR "fmi: port 0x%x already in use\n", io);
return -EBUSY;
@@ -306,9 +306,11 @@ static int __init fmi_init(void)
init_MUTEX(&lock);
if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1)
+ {
+ release_region(io, 2);
return -EINVAL;
+ }
- request_region(io, 2, "fmi");
printk(KERN_INFO "SF16FMx radio card driver at 0x%x.\n", io);
printk(KERN_INFO "(c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz.\n");
/* mute card - prevents noisy bootups */
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 28094e3cd..6f2ff8ee6 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -309,7 +309,7 @@ static int __init terratec_init(void)
printk(KERN_ERR "You must set an I/O address with io=0x???\n");
return -EINVAL;
}
- if (check_region(io, 2))
+ if (request_region(io, 2, "terratec"))
{
printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io);
return -EBUSY;
@@ -320,9 +320,11 @@ static int __init terratec_init(void)
spin_lock_init(&lock);
if(video_register_device(&terratec_radio, VFL_TYPE_RADIO)==-1)
+ {
+ release_region(io,2);
return -EINVAL;
+ }
- request_region(io, 2, "terratec");
printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n");
/* mute card - prevents noisy bootups */
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index 2fb6ed26d..cf4aa8b00 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -300,14 +300,15 @@ static int __init trust_init(void)
printk(KERN_ERR "You must set an I/O address with io=0x???\n");
return -EINVAL;
}
- if(check_region(io, 2)) {
+ if(request_region(io, 2, "Trust FM Radio")) {
printk(KERN_ERR "trust: port 0x%x already in use\n", io);
return -EBUSY;
}
if(video_register_device(&trust_radio, VFL_TYPE_RADIO)==-1)
+ {
+ release_region(io, 2);
return -EINVAL;
-
- request_region(io, 2, "Trust FM Radio");
+ }
printk(KERN_INFO "Trust FM Radio card driver v1.0.\n");
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index c550fd45c..d02d7f1be 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -350,7 +350,7 @@ static int __init typhoon_init(void)
printk(KERN_INFO BANNER);
io = typhoon_unit.iobase;
- if (check_region(io, 8)) {
+ if (request_region(io, 8, "typhoon")) {
printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
typhoon_unit.iobase);
return -EBUSY;
@@ -358,9 +358,10 @@ static int __init typhoon_init(void)
typhoon_radio.priv = &typhoon_unit;
if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1)
+ {
+ release_region(io, 8);
return -EINVAL;
-
- request_region(typhoon_unit.iobase, 8, "typhoon");
+ }
printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
typhoon_unit.mutefreq);
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 940447bb9..e9adaef7a 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -355,20 +355,22 @@ static int __init zoltrix_init(void)
printk(KERN_ERR "You must set an I/O address with io=0x???\n");
return -EINVAL;
}
- if (check_region(io, 2)) {
- printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
- return -EBUSY;
- }
if ((io != 0x20c) && (io != 0x30c)) {
printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n");
return -ENXIO;
}
+
zoltrix_radio.priv = &zoltrix_unit;
+ if (request_region(io, 2, "zoltrix")) {
+ printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
+ return -EBUSY;
+ }
if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO) == -1)
+ {
+ release_region(io, 2);
return -EINVAL;
-
- request_region(io, 2, "zoltrix");
+ }
printk(KERN_INFO "Zoltrix Radio Plus card driver.\n");
init_MUTEX(&zoltrix_unit.lock);
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 11c6474c7..886782f18 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -1319,6 +1319,24 @@ terratv_audio(struct bttv *btv, struct video_audio *v, int set)
}
}
+#ifndef MODULE
+
+static int __init bttv_card_setup(char *str)
+{
+ int i,number,res = 2;
+
+ for (i = 0; res == 2 && i < BTTV_MAX; i++) {
+ res = get_option(&str,&number);
+ if (res)
+ card[i] = number;
+ }
+ return 1;
+}
+
+__setup("bttv_card=", bttv_card_setup);
+
+#endif /* not MODULE */
+
/*
* Local variables:
* c-basic-offset: 8
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 6bc9c554e..248bda8a0 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -3082,6 +3082,24 @@ void bttv_cleanup_module(void)
module_init(bttv_init_module);
module_exit(bttv_cleanup_module);
+#ifndef MODULE
+
+static int __init bttv_radio_setup(char *str)
+{
+ int i,number,res = 2;
+
+ for (i = 0; res == 2 && i < BTTV_MAX; i++) {
+ res = get_option(&str,&number);
+ if (res)
+ radio[i] = number;
+ }
+ return 1;
+}
+
+__setup("bttv_radio=", bttv_radio_setup);
+
+#endif /* not MODULE */
+
/*
* Local variables:
* c-basic-offset: 8
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 92d71ba59..602adb7d5 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -865,12 +865,9 @@ static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCGWIN:
{
struct video_window vw;
- vw.x=0;
- vw.y=0;
+ memset(&vw, 0, sizeof(vw));
vw.width=qcam->width/qcam->transfer_scale;
vw.height=qcam->height/qcam->transfer_scale;
- vw.chromakey=0;
- vw.flags=0;
if(copy_to_user(arg, &vw, sizeof(vw)))
return -EFAULT;
return 0;
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 2b0444582..642049de9 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -679,12 +679,9 @@ static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCGWIN:
{
struct video_window vw;
- vw.x=0;
- vw.y=0;
+ memset(&vw, 0, sizeof(vw));
vw.width=qcam->width;
vw.height=qcam->height;
- vw.chromakey=0;
- vw.flags=0;
if(copy_to_user(arg, &vw, sizeof(vw)))
return -EFAULT;
return 0;
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 385beb49c..b6ae3f62c 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -912,7 +912,7 @@ done:
msp->thread = NULL;
if(msp->notify != NULL)
- up(msp->notify);
+ up_and_exit(msp->notify, 0);
return 0;
}
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 5ed1a1097..5a9c4575c 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -14,6 +14,7 @@
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -291,7 +292,7 @@ static int chip_thread(void *data)
chip->thread = NULL;
dprintk("%s: thread exiting\n", chip->c.name);
if(chip->notify != NULL)
- up(chip->notify);
+ up_and_exit(chip->notify,0);
return 0;
}
diff --git a/drivers/media/video/zr36120.h b/drivers/media/video/zr36120.h
index e500de10d..571f8e84b 100644
--- a/drivers/media/video/zr36120.h
+++ b/drivers/media/video/zr36120.h
@@ -130,7 +130,7 @@ struct zoran
int tuner_type; /* tuner type, when found */
int running; /* are we rolling? */
rwlock_t lock;
- int state; /* what is requested of us? */
+ long state; /* what is requested of us? */
#define STATE_OVERLAY 0
#define STATE_VBI 1
struct vidinfo* workqueue; /* buffers to grab, head is active */
diff --git a/drivers/mtd/Config.in b/drivers/mtd/Config.in
index 9023f0a81..87bf2e9b6 100644
--- a/drivers/mtd/Config.in
+++ b/drivers/mtd/Config.in
@@ -1,15 +1,21 @@
-# $Id: Config.in,v 1.20 2000/07/13 12:40:46 scote1 Exp $
+# $Id: No. :) $
mainmenu_option next_comment
comment 'Memory Technology Devices (MTD)'
tristate 'Memory Technology Device (MTD) support' CONFIG_MTD
-if [ "$CONFIG_MTD" != "n" ]; then
- dep_tristate ' M-Systems Disk-On-Chip 1000 support' CONFIG_MTD_DOC1000 $CONFIG_MTD
- dep_tristate ' M-Systems Disk-On-Chip 2000' CONFIG_MTD_DOC2000 $CONFIG_MTD
- dep_tristate ' M-Systems Disk-On-Chip Millennium' CONFIG_MTD_DOC2001 $CONFIG_MTD
+if [ "$CONFIG_MTD" = "y" -o "$CONFIG_MTD" = "m" ]; then
+ bool 'Debugging' CONFIG_MTD_DEBUG
+ if [ "$CONFIG_MTD_DEBUG" = "y" ]; then
+ int ' Debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_MTD_DEBUG_VERBOSE 0
+ fi
+
+comment 'Disk-On-Chip Device Drivers'
+ dep_tristate ' M-Systems Disk-On-Chip 1000' CONFIG_MTD_DOC1000 $CONFIG_MTD
+ dep_tristate ' M-Systems Disk-On-Chip 2000 and Millennium' CONFIG_MTD_DOC2000 $CONFIG_MTD
+ dep_tristate ' M-Systems Disk-On-Chip Millennium-only alternative driver' CONFIG_MTD_DOC2001 $CONFIG_MTD
if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then
define_tristate CONFIG_MTD_DOCPROBE y
else
@@ -19,10 +25,18 @@ if [ "$CONFIG_MTD" != "n" ]; then
define_tristate CONFIG_MTD_DOCPROBE n
fi
fi
+ if [ "$CONFIG_MTD_DOCPROBE" = "y" -o "$CONFIG_MTD_DOCPROBE" = "m" ]; then
+ hex ' Physical address of DiskOnChip' CONFIG_MTD_DOCPROBE_ADDRESS 0x0000
+ bool ' Probe high addresses' CONFIG_MTD_DOCPROBE_HIGH
+ bool ' Probe for 0x55 0xAA BIOS Extension Signature' CONFIG_MTD_DOCPROBE_55AA
+ fi
+
+comment 'RAM/ROM Device Drivers'
dep_tristate ' Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD
dep_tristate ' Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI
if [ "$CONFIG_MTD_PMC551" != "n" ]; then
bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
+ bool ' PMC551 Debugging' CONFIG_MTD_PMC551_DEBUG
fi
dep_tristate ' Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD
if [ "$CONFIG_MTD_MTDRAM" != "n" ]; then
@@ -30,20 +44,21 @@ if [ "$CONFIG_MTD" != "n" ]; then
int 'Size of the erase sectors in kB' CONFIG_MTDRAM_ERASE_SIZE 128
fi
-comment 'MTD drivers for mapped chips'
+comment 'Linearly Mapped Flash Device Drivers'
dep_tristate ' Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD
dep_tristate ' CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI
dep_tristate ' CFI support for AMD/Fujitsu Standard Command Set chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_CFI
+ dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD
+ dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD
# These will later become config-options
define_bool CONFIG_MTD_JEDEC n
-define_bool CONFIG_MTD_RAM n
-define_bool CONFIG_MTD_ROM n
- dep_tristate ' Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI
- if [ "$CONFIG_MTD_PHYSMAP" != "n" ]; then
- hex 'Physical start location of flash chip mapping' CONFIG_MTD_PHYSMAP_START 0x8000000
- hex 'Physical length of flash chip mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
+ dep_tristate ' Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI
+ if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then
+ hex ' Physical start location of flash chip mapping' CONFIG_MTD_PHYSMAP_START 0x8000000
+ hex ' Physical length of flash chip mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000
+ int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2
fi
comment 'Drivers for chip mappings'
@@ -56,11 +71,11 @@ comment 'Drivers for chip mappings'
comment 'User modules and translation layers for MTD devices'
dep_tristate ' Direct chardevice access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD
- dep_tristate ' Pseudo-blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD
+ dep_tristate ' Caching blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD
dep_tristate ' FTL (Flash Translation Layer) support' CONFIG_FTL $CONFIG_MTD
dep_tristate ' NFTL (NAND Flash Translation Layer) support' CONFIG_NFTL $CONFIG_MTD
- if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NFTL" != "n" ]; then
- bool ' Write support for NFTL (EXPERIMENTAL)' CONFIG_NFTL_RW
+ if [ "$CONFIG_NFTL" = "y" -o "$CONFIG_NFTL" = "m" ]; then
+ bool ' Write support for NFTL (BETA)' CONFIG_NFTL_RW
fi
fi
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 3f28868e3..7fdbf65a4 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -44,7 +44,7 @@ SUB_DIRS :=
ALL_SUB_DIRS :=
MOD_SUB_DIRS :=
-export-objs := mtdcore.o
+export-objs := mtdcore.o mtdpart.o
list-multi :=
# MTD devices
@@ -52,7 +52,7 @@ obj-$(CONFIG_MTD) += mtdcore.o
obj-$(CONFIG_MTD_DOC1000) += doc1000.o
obj-$(CONFIG_MTD_DOC2000) += doc2000.o
obj-$(CONFIG_MTD_DOC2001) += doc2001.o
-obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o
+obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o docecc.o
obj-$(CONFIG_MTD_SLRAM) += slram.o
obj-$(CONFIG_MTD_PMC551) += pmc551.o
obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
@@ -70,7 +70,7 @@ obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
obj-$(CONFIG_MTD_MIXMEM) += mixmem.o
obj-$(CONFIG_MTD_NORA) += nora.o
obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
-obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
+obj-$(CONFIG_MTD_PNC2000) += pnc2000.o mtdpart.o
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
obj-$(CONFIG_MTD_VMAX) += vmax301.o
@@ -78,7 +78,7 @@ obj-$(CONFIG_MTD_VMAX) += vmax301.o
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
obj-$(CONFIG_MTD_BLOCK) += mtdblock.o
obj-$(CONFIG_FTL) += ftl.o
-obj-$(CONFIG_NFTL) += nftl.o
+obj-$(CONFIG_NFTL) += nftl.o nftlmount.o
# Extract lists of the multi-part drivers.
# The 'int-*' lists are the intermediate files used to build the multi's.
diff --git a/drivers/mtd/cfi_cmdset_0002.c b/drivers/mtd/cfi_cmdset_0002.c
index d6cce6474..6cb0de4e9 100644
--- a/drivers/mtd/cfi_cmdset_0002.c
+++ b/drivers/mtd/cfi_cmdset_0002.c
@@ -437,7 +437,7 @@ static int cfi_amdext_erase_2_by_16 (struct mtd_info *mtd, struct erase_info *in
adr = instr->addr - (chipnum << cfi->chipshift) * (cfi->interleave);
len = instr->len;
-printk("erase : 0x%lx 0x%lx 0x%x 0x%x\n", adr, len, chipnum, mtd->size);
+ printk("erase : 0x%lx 0x%lx 0x%x 0x%lx\n", adr, len, chipnum, mtd->size);
while(len) {
//printk("erase : 0x%x 0x%x 0x%x 0x%x\n", chipnum, adr, len, cfi->chipshift);
diff --git a/drivers/mtd/doc1000.c b/drivers/mtd/doc1000.c
index ce1b6fdd8..584745359 100644
--- a/drivers/mtd/doc1000.c
+++ b/drivers/mtd/doc1000.c
@@ -1,16 +1,7 @@
/*======================================================================
- $Id: doc1000.c,v 1.8 2000/07/03 10:01:38 dwmw2 Exp $
+ $Id: doc1000.c,v 1.11 2000/11/24 13:43:16 dwmw2 Exp $
- A general driver for accessing PCMCIA card memory via Bulk
- Memory Services.
-
- This driver provides the equivalent of /dev/mem for a PCMCIA
- card's attribute and common memory. It includes character
- and block devices.
-
- Written by David Hinds, dhinds@allegro.stanford.edu
-
======================================================================*/
@@ -295,10 +286,9 @@ int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen
static inline int byte_write (volatile u_char *addr, u_char byte)
{
register u_char status;
- register u_short i;
-
- for (i = 0; i < max_tries; i++)
- {
+ register u_short i = 0;
+
+ do {
status = readb(addr);
if (status & CSR_WR_READY)
{
@@ -306,7 +296,9 @@ static inline int byte_write (volatile u_char *addr, u_char byte)
writeb(byte, addr);
return 0;
}
- }
+ i++;
+ } while(i < max_tries);
+
printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status);
return -EIO;
@@ -314,11 +306,10 @@ static inline int byte_write (volatile u_char *addr, u_char byte)
static inline int word_write (volatile u_char *addr, __u16 word)
{
- register u_short status = 0;
- register u_short i;
+ register u_short status;
+ register u_short i = 0;
- for (i = 0; i < max_tries; i++)
- {
+ do {
status = readw(addr);
if ((status & CSR_WR_READY) == CSR_WR_READY)
{
@@ -326,7 +317,8 @@ static inline int word_write (volatile u_char *addr, __u16 word)
writew(word, addr);
return 0;
}
- }
+ i++;
+ } while(i < max_tries);
printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status);
return -EIO;
@@ -362,24 +354,22 @@ static inline int check_erase(volatile u_char *addr)
static inline int suspend_erase(volatile u_char *addr)
{
- __u16 status = 0;
- u_long i;
+ __u16 status;
+ u_long i = 0;
writew(IF_ERASE_SUSPEND, addr);
writew(IF_READ_CSR, addr);
- for (i = 0; i < max_tries; i++)
- {
+ do {
status = readw(addr);
- if ((status & CSR_WR_READY) == CSR_WR_READY) break;
- }
- if (i == max_tries)
- {
- printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status);
- return -EIO;
- }
-
- return 0;
+ if ((status & CSR_WR_READY) == CSR_WR_READY)
+ return 0;
+ i++;
+ } while(i < max_tries);
+
+ printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status);
+ return -EIO;
+
}
static inline void resume_erase(volatile u_char *addr)
@@ -413,12 +403,11 @@ static inline void reset_block(volatile u_char *addr)
static inline int check_write(volatile u_char *addr)
{
- u_short status = 0, i;
+ u_short status, i = 0;
writew(IF_READ_CSR, addr);
- for (i=0; i < max_tries; i++)
- {
+ do {
status = readw(addr);
if (status & (CSR_WR_ERR | CSR_VPP_LOW))
{
@@ -428,7 +417,9 @@ static inline int check_write(volatile u_char *addr)
}
if ((status & CSR_WR_READY) == CSR_WR_READY)
return 0;
- }
+ i++;
+ } while (i < max_tries);
+
printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status);
return -EIO;
}
@@ -519,7 +510,7 @@ static void flashcard_periodic(unsigned long data)
}
-#if defined (MODULE) && LINUX_VERSION_CODE < 0x20300
+#if defined (MODULE) && LINUX_VERSION_CODE < 0x20211
#define init_doc1000 init_module
#define cleanup_doc1000 cleanup_module
#endif
@@ -600,3 +591,7 @@ static void __init cleanup_doc1000(void)
kfree(mymtd);
}
+#if LINUX_VERSION_CODE >= 0x20211
+module_init(init_doc1000);
+module_exit(cleanup_doc1000);
+#endif
diff --git a/drivers/mtd/doc2000.c b/drivers/mtd/doc2000.c
index cef67512b..22ef68e62 100644
--- a/drivers/mtd/doc2000.c
+++ b/drivers/mtd/doc2000.c
@@ -1,8 +1,11 @@
-/* Linux driver for Disk-On-Chip 2000 */
-/* (c) 1999 Machine Vision Holdings, Inc. */
-/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.c,v 1.24 2000/07/13 10:03:31 dwmw2 Exp $ */
+/*
+ * Linux driver for Disk-On-Chip 2000 and Millennium
+ * (c) 1999 Machine Vision Holdings, Inc.
+ * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
+ *
+ * $Id: doc2000.c,v 1.39 2000/12/01 17:34:29 dwmw2 Exp $
+ */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -19,286 +22,383 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ids.h>
#include <linux/mtd/doc2000.h>
-//#define PRERELEASE
+#define DOC_SUPPORT_2000
+#define DOC_SUPPORT_MILLENNIUM
-static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eecbuf);
-static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf);
-static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
+#ifdef DOC_SUPPORT_2000
+#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k)
+#else
+#define DoC_is_2000(doc) (0)
+#endif
+#ifdef DOC_SUPPORT_MILLENNIUM
+#define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil)
+#else
+#define DoC_is_Millennium(doc) (0)
+#endif
+
+/* #define ECC_DEBUG */
+
+/* I have no idea why some DoC chips can not use memcpy_from|to_io().
+ * This may be due to the different revisions of the ASIC controller built-in or
+ * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
+ * this:
+ #undef USE_MEMCPY
+*/
+
+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf);
+static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf);
+static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf, u_char *eccbuf);
+static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf, u_char *eccbuf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, u_char *buf);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, const u_char *buf);
+static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
static struct mtd_info *doc2klist = NULL;
-/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
+/* Perform the required delay cycles by reading from the appropriate register */
+static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles)
+{
+ volatile char dummy;
+ int i;
+
+ for (i = 0; i < cycles; i++) {
+ if (DoC_is_Millennium(doc))
+ dummy = ReadDOC(doc->virtadr, NOP);
+ else
+ dummy = ReadDOC(doc->virtadr, DOCStatus);
+ }
+
+}
-static int _DoC_WaitReady (unsigned long docptr)
+/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
+static int _DoC_WaitReady(struct DiskOnChip *doc)
{
- //long c=-1;
- short c=-1;
+ unsigned long docptr = doc->virtadr;
+ unsigned short c = 0xffff;
- DEBUG(2,"_DoC_WaitReady called for out-of-line wait\n");
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "_DoC_WaitReady called for out-of-line wait\n");
/* Out-of-line routine to wait for chip response */
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
;
if (c == 0)
- DEBUG(2, "_DoC_WaitReady timed out.\n");
-
- return (c==0);
+ DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+
+ return (c == 0);
}
-static inline int DoC_WaitReady(unsigned long docptr)
+static inline int DoC_WaitReady(struct DiskOnChip *doc)
{
+ unsigned long docptr = doc->virtadr;
/* This is inline, to optimise the common case, where it's ready instantly */
- volatile char dummy;
int ret = 0;
- /* Out-of-line routine to wait for chip response */
- /* TPW: Add 4 reads - see Software Requirement 2.3.2 */
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
-
+ /* 4 read form NOP register should be issued in prior to the read from CDSNControl
+ see Software Requirement 11.4 item 2. */
+ DoC_Delay(doc, 4);
+
if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
- ret = _DoC_WaitReady(docptr); /* Call the out-of-line routine to wait */
-
- /* TPW: Add 2 reads - see Software Requirement 2.3.2 */
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
+ /* Call the out-of-line routine to wait */
+ ret = _DoC_WaitReady(doc);
+
+ /* issue 2 read from NOP register after reading from CDSNControl register
+ see Software Requirement 11.4 item 2. */
+ DoC_Delay(doc, 2);
return ret;
}
+/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to
+ bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
+ required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-/* DoC_Command: Send a flash command to the flash chip */
-
-static inline int DoC_Command(unsigned long docptr, unsigned char command, unsigned char xtraflags)
+static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command,
+ unsigned char xtraflags)
{
+ unsigned long docptr = doc->virtadr;
+
+ if (DoC_is_2000(doc))
+ xtraflags |= CDSN_CTRL_FLASH_IO;
+
/* Assert the CLE (Command Latch Enable) line to the flash chip */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE,
- docptr, CDSNControl);
+ WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
+
+ if (DoC_is_Millennium(doc))
+ WriteDOC(command, docptr, CDSNSlowIO);
/* Send the command */
- WriteDOC(command, docptr, 2k_CDSN_IO);
-
+ WriteDOC_(command, docptr, doc->ioreg);
+
/* Lower the CLE line */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
+ WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
- /* Wait for the chip to respond */
- return DoC_WaitReady(docptr);
+ /* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */
+ return DoC_WaitReady(doc);
}
-/* DoC_Address: Set the current address for the flash chip */
+/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to
+ bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
+ required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static inline int DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs,
- unsigned char xtraflags1, unsigned char xtraflags2)
+static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs,
+ unsigned char xtraflags1, unsigned char xtraflags2)
{
- /* Assert the ALE (Address Latch Enable line to the flash chip */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE,
- docptr, CDSNControl);
+ unsigned long docptr;
+ int i;
+
+ docptr = doc->virtadr;
+
+ if (DoC_is_2000(doc))
+ xtraflags1 |= CDSN_CTRL_FLASH_IO;
+
+ /* Assert the ALE (Address Latch Enable) line to the flash chip */
+ WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
+
+ DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
/* Send the address */
- /* Three cases:
- numbytes == 1: Send single byte, bits 0-7.
- numbytes == 2: Send bits 9-16 followed by 17-23
- numbytes == 3: Send 0-7, 9-16, then 17-23
- */
- if (numbytes != 2)
- WriteDOC(ofs & 0xff, docptr, 2k_CDSN_IO);
-
- if (numbytes != 1) {
- WriteDOC((ofs >> 9) & 0xff, docptr, 2k_CDSN_IO);
- WriteDOC((ofs >> 17) & 0xff, docptr, 2k_CDSN_IO);
+ /* Devices with 256-byte page are addressed as:
+ Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
+ * there is no device on the market with page256
+ and more than 24 bits.
+ Devices with 512-byte page are addressed as:
+ Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
+ * 25-31 is sent only if the chip support it.
+ * bit 8 changes the read command to be sent
+ (NAND_CMD_READ0 or NAND_CMD_READ1).
+ */
+
+ if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) {
+ if (DoC_is_Millennium(doc))
+ WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
+ WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
}
- /* Lower the ALE line */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
+
+ if (doc->page256) {
+ ofs = ofs >> 8;
+ } else {
+ ofs = ofs >> 9;
+ }
+
+ if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) {
+ for (i = 0; i < doc->pageadrlen; i++, ofs = ofs >> 8) {
+ if (DoC_is_Millennium(doc))
+ WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
+ WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
+ }
+ }
+
+ DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */
- /* Wait for the chip to respond */
- return DoC_WaitReady(docptr);
+ /* FIXME: The SlowIO's for millennium could be replaced by
+ a single WritePipeTerm here. mf. */
+
+ /* Lower the ALE line */
+ WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr,
+ CDSNControl);
+
+ DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
+
+ /* Wait for the chip to respond - Software requirement 11.4.1 */
+ return DoC_WaitReady(doc);
+}
+
+/* Read a buffer from DoC, taking care of Millennium odditys */
+static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len)
+{
+ int dummy;
+ int modulus = 0xffff;
+ unsigned long docptr;
+ int i;
+
+ docptr = doc->virtadr;
+
+ if (len <= 0)
+ return;
+
+ if (DoC_is_Millennium(doc)) {
+ /* Read the data via the internal pipeline through CDSN IO register,
+ see Pipelined Read Operations 11.3 */
+ dummy = ReadDOC(docptr, ReadPipeInit);
+
+ /* Millennium should use the LastDataRead register - Pipeline Reads */
+ len--;
+
+ /* This is needed for correctly ECC calculation */
+ modulus = 0xff;
+ }
+
+ for (i = 0; i < len; i++)
+ buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus));
+
+ if (DoC_is_Millennium(doc)) {
+ buf[i] = ReadDOC(docptr, LastDataRead);
+ }
+}
+
+/* Write a buffer to DoC, taking care of Millennium odditys */
+static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len)
+{
+ unsigned long docptr;
+ int i;
+
+ docptr = doc->virtadr;
+
+ if (len <= 0)
+ return;
+
+ for (i = 0; i < len; i++)
+ WriteDOC_(buf[i], docptr, doc->ioreg + i);
+
+ if (DoC_is_Millennium(doc)) {
+ WriteDOC(0x00, docptr, WritePipeTerm);
+ }
}
+
/* DoC_SelectChip: Select a given flash chip within the current floor */
-static inline int DoC_SelectChip(unsigned long docptr, int chip)
+static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip)
{
+ unsigned long docptr = doc->virtadr;
+
+ /* Software requirement 11.4.4 before writing DeviceSelect */
+ /* Deassert the CE line to eliminate glitches on the FCE# outputs */
+ WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl);
+ DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
+
/* Select the individual flash chip requested */
- WriteDOC( chip, docptr, CDSNDeviceSelect);
-
+ WriteDOC(chip, docptr, CDSNDeviceSelect);
+ DoC_Delay(doc, 4);
+
+ /* Reassert the CE line */
+ WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr,
+ CDSNControl);
+ DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
+
/* Wait for it to be ready */
- return DoC_WaitReady(docptr);
+ return DoC_WaitReady(doc);
}
/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
-static inline int DoC_SelectFloor(unsigned long docptr, int floor)
+static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor)
{
+ unsigned long docptr = doc->virtadr;
+
/* Select the floor (bank) of chips required */
- WriteDOC( floor, docptr, FloorSelect);
+ WriteDOC(floor, docptr, FloorSelect);
/* Wait for the chip to be ready */
- return DoC_WaitReady(docptr);
+ return DoC_WaitReady(doc);
}
-
+
/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
{
- int mfr, id, chipshift=0;
- char *mfrname=NULL, *idname=NULL;
+ int mfr, id, i;
+ volatile char dummy;
/* Page in the required floor/chip */
- DoC_SelectFloor(doc->virtadr, floor);
- DoC_SelectChip(doc->virtadr, chip);
+ DoC_SelectFloor(doc, floor);
+ DoC_SelectChip(doc, chip);
/* Reset the chip */
- if (DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP)) {
- DEBUG(2, "DoC_Command (reset) for %d,%d returned true\n", floor,chip);
+ if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
+ DEBUG(MTD_DEBUG_LEVEL2,
+ "DoC_Command (reset) for %d,%d returned true\n",
+ floor, chip);
return 0;
}
-
- /* Read the NAND chip ID: 1. Send ReadID command */
- if(DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP)) {
- DEBUG(2,"DoC_Command (ReadID) for %d,%d returned true\n", floor,chip);
+
+
+ /* Read the NAND chip ID: 1. Send ReadID command */
+ if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
+ DEBUG(MTD_DEBUG_LEVEL2,
+ "DoC_Command (ReadID) for %d,%d returned true\n",
+ floor, chip);
return 0;
}
- /* Read the NAND chip ID: 2. Send address byte zero
- */
- DoC_Address(doc->virtadr, 1, 0, CDSN_CTRL_WP, 0);
-
+ /* Read the NAND chip ID: 2. Send address byte zero */
+ DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0);
+
/* Read the manufacturer and device id codes from the device */
- mfr = ReadDOC(doc->virtadr, 2k_CDSN_IO);
- id = ReadDOC(doc->virtadr, 2k_CDSN_IO);
-
+
+ /* CDSN Slow IO register see Software Requirement 11.4 item 5. */
+ dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
+ DoC_Delay(doc, 2);
+ mfr = ReadDOC_(doc->virtadr, doc->ioreg);
+
+ /* CDSN Slow IO register see Software Requirement 11.4 item 5. */
+ dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
+ DoC_Delay(doc, 2);
+ id = ReadDOC_(doc->virtadr, doc->ioreg);
+
/* No response - return failure */
if (mfr == 0xff || mfr == 0)
return 0;
-
+
/* Check it's the same as the first chip we identified.
* M-Systems say that any given DiskOnChip device should only
* contain _one_ type of flash part, although that's not a
* hardware restriction. */
if (doc->mfr) {
if (doc->mfr == mfr && doc->id == id)
- return 1; /* This is another the same the first */
+ return 1; /* This is another the same the first */
else
- printk(KERN_WARNING "Flash chip at floor %d, chip %d is different:\n",
+ printk(KERN_WARNING
+ "Flash chip at floor %d, chip %d is different:\n",
floor, chip);
}
-
- /* Print (and store if first time) the manufacturer and ID codes. */
-
- switch(mfr) {
- case NAND_MFR_TOSHIBA: /* Toshiba */
- mfrname = "Toshiba";
-
- switch(id) {
- case 0x64:
- idname = "TC5816BDC";
- chipshift = 21;
- break;
-
- case 0x6b:
- idname = "TC5832DC";
- chipshift = 22;
- break;
-
- case 0x73:
- idname = "TH58V128DC";
- chipshift = 24;
- break;
-
- case 0x75:
- idname = "TC58256FT/DC";
- chipshift = 25;
- break;
-
- case 0xe5:
- idname = "TC58V32DC";
- chipshift = 22;
- break;
-
- case 0xe6:
- idname = "TC58V64DC";
- chipshift = 23;
- break;
-
- case 0xea:
- idname = "TC58V16BDC";
- chipshift = 21;
- break;
- }
- break; /* End of Toshiba parts */
-
- case NAND_MFR_SAMSUNG: /* Samsung */
- mfrname = "Samsung";
-
- switch(id) {
- case 0x64:
- idname = "KM29N16000";
- chipshift = 21;
-
- case 0x73:
- idname = "KM29U128T";
- chipshift = 24;
- break;
-
- case 0x75:
- idname = "KM29U256T";
- chipshift = 25;
- break;
-
- case 0xe3:
- idname = "KM29W32000";
- chipshift = 22;
- break;
-
- case 0xe6:
- idname = "KM29U64000";
- chipshift = 23;
- break;
-
- case 0xea:
- idname = "KM29W16000";
- chipshift = 21;
- break;
- }
- break; /* End of Samsung parts */
- }
-
- /* If we've identified it fully, print the full names */
- if (idname) {
-#ifdef PRERELEASE
- DEBUG(1, "Flash chip found: %2.2X %2.2X (%s %s)\n",
- mfr,id,mfrname,idname);
-#endif
- /* If this is the first chip, store the id codes */
- if (!doc->mfr) {
- doc->mfr = mfr;
- doc->id = id;
- doc->chipshift = chipshift;
- return 1;
+
+ /* Print and store the manufacturer and ID codes. */
+ for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+ if (mfr == nand_flash_ids[i].manufacture_id &&
+ id == nand_flash_ids[i].model_id) {
+ printk(KERN_INFO
+ "Flash chip found: Manufacturer ID: %2.2X, "
+ "Chip ID: %2.2X (%s)\n", mfr, id,
+ nand_flash_ids[i].name);
+ if (!doc->mfr) {
+ doc->mfr = mfr;
+ doc->id = id;
+ doc->chipshift =
+ nand_flash_ids[i].chipshift;
+ doc->page256 = nand_flash_ids[i].page256;
+ doc->pageadrlen =
+ nand_flash_ids[i].pageadrlen;
+ doc->erasesize =
+ nand_flash_ids[i].erasesize;
+ return 1;
+ }
+ return 0;
}
- return 0;
}
+
/* We haven't fully identified the chip. Print as much as we know. */
- if (mfrname)
- printk(KERN_WARNING "Unknown %s flash chip found: %2.2X %2.2X\n", mfrname,
- id, mfr);
- else
- printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", id, mfr);
-
- printk(KERN_WARNING "Please report to David.Woodhouse@mvhi.com\n");
+ printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n",
+ id, mfr);
+
+ printk(KERN_WARNING "Please report to dwmw2@infradead.org\n");
return 0;
-}
+}
/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
@@ -306,18 +406,22 @@ static void DoC_ScanChips(struct DiskOnChip *this)
{
int floor, chip;
int numchips[MAX_FLOORS];
+ int maxchips = MAX_CHIPS;
int ret = 1;
-
+
this->numchips = 0;
this->mfr = 0;
this->id = 0;
-
+
+ if (DoC_is_Millennium(this))
+ maxchips = MAX_CHIPS_MIL;
+
/* For each floor, find the number of valid chips it contains */
- for (floor = 0 ; floor < MAX_FLOORS ; floor++) {
+ for (floor = 0; floor < MAX_FLOORS; floor++) {
ret = 1;
- numchips[floor]=0;
- for (chip = 0 ; chip < MAX_CHIPS && ret != 0; chip++ ) {
-
+ numchips[floor] = 0;
+ for (chip = 0; chip < maxchips && ret != 0; chip++) {
+
ret = DoC_IdentChip(this, floor, chip);
if (ret) {
numchips[floor]++;
@@ -325,26 +429,26 @@ static void DoC_ScanChips(struct DiskOnChip *this)
}
}
}
-
+
/* If there are none at all that we recognise, bail */
if (!this->numchips) {
printk("No flash chips recognised.\n");
return;
}
-
+
/* Allocate an array to hold the information for each chip */
this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
- if (!this->chips){
+ if (!this->chips) {
printk("No memory for allocating chip info structures\n");
return;
}
-
+
ret = 0;
-
+
/* Fill out the chip array with {floor, chipno} for each
* detected chip in the device. */
for (floor = 0; floor < MAX_FLOORS; floor++) {
- for (chip = 0 ; chip < numchips[floor] ; chip++) {
+ for (chip = 0; chip < numchips[floor]; chip++) {
this->chips[ret].floor = floor;
this->chips[ret].chip = chip;
this->chips[ret].curadr = 0;
@@ -356,8 +460,9 @@ static void DoC_ScanChips(struct DiskOnChip *this)
/* Calculate and print the total size of the device */
this->totlen = this->numchips * (1 << this->chipshift);
- printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mb\n", this->numchips ,
- this->totlen >> 20);
+ printk(KERN_INFO
+ "%d flash chips found. Total DiskOnChip size: %ld Mb\n",
+ this->numchips, this->totlen >> 20);
}
@@ -371,15 +476,15 @@ static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
* purpose. If it's value is the same on both chips, they might
* be the same chip, and we write to one and check for a change in
* the other. It's unclear if this register is usuable in the
- * DoC 2000 (it's in the Millenium docs), but it seems to work. */
+ * DoC 2000 (it's in the Millennium docs), but it seems to work. */
tmp1 = ReadDOC(doc1->virtadr, AliasResolution);
tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
if (tmp1 != tmp2)
return 0;
-
- WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution);
+
+ WriteDOC((tmp1 + 1) % 0xff, doc1->virtadr, AliasResolution);
tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
- if (tmp2 == (tmp1+1) % 0xff)
+ if (tmp2 == (tmp1 + 1) % 0xff)
retval = 1;
else
retval = 0;
@@ -387,11 +492,10 @@ static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
/* Restore register contents. May not be necessary, but do it just to
* be safe. */
WriteDOC(tmp1, doc1->virtadr, AliasResolution);
-
+
return retval;
}
-
static const char im_name[] = "DoC2k_init";
/* This routine is made available to other mtd code via
@@ -403,36 +507,48 @@ static const char im_name[] = "DoC2k_init";
*/
static void DoC2k_init(struct mtd_info *mtd)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
struct DiskOnChip *old = NULL;
/* We must avoid being called twice for the same device. */
if (doc2klist)
- old = (struct DiskOnChip *)doc2klist->priv;
+ old = (struct DiskOnChip *) doc2klist->priv;
while (old) {
if (DoC2k_is_alias(old, this)) {
- printk(KERN_NOTICE "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n",
+ printk(KERN_NOTICE
+ "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n",
this->physadr);
- iounmap((void *)this->virtadr);
+ iounmap((void *) this->virtadr);
kfree(mtd);
return;
}
if (old->nextdoc)
- old = (struct DiskOnChip *)old->nextdoc->priv;
+ old = (struct DiskOnChip *) old->nextdoc->priv;
else
old = NULL;
}
-
-
- mtd->name = "DiskOnChip 2000";
- printk(KERN_NOTICE "DiskOnChip 2000 found at address 0x%lX\n",this->physadr);
+
+
+ switch (this->ChipID) {
+ case DOC_ChipID_Doc2k:
+ mtd->name = "DiskOnChip 2000";
+ this->ioreg = DoC_2k_CDSN_IO;
+ break;
+ case DOC_ChipID_DocMil:
+ mtd->name = "DiskOnChip Millennium";
+ this->ioreg = DoC_Mil_CDSN_IO;
+ break;
+ }
+
+ printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name,
+ this->physadr);
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->size = 0;
- mtd->erasesize = 0x2000;
+ mtd->erasesize = 0;
mtd->oobblock = 512;
mtd->oobsize = 16;
mtd->module = THIS_MODULE;
@@ -446,131 +562,182 @@ static void DoC2k_init(struct mtd_info *mtd)
mtd->read_oob = doc_read_oob;
mtd->write_oob = doc_write_oob;
mtd->sync = NULL;
-
+
this->totlen = 0;
this->numchips = 0;
-
+
this->curfloor = -1;
this->curchip = -1;
-
+
/* Ident all the chips present. */
DoC_ScanChips(this);
-
+
if (!this->totlen) {
kfree(mtd);
- iounmap((void *)this->virtadr);
+ iounmap((void *) this->virtadr);
} else {
this->nextdoc = doc2klist;
doc2klist = mtd;
- mtd->size = this->totlen;
+ mtd->size = this->totlen;
+ mtd->erasesize = this->erasesize;
add_mtd_device(mtd);
return;
}
}
-
-static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf)
{
/* Just a special case of doc_read_ecc */
return doc_read_ecc(mtd, from, len, retlen, buf, NULL);
}
-static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf)
+static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf, u_char * eccbuf)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- int di=0; /* Yes, DI is a hangover from when I was disassembling the binary driver */
+ struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
unsigned long docptr;
struct Nand *mychip;
+ unsigned char syndrome[6];
+ volatile char dummy;
+ int i, len256 = 0, ret=0;
docptr = this->virtadr;
/* Don't allow read past end of device */
if (from >= this->totlen)
return -EINVAL;
-
+
/* Don't allow a single read to cross a 512-byte block boundary */
- if (from + len > ( (from | 0x1ff) + 1))
+ if (from + len > ((from | 0x1ff) + 1))
len = ((from | 0x1ff) + 1) - from;
+ /* The ECC will not be calculated correctly if less than 512 is read */
+ if (len != 0x200 && eccbuf)
+ printk(KERN_WARNING
+ "ECC needs a full sector read (adr: %lx size %lx)\n",
+ (long) from, (long) len);
+
+ /* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */
+
+
/* Find the chip which is to be used and select it */
mychip = &this->chips[from >> (this->chipshift)];
-
+
if (this->curfloor != mychip->floor) {
- DoC_SelectFloor(docptr, mychip->floor);
- DoC_SelectChip(docptr, mychip->chip);
+ DoC_SelectFloor(this, mychip->floor);
+ DoC_SelectChip(this, mychip->chip);
+ } else if (this->curchip != mychip->chip) {
+ DoC_SelectChip(this, mychip->chip);
}
- else if (this->curchip != mychip->chip) {
- DoC_SelectChip(docptr, mychip->chip);
- }
-
+
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
+
+ DoC_Command(this,
+ (!this->page256
+ && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
+ CDSN_CTRL_WP);
+ DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
+ CDSN_CTRL_ECC_IO);
if (eccbuf) {
/* Prime the ECC engine */
- WriteDOC ( DOC_ECC_RESET, docptr, ECCConf);
- WriteDOC ( DOC_ECC_EN, docptr, ECCConf);
+ WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC(DOC_ECC_EN, docptr, ECCConf);
+ } else {
+ /* disable the ECC engine */
+ WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
}
- DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP);
- DoC_Address(docptr, 3, from, CDSN_CTRL_WP , CDSN_CTRL_ECC_IO);
+ /* treat crossing 256-byte sector for 2M x 8bits devices */
+ if (this->page256 && from + len > (from | 0xff) + 1) {
+ len256 = (from | 0xff) + 1 - from;
+ DoC_ReadBuf(this, buf, len256);
- for (di=0; di < len ; di++) {
- buf[di] = ReadDOC(docptr, 2k_CDSN_IO);
+ DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);
+ DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,
+ CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);
}
+ DoC_ReadBuf(this, &buf[len256], len - len256);
+
/* Let the caller know we completed it */
*retlen = len;
if (eccbuf) {
/* Read the ECC data through the DiskOnChip ECC logic */
- for (di=0; di<6; di++) {
- eccbuf[di] = ReadDOC(docptr, 2k_CDSN_IO);
- }
-
+ /* Note: this will work even with 2M x 8bit devices as */
+ /* they have 8 bytes of OOB per 256 page. mf. */
+ DoC_ReadBuf(this, eccbuf, 6);
+
/* Flush the pipeline */
- (void) ReadDOC(docptr, 2k_ECCStatus);
- (void) ReadDOC(docptr, 2k_ECCStatus);
-
+ if (DoC_is_Millennium(this)) {
+ dummy = ReadDOC(docptr, ECCConf);
+ dummy = ReadDOC(docptr, ECCConf);
+ i = ReadDOC(docptr, ECCConf);
+ } else {
+ dummy = ReadDOC(docptr, 2k_ECCStatus);
+ dummy = ReadDOC(docptr, 2k_ECCStatus);
+ i = ReadDOC(docptr, 2k_ECCStatus);
+ }
+
/* Check the ECC Status */
- if (ReadDOC(docptr, 2k_ECCStatus) & 0x80) {
+ if (i & 0x80) {
+ int nb_errors;
/* There was an ECC error */
+#ifdef ECC_DEBUG
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
+#endif
+ /* Read the ECC syndrom through the DiskOnChip ECC logic.
+ These syndrome will be all ZERO when there is no error */
+ for (i = 0; i < 6; i++) {
+ syndrome[i] =
+ ReadDOC(docptr, ECCSyndrome0 + i);
+ }
+ nb_errors = doc_decode_ecc(buf, syndrome);
- /* FIXME: Implement ECC error correction, don't just whinge */
-
- /* We return error, but have actually done the read. Not that
- this can be told to user-space, via sys_read(), but at least
- MTD-aware stuff can know about it by checking *retlen */
- return -EIO;
+#ifdef ECC_DEBUG
+ printk("Errors corrected: %x\n", nb_errors);
+#endif
+ if (nb_errors < 0) {
+ /* We return error, but have actually done the read. Not that
+ this can be told to user-space, via sys_read(), but at least
+ MTD-aware stuff can know about it by checking *retlen */
+ ret = -EIO;
+ }
}
+
#ifdef PSYCHO_DEBUG
- else
- printk("ECC OK at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
- (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4],
- eccbuf[5]);
+ printk("ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+ (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
+ eccbuf[3], eccbuf[4], eccbuf[5]);
#endif
- /* Reset the ECC engine */
- WriteDOC(DOC_ECC_RESV, docptr , ECCConf);
-
+ /* disable the ECC engine */
+ WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
}
- return 0;
+ return ret;
}
-static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
+static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
{
- static char as[6];
- return doc_write_ecc(mtd, to, len, retlen, buf, as);
+ char eccbuf[6];
+ return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf);
}
-static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf)
+static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf,
+ u_char * eccbuf)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- int di=0;
+ struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
+ int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
unsigned long docptr;
+ volatile char dummy;
+ int len256 = 0;
struct Nand *mychip;
docptr = this->virtadr;
@@ -578,82 +745,118 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *r
/* Don't allow write past end of device */
if (to >= this->totlen)
return -EINVAL;
-#if 0
+
/* Don't allow a single write to cross a 512-byte block boundary */
- if (to + len > ( (to | 0x1ff) + 1))
+ if (to + len > ((to | 0x1ff) + 1))
len = ((to | 0x1ff) + 1) - to;
-#else
- /* Don't allow writes which aren't exactly one block */
- if (to & 0x1ff || len != 0x200)
- return -EINVAL;
-#endif
+ /* The ECC will not be calculated correctly if less than 512 is written */
+ if (len != 0x200 && eccbuf)
+ printk(KERN_WARNING
+ "ECC needs a full sector write (adr: %lx size %lx)\n",
+ (long) to, (long) len);
+
+ /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */
/* Find the chip which is to be used and select it */
mychip = &this->chips[to >> (this->chipshift)];
-
+
if (this->curfloor != mychip->floor) {
- DoC_SelectFloor(docptr, mychip->floor);
- DoC_SelectChip(docptr, mychip->chip);
+ DoC_SelectFloor(this, mychip->floor);
+ DoC_SelectChip(this, mychip->chip);
+ } else if (this->curchip != mychip->chip) {
+ DoC_SelectChip(this, mychip->chip);
}
- else if (this->curchip != mychip->chip) {
- DoC_SelectChip(docptr, mychip->chip);
- }
-
+
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
+
/* Set device to main plane of flash */
- DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
- DoC_Command(docptr, NAND_CMD_READ0, CDSN_CTRL_WP);
+ DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
+ DoC_Command(this,
+ (!this->page256
+ && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
+ CDSN_CTRL_WP);
+
+ DoC_Command(this, NAND_CMD_SEQIN, 0);
+ DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
if (eccbuf) {
/* Prime the ECC engine */
- WriteDOC ( DOC_ECC_RESET, docptr, ECCConf);
- WriteDOC ( DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+ WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+ } else {
+ /* disable the ECC engine */
+ WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
}
- DoC_Command(docptr, NAND_CMD_SEQIN, 0);
- DoC_Address(docptr, 3, to, 0, CDSN_CTRL_ECC_IO);
+ /* treat crossing 256-byte sector for 2M x 8bits devices */
+ if (this->page256 && to + len > (to | 0xff) + 1) {
+ len256 = (to | 0xff) + 1 - to;
+ DoC_WriteBuf(this, buf, len256);
+
+ DoC_Command(this, NAND_CMD_PAGEPROG, 0);
+
+ DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
+ /* There's an implicit DoC_WaitReady() in DoC_Command */
+
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(this, 2);
- for (di=0; di < len ; di++) {
- WriteDOC(buf[di], docptr, 2k_CDSN_IO);
+ if (ReadDOC_(docptr, this->ioreg) & 1) {
+ printk("Error programming flash\n");
+ /* Error in programming */
+ *retlen = 0;
+ return -EIO;
+ }
+
+ DoC_Command(this, NAND_CMD_SEQIN, 0);
+ DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
+ CDSN_CTRL_ECC_IO);
}
+ DoC_WriteBuf(this, &buf[len256], len - len256);
if (eccbuf) {
- WriteDOC( CDSN_CTRL_ECC_IO | CDSN_CTRL_CE , docptr, CDSNControl );
-
-#if 1
- /* eduardp@m-sys.com says this shouldn't be necessary,
- * but it doesn't actually work without it, so I've
- * left it in for now. dwmw2.
- */
-
- WriteDOC( 0, docptr, 2k_CDSN_IO);
- WriteDOC( 0, docptr, 2k_CDSN_IO);
- WriteDOC( 0, docptr, 2k_CDSN_IO);
-#endif
+ WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
+ CDSNControl);
+
+ if (DoC_is_Millennium(this)) {
+ WriteDOC(0, docptr, NOP);
+ WriteDOC(0, docptr, NOP);
+ WriteDOC(0, docptr, NOP);
+ } else {
+ WriteDOC_(0, docptr, this->ioreg);
+ WriteDOC_(0, docptr, this->ioreg);
+ WriteDOC_(0, docptr, this->ioreg);
+ }
+
/* Read the ECC data through the DiskOnChip ECC logic */
- for (di=0; di<6; di++) {
+ for (di = 0; di < 6; di++) {
eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
}
+
+ /* Reset the ECC engine */
+ WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+
#ifdef PSYCHO_DEBUG
- printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
- (long) to, eccbuf[0], eccbuf[1], eccbuf[2],
- eccbuf[3], eccbuf[4], eccbuf[5] );
+ printk
+ ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+ (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
+ eccbuf[4], eccbuf[5]);
#endif
- /* Reset the ECC engine */
- WriteDOC(DOC_ECC_RESV, docptr , ECCConf);
-
}
- DoC_Command(docptr, NAND_CMD_PAGEPROG, 0);
+ DoC_Command(this, NAND_CMD_PAGEPROG, 0);
- DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
+ DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
/* There's an implicit DoC_WaitReady() in DoC_Command */
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(this, 2);
+
+ if (ReadDOC_(docptr, this->ioreg) & 1) {
printk("Error programming flash\n");
/* Error in programming */
*retlen = 0;
@@ -662,84 +865,155 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *r
/* Let the caller know we completed it */
*retlen = len;
+
+ if (eccbuf) {
+ unsigned char x[8];
+ size_t dummy;
+
+ /* Write the ECC data to flash */
+ for (di=0; di<6; di++)
+ x[di] = eccbuf[di];
+
+ x[6]=0x55;
+ x[7]=0x55;
+
+ return doc_write_oob(mtd, to, 8, &dummy, x);
+ }
return 0;
}
-
-
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t * retlen, u_char * buf)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- int i;
+ struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
+ int len256 = 0;
unsigned long docptr;
struct Nand *mychip;
-
+
docptr = this->virtadr;
-
+
mychip = &this->chips[ofs >> this->chipshift];
-
+
if (this->curfloor != mychip->floor) {
- DoC_SelectFloor(docptr, mychip->floor);
- DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
- DoC_SelectChip(docptr, mychip->chip);
+ DoC_SelectFloor(this, mychip->floor);
+ DoC_SelectChip(this, mychip->chip);
+ } else if (this->curchip != mychip->chip) {
+ DoC_SelectChip(this, mychip->chip);
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
-
-
- DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
- DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0);
-
- for (i=0; i<len; i++)
- buf[i] = ReadDOC(docptr, 2k_CDSN_IO);
-
+
+ /* update address for 2M x 8bit devices. OOB starts on the second */
+ /* page to maintain compatibility with doc_read_ecc. */
+ if (this->page256) {
+ if (!(ofs & 0x8))
+ ofs += 0x100;
+ else
+ ofs -= 0x8;
+ }
+
+ DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
+ DoC_Address(this, ADDR_COLUMN_PAGE, ofs, CDSN_CTRL_WP, 0);
+
+ /* treat crossing 8-byte OOB data for 2M x 8bit devices */
+ /* Note: datasheet says it should automaticaly wrap to the */
+ /* next OOB block, but it didn't work here. mf. */
+ if (this->page256 && ofs + len > (ofs | 0x7) + 1) {
+ len256 = (ofs | 0x7) + 1 - ofs;
+ DoC_ReadBuf(this, buf, len256);
+
+ DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
+ DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff),
+ CDSN_CTRL_WP, 0);
+ }
+
+ DoC_ReadBuf(this, &buf[len256], len - len256);
+
*retlen = len;
return 0;
}
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t * retlen, const u_char * buf)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- int i;
- unsigned long docptr;
- struct Nand *mychip;
+ struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
+ int len256 = 0;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[ofs >> this->chipshift];
+ int dummy;
- // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len,
+ // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len,
// buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]);
- docptr = this->virtadr;
-
- mychip = &this->chips[ofs >> this->chipshift];
-
+ /* Find the chip which is to be used and select it */
if (this->curfloor != mychip->floor) {
- DoC_SelectFloor(docptr, mychip->floor);
- DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
- DoC_SelectChip(docptr, mychip->chip);
+ DoC_SelectFloor(this, mychip->floor);
+ DoC_SelectChip(this, mychip->chip);
+ } else if (this->curchip != mychip->chip) {
+ DoC_SelectChip(this, mychip->chip);
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
- DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
- DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
- DoC_Command(docptr, NAND_CMD_SEQIN, 0);
- DoC_Address(docptr, 3, ofs, 0, 0);
-
- for (i=0; i<len; i++)
- WriteDOC(buf[i], docptr, 2k_CDSN_IO);
+ /* disable the ECC engine */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
+
+ /* Reset the chip, see Software Requirement 11.4 item 1. */
+ DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
- DoC_Command(docptr, NAND_CMD_PAGEPROG, 0);
- DoC_Command(docptr, NAND_CMD_STATUS, 0);
+ /* issue the Read2 command to set the pointer to the Spare Data Area. */
+ DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
+
+ /* update address for 2M x 8bit devices. OOB starts on the second */
+ /* page to maintain compatibility with doc_read_ecc. */
+ if (this->page256) {
+ if (!(ofs & 0x8))
+ ofs += 0x100;
+ else
+ ofs -= 0x8;
+ }
+
+ /* issue the Serial Data In command to initial the Page Program process */
+ DoC_Command(this, NAND_CMD_SEQIN, 0);
+ DoC_Address(this, ADDR_COLUMN_PAGE, ofs, 0, 0);
+
+ /* treat crossing 8-byte OOB data for 2M x 8bit devices */
+ /* Note: datasheet says it should automaticaly wrap to the */
+ /* next OOB block, but it didn't work here. mf. */
+ if (this->page256 && ofs + len > (ofs | 0x7) + 1) {
+ len256 = (ofs | 0x7) + 1 - ofs;
+ DoC_WriteBuf(this, buf, len256);
+
+ DoC_Command(this, NAND_CMD_PAGEPROG, 0);
+ DoC_Command(this, NAND_CMD_STATUS, 0);
+ /* DoC_WaitReady() is implicit in DoC_Command */
+
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(this, 2);
+
+ if (ReadDOC_(docptr, this->ioreg) & 1) {
+ printk("Error programming oob data\n");
+ /* There was an error */
+ *retlen = 0;
+ return -EIO;
+ }
+ DoC_Command(this, NAND_CMD_SEQIN, 0);
+ DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), 0, 0);
+ }
+
+ DoC_WriteBuf(this, &buf[len256], len - len256);
+
+ DoC_Command(this, NAND_CMD_PAGEPROG, 0);
+ DoC_Command(this, NAND_CMD_STATUS, 0);
/* DoC_WaitReady() is implicit in DoC_Command */
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(this, 2);
+
+ if (ReadDOC_(docptr, this->ioreg) & 1) {
printk("Error programming oob data\n");
/* There was an error */
*retlen = 0;
@@ -751,102 +1025,89 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *r
}
-
-int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
+int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
unsigned long ofs = instr->addr;
unsigned long len = instr->len;
unsigned long docptr;
struct Nand *mychip;
-
- if(len != mtd->erasesize)
- printk(KERN_WARNING "Erase not right size (%lx != %lx)n", len, mtd->erasesize);
-
+
+ if (len != mtd->erasesize)
+ printk(KERN_WARNING "Erase not right size (%lx != %lx)n",
+ len, mtd->erasesize);
docptr = this->virtadr;
-
+
mychip = &this->chips[ofs >> this->chipshift];
-
+
if (this->curfloor != mychip->floor) {
- DoC_SelectFloor(docptr, mychip->floor);
- DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
- DoC_SelectChip(docptr, mychip->chip);
+ DoC_SelectFloor(this, mychip->floor);
+ DoC_SelectChip(this, mychip->chip);
+ } else if (this->curchip != mychip->chip) {
+ DoC_SelectChip(this, mychip->chip);
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
+
instr->state = MTD_ERASE_PENDING;
- DoC_Command(docptr, NAND_CMD_ERASE1, 0);
- DoC_Address(docptr, 2, ofs, 0, 0);
- DoC_Command(docptr, NAND_CMD_ERASE2, 0);
+ DoC_Command(this, NAND_CMD_ERASE1, 0);
+ DoC_Address(this, ADDR_PAGE, ofs, 0, 0);
+ DoC_Command(this, NAND_CMD_ERASE2, 0);
instr->state = MTD_ERASING;
- DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
+ DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
+ if (ReadDOC_(docptr, this->ioreg) & 1) {
printk("Error writing\n");
/* There was an error */
instr->state = MTD_ERASE_FAILED;
- }
- else
+ } else
instr->state = MTD_ERASE_DONE;
- if (instr->callback)
+ if (instr->callback)
instr->callback(instr);
-
+
return 0;
}
-
-
-
/****************************************************************************
*
* Module stuff
*
****************************************************************************/
-static int __init init_doc2000(void)
-{
- inter_module_register(im_name, THIS_MODULE, &DoC2k_init);
- return 0;
-}
-
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define cleanup_doc2000 cleanup_module
-#endif
-#define __exit
+#define init_doc2000 init_module
#endif
+int __init init_doc2000(void)
+{
+ inter_module_register(im_name, THIS_MODULE, &DoC2k_init);
+ return 0;
+}
static void __exit cleanup_doc2000(void)
{
struct mtd_info *mtd;
struct DiskOnChip *this;
- while((mtd=doc2klist)) {
- this = (struct DiskOnChip *)mtd->priv;
+ while ((mtd = doc2klist)) {
+ this = (struct DiskOnChip *) mtd->priv;
doc2klist = this->nextdoc;
-
+
del_mtd_device(mtd);
-
- iounmap((void *)this->virtadr);
+
+ iounmap((void *) this->virtadr);
kfree(this->chips);
kfree(mtd);
}
inter_module_unregister(im_name);
-
}
-module_init(init_doc2000);
-
-#if LINUX_VERSION_CODE > 0x20300
module_exit(cleanup_doc2000);
-#endif
+module_init(init_doc2000);
diff --git a/drivers/mtd/doc2001.c b/drivers/mtd/doc2001.c
index 8a9f03235..79aa3630d 100644
--- a/drivers/mtd/doc2001.c
+++ b/drivers/mtd/doc2001.c
@@ -1,7 +1,11 @@
-/* Linux driver for Disk-On-Chip Millennium */
-/* (c) 1999 Machine Vision Holdings, Inc. */
-/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2001.c,v 1.7 2000/07/13 10:41:39 dwmw2 Exp $ */
+
+/*
+ * Linux driver for Disk-On-Chip Millennium
+ * (c) 1999 Machine Vision Holdings, Inc.
+ * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
+ *
+ * $Id: doc2001.c,v 1.24 2000/12/01 13:11:02 dwmw2 Exp $
+ */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -18,38 +22,26 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ids.h>
#include <linux/mtd/doc2000.h>
-static struct {
- char * name;
- int manufacture_id;
- int model_id;
- int chipshift;
-} nand_flash_ids[] = {
- {"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21},
- {"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22},
- {"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24},
- {"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25},
- {"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22},
- {"Toshiba TC58V64DC", NAND_MFR_TOSHIBA, 0xe6, 23},
- {"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21},
- {"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21},
- {"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24},
- {"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25},
- {"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22},
- {"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23},
- {"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21},
- {NULL,}
-};
-
-static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf);
-static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf);
-static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf, u_char *eecbuf);
-static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf, u_char *eccbuf);
+/* #define ECC_DEBUG */
+
+/* I have no idea why some DoC chips can not use memcop_form|to_io().
+ * This may be due to the different revisions of the ASIC controller built-in or
+ * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
+ * this:
+ #undef USE_MEMCPY
+*/
+
+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf);
+static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf);
+static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf, u_char *eccbuf);
+static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf, u_char *eccbuf);
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
size_t *retlen, u_char *buf);
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
@@ -58,6 +50,7 @@ static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
static struct mtd_info *docmillist = NULL;
+/* Perform the required delay cycles by reading from the NOP register */
static void DoC_Delay(unsigned long docptr, unsigned short cycles)
{
volatile char dummy;
@@ -72,14 +65,20 @@ static int _DoC_WaitReady(unsigned long docptr)
{
unsigned short c = 0xffff;
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "_DoC_WaitReady called for out-of-line wait\n");
+
/* Out-of-line routine to wait for chip response */
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
;
+ if (c == 0)
+ DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+
return (c == 0);
}
-static __inline__ int DoC_WaitReady(unsigned long docptr)
+static inline int DoC_WaitReady(unsigned long docptr)
{
/* This is inline, to optimise the common case, where it's ready instantly */
int ret = 0;
@@ -99,33 +98,35 @@ static __inline__ int DoC_WaitReady(unsigned long docptr)
return ret;
}
-/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to bypass
- the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after
- writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static __inline__ void DoC_Command(unsigned long docptr, unsigned char command,
- unsigned char xtraflags)
+/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to
+ bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
+ required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
+
+static inline void DoC_Command(unsigned long docptr, unsigned char command,
+ unsigned char xtraflags)
{
/* Assert the CLE (Command Latch Enable) line to the flash chip */
- WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
+ WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
DoC_Delay(docptr, 4);
/* Send the command */
WriteDOC(command, docptr, CDSNSlowIO);
WriteDOC(command, docptr, Mil_CDSN_IO);
-
+
/* Lower the CLE line */
WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
DoC_Delay(docptr, 4);
}
-/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to bypass
- the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after
- writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static __inline__ void DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs,
+/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to
+ bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
+ required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
+
+static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long ofs,
unsigned char xtraflags1, unsigned char xtraflags2)
{
- /* Assert the ALE (Address Latch Enable line to the flash chip */
- WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
+ /* Assert the ALE (Address Latch Enable) line to the flash chip */
+ WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
DoC_Delay(docptr, 4);
/* Send the address */
@@ -217,11 +218,11 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
if (mfr == 0xff || mfr == 0)
return 0;
- /* FIXME: to deal with mulit-flash on multi-Millennium case more carefully */
+ /* FIXME: to deal with multi-flash on multi-Millennium case more carefully */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (mfr == nand_flash_ids[i].manufacture_id &&
id == nand_flash_ids[i].model_id) {
- printk(KERN_INFO "Flash chip found: Manufacture ID: %2.2X, "
+ printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, "
"Chip ID: %2.2X (%s)\n",
mfr, id, nand_flash_ids[i].name);
doc->mfr = mfr;
@@ -235,7 +236,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
return 0;
else
return 1;
-}
+}
/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
static void DoC_ScanChips(struct DiskOnChip *this)
@@ -243,11 +244,11 @@ static void DoC_ScanChips(struct DiskOnChip *this)
int floor, chip;
int numchips[MAX_FLOORS_MIL];
int ret;
-
+
this->numchips = 0;
this->mfr = 0;
this->id = 0;
-
+
/* For each floor, find the number of valid chips it contains */
for (floor = 0,ret = 1; floor < MAX_FLOORS_MIL; floor++) {
numchips[floor] = 0;
@@ -264,14 +265,14 @@ static void DoC_ScanChips(struct DiskOnChip *this)
printk("No flash chips recognised.\n");
return;
}
-
+
/* Allocate an array to hold the information for each chip */
this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
if (!this->chips){
printk("No memory for allocating chip info structures\n");
return;
}
-
+
/* Fill out the chip array with {floor, chipno} for each
* detected chip in the device. */
for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) {
@@ -286,7 +287,7 @@ static void DoC_ScanChips(struct DiskOnChip *this)
/* Calculate and print the total size of the device */
this->totlen = this->numchips * (1 << this->chipshift);
- printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mbytes\n",
+ printk(KERN_NOTICE "%d flash chips found. Total DiskOnChip size: %ld Mbytes\n",
this->numchips ,this->totlen >> 20);
}
@@ -317,7 +318,7 @@ static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
/* Restore register contents. May not be necessary, but do it just to
* be safe. */
WriteDOC(tmp1, doc1->virtadr, AliasResolution);
-
+
return retval;
}
@@ -330,7 +331,7 @@ static const char im_name[] = "DoCMil_init";
* this module is non-zero, i.e. between inter_module_get and
* inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
*/
-void DoCMil_init(struct mtd_info *mtd)
+static void DoCMil_init(struct mtd_info *mtd)
{
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
struct DiskOnChip *old = NULL;
@@ -355,12 +356,15 @@ void DoCMil_init(struct mtd_info *mtd)
mtd->name = "DiskOnChip Millennium";
printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n",
- this->physadr);
+ this->physadr);
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->size = 0;
+
+ /* FIXME: erase size is not always 8kB */
mtd->erasesize = 0x2000;
+
mtd->oobblock = 512;
mtd->oobsize = 16;
mtd->module = THIS_MODULE;
@@ -374,15 +378,15 @@ void DoCMil_init(struct mtd_info *mtd)
mtd->read_oob = doc_read_oob;
mtd->write_oob = doc_write_oob;
mtd->sync = NULL;
-
+
this->totlen = 0;
- this->numchips = 0;
+ this->numchips = 0;
this->curfloor = -1;
this->curchip = -1;
-
+
/* Ident all the chips present. */
DoC_ScanChips(this);
-
+
if (!this->totlen) {
kfree(mtd);
iounmap((void *)this->virtadr);
@@ -405,8 +409,9 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf, u_char *eccbuf)
{
- int i;
+ int i, ret;
volatile char dummy;
+ unsigned char syndrome[6];
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
unsigned long docptr = this->virtadr;
struct Nand *mychip = &this->chips[from >> (this->chipshift)];
@@ -429,45 +434,55 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
+ /* issue the Read0 or Read1 command depend on which half of the page
+ we are accessing. Polling the Flash Ready bit after issue 3 bytes
+ address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/
+ DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP);
+ DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
+ DoC_WaitReady(docptr);
+
if (eccbuf) {
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_EN, docptr, ECCConf);
} else {
- /* disable the ECC engine, FIXME: is this correct ?? */
+ /* disable the ECC engine */
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
- WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
}
- /* issue the Read0 or Read1 command depend on which half of the page
- we are accessing. Polling the Flash Ready bit after issue 3 bytes
- address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/
- DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP);
- DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
- DoC_WaitReady(docptr);
-
/* Read the data via the internal pipeline through CDSN IO register,
see Pipelined Read Operations 11.3 */
dummy = ReadDOC(docptr, ReadPipeInit);
+#ifndef USE_MEMCPY
for (i = 0; i < len-1; i++) {
- buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
+ /* N.B. you have to increase the source address in this way or the
+ ECC logic will not work properly */
+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
}
- buf[i] = ReadDOC(docptr, LastDataRead);
+#else
+ memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1);
+#endif
+ buf[len - 1] = ReadDOC(docptr, LastDataRead);
/* Let the caller know we completed it */
*retlen = len;
+ ret = 0;
if (eccbuf) {
- /* FIXME: are we reading the ECC from the ECC logic of DOC or
- the spare data space on the flash chip i.e. How do we
- control the Spare Area Enable bit of the flash ?? */
- /* Read the ECC data through the DiskOnChip ECC logic
+ /* Read the ECC data from Spare Data Area,
see Reed-Solomon EDC/ECC 11.1 */
dummy = ReadDOC(docptr, ReadPipeInit);
+#ifndef USE_MEMCPY
for (i = 0; i < 5; i++) {
- eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO);
+ /* N.B. you have to increase the source address in this way or the
+ ECC logic will not work properly */
+ eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
}
- eccbuf[i] = ReadDOC(docptr, LastDataRead);
+#else
+ memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5);
+#endif
+ eccbuf[5] = ReadDOC(docptr, LastDataRead);
/* Flush the pipeline */
dummy = ReadDOC(docptr, ECCConf);
@@ -475,34 +490,45 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
/* Check the ECC Status */
if (ReadDOC(docptr, ECCConf) & 0x80) {
+ int nb_errors;
/* There was an ECC error */
+#ifdef ECC_DEBUG
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
-
- /* FIXME: Implement ECC error correction, don't just whinge */
-
- /* We return error, but have actually done the read. Not that
- this can be told to user-space, via sys_read(), but at least
- MTD-aware stuff can know about it by checking *retlen */
- return -EIO;
+#endif
+ /* Read the ECC syndrom through the DiskOnChip ECC logic.
+ These syndrome will be all ZERO when there is no error */
+ for (i = 0; i < 6; i++) {
+ syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
+ }
+ nb_errors = doc_decode_ecc(buf, syndrome);
+#ifdef ECC_DEBUG
+ printk("Errors corrected: %x\n", nb_errors);
+#endif
+ if (nb_errors < 0) {
+ /* We return error, but have actually done the read. Not that
+ this can be told to user-space, via sys_read(), but at least
+ MTD-aware stuff can know about it by checking *retlen */
+ ret = -EIO;
+ }
}
+
#ifdef PSYCHO_DEBUG
- else
- printk("ECC OK at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
- (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
- eccbuf[4], eccbuf[5]);
+ printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+ (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
+ eccbuf[4], eccbuf[5]);
#endif
- /* Reset the ECC engine */
- WriteDOC(DOC_ECC_RESV, docptr , ECCConf);
+ /* disable the ECC engine */
+ WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
}
- return 0;
+ return ret;
}
static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
- static char as[6];
- return doc_write_ecc(mtd, to, len, retlen, buf, as);
+ char eccbuf[6];
+ return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf);
}
static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
@@ -532,42 +558,48 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
+ } else if (this->curchip != mychip->chip) {
DoC_SelectChip(docptr, mychip->chip);
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
/* Reset the chip, see Software Requirement 11.4 item 1. */
- DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
+ DoC_Command(docptr, NAND_CMD_RESET, 0x00);
DoC_WaitReady(docptr);
/* Set device to main plane of flash */
- DoC_Command(docptr, NAND_CMD_READ0, CDSN_CTRL_WP);
+ DoC_Command(docptr, NAND_CMD_READ0, 0x00);
+
+ /* issue the Serial Data In command to initial the Page Program process */
+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
+ DoC_Address(docptr, 3, to, 0x00, 0x00);
+ DoC_WaitReady(docptr);
if (eccbuf) {
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
} else {
- /* disable the ECC engine, FIXME: is this correct ?? */
+ /* disable the ECC engine */
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
}
- /* issue the Serial Data In command to initial the Page Program process */
- DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
- DoC_Address(docptr, 3, to, 0x00, 0x00);
-
/* Write the data via the internal pipeline through CDSN IO register,
see Pipelined Write Operations 11.2 */
+#ifndef USE_MEMCPY
for (i = 0; i < len; i++) {
- WriteDOC(buf[i], docptr, Mil_CDSN_IO);
+ /* N.B. you have to increase the source address in this way or the
+ ECC logic will not work properly */
+ WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
}
+#else
+ memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
+#endif
WriteDOC(0x00, docptr, WritePipeTerm);
if (eccbuf) {
- /* Write ECC data to flash, the ECC info is generated by the DiskOnChip DECC logic
+ /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
see Reed-Solomon EDC/ECC 11.1 */
WriteDOC(0, docptr, NOP);
WriteDOC(0, docptr, NOP);
@@ -578,10 +610,26 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
}
+ /* ignore the ECC engine */
+ WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
+
+#ifndef USE_MEMCPY
/* Write the ECC data to flash */
for (i = 0; i < 6; i++) {
- WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO);
+ /* N.B. you have to increase the source address in this way or the
+ ECC logic will not work properly */
+ WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i);
}
+#else
+ memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6);
+#endif
+
+ /* write the block status BLOCK_USED (0x5555) at the end of ECC data
+ FIXME: this is only a hack for programming the IPL area for LinuxBIOS
+ and should be replace with proper codes in user space utilities */
+ WriteDOC(0x55, docptr, Mil_CDSN_IO);
+ WriteDOC(0x55, docptr, Mil_CDSN_IO + 1);
+
WriteDOC(0x00, docptr, WritePipeTerm);
#ifdef PSYCHO_DEBUG
@@ -589,9 +637,6 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
eccbuf[4], eccbuf[5]);
#endif
-
- /* Reset the ECC engine */
- WriteDOC(DOC_ECC_RESV, docptr , ECCConf);
}
/* Commit the Page Program command and wait for ready
@@ -601,12 +646,13 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
/* Read the status of the flash device through CDSN Slow IO register
see Software Requirement 11.4 item 5.*/
- DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
+ DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
dummy = ReadDOC(docptr, CDSNSlowIO);
DoC_Delay(docptr, 2);
if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
printk("Error programming flash\n");
- /* Error in programming */
+ /* Error in programming
+ FIXME: implement Bad Block Replacement (in nftl.c ??) */
*retlen = 0;
return -EIO;
}
@@ -620,31 +666,29 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
size_t *retlen, u_char *buf)
{
- volatile char dummy;
+#ifndef USE_MEMCPY
int i;
+#endif
+ volatile char dummy;
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
unsigned long docptr = this->virtadr;
struct Nand *mychip = &this->chips[ofs >> this->chipshift];
- /* FIXME: should we restrict the access between 512 to 527 ?? */
-
/* Find the chip which is to be used and select it */
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
+ } else if (this->curchip != mychip->chip) {
DoC_SelectChip(docptr, mychip->chip);
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
- /* FIXME: should we disable ECC engine in this way ?? */
- /* disable the ECC engine, FIXME: is this correct ?? */
+ /* disable the ECC engine */
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
- /* issue the Read2 command to read the Spare Data Area.
+ /* issue the Read2 command to set the pointer to the Spare Data Area.
Polling the Flash Ready bit after issue 3 bytes address in
Sequence Read Mode, see Software Requirement 11.4 item 1.*/
DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
@@ -654,10 +698,17 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
/* Read the data out via the internal pipeline through CDSN IO register,
see Pipelined Read Operations 11.3 */
dummy = ReadDOC(docptr, ReadPipeInit);
+#ifndef USE_MEMCPY
for (i = 0; i < len-1; i++) {
- buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
+ /* N.B. you have to increase the source address in this way or the
+ ECC logic will not work properly */
+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
}
buf[i] = ReadDOC(docptr, LastDataRead);
+#else
+ memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1);
+#endif
+ buf[len - 1] = ReadDOC(docptr, LastDataRead);
*retlen = len;
@@ -667,32 +718,32 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
size_t *retlen, const u_char *buf)
{
+#ifndef USE_MEMCPY
int i;
+#endif
volatile char dummy;
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
unsigned long docptr = this->virtadr;
struct Nand *mychip = &this->chips[ofs >> this->chipshift];
/* Find the chip which is to be used and select it */
- if (this->curfloor != mychip->floor) {
+ if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
+ } else if (this->curchip != mychip->chip) {
DoC_SelectChip(docptr, mychip->chip);
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
- /* FIXME: should we disable ECC engine in this way ?? */
- /* disable the ECC engine, FIXME: is this correct ?? */
+ /* disable the ECC engine */
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
/* Reset the chip, see Software Requirement 11.4 item 1. */
DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
DoC_WaitReady(docptr);
- /* issue the Read2 command to read the Spare Data Area. */
+ /* issue the Read2 command to set the pointer to the Spare Data Area. */
DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
/* issue the Serial Data In command to initial the Page Program process */
@@ -701,8 +752,15 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
/* Write the data via the internal pipeline through CDSN IO register,
see Pipelined Write Operations 11.2 */
- for (i = 0; i < len; i++)
- WriteDOC(buf[i], docptr, Mil_CDSN_IO);
+#ifndef USE_MEMCPY
+ for (i = 0; i < len; i++) {
+ /* N.B. you have to increase the source address in this way or the
+ ECC logic will not work properly */
+ WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
+ }
+#else
+ memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
+#endif
WriteDOC(0x00, docptr, WritePipeTerm);
/* Commit the Page Program command and wait for ready
@@ -717,6 +775,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
DoC_Delay(docptr, 2);
if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
printk("Error programming oob data\n");
+ /* FIXME: implement Bad Block Replacement (in nftl.c ??) */
*retlen = 0;
return -EIO;
}
@@ -743,13 +802,12 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
+ } else if (this->curchip != mychip->chip) {
DoC_SelectChip(docptr, mychip->chip);
}
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
+
instr->state = MTD_ERASE_PENDING;
/* issue the Erase Setup command */
@@ -764,13 +822,16 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASING;
/* Read the status of the flash device through CDSN Slow IO register
- see Software Requirement 11.4 item 5.*/
+ see Software Requirement 11.4 item 5.
+ FIXME: it seems that we are not wait long enough, some blocks are not
+ erased fully */
DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
dummy = ReadDOC(docptr, CDSNSlowIO);
DoC_Delay(docptr, 2);
if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
- printk("Error Erasing\n");
- /* There was an error */
+ printk("Error Erasing at 0x%lx\n", ofs);
+ /* There was an error
+ FIXME: implement Bad Block Replacement (in nftl.c ??) */
instr->state = MTD_ERASE_FAILED;
} else
instr->state = MTD_ERASE_DONE;
@@ -787,20 +848,17 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
*
****************************************************************************/
-static int __init init_doc2001(void)
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
+#define cleanup_doc2001 cleanup_module
+#define init_doc2001 init_module
+#endif
+
+int __init init_doc2001(void)
{
inter_module_register(im_name, THIS_MODULE, &DoCMil_init);
return 0;
}
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
-#define cleanup_doc2001 cleanup_module
-#endif
-#define __exit
-#endif
-
-
static void __exit cleanup_doc2001(void)
{
struct mtd_info *mtd;
@@ -817,11 +875,9 @@ static void __exit cleanup_doc2001(void)
kfree(mtd);
}
inter_module_unregister(im_name);
-
}
+module_exit(cleanup_doc2001);
module_init(init_doc2001);
-#if LINUX_VERSION_CODE > 0x20300
-module_exit(cleanup_doc2001);
-#endif
+
diff --git a/drivers/mtd/docecc.c b/drivers/mtd/docecc.c
new file mode 100644
index 000000000..cddc968c0
--- /dev/null
+++ b/drivers/mtd/docecc.c
@@ -0,0 +1,522 @@
+/*
+ * ECC algorithm for M-systems disk on chip. We use the excellent Reed
+ * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the
+ * GNU GPL License. The rest is simply to convert the disk on chip
+ * syndrom into a standard syndom.
+ *
+ * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
+ * Copyright (C) 2000 Netgem S.A.
+ *
+ * $Id: docecc.c,v 1.1 2000/11/03 12:43:43 dwmw2 Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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/module.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/doc2000.h>
+
+/* need to undef it (from asm/termbits.h) */
+#undef B0
+
+#define MM 10 /* Symbol size in bits */
+#define KK (1023-4) /* Number of data symbols per block */
+#define B0 510 /* First root of generator polynomial, alpha form */
+#define PRIM 1 /* power of alpha used to generate roots of generator poly */
+#define NN ((1 << MM) - 1)
+
+typedef unsigned short dtype;
+
+/* 1+x^3+x^10 */
+static const int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
+
+/* This defines the type used to store an element of the Galois Field
+ * used by the code. Make sure this is something larger than a char if
+ * if anything larger than GF(256) is used.
+ *
+ * Note: unsigned char will work up to GF(256) but int seems to run
+ * faster on the Pentium.
+ */
+typedef int gf;
+
+/* No legal value in index form represents zero, so
+ * we need a special value for this purpose
+ */
+#define A0 (NN)
+
+/* Compute x % NN, where NN is 2**MM - 1,
+ * without a slow divide
+ */
+static inline gf
+modnn(int x)
+{
+ while (x >= NN) {
+ x -= NN;
+ x = (x >> MM) + (x & NN);
+ }
+ return x;
+}
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+#define CLEAR(a,n) {\
+int ci;\
+for(ci=(n)-1;ci >=0;ci--)\
+(a)[ci] = 0;\
+}
+
+#define COPY(a,b,n) {\
+int ci;\
+for(ci=(n)-1;ci >=0;ci--)\
+(a)[ci] = (b)[ci];\
+}
+
+#define COPYDOWN(a,b,n) {\
+int ci;\
+for(ci=(n)-1;ci >=0;ci--)\
+(a)[ci] = (b)[ci];\
+}
+
+#define Ldec 1
+
+/* generate GF(2**m) from the irreducible polynomial p(X) in Pp[0]..Pp[m]
+ lookup tables: index->polynomial form alpha_to[] contains j=alpha**i;
+ polynomial form -> index form index_of[j=alpha**i] = i
+ alpha=2 is the primitive element of GF(2**m)
+ HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:
+ Let @ represent the primitive element commonly called "alpha" that
+ is the root of the primitive polynomial p(x). Then in GF(2^m), for any
+ 0 <= i <= 2^m-2,
+ @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
+ where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation
+ of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for
+ example the polynomial representation of @^5 would be given by the binary
+ representation of the integer "alpha_to[5]".
+ Similarily, index_of[] can be used as follows:
+ As above, let @ represent the primitive element of GF(2^m) that is
+ the root of the primitive polynomial p(x). In order to find the power
+ of @ (alpha) that has the polynomial representation
+ a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
+ we consider the integer "i" whose binary representation with a(0) being LSB
+ and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry
+ "index_of[i]". Now, @^index_of[i] is that element whose polynomial
+ representation is (a(0),a(1),a(2),...,a(m-1)).
+ NOTE:
+ The element alpha_to[2^m-1] = 0 always signifying that the
+ representation of "@^infinity" = 0 is (0,0,0,...,0).
+ Similarily, the element index_of[0] = A0 always signifying
+ that the power of alpha which has the polynomial representation
+ (0,0,...,0) is "infinity".
+
+*/
+
+static void
+generate_gf(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1])
+{
+ register int i, mask;
+
+ mask = 1;
+ Alpha_to[MM] = 0;
+ for (i = 0; i < MM; i++) {
+ Alpha_to[i] = mask;
+ Index_of[Alpha_to[i]] = i;
+ /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */
+ if (Pp[i] != 0)
+ Alpha_to[MM] ^= mask; /* Bit-wise EXOR operation */
+ mask <<= 1; /* single left-shift */
+ }
+ Index_of[Alpha_to[MM]] = MM;
+ /*
+ * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by
+ * poly-repr of @^i shifted left one-bit and accounting for any @^MM
+ * term that may occur when poly-repr of @^i is shifted.
+ */
+ mask >>= 1;
+ for (i = MM + 1; i < NN; i++) {
+ if (Alpha_to[i - 1] >= mask)
+ Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);
+ else
+ Alpha_to[i] = Alpha_to[i - 1] << 1;
+ Index_of[Alpha_to[i]] = i;
+ }
+ Index_of[0] = A0;
+ Alpha_to[NN] = 0;
+}
+
+/*
+ * Performs ERRORS+ERASURES decoding of RS codes. bb[] is the content
+ * of the feedback shift register after having processed the data and
+ * the ECC.
+ *
+ * Return number of symbols corrected, or -1 if codeword is illegal
+ * or uncorrectable. If eras_pos is non-null, the detected error locations
+ * are written back. NOTE! This array must be at least NN-KK elements long.
+ * The corrected data are written in eras_val[]. They must be xor with the data
+ * to retrieve the correct data : data[erase_pos[i]] ^= erase_val[i] .
+ *
+ * First "no_eras" erasures are declared by the calling program. Then, the
+ * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).
+ * If the number of channel errors is not greater than "t_after_eras" the
+ * transmitted codeword will be recovered. Details of algorithm can be found
+ * in R. Blahut's "Theory ... of Error-Correcting Codes".
+
+ * Warning: the eras_pos[] array must not contain duplicate entries; decoder failure
+ * will result. The decoder *could* check for this condition, but it would involve
+ * extra time on every decoding operation.
+ * */
+static int
+eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
+ gf bb[NN - KK + 1], gf eras_val[NN-KK], int eras_pos[NN-KK],
+ int no_eras)
+{
+ int deg_lambda, el, deg_omega;
+ int i, j, r,k;
+ gf u,q,tmp,num1,num2,den,discr_r;
+ gf lambda[NN-KK + 1], s[NN-KK + 1]; /* Err+Eras Locator poly
+ * and syndrome poly */
+ gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];
+ gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];
+ int syn_error, count;
+
+ syn_error = 0;
+ for(i=0;i<NN-KK;i++)
+ syn_error |= bb[i];
+
+ if (!syn_error) {
+ /* if remainder is zero, data[] is a codeword and there are no
+ * errors to correct. So return data[] unmodified
+ */
+ count = 0;
+ goto finish;
+ }
+
+ for(i=1;i<=NN-KK;i++){
+ s[i] = bb[0];
+ }
+ for(j=1;j<NN-KK;j++){
+ if(bb[j] == 0)
+ continue;
+ tmp = Index_of[bb[j]];
+
+ for(i=1;i<=NN-KK;i++)
+ s[i] ^= Alpha_to[modnn(tmp + (B0+i-1)*PRIM*j)];
+ }
+
+ /* undo the feedback register implicit multiplication and convert
+ syndromes to index form */
+
+ for(i=1;i<=NN-KK;i++) {
+ tmp = Index_of[s[i]];
+ if (tmp != A0)
+ tmp = modnn(tmp + 2 * KK * (B0+i-1)*PRIM);
+ s[i] = tmp;
+ }
+
+ CLEAR(&lambda[1],NN-KK);
+ lambda[0] = 1;
+
+ if (no_eras > 0) {
+ /* Init lambda to be the erasure locator polynomial */
+ lambda[1] = Alpha_to[modnn(PRIM * eras_pos[0])];
+ for (i = 1; i < no_eras; i++) {
+ u = modnn(PRIM*eras_pos[i]);
+ for (j = i+1; j > 0; j--) {
+ tmp = Index_of[lambda[j - 1]];
+ if(tmp != A0)
+ lambda[j] ^= Alpha_to[modnn(u + tmp)];
+ }
+ }
+#if DEBUG >= 1
+ /* Test code that verifies the erasure locator polynomial just constructed
+ Needed only for decoder debugging. */
+
+ /* find roots of the erasure location polynomial */
+ for(i=1;i<=no_eras;i++)
+ reg[i] = Index_of[lambda[i]];
+ count = 0;
+ for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) {
+ q = 1;
+ for (j = 1; j <= no_eras; j++)
+ if (reg[j] != A0) {
+ reg[j] = modnn(reg[j] + j);
+ q ^= Alpha_to[reg[j]];
+ }
+ if (q != 0)
+ continue;
+ /* store root and error location number indices */
+ root[count] = i;
+ loc[count] = k;
+ count++;
+ }
+ if (count != no_eras) {
+ printf("\n lambda(x) is WRONG\n");
+ count = -1;
+ goto finish;
+ }
+#if DEBUG >= 2
+ printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
+ for (i = 0; i < count; i++)
+ printf("%d ", loc[i]);
+ printf("\n");
+#endif
+#endif
+ }
+ for(i=0;i<NN-KK+1;i++)
+ b[i] = Index_of[lambda[i]];
+
+ /*
+ * Begin Berlekamp-Massey algorithm to determine error+erasure
+ * locator polynomial
+ */
+ r = no_eras;
+ el = no_eras;
+ while (++r <= NN-KK) { /* r is the step number */
+ /* Compute discrepancy at the r-th step in poly-form */
+ discr_r = 0;
+ for (i = 0; i < r; i++){
+ if ((lambda[i] != 0) && (s[r - i] != A0)) {
+ discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];
+ }
+ }
+ discr_r = Index_of[discr_r]; /* Index form */
+ if (discr_r == A0) {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ COPYDOWN(&b[1],b,NN-KK);
+ b[0] = A0;
+ } else {
+ /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
+ t[0] = lambda[0];
+ for (i = 0 ; i < NN-KK; i++) {
+ if(b[i] != A0)
+ t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];
+ else
+ t[i+1] = lambda[i+1];
+ }
+ if (2 * el <= r + no_eras - 1) {
+ el = r + no_eras - el;
+ /*
+ * 2 lines below: B(x) <-- inv(discr_r) *
+ * lambda(x)
+ */
+ for (i = 0; i <= NN-KK; i++)
+ b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);
+ } else {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ COPYDOWN(&b[1],b,NN-KK);
+ b[0] = A0;
+ }
+ COPY(lambda,t,NN-KK+1);
+ }
+ }
+
+ /* Convert lambda to index form and compute deg(lambda(x)) */
+ deg_lambda = 0;
+ for(i=0;i<NN-KK+1;i++){
+ lambda[i] = Index_of[lambda[i]];
+ if(lambda[i] != A0)
+ deg_lambda = i;
+ }
+ /*
+ * Find roots of the error+erasure locator polynomial by Chien
+ * Search
+ */
+ COPY(&reg[1],&lambda[1],NN-KK);
+ count = 0; /* Number of roots of lambda(x) */
+ for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) {
+ q = 1;
+ for (j = deg_lambda; j > 0; j--){
+ if (reg[j] != A0) {
+ reg[j] = modnn(reg[j] + j);
+ q ^= Alpha_to[reg[j]];
+ }
+ }
+ if (q != 0)
+ continue;
+ /* store root (index-form) and error location number */
+ root[count] = i;
+ loc[count] = k;
+ /* If we've already found max possible roots,
+ * abort the search to save time
+ */
+ if(++count == deg_lambda)
+ break;
+ }
+ if (deg_lambda != count) {
+ /*
+ * deg(lambda) unequal to number of roots => uncorrectable
+ * error detected
+ */
+ count = -1;
+ goto finish;
+ }
+ /*
+ * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
+ * x**(NN-KK)). in index form. Also find deg(omega).
+ */
+ deg_omega = 0;
+ for (i = 0; i < NN-KK;i++){
+ tmp = 0;
+ j = (deg_lambda < i) ? deg_lambda : i;
+ for(;j >= 0; j--){
+ if ((s[i + 1 - j] != A0) && (lambda[j] != A0))
+ tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
+ }
+ if(tmp != 0)
+ deg_omega = i;
+ omega[i] = Index_of[tmp];
+ }
+ omega[NN-KK] = A0;
+
+ /*
+ * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
+ * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form
+ */
+ for (j = count-1; j >=0; j--) {
+ num1 = 0;
+ for (i = deg_omega; i >= 0; i--) {
+ if (omega[i] != A0)
+ num1 ^= Alpha_to[modnn(omega[i] + i * root[j])];
+ }
+ num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];
+ den = 0;
+
+ /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
+ for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {
+ if(lambda[i+1] != A0)
+ den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
+ }
+ if (den == 0) {
+#if DEBUG >= 1
+ printf("\n ERROR: denominator = 0\n");
+#endif
+ /* Convert to dual- basis */
+ count = -1;
+ goto finish;
+ }
+ /* Apply error to data */
+ if (num1 != 0) {
+ eras_val[j] = Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];
+ } else {
+ eras_val[j] = 0;
+ }
+ }
+ finish:
+ for(i=0;i<count;i++)
+ eras_pos[i] = loc[i];
+ return count;
+}
+
+/***************************************************************************/
+/* The DOC specific code begins here */
+
+#define SECTOR_SIZE 512
+/* The sector bytes are packed into NB_DATA MM bits words */
+#define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / MM)
+
+/*
+ * Correct the errors in 'sector[]' by using 'ecc1[]' which is the
+ * content of the feedback shift register applyied to the sector and
+ * the ECC. Return the number of errors corrected (and correct them in
+ * sector), or -1 if error
+ */
+int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6])
+{
+ int parity, i, nb_errors;
+ gf bb[NN - KK + 1];
+ gf error_val[NN-KK];
+ int error_pos[NN-KK], pos, bitpos, index, val;
+ dtype *Alpha_to, *Index_of;
+
+ /* init log and exp tables here to save memory. However, it is slower */
+ Alpha_to = kmalloc((NN + 1) * sizeof(dtype), GFP_KERNEL);
+ if (!Alpha_to)
+ return -1;
+
+ Index_of = kmalloc((NN + 1) * sizeof(dtype), GFP_KERNEL);
+ if (!Index_of) {
+ kfree(Alpha_to);
+ return -1;
+ }
+
+ generate_gf(Alpha_to, Index_of);
+
+ parity = ecc1[1];
+
+ bb[0] = (ecc1[4] & 0xff) | ((ecc1[5] & 0x03) << 8);
+ bb[1] = ((ecc1[5] & 0xfc) >> 2) | ((ecc1[2] & 0x0f) << 6);
+ bb[2] = ((ecc1[2] & 0xf0) >> 4) | ((ecc1[3] & 0x3f) << 4);
+ bb[3] = ((ecc1[3] & 0xc0) >> 6) | ((ecc1[0] & 0xff) << 2);
+
+ nb_errors = eras_dec_rs(Alpha_to, Index_of, bb,
+ error_val, error_pos, 0);
+ if (nb_errors <= 0)
+ goto the_end;
+
+ /* correct the errors */
+ for(i=0;i<nb_errors;i++) {
+ pos = error_pos[i];
+ if (pos >= NB_DATA && pos < KK) {
+ nb_errors = -1;
+ goto the_end;
+ }
+ if (pos < NB_DATA) {
+ /* extract bit position (MSB first) */
+ pos = 10 * (NB_DATA - 1 - pos) - 6;
+ /* now correct the following 10 bits. At most two bytes
+ can be modified since pos is even */
+ index = (pos >> 3) ^ 1;
+ bitpos = pos & 7;
+ if ((index >= 0 && index < SECTOR_SIZE) ||
+ index == (SECTOR_SIZE + 1)) {
+ val = error_val[i] >> (2 + bitpos);
+ parity ^= val;
+ if (index < SECTOR_SIZE)
+ sector[index] ^= val;
+ }
+ index = ((pos >> 3) + 1) ^ 1;
+ bitpos = (bitpos + 10) & 7;
+ if (bitpos == 0)
+ bitpos = 8;
+ if ((index >= 0 && index < SECTOR_SIZE) ||
+ index == (SECTOR_SIZE + 1)) {
+ val = error_val[i] << (8 - bitpos);
+ parity ^= val;
+ if (index < SECTOR_SIZE)
+ sector[index] ^= val;
+ }
+ }
+ }
+
+ /* use parity to test extra errors */
+ if ((parity & 0xff) != 0)
+ nb_errors = -1;
+
+ the_end:
+ kfree(Alpha_to);
+ kfree(Index_of);
+ return nb_errors;
+}
+
diff --git a/drivers/mtd/docprobe.c b/drivers/mtd/docprobe.c
index b38b4352d..c67a3489a 100644
--- a/drivers/mtd/docprobe.c
+++ b/drivers/mtd/docprobe.c
@@ -3,7 +3,7 @@
/* Probe routines common to all DoC devices */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: docprobe.c,v 1.10 2000/07/13 14:23:20 dwmw2 Exp $ */
+/* $Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $ */
@@ -26,6 +26,21 @@
#define DOC_PASSIVE_PROBE
*/
+
+/* DOC_SINGLE_DRIVER:
+ Millennium driver has been merged into DOC2000 driver.
+
+ The newly-merged driver doesn't appear to work for writing. It's the
+ same with the DiskOnChip 2000 and the Millennium. If you have a
+ Millennium and you want write support to work, remove the definition
+ of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver.
+
+ Otherwise, it's left on in the hope that it'll annoy someone with
+ a Millennium enough that they go through and work out what the
+ difference is :)
+*/
+#define DOC_SINGLE_DRIVER
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/errno.h>
@@ -44,21 +59,36 @@
#include <linux/mtd/doc2000.h>
/* Where to look for the devices? */
+#ifndef CONFIG_MTD_DOCPROBE_ADDRESS
+#define CONFIG_MTD_DOCPROBE_ADDRESS 0
+#endif
+
+
+static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
+MODULE_PARM(doc_config_location, "l");
+
+static unsigned long __initdata doc_locations[] = {
#if defined (__alpha__) || defined(__i386__)
-static unsigned long __initdata doc_locations[] = {
- 0xc8000, 0xca000, 0xcc000, 0xce000,
- 0xd0000, 0xd2000, 0xd4000, 0xd6000,
- 0xd8000, 0xda000, 0xdc000, 0xde000,
- 0xe0000, 0xe2000, 0xe4000, 0xe6000,
- 0xe8000, 0xea000, 0xec000, 0xee000, 0 };
+#ifdef CONFIG_MTD_DOCPROBE_HIGH
+ 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
+ 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
+ 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
+ 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
+ 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
+#else /* CONFIG_MTD_DOCPROBE_HIGH */
+ 0xc8000, 0xca000, 0xcc000, 0xce000,
+ 0xd0000, 0xd2000, 0xd4000, 0xd6000,
+ 0xd8000, 0xda000, 0xdc000, 0xde000,
+ 0xe0000, 0xe2000, 0xe4000, 0xe6000,
+ 0xe8000, 0xea000, 0xec000, 0xee000,
+#endif /* CONFIG_MTD_DOCPROBE_HIGH */
#elif defined(__ppc__)
-static unsigned long __initdata doc_locations[] = {
- 0xe4000000, 0};
+ 0xe4000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
#endif
-
+ 0 };
/* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
@@ -71,10 +101,13 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
#endif
/* Routine copied from the Linux DOC driver */
-
- /* Check for 0x55 0xAA signature at beginning of window */
+
+#ifdef CONFIG_MTD_DOCPROBE_55AA
+ /* Check for 0x55 0xAA signature at beginning of window,
+ this is no longer true once we remove the IPL (for Millennium */
if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
return 0;
+#endif /* CONFIG_MTD_DOCPROBE_55AA */
#ifndef DOC_PASSIVE_PROBE
/* It's not possible to cleanly detect the DiskOnChip - the
@@ -118,9 +151,10 @@ static inline int __init doccheck(unsigned long potential, unsigned long physadr
break;
default:
+#ifndef CONFIG_MTD_DOCPROBE_55AA
printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
ChipID, physadr);
-
+#endif
#ifndef DOC_PASSIVE_PROBE
/* Put back the contents of the DOCControl register, in case it's not
* actually a DiskOnChip.
@@ -177,28 +211,35 @@ static void DoC_Probe(unsigned long physadr)
this->physadr = physadr;
this->ChipID = ChipID;
sprintf(namebuf, "with ChipID %2.2X", ChipID);
-
+
switch(ChipID) {
case DOC_ChipID_Doc2k:
name="2000";
im_funcname = "DoC2k_init";
im_modname = "doc2000";
break;
-
+
case DOC_ChipID_DocMil:
name="Millennium";
+#ifdef DOC_SINGLE_DRIVER
+ im_funcname = "DoC2k_init";
+ im_modname = "doc2000";
+#else
im_funcname = "DoCMil_init";
im_modname = "doc2001";
+#endif /* DOC_SINGLE_DRIVER */
break;
}
+
if (im_funcname)
initroutine = inter_module_get_request(im_funcname, im_modname);
+
if (initroutine) {
(*initroutine)(mtd);
inter_module_put(im_funcname);
return;
}
- printk("Cannot find driver for DiskOnChip %s at 0x%X\n", name, physadr);
+ printk("Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
}
iounmap((void *)docptr);
}
@@ -210,12 +251,9 @@ static void DoC_Probe(unsigned long physadr)
*
****************************************************************************/
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_doc init_module
#endif
-#define __exit
-#endif
int __init init_doc(void)
{
@@ -223,19 +261,22 @@ int __init init_doc(void)
printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n");
#ifdef PRERELEASE
- printk(KERN_INFO "$Id: docprobe.c,v 1.10 2000/07/13 14:23:20 dwmw2 Exp $\n");
+ printk(KERN_INFO "$Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $\n");
#endif
-
- for (i=0; doc_locations[i]; i++) {
- DoC_Probe(doc_locations[i]);
+ if (doc_config_location) {
+ printk("Using configured probe address 0x%lx\n", doc_config_location);
+ DoC_Probe(doc_config_location);
+ } else {
+ for (i=0; doc_locations[i]; i++) {
+ DoC_Probe(doc_locations[i]);
+ }
}
-
+ /* So it looks like we've been used and we get unloaded */
+ MOD_INC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
return 0;
}
-
-#if LINUX_VERSION_CODE > 0x20300
module_init(init_doc);
-#endif
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 1cf4a5f16..21ed0cecd 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1,6 +1,10 @@
/* This version ported to the Linux-MTD system by dwmw2@infradead.org
- * $Id: ftl.c,v 1.20 2000/06/23 15:17:53 dwmw2 Exp $
- * Based on:
+ *
+ * - Based on Id: ftl.c,v 1.21 2000/08/01 13:07:49 dwmw2 Exp
+ * - With the Franz Galiana's set_bam_entry fix from v1.23
+ * - Perhaps it's about time I made a branch for the 2.4 series.
+
+ * Originally based on:
*/
/*======================================================================
@@ -263,12 +267,13 @@ static struct block_device_operations ftl_blk_fops = {
static int scan_header(partition_t *part)
{
erase_unit_header_t header;
- loff_t offset;
+ loff_t offset, max_offset;
int ret;
part->header.FormattedSize = 0;
+ max_offset = (0x100000<part->mtd->size)?0x100000:part->mtd->size;
/* Search first megabyte for a valid FTL header */
for (offset = 0;
- offset < 0x100000;
+ offset < max_offset;
offset += part->mtd->erasesize?part->mtd->erasesize:0x2000) {
ret = part->mtd->read(part->mtd, offset, sizeof(header), &ret,
@@ -280,7 +285,7 @@ static int scan_header(partition_t *part)
if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
}
- if (offset == 0x100000) {
+ if (offset == max_offset) {
printk(KERN_NOTICE "ftl_cs: FTL header not found.\n");
return -ENOENT;
}
@@ -998,7 +1003,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
static int set_bam_entry(partition_t *part, u_int32_t log_addr,
u_int32_t virt_addr)
{
- u_int32_t bsize, blk;
+ u_int32_t bsize, blk, le_virt_addr;
#ifdef PSYCHO_DEBUG
u_int32_t old_addr;
#endif
@@ -1035,6 +1040,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
return -EIO;
}
#endif
+ le_virt_addr = cpu_to_le32(virt_addr);
if (part->bam_index == eun) {
#ifdef PSYCHO_DEBUG
if (le32_to_cpu(part->bam_cache[blk]) != old_addr) {
@@ -1049,10 +1055,10 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
return -EIO;
}
#endif
- part->bam_cache[blk] = cpu_to_le32(virt_addr);
+ part->bam_cache[blk] = le_virt_addr;
}
ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t),
- &retlen, (u_char *)&part->bam_cache[blk]);
+ &retlen, (u_char *)&le_virt_addr);
if (ret) {
printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n");
@@ -1410,8 +1416,6 @@ mod_init_t init_ftl(void)
memset(myparts, 0, sizeof(myparts));
- DEBUG(0, "$Id: ftl.c,v 1.20 2000/06/23 15:17:53 dwmw2 Exp $\n");
-
if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {
printk(KERN_NOTICE "ftl_cs: unable to grab major "
"device number!\n");
diff --git a/drivers/mtd/map_ram.c b/drivers/mtd/map_ram.c
index c62515406..00c009d7f 100644
--- a/drivers/mtd/map_ram.c
+++ b/drivers/mtd/map_ram.c
@@ -1,7 +1,7 @@
/*
* Common code to handle map devices which are simple RAM
* (C) 2000 Red Hat. GPL'd.
- * $Id: map_ram.c,v 1.2 2000/07/03 10:01:38 dwmw2 Exp $
+ * $Id: map_ram.c,v 1.7 2000/12/10 01:39:13 dwmw2 Exp $
*/
#include <linux/module.h>
@@ -29,6 +29,7 @@ static const char im_name[] = "map_ram_probe";
* this module is non-zero, i.e. between inter_module_get and
* inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
*/
+
static struct mtd_info *map_ram_probe(struct map_info *map)
{
struct mtd_info *mtd;
@@ -59,6 +60,7 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
memset(mtd, 0, sizeof(*mtd));
+ map->im_name = im_name;
map->fldrv_destroy = mapram_nop;
mtd->priv = map;
mtd->name = map->name;
@@ -69,9 +71,9 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
mtd->read = mapram_read;
mtd->write = mapram_write;
mtd->sync = mapram_nop;
- mtd->im_name = im_name;
mtd->flags = MTD_CAP_RAM | MTD_VOLATILE;
-
+ mtd->erasesize = PAGE_SIZE;
+
return mtd;
}
@@ -115,6 +117,11 @@ static void mapram_nop(struct mtd_info *mtd)
/* Nothing to see here */
}
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
+#define map_ram_init init_module
+#define map_ram_exit cleanup_module
+#endif
+
static int __init map_ram_init(void)
{
inter_module_register(im_name, THIS_MODULE, &map_ram_probe);
diff --git a/drivers/mtd/map_rom.c b/drivers/mtd/map_rom.c
index d353938e9..c976c7ecf 100644
--- a/drivers/mtd/map_rom.c
+++ b/drivers/mtd/map_rom.c
@@ -1,7 +1,7 @@
/*
* Common code to handle map devices which are simple ROM
* (C) 2000 Red Hat. GPL'd.
- * $Id: map_rom.c,v 1.2 2000/07/03 10:01:38 dwmw2 Exp $
+ * $Id: map_rom.c,v 1.10 2000/12/10 01:39:13 dwmw2 Exp $
*/
#include <linux/module.h>
@@ -14,12 +14,19 @@
#include <linux/mtd/map.h>
-
static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
static void maprom_nop (struct mtd_info *);
-struct mtd_info *map_rom_probe(struct map_info *);
-EXPORT_SYMBOL(map_rom_probe);
+static const char im_name[] = "map_rom_probe";
+
+/* This routine is made available to other mtd code via
+ * inter_module_register. It must only be accessed through
+ * inter_module_get which will bump the use count of this module. The
+ * addresses passed back in mtd are valid as long as the use count of
+ * this module is non-zero, i.e. between inter_module_get and
+ * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
+ */
struct mtd_info *map_rom_probe(struct map_info *map)
{
@@ -31,16 +38,18 @@ struct mtd_info *map_rom_probe(struct map_info *map)
memset(mtd, 0, sizeof(*mtd));
+ map->im_name = im_name;
map->fldrv_destroy = maprom_nop;
mtd->priv = map;
mtd->name = map->name;
mtd->type = MTD_ROM;
mtd->size = map->size;
mtd->read = maprom_read;
+ mtd->write = maprom_write;
mtd->sync = maprom_nop;
mtd->flags = MTD_CAP_ROM;
-
- MOD_INC_USE_COUNT;
+ mtd->erasesize = 131072;
+
return mtd;
}
@@ -58,3 +67,28 @@ static void maprom_nop(struct mtd_info *mtd)
{
/* Nothing to see here */
}
+
+static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
+{
+ printk(KERN_NOTICE "maprom_write called\n");
+ return -EIO;
+}
+
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
+#define map_rom_init init_module
+#define map_rom_exit cleanup_module
+#endif
+
+static int __init map_rom_init(void)
+{
+ inter_module_register(im_name, THIS_MODULE, &map_rom_probe);
+ return 0;
+}
+
+static void __exit map_rom_exit(void)
+{
+ inter_module_unregister(im_name);
+}
+
+module_init(map_rom_init);
+module_exit(map_rom_exit);
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index b728ddcd2..0a33ed1cf 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -1,16 +1,15 @@
/*
* Direct MTD block device access
*
- * $Id: mtdblock.c,v 1.17 2000/07/13 14:25:54 dwmw2 Exp $
+ * $Id: mtdblock.c,v 1.38 2000/11/27 08:50:22 dwmw2 Exp $
+ *
+ * 02-nov-2000 Nicolas Pitre Added read-modify-write with cache
*/
-#ifdef MTDBLOCK_DEBUG
-#define DEBUGLVL debug
-#endif
-
#include <linux/types.h>
#include <linux/module.h>
-
+#include <linux/kernel.h>
+#include <linux/malloc.h>
#include <linux/mtd/mtd.h>
#define MAJOR_NR MTD_BLOCK_MAJOR
@@ -21,62 +20,332 @@
#define DEVICE_OFF(device)
#define DEVICE_NO_RANDOM
#include <linux/blk.h>
-
+/* for old kernels... */
+#ifndef QUEUE_EMPTY
+#define QUEUE_EMPTY (!CURRENT)
+#endif
#if LINUX_VERSION_CODE < 0x20300
-#define RQFUNC_ARG void
-#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0)
+#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync)
#else
-#define RQFUNC_ARG request_queue_t *q
+#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged)
#endif
-#ifdef MTDBLOCK_DEBUG
-static int debug = MTDBLOCK_DEBUG;
-MODULE_PARM(debug, "i");
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+static void mtd_notify_add(struct mtd_info* mtd);
+static void mtd_notify_remove(struct mtd_info* mtd);
+static struct mtd_notifier notifier = {
+ mtd_notify_add,
+ mtd_notify_remove,
+ NULL
+};
+static devfs_handle_t devfs_dir_handle = NULL;
+static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES];
#endif
-#if 1
-static void mtdblock_end_request(struct request *req, int res)
+static struct mtdblk_dev {
+ struct mtd_info *mtd; /* Locked */
+ int count;
+ struct semaphore cache_sem;
+ unsigned char *cache_data;
+ unsigned long cache_offset;
+ unsigned int cache_size;
+ enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
+} *mtdblks[MAX_MTD_DEVICES];
+
+static spinlock_t mtdblks_lock;
+
+static int mtd_sizes[MAX_MTD_DEVICES];
+static int mtd_blksizes[MAX_MTD_DEVICES];
+
+
+/*
+ * Cache stuff...
+ *
+ * Since typical flash erasable sectors are much larger than what Linux's
+ * buffer cache can handle, we must implement read-modify-write on flash
+ * sectors for each block write requests. To avoid over-erasing flash sectors
+ * and to speed things up, we locally cache a whole flash sector while it is
+ * being written to until a different sector is required.
+ */
+
+static void erase_callback(struct erase_info *done)
{
- if (end_that_request_first( req, res, "mtdblock" ))
- return;
- end_that_request_last( req );
+ wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
+ wake_up(wait_q);
}
-#endif
-static int mtd_sizes[MAX_MTD_DEVICES];
+static int erase_write (struct mtd_info *mtd, unsigned long pos,
+ int len, const char *buf)
+{
+ struct erase_info erase;
+ DECLARE_WAITQUEUE(wait, current);
+ wait_queue_head_t wait_q;
+ size_t retlen;
+ int ret;
+
+ /*
+ * First, let's erase the flash block.
+ */
+
+ init_waitqueue_head(&wait_q);
+ erase.mtd = mtd;
+ erase.callback = erase_callback;
+ erase.addr = pos;
+ erase.len = len;
+ erase.priv = (u_long)&wait_q;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&wait_q, &wait);
+
+ ret = MTD_ERASE(mtd, &erase);
+ if (ret) {
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&wait_q, &wait);
+ printk (KERN_WARNING "mtdblock: erase of region [0x%lx, 0x%x] "
+ "on \"%s\" failed\n",
+ pos, len, mtd->name);
+ return ret;
+ }
+ schedule(); /* Wait for erase to finish. */
+ remove_wait_queue(&wait_q, &wait);
-/* Keeping a separate list rather than just getting stuff directly out of
- the MTD core's mtd_table is perhaps not very nice, but I happen
- to dislike the idea of directly accessing mtd_table even more.
- dwmw2 31/3/0
-*/
+ /*
+ * Next, writhe data to flash.
+ */
-static int mtdblock_open(struct inode *inode, struct file *file)
+ ret = MTD_WRITE (mtd, pos, len, &retlen, buf);
+ if (ret)
+ return ret;
+ if (retlen != len)
+ return -EIO;
+ return 0;
+}
+
+
+static int write_cached_data (struct mtdblk_dev *mtdblk)
+{
+ struct mtd_info *mtd = mtdblk->mtd;
+ int ret;
+
+ if (mtdblk->cache_state != STATE_DIRTY)
+ return 0;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" "
+ "at 0x%lx, size 0x%x\n", mtd->name,
+ mtdblk->cache_offset, mtdblk->cache_size);
+
+ ret = erase_write (mtd, mtdblk->cache_offset,
+ mtdblk->cache_size, mtdblk->cache_data);
+ if (ret)
+ return ret;
+
+ /*
+ * Here we could argably set the cache state to STATE_CLEAN.
+ * However this could lead to inconsistency since we will not
+ * be notified if this content is altered on the flash by other
+ * means. Let's declare it empty and leave buffering tasks to
+ * the buffer cache instead.
+ */
+ mtdblk->cache_state = STATE_EMPTY;
+ return 0;
+}
+
+
+static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
+ int len, const char *buf)
{
- struct mtd_info *mtd = NULL;
+ struct mtd_info *mtd = mtdblk->mtd;
+ unsigned int sect_size = mtd->erasesize;
+ size_t retlen;
+ int ret;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",
+ mtd->name, pos, len);
+
+ while (len > 0) {
+ unsigned long sect_start = (pos/sect_size)*sect_size;
+ unsigned int offset = pos - sect_start;
+ unsigned int size = sect_size - offset;
+ if( size > len )
+ size = len;
+
+ if (size == sect_size) {
+ /*
+ * We are covering a whole sector. Thus there is no
+ * need to bother with the cache while it may still be
+ * useful for other partial writes.
+ */
+ ret = erase_write (mtd, pos, size, buf);
+ if (ret)
+ return ret;
+ } else {
+ /* Partial sector: need to use the cache */
+
+ if (mtdblk->cache_state == STATE_DIRTY &&
+ mtdblk->cache_offset != sect_start) {
+ ret = write_cached_data(mtdblk);
+ if (ret)
+ return ret;
+ }
+
+ if (mtdblk->cache_state == STATE_EMPTY ||
+ mtdblk->cache_offset != sect_start) {
+ /* fill the cache with the current sector */
+ mtdblk->cache_state = STATE_EMPTY;
+ ret = MTD_READ(mtd, sect_start, sect_size, &retlen, mtdblk->cache_data);
+ if (ret)
+ return ret;
+ if (retlen != sect_size)
+ return -EIO;
+
+ mtdblk->cache_offset = sect_start;
+ mtdblk->cache_size = sect_size;
+ mtdblk->cache_state = STATE_CLEAN;
+ }
+
+ /* write data to our local cache */
+ memcpy (mtdblk->cache_data + offset, buf, size);
+ mtdblk->cache_state = STATE_DIRTY;
+ }
+
+ buf += size;
+ pos += size;
+ len -= size;
+ }
+
+ return 0;
+}
+
+
+static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
+ int len, char *buf)
+{
+ struct mtd_info *mtd = mtdblk->mtd;
+ unsigned int sect_size = mtd->erasesize;
+ size_t retlen;
+ int ret;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
+ mtd->name, pos, len);
+
+ while (len > 0) {
+ unsigned long sect_start = (pos/sect_size)*sect_size;
+ unsigned int offset = pos - sect_start;
+ unsigned int size = sect_size - offset;
+ if (size > len)
+ size = len;
+
+ /*
+ * Check if the requested data is already cached
+ * Read the requested amount of data from our internal cache if it
+ * contains what we want, otherwise we read the data directly
+ * from flash.
+ */
+ if (mtdblk->cache_state != STATE_EMPTY &&
+ mtdblk->cache_offset == sect_start) {
+ memcpy (buf, mtdblk->cache_data + offset, size);
+ } else {
+ ret = MTD_READ (mtd, pos, size, &retlen, buf);
+ if (ret)
+ return ret;
+ if (retlen != size)
+ return -EIO;
+ }
+
+ buf += size;
+ pos += size;
+ len -= size;
+ }
+
+ return 0;
+}
+
+
+static int mtdblock_open(struct inode *inode, struct file *file)
+{
+ struct mtdblk_dev *mtdblk;
int dev;
- DEBUG(1,"mtdblock_open\n");
+ DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
- if (inode == 0)
+ if (!inode)
return -EINVAL;
dev = MINOR(inode->i_rdev);
+ if (dev >= MAX_MTD_DEVICES)
+ return -EINVAL;
MOD_INC_USE_COUNT;
- mtd = get_mtd_device(NULL, dev);
+ spin_lock(&mtdblks_lock);
+
+ /* If it's already open, no need to piss about. */
+ if (mtdblks[dev]) {
+ mtdblks[dev]->count++;
+ spin_unlock(&mtdblks_lock);
+ return 0;
+ }
+
+ /* OK, it's not open. Try to find it */
+
+ /* First we have to drop the lock, because we have to
+ to things which might sleep.
+ */
+ spin_unlock(&mtdblks_lock);
+
+ mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
+ if (!mtdblk) {
+ MOD_DEC_USE_COUNT;
+ return -ENOMEM;
+ }
+ memset(mtdblk, 0, sizeof(*mtdblk));
+ mtdblk->count = 1;
+ mtdblk->mtd = get_mtd_device(NULL, dev);
- if (!mtd) {
+ if (!mtdblk->mtd) {
+ kfree(mtdblk);
MOD_DEC_USE_COUNT;
return -ENODEV;
}
- mtd_sizes[dev] = mtd->size>>9;
+ init_MUTEX (&mtdblk->cache_sem);
+ mtdblk->cache_state = STATE_EMPTY;
+ mtdblk->cache_size = mtdblk->mtd->erasesize;
+ mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
+ if (!mtdblk->cache_data) {
+ put_mtd_device(mtdblk->mtd);
+ kfree(mtdblk);
+ MOD_DEC_USE_COUNT;
+ return -ENOMEM;
+ }
+
+ /* OK, we've created a new one. Add it to the list. */
+
+ spin_lock(&mtdblks_lock);
- DEBUG(1, "ok\n");
+ if (mtdblks[dev]) {
+ /* Another CPU made one at the same time as us. */
+ mtdblks[dev]->count++;
+ spin_unlock(&mtdblks_lock);
+ put_mtd_device(mtdblk->mtd);
+ vfree(mtdblk->cache_data);
+ kfree(mtdblk);
+ return 0;
+ }
+
+ mtdblks[dev] = mtdblk;
+ mtd_sizes[dev] = mtdblk->mtd->size/1024;
+ mtd_blksizes[dev] = mtdblk->mtd->erasesize;
+ if (mtd_blksizes[dev] > PAGE_SIZE)
+ mtd_blksizes[dev] = PAGE_SIZE;
+ set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE));
+
+ spin_unlock(&mtdblks_lock);
+
+ DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
return 0;
}
@@ -84,11 +353,11 @@ static int mtdblock_open(struct inode *inode, struct file *file)
static release_t mtdblock_release(struct inode *inode, struct file *file)
{
int dev;
- struct mtd_info *mtd;
+ struct mtdblk_dev *mtdblk;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
struct super_block * sb = get_super(inode->i_rdev);
#endif
- DEBUG(1, "mtdblock_release\n");
+ DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
if (inode == NULL)
release_return(-ENODEV);
@@ -100,150 +369,189 @@ static release_t mtdblock_release(struct inode *inode, struct file *file)
invalidate_buffers(inode->i_rdev);
dev = MINOR(inode->i_rdev);
- mtd = __get_mtd_device(NULL, dev);
-
- if (!mtd) {
- printk(KERN_WARNING "MTD device is absent on mtd_release!\n");
- MOD_DEC_USE_COUNT;
- release_return(-ENODEV);
-
+ mtdblk = mtdblks[dev];
+
+ down(&mtdblk->cache_sem);
+ write_cached_data(mtdblk);
+ up(&mtdblk->cache_sem);
+
+ spin_lock(&mtdblks_lock);
+ if (!--mtdblk->count) {
+ /* It was the last usage. Free the device */
+ mtdblks[dev] = NULL;
+ spin_unlock(&mtdblks_lock);
+ if (mtdblk->mtd->sync)
+ mtdblk->mtd->sync(mtdblk->mtd);
+ put_mtd_device(mtdblk->mtd);
+ vfree(mtdblk->cache_data);
+ kfree(mtdblk);
+ } else {
+ spin_unlock(&mtdblks_lock);
}
-
- if (mtd->sync)
- mtd->sync(mtd);
-
- put_mtd_device(mtd);
- DEBUG(1, "ok\n");
+ DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
MOD_DEC_USE_COUNT;
release_return(0);
}
-static void mtdblock_request(RQFUNC_ARG)
+/*
+ * This is a special request_fn because it is executed in a process context
+ * to be able to sleep independently of the caller. The io_request_lock
+ * is held upon entry and exit.
+ * The head of our request queue is considered active so there is no need
+ * to dequeue requests before we are done.
+ */
+static void handle_mtdblock_request(void)
{
- struct request *current_request;
- unsigned int res = 0;
- struct mtd_info *mtd;
-
- while (1)
- {
- /* Grab the Request and unlink it from the request list, INIT_REQUEST
- will execute a return if we are done. */
- INIT_REQUEST;
- current_request = CURRENT;
-
- if (MINOR(current_request->rq_dev) >= MAX_MTD_DEVICES)
- {
- printk("mtd: Unsupported device!\n");
- end_request(0);
- continue;
- }
-
- // Grab our MTD structure
-
- mtd = __get_mtd_device(NULL, MINOR(current_request->rq_dev));
- if (!mtd) {
- printk("MTD device %d doesn't appear to exist any more\n", CURRENT_DEV);
- end_request(0);
- }
-
- if (current_request->sector << 9 > mtd->size ||
- (current_request->sector + current_request->nr_sectors) << 9 > mtd->size)
- {
- printk("mtd: Attempt to read past end of device!\n");
- printk("size: %lx, sector: %lx, nr_sectors %lx\n", mtd->size, current_request->sector, current_request->nr_sectors);
- end_request(0);
- continue;
- }
-
- /* Remove the request we are handling from the request list so nobody messes
- with it */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- blkdev_dequeue_request(current_request);
-
- /* Now drop the lock that the ll_rw_blk functions grabbed for us
- and process the request. This is necessary due to the extreme time
- we spend processing it. */
- spin_unlock_irq(&io_request_lock);
-#endif
+ struct request *req;
+ struct mtdblk_dev *mtdblk;
+ unsigned int res;
+
+ for (;;) {
+ INIT_REQUEST;
+ req = CURRENT;
+ spin_unlock_irq(&io_request_lock);
+ mtdblk = mtdblks[MINOR(req->rq_dev)];
+ res = 0;
+
+ if (MINOR(req->rq_dev) >= MAX_MTD_DEVICES)
+ panic(__FUNCTION__": minor out of bound");
+
+ if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9))
+ goto end_req;
+
+ // Handle the request
+ switch (req->cmd)
+ {
+ int err;
+
+ case READ:
+ down(&mtdblk->cache_sem);
+ err = do_cached_read (mtdblk, req->sector << 9,
+ req->current_nr_sectors << 9,
+ req->buffer);
+ up(&mtdblk->cache_sem);
+ if (!err)
+ res = 1;
+ break;
+
+ case WRITE:
+ // Read only device
+ if ( !(mtdblk->mtd->flags & MTD_WRITEABLE) )
+ break;
+
+ // Do the write
+ down(&mtdblk->cache_sem);
+ err = do_cached_write (mtdblk, req->sector << 9,
+ req->current_nr_sectors << 9,
+ req->buffer);
+ up(&mtdblk->cache_sem);
+ if (!err)
+ res = 1;
+ break;
+ }
+
+end_req:
+ spin_lock_irq(&io_request_lock);
+ end_request(res);
+ }
+}
- // Handle the request
- switch (current_request->cmd)
- {
- size_t retlen;
-
- case READ:
- if (mtd->read(mtd,current_request->sector<<9,
- current_request->nr_sectors << 9,
- &retlen, current_request->buffer) == 0)
- res = 1;
- else
- res = 0;
- break;
-
- case WRITE:
-//printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector,
-// current_request->nr_sectors);
-
- // Read only device
- if ((mtd->flags & MTD_CAP_RAM) == 0)
- {
- res = 0;
- break;
- }
-
- // Do the write
- if (mtd->write(mtd,current_request->sector<<9,
- current_request->nr_sectors << 9,
- &retlen, current_request->buffer) == 0)
- res = 1;
- else
- res = 0;
- break;
-
- // Shouldn't happen
- default:
- printk("mtd: unknown request\n");
- break;
- }
-
- // Grab the lock and re-thread the item onto the linked list
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- spin_lock_irq(&io_request_lock);
- mtdblock_end_request(current_request, res);
+static volatile int leaving = 0;
+#if LINUX_VERSION_CODE > 0x020300
+static DECLARE_MUTEX_LOCKED(thread_sem);
+static DECLARE_WAIT_QUEUE_HEAD(thr_wq);
#else
- end_request(res);
+static struct semaphore thread_sem = MUTEX_LOCKED;
+DECLARE_WAIT_QUEUE_HEAD(thr_wq);
#endif
- }
+
+int mtdblock_thread(void *dummy)
+{
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+
+ tsk->session = 1;
+ tsk->pgrp = 1;
+ /* we might get involved when memory gets low, so use PF_MEMALLOC */
+ tsk->flags |= PF_MEMALLOC;
+ strcpy(tsk->comm, "mtdblockd");
+ tsk->tty = NULL;
+ spin_lock_irq(&tsk->sigmask_lock);
+ sigfillset(&tsk->blocked);
+ recalc_sigpending(tsk);
+ spin_unlock_irq(&tsk->sigmask_lock);
+ exit_mm(tsk);
+ exit_files(tsk);
+ exit_sighand(tsk);
+ exit_fs(tsk);
+
+ while (!leaving) {
+ add_wait_queue(&thr_wq, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_lock_irq(&io_request_lock);
+ if (QUEUE_EMPTY || QUEUE_PLUGGED) {
+ spin_unlock_irq(&io_request_lock);
+ schedule();
+ remove_wait_queue(&thr_wq, &wait);
+ } else {
+ remove_wait_queue(&thr_wq, &wait);
+ set_current_state(TASK_RUNNING);
+ handle_mtdblock_request();
+ spin_unlock_irq(&io_request_lock);
+ }
+ }
+
+ up(&thread_sem);
+ return 0;
}
+#if LINUX_VERSION_CODE < 0x20300
+#define RQFUNC_ARG void
+#else
+#define RQFUNC_ARG request_queue_t *q
+#endif
+
+static void mtdblock_request(RQFUNC_ARG)
+{
+ /* Don't do anything, except wake the thread if necessary */
+ wake_up(&thr_wq);
+}
static int mtdblock_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct mtd_info *mtd;
+ struct mtdblk_dev *mtdblk;
- mtd = __get_mtd_device(NULL, MINOR(inode->i_rdev));
+ mtdblk = mtdblks[MINOR(inode->i_rdev)];
- if (!mtd) return -EINVAL;
+#ifdef PARANOIA
+ if (!mtdblk)
+ BUG();
+#endif
switch (cmd) {
case BLKGETSIZE: /* Return device size */
- if (!arg) return -EFAULT;
- return put_user((mtd->size >> 9),
- (long *) arg);
+ if (!arg)
+ return -EFAULT;
+ return put_user((mtdblk->mtd->size >> 9),
+ (long *) arg)?-EFAULT:0;
case BLKFLSBUF:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- if(!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN))
+ return -EACCES;
#endif
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
- if (mtd->sync)
- mtd->sync(mtd);
+ down(&mtdblk->cache_sem);
+ write_cached_data(mtdblk);
+ up(&mtdblk->cache_sem);
+ if (mtdblk->mtd->sync)
+ mtdblk->mtd->sync(mtdblk->mtd);
return 0;
default:
@@ -251,7 +559,6 @@ static int mtdblock_ioctl(struct inode * inode, struct file * file,
}
}
- /*}}}*/
#if LINUX_VERSION_CODE < 0x20326
static struct file_operations mtd_fops =
{
@@ -270,32 +577,69 @@ static struct block_device_operations mtd_fops =
};
#endif
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#ifdef CONFIG_DEVFS_FS
+/* Notification that a new device has been added. Create the devfs entry for
+ * it. */
+
+static void mtd_notify_add(struct mtd_info* mtd)
+{
+ char name[8];
+
+ if (!mtd)
+ return;
+
+ sprintf(name, "%d", mtd->index);
+ devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name,
+ DEVFS_FL_DEFAULT, MTD_BLOCK_MAJOR, mtd->index,
+ S_IFBLK | S_IRUGO | S_IWUGO,
+ &mtd_fops, NULL);
+}
+
+static void mtd_notify_remove(struct mtd_info* mtd)
+{
+ if (!mtd)
+ return;
+
+ devfs_unregister(devfs_rw_handle[mtd->index]);
+}
+#endif
+
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_mtdblock init_module
#define cleanup_mtdblock cleanup_module
#endif
-#define __exit
-#endif
-
int __init init_mtdblock(void)
{
int i;
+ spin_lock_init(&mtdblks_lock);
+#ifdef CONFIG_DEVFS_FS
+ if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops))
+ {
+ printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
+ MTD_BLOCK_MAJOR);
+ return -EAGAIN;
+ }
+
+ devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
+ register_mtd_user(&notifier);
+#else
if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
MTD_BLOCK_MAJOR);
return -EAGAIN;
}
+#endif
/* We fill it in at open() time. */
for (i=0; i< MAX_MTD_DEVICES; i++) {
mtd_sizes[i] = 0;
+ mtd_blksizes[i] = BLOCK_SIZE;
}
-
+ init_waitqueue_head(&thr_wq);
/* Allow the block size to default to BLOCK_SIZE. */
- blksize_size[MAJOR_NR] = NULL;
+ blksize_size[MAJOR_NR] = mtd_blksizes;
blk_size[MAJOR_NR] = mtd_sizes;
#if LINUX_VERSION_CODE < 0x20320
@@ -303,15 +647,30 @@ int __init init_mtdblock(void)
#else
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request);
#endif
+ kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
return 0;
}
static void __exit cleanup_mtdblock(void)
{
+ leaving = 1;
+ wake_up(&thr_wq);
+ down(&thread_sem);
+#ifdef CONFIG_DEVFS_FS
+ unregister_mtd_user(&notifier);
+ devfs_unregister(devfs_dir_handle);
+ devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME);
+#else
unregister_blkdev(MAJOR_NR,DEVICE_NAME);
+#endif
+#if LINUX_VERSION_CODE < 0x20320
+ blk_dev[MAJOR_NR].request_fn = NULL;
+#else
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+#endif
+ blksize_size[MAJOR_NR] = NULL;
+ blk_size[MAJOR_NR] = NULL;
}
-#if LINUX_VERSION_CODE > 0x20300
module_init(init_mtdblock);
module_exit(cleanup_mtdblock);
-#endif
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 0bb15a8fc..bccb687c0 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1,5 +1,6 @@
/*
- * $Id: mtdchar.c,v 1.7 2000/06/30 15:54:19 dwmw2 Exp $
+ * Almost: $Id: mtdchar.c,v 1.21 2000/12/09 21:15:12 dwmw2 Exp $
+ * (With some of the compatibility for previous kernels taken out)
*
* Character-device access to raw MTD devices.
*
@@ -13,6 +14,20 @@
#include <linux/mtd/mtd.h>
#include <linux/malloc.h>
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+static void mtd_notify_add(struct mtd_info* mtd);
+static void mtd_notify_remove(struct mtd_info* mtd);
+static struct mtd_notifier notifier = {
+ mtd_notify_add,
+ mtd_notify_remove,
+ NULL
+};
+static devfs_handle_t devfs_dir_handle = NULL;
+static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES];
+static devfs_handle_t devfs_ro_handle[MAX_MTD_DEVICES];
+#endif
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
#else
@@ -22,11 +37,11 @@ static int mtd_lseek (struct inode *inode, struct file *file, off_t offset, int
struct mtd_info *mtd=(struct mtd_info *)file->private_data;
switch (orig) {
- case 0:
+ case 0:
/* SEEK_SET */
file->f_pos = offset;
break;
- case 1:
+ case 1:
/* SEEK_CUR */
file->f_pos += offset;
break;
@@ -34,11 +49,11 @@ static int mtd_lseek (struct inode *inode, struct file *file, off_t offset, int
/* SEEK_END */
file->f_pos =mtd->size + offset;
break;
- default:
+ default:
return -EINVAL;
}
- if (file->f_pos < 0)
+ if (file->f_pos < 0)
file->f_pos = 0;
else if (file->f_pos >= mtd->size)
file->f_pos = mtd->size - 1;
@@ -54,7 +69,7 @@ static int mtd_open(struct inode *inode, struct file *file)
int devnum = minor >> 1;
struct mtd_info *mtd;
- DEBUG(0, "MTD_open\n");
+ DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
if (devnum >= MAX_MTD_DEVICES)
return -ENODEV;
@@ -86,7 +101,7 @@ static release_t mtd_close(struct inode *inode,
{
struct mtd_info *mtd;
- DEBUG(0, "MTD_close\n");
+ DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
mtd = (struct mtd_info *)file->private_data;
@@ -115,7 +130,7 @@ static int mtd_read(struct inode *inode,struct file *file, char *buf, int count)
int ret=0;
char *kbuf;
- DEBUG(0,"MTD_read\n");
+ DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
if (FILE_POS + count > mtd->size)
count = mtd->size - FILE_POS;
@@ -124,7 +139,7 @@ static int mtd_read(struct inode *inode,struct file *file, char *buf, int count)
return 0;
/* FIXME: Use kiovec in 2.3 or 2.2+rawio, or at
- * least split the IO into smaller chunks.
+ * least split the IO into smaller chunks.
*/
kbuf = vmalloc(count);
@@ -157,7 +172,7 @@ static read_write_t mtd_write(struct inode *inode,struct file *file, const char
size_t retlen;
int ret=0;
- DEBUG(0,"MTD_write\n");
+ DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
if (FILE_POS == mtd->size)
return -ENOSPC;
@@ -208,7 +223,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
int ret = 0;
u_long size;
- DEBUG(0, "MTD_ioctl\n");
+ DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
if (cmd & IOC_IN) {
@@ -222,8 +237,9 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case MEMGETINFO:
- copy_to_user((struct mtd_info *)arg, mtd,
- sizeof(struct mtd_info_user));
+ if (copy_to_user((struct mtd_info *)arg, mtd,
+ sizeof(struct mtd_info_user)))
+ return -EFAULT;
break;
case MEMERASE:
@@ -238,28 +254,23 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
init_waitqueue_head(&waitq);
memset (erase,0,sizeof(struct erase_info));
- copy_from_user(&erase->addr, (u_long *)arg,
- 2 * sizeof(u_long));
+ if (copy_from_user(&erase->addr, (u_long *)arg,
+ 2 * sizeof(u_long))) {
+ kfree(erase);
+ return -EFAULT;
+ }
erase->mtd = mtd;
erase->callback = mtd_erase_callback;
erase->priv = (unsigned long)&waitq;
- /* FIXME: Allow INTERRUPTIBLE. Which means
- not having the wait_queue head on the stack
-
- Does it? Why? Who wrote this? Was it my alter
- ago - the intelligent one? Or was it the stupid
- one, and now I'm being clever I don't know what
- it was on about?
-
- dwmw2.
-
- It was the intelligent one. If the wq_head is
- on the stack, and we leave because we got
- interrupted, then the wq_head is no longer
- there when the callback routine tries to
- wake us up --> BOOM!.
-
+ /*
+ FIXME: Allow INTERRUPTIBLE. Which means
+ not having the wait_queue head on the stack.
+
+ If the wq_head is on the stack, and we
+ leave because we got interrupted, then the
+ wq_head is no longer there when the
+ callback routine tries to wake us up.
*/
current->state = TASK_UNINTERRUPTIBLE;
add_wait_queue(&waitq, &wait);
@@ -281,7 +292,8 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
void *databuf;
ssize_t retlen;
- copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf));
+ if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)))
+ return -EFAULT;
if (buf.length > 0x4096)
return -EINVAL;
@@ -298,11 +310,13 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
if (!databuf)
return -ENOMEM;
- copy_from_user(databuf, buf.ptr, buf.length);
+ if (copy_from_user(databuf, buf.ptr, buf.length))
+ return -EFAULT;
ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);
- copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t));
+ if (copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t)))
+ ret = -EFAULT;
kfree(databuf);
break;
@@ -315,7 +329,8 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
void *databuf;
ssize_t retlen;
- copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf));
+ if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)))
+ return -EFAULT;
if (buf.length > 0x4096)
return -EINVAL;
@@ -334,19 +349,42 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);
- copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t));
-
- if (retlen)
- copy_to_user(buf.ptr, databuf, retlen);
-
+ if (copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t)))
+ ret = -EFAULT;
+ else if (retlen && copy_to_user(buf.ptr, databuf, retlen))
+ ret = -EFAULT;
+
kfree(databuf);
break;
}
-
-
-
-
+ case MEMLOCK:
+ {
+ unsigned long adrs[2];
+
+ if (copy_from_user(adrs ,(void *)arg, 2* sizeof(unsigned long)))
+ return -EFAULT;
+
+ if (!mtd->lock)
+ ret = -EOPNOTSUPP;
+ else
+ ret = mtd->lock(mtd, adrs[0], adrs[1]);
+ }
+
+ case MEMUNLOCK:
+ {
+ unsigned long adrs[2];
+
+ if (copy_from_user(adrs, (void *)arg, 2* sizeof(unsigned long)))
+ return -EFAULT;
+
+ if (!mtd->unlock)
+ ret = -EOPNOTSUPP;
+ else
+ ret = mtd->unlock(mtd, adrs[0], adrs[1]);
+ }
+
+
default:
printk("Invalid ioctl %x (MEMGETINFO = %x)\n",cmd, MEMGETINFO);
ret = -EINVAL;
@@ -366,31 +404,84 @@ static struct file_operations mtd_fops = {
};
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#ifdef CONFIG_DEVFS_FS
+/* Notification that a new device has been added. Create the devfs entry for
+ * it. */
+
+static void mtd_notify_add(struct mtd_info* mtd)
+{
+ char name[8];
+
+ if (!mtd)
+ return;
+
+ sprintf(name, "%d", mtd->index);
+ devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name,
+ DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2,
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ &mtd_fops, NULL);
+
+ sprintf(name, "%dro", mtd->index);
+ devfs_ro_handle[mtd->index] = devfs_register(devfs_dir_handle, name,
+ DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2+1,
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ &mtd_fops, NULL);
+}
+
+static void mtd_notify_remove(struct mtd_info* mtd)
+{
+ if (!mtd)
+ return;
+
+ devfs_unregister(devfs_rw_handle[mtd->index]);
+ devfs_unregister(devfs_ro_handle[mtd->index]);
+}
+#endif
+
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_mtdchar init_module
#define cleanup_mtdchar cleanup_module
#endif
-#endif
mod_init_t init_mtdchar(void)
{
-
- if (register_chrdev(MTD_CHAR_MAJOR,"mtd",&mtd_fops)) {
+#ifdef CONFIG_DEVFS_FS
+ int i;
+ char name[8];
+ struct mtd_info* mtd;
+
+ if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))
+ {
+ printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
+ MTD_CHAR_MAJOR);
+ return -EAGAIN;
+ }
+
+ devfs_dir_handle = devfs_mk_dir(NULL, "mtd", NULL);
+
+ register_mtd_user(&notifier);
+#else
+ if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))
+ {
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
MTD_CHAR_MAJOR);
return -EAGAIN;
}
+#endif
return 0;
}
mod_exit_t cleanup_mtdchar(void)
{
- unregister_chrdev(MTD_CHAR_MAJOR,"mtd");
+#ifdef CONFIG_DEVFS_FS
+ unregister_mtd_user(&notifier);
+ devfs_unregister(devfs_dir_handle);
+ devfs_unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
+#else
+ unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
+#endif
}
-#if LINUX_VERSION_CODE > 0x20300
module_init(init_mtdchar);
module_exit(cleanup_mtdchar);
-#endif
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index b3f0157eb..8c30838ba 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1,15 +1,11 @@
/*
- * $Id: mtdcore.c,v 1.13 2000/07/13 14:27:37 dwmw2 Exp $
+ * $Id: mtdcore.c,v 1.27 2000/12/10 01:10:09 dwmw2 Exp $
*
- * Core registration and callback routines for MTD
+ * Core registration and callback routines for MTD
* drivers and users.
*
*/
-#ifdef MTD_DEBUG
-#define DEBUGLVL debug
-#endif
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -29,67 +25,12 @@
#include <linux/mtd/mtd.h>
-#ifdef MTD_DEBUG
-static int debug = MTD_DEBUG;
-MODULE_PARM(debug, "i");
-#endif
-
-/* Init code required for 2.2 kernels */
-
-#if LINUX_VERSION_CODE < 0x20300
-
-#ifdef CONFIG_MTD_DOC1000
-extern int init_doc1000(void);
-#endif
-#ifdef CONFIG_MTD_DOCPROBE
-extern int init_doc(void);
-#endif
-#ifdef CONFIG_MTD_PHYSMAP
-extern int init_physmap(void);
-#endif
-#ifdef CONFIG_MTD_RPXLITE
-extern int init_rpxlite(void);
-#endif
-#ifdef CONFIG_MTD_OCTAGON
-extern int init_octagon5066(void);
-#endif
-#ifdef CONFIG_MTD_PNC2000
-extern int init_pnc2000(void);
-#endif
-#ifdef CONFIG_MTD_VMAX
-extern int init_vmax301(void);
-#endif
-#ifdef CONFIG_MTD_MIXMEM
-extern int init_mixmem(void);
-#endif
-#ifdef CONFIG_MTD_PMC551
-extern int init_pmc551(void);
-#endif
-#ifdef CONFIG_MTD_NORA
-extern int init_nora(void);
-#endif
-#ifdef CONFIG_FTL
-extern int init_ftl(void);
-#endif
-#ifdef CONFIG_NFTL
-extern int init_nftl(void);
-#endif
-#ifdef CONFIG_MTD_BLOCK
-extern int init_mtdblock(void);
-#endif
-#ifdef CONFIG_MTD_CHAR
-extern int init_mtdchar(void);
-#endif
-
-#endif /* LINUX_VERSION_CODE < 0x20300 */
-
-
static DECLARE_MUTEX(mtd_table_mutex);
static struct mtd_info *mtd_table[MAX_MTD_DEVICES];
static struct mtd_notifier *mtd_notifiers = NULL;
/**
- * add_mtd_device - register an MTD device
+ * add_mtd_device - register an MTD device
* @mtd: pointer to new MTD device info structure
*
* Add a device to the list of MTD devices present in the system, and
@@ -110,6 +51,7 @@ int add_mtd_device(struct mtd_info *mtd)
struct mtd_notifier *not=mtd_notifiers;
mtd_table[i] = mtd;
+ mtd->index = i;
DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);
while (not)
{
@@ -126,7 +68,7 @@ int add_mtd_device(struct mtd_info *mtd)
}
/**
- * del_mtd_device - unregister an MTD device
+ * del_mtd_device - unregister an MTD device
* @mtd: pointer to MTD device info structure
*
* Remove a device from the list of MTD devices present in the system,
@@ -194,7 +136,7 @@ void register_mtd_user (struct mtd_notifier *new)
* @new: pointer to notifier info structure
*
* Removes a callback function pair from the list of 'users' to be
- * notified upon addition or removal of MTD devices. Causes the
+ * notified upon addition or removal of MTD devices. Causes the
* 'remove' callback to be immediately invoked for each MTD device
* currently present in the system.
*/
@@ -232,7 +174,7 @@ int unregister_mtd_user (struct mtd_notifier *old)
* @mtd: last known address of the required MTD device
* @num: internal device number of the required MTD device
*
- * Given a number and NULL address, return the num'th entry in the device
+ * Given a number and NULL address, return the num'th entry in the device
* table, if any. Given an address and num == -1, search the device table
* for a device with that address and return if it's still present. Given
* both, return the num'th driver only if its address matches. Return NULL
@@ -313,10 +255,10 @@ static inline int mtd_proc_info (char *buf, int i)
{
struct mtd_info *this = mtd_table[i];
- if (!this)
+ if (!this)
return 0;
- return sprintf(buf, "mtd%d: %8.8lx \"%s\"\n", i, this->size,
+ return sprintf(buf, "mtd%d: %8.8lx \"%s\"\n", i, this->size,
this->name);
}
@@ -330,7 +272,7 @@ static int mtd_read_proc ( char *page, char **start, off_t off,int count
{
int len = 0, l, i;
off_t begin = 0;
-
+
down(&mtd_table_mutex);
for (i=0; i< MAX_MTD_DEVICES; i++) {
@@ -374,79 +316,13 @@ struct proc_dir_entry mtd_proc_entry = {
/*====================================================================*/
/* Init code */
-#if LINUX_VERSION_CODE < 0x20300
-
-static inline void init_others(void)
-{
- /* Shedloads of calls to init functions of all the
- * other drivers and users of MTD, which we can
- * ditch in 2.3 because of the sexy new way of
- * finding init routines.
- */
-#ifdef CONFIG_MTD_DOC1000
- init_doc1000();
-#endif
-#ifdef CONFIG_MTD_DOCPROBE
- init_doc(); /* This covers both the DiskOnChip 2000
- * and the DiskOnChip Millennium.
- * Theoretically all other DiskOnChip
- * devices too. */
-#endif
-#ifdef CONFIG_MTD_PHYSMAP
- init_physmap();
-#endif
-#ifdef CONFIG_MTD_RPXLITE
- init_rpxlite();
-#endif
-#ifdef CONFIG_MTD_OCTAGON
- init_octagon5066();
-#endif
-#ifdef CONFIG_MTD_PNC2000
- init_pnc2000();
-#endif
-#ifdef CONFIG_MTD_VMAX
- init_vmax301();
-#endif
-#ifdef CONFIGF_MTD_MIXMEM
- init_mixmem();
-#endif
-#ifdef CONFIG_MTD_PMC551
- init_pmc551();
-#endif
-#ifdef CONFIG_MTD_NORA
- init_nora();
-#endif
-#ifdef CONFIG_MTD_MTDRAM
- init_mtdram();
-#endif
-#ifdef CONFIG_FTL
- init_ftl();
-#endif
-#ifdef CONFIG_NFTL
- init_nftl();
-#endif
-#ifdef CONFIG_MTD_BLOCK
- init_mtdblock();
-#endif
-#ifdef CONFIG_MTD_CHAR
- init_mtdchar();
-#endif
-}
-
-#ifdef MODULE
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_mtd init_module
#define cleanup_mtd cleanup_module
#endif
-#endif /* LINUX_VERSION_CODE < 0x20300 */
-
mod_init_t init_mtd(void)
{
- int i;
- DEBUG(1, "INIT_MTD:\n");
- for (i=0; i<MAX_MTD_DEVICES; i++)
- mtd_table[i]=NULL;
-
#ifdef CONFIG_PROC_FS
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
if ((proc_mtd = create_proc_entry( "mtd", 0, 0 )))
@@ -454,12 +330,12 @@ mod_init_t init_mtd(void)
#else
proc_register_dynamic(&proc_root,&mtd_proc_entry);
#endif
-
#endif
-#if LINUX_VERSION_CODE < 0x20300
- init_others();
+#if LINUX_VERSION_CODE < 0x20212
+ init_mtd_devices();
#endif
+
#ifdef CONFIG_PM
mtd_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, mtd_pm_callback);
#endif
@@ -468,13 +344,13 @@ mod_init_t init_mtd(void)
mod_exit_t cleanup_mtd(void)
{
- unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
#ifdef CONFIG_PM
if (mtd_pm_dev) {
pm_unregister(mtd_pm_dev);
mtd_pm_dev = NULL;
}
#endif
+
#ifdef CONFIG_PROC_FS
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
if (proc_mtd)
@@ -484,10 +360,8 @@ mod_exit_t cleanup_mtd(void)
#endif
#endif
}
-
-#if LINUX_VERSION_CODE > 0x20300
+
module_init(init_mtd);
module_exit(cleanup_mtd);
-#endif
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
new file mode 100644
index 000000000..0135be39e
--- /dev/null
+++ b/drivers/mtd/mtdpart.c
@@ -0,0 +1,228 @@
+/*
+ * Simple MTD partitioning layer
+ *
+ * (C) 2000 Nicolas Pitre <nico@cam.org>
+ *
+ * This code is GPL
+ *
+ * $Id: mtdpart.c,v 1.7 2000/12/09 23:29:47 dwmw2 Exp $
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/list.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+
+/* Our partition linked list */
+static LIST_HEAD(mtd_partitions);
+
+/* Our partition node structure */
+struct mtd_part {
+ struct mtd_info mtd;
+ struct mtd_info *master;
+ loff_t offset;
+ int index;
+ struct list_head list;
+};
+
+/*
+ * Given a pointer to the MTD object in the mtd_part structure, we can retrieve
+ * the pointer to that structure with this macro.
+ */
+#define PART(x) ((struct mtd_part *)(x))
+
+
+/*
+ * MTD methods which simply translate the effective address and pass through
+ * to the _real_ device.
+ */
+
+static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct mtd_part *part = PART(mtd);
+ if (from >= mtd->size)
+ len = 0;
+ else if (from + len > mtd->size)
+ len = mtd->size - from;
+ return part->master->read (part->master, from + part->offset,
+ len, retlen, buf);
+}
+
+static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct mtd_part *part = PART(mtd);
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+ if (to >= mtd->size)
+ len = 0;
+ else if (to + len > mtd->size)
+ len = mtd->size - to;
+ return part->master->write (part->master, to + part->offset,
+ len, retlen, buf);
+}
+
+static int part_writev (struct mtd_info *mtd, const struct iovec *vecs,
+ unsigned long count, loff_t to, size_t *retlen)
+{
+ struct mtd_part *part = PART(mtd);
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+ return part->master->writev (part->master, vecs, count,
+ to + part->offset, retlen);
+}
+
+static int part_readv (struct mtd_info *mtd, struct iovec *vecs,
+ unsigned long count, loff_t from, size_t *retlen)
+{
+ struct mtd_part *part = PART(mtd);
+ return part->master->readv (part->master, vecs, count,
+ from + part->offset, retlen);
+}
+
+static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct mtd_part *part = PART(mtd);
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+ if (instr->addr >= mtd->size)
+ return -EINVAL;
+ instr->addr += part->offset;
+ return part->master->erase(part->master, instr);
+}
+
+static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct mtd_part *part = PART(mtd);
+ return part->master->lock(part->master, ofs + part->offset, len);
+}
+
+static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct mtd_part *part = PART(mtd);
+ return part->master->unlock(part->master, ofs + part->offset, len);
+}
+
+
+/*
+ * This function unregisters and destroy all slave MTD objects which are
+ * attached to the given master MTD object.
+ */
+
+int del_mtd_partitions(struct mtd_info *master)
+{
+ struct list_head *node;
+ struct mtd_part *slave;
+
+ for (node = mtd_partitions.next;
+ node != &mtd_partitions;
+ node = node->next) {
+ slave = list_entry(node, struct mtd_part, list);
+ if (slave->master == master) {
+ struct list_head *prev = node->prev;
+ __list_del(prev, node->next);
+ del_mtd_device(&slave->mtd);
+ kfree(slave);
+ node = prev;
+ MOD_DEC_USE_COUNT;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * This function, given a master MTD object and a partition table, creates
+ * and registers slave MTD objects which are bound to the master according to
+ * the partition definitions.
+ * (Q: should we register the master MTD object as well?)
+ */
+
+int add_mtd_partitions(struct mtd_info *master,
+ struct mtd_partition *parts,
+ int nbparts)
+{
+ struct mtd_part *slave;
+ u_long cur_offset = 0;
+ int i;
+
+ for (i = 0; i < nbparts; i++) {
+ /* allocate the partition structure */
+ slave = kmalloc (sizeof(*slave), GFP_KERNEL);
+ if (!slave) {
+ printk ("memory allocation error while creating partitions for \"%s\"\n",
+ master->name);
+ del_mtd_partitions(master);
+ return -ENOMEM;
+ }
+ list_add(&slave->list, &mtd_partitions);
+
+ /* set up the MTD object for this partition */
+ slave->mtd = *master;
+ slave->mtd.name = parts[i].name;
+ slave->mtd.size = parts[i].size;
+ slave->mtd.flags &= ~parts[i].mask_flags;
+ slave->mtd.read = part_read;
+ slave->mtd.write = part_write;
+ if (slave->mtd.writev)
+ slave->mtd.writev = part_writev;
+ if (slave->mtd.readv)
+ slave->mtd.readv = part_readv;
+ if (slave->mtd.lock)
+ slave->mtd.lock = part_lock;
+ if (slave->mtd.unlock)
+ slave->mtd.unlock = part_unlock;
+ slave->mtd.erase = part_erase;
+ slave->master = master;
+ slave->offset = parts[i].offset;
+ slave->index = i;
+
+ if (slave->offset == 0)
+ slave->offset = cur_offset;
+ if (slave->mtd.size == 0)
+ slave->mtd.size = master->size - slave->offset;
+ cur_offset = slave->offset + slave->mtd.size;
+
+ /* let's do some sanity checks */
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
+ (parts[i].offset % master->erasesize)) {
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
+ parts[i].name);
+ }
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
+ (parts[i].size % master->erasesize)) {
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
+ parts[i].name);
+ }
+ if (parts[i].offset >= master->size) {
+ /* let's register it anyway to preserve ordering */
+ slave->offset = 0;
+ slave->mtd.size = 0;
+ printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
+ parts[i].name);
+ }
+ if (parts[i].offset + parts[i].size > master->size) {
+ slave->mtd.size = master->size - parts[i].offset;
+ printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#lx\n",
+ parts[i].name, master->name, slave->mtd.size);
+ }
+
+ /* register our partition */
+ add_mtd_device(&slave->mtd);
+ MOD_INC_USE_COUNT;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL(add_mtd_partitions);
+EXPORT_SYMBOL(del_mtd_partitions);
diff --git a/drivers/mtd/nftl.c b/drivers/mtd/nftl.c
index e7040863f..d7e2aeaad 100644
--- a/drivers/mtd/nftl.c
+++ b/drivers/mtd/nftl.c
@@ -1,32 +1,35 @@
-
/* Linux driver for NAND Flash Translation Layer */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@infradead.org> */
-/* $Id: nftl.c,v 1.36 2000/07/13 14:14:20 dwmw2 Exp $ */
+/* $Id: nftl.c,v 1.57 2000/12/01 17:51:54 dwmw2 Exp $ */
/*
- The contents of this file are distributed under the GNU Public
- Licence version 2 ("GPL"). The legal note below refers only to the
- _use_ of the code in some jurisdictions, and does not in any way
- affect the copying, distribution and modification of this code,
- which is permitted under the terms of the GPL.
+ The contents of this file are distributed under the GNU General
+ Public License version 2 ("GPL"). The author places no additional
+ restrictions of any kind on it. However, local legislation in some
+ countries may restrict the use of the algorithms implemented by this
+ code in certain circumstances.
- Section 0 of the GPL says:
+ The legal note below refers only to the _use_ of the code in the
+ affected jurisdictions, and does not in any way affect the copying,
+ distribution and modification of this code, which are permitted, and
+ indeed required, under the terms of the GPL.
+ Section 0 of the GPL says:
"Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope."
You may copy, distribute and modify this code to your hearts'
content - it's just that in some jurisdictions, you may only _use_
- it under the terms of the licence below. This puts it in a similar
- situation to the ISDN code, which you may need telco approval to
- use, and indeed any code which has uses that may be restricted in
- law. For example, certain malicious uses of the networking stack
- may be illegal, but that doesn't prevent the networking code from
- being under GPL.
+ it under the terms of the patent grant below. This puts it in a
+ similar situation to the ISDN code, which you may need telco
+ approval to use, and indeed any code which has uses that may be
+ restricted in law. For example, certain malicious uses of the
+ networking stack may be illegal, but that doesn't prevent the
+ networking code from being under GPL.
In fact the ISDN case is worse than this, because modification of
- the code automatically invalidates its approval. Modificiation,
+ the code automatically invalidates its approval. Modification,
unlike usage, _is_ one of the rights which is protected by the
GPL. Happily, the law in those places where approval is required
doesn't actually prevent you from modifying the code - it's just
@@ -34,7 +37,7 @@
because usage isn't addressed by the GPL, that's just fine.
dwmw2@infradead.org
- 6/7/0
+ 30/10/0
LEGAL NOTE: The NFTL format is patented by M-Systems. They have
granted a licence for its use with their DiskOnChip products:
@@ -51,10 +54,6 @@
#define PRERELEASE
-#ifdef NFTL_DEBUG
-#define DEBUGLVL debug
-#endif
-
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -67,42 +66,28 @@
#include <linux/malloc.h>
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/blkpg.h>
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
#include <linux/mtd/mtd.h>
#include <linux/mtd/nftl.h>
#include <linux/mtd/compatmac.h>
-#undef WE_KNOW_WTF_THIS_DOES_NOT_WORK
+/* maximum number of loops while examining next block, to have a
+ chance to detect consistency problems (they should never happen
+ because of the checks done in the mounting */
+
+#define MAX_LOOPS 10000
/* NFTL block device stuff */
#define MAJOR_NR NFTL_MAJOR
#define DEVICE_REQUEST nftl_request
#define DEVICE_OFF(device)
-#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK
-#define LOCAL_END_REQUEST
-#endif
-#include <linux/blk.h>
-#include <linux/hdreg.h>
-
-
-#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK
-
-static void nftl_end_request(struct request *req, int res)
-{
- req->sector += req->current_nr_sectors;
- req->nr_sectors -= req->current_nr_sectors;
-
- if (end_that_request_first( req, res, "nftl" ))
- return;
- end_that_request_last( req );
-}
-#endif
-
-#ifdef NFTL_DEBUG
-static int debug = NFTL_DEBUG;
-MODULE_PARM(debug, "i");
-#endif
+#include <linux/blk.h>
+#include <linux/hdreg.h>
/* Linux-specific block device functions */
@@ -110,11 +95,10 @@ MODULE_PARM(debug, "i");
* encountered, except ...
*/
-static int nftl_sizes[256]={0,};
+static int nftl_sizes[256] = {0,};
static int nftl_blocksizes[256] = {0,};
/* .. for the Linux partition table handling. */
-
struct hd_struct part_table[256] = {{0,0},};
#if LINUX_VERSION_CODE < 0x20328
@@ -123,8 +107,8 @@ static void dummy_init (struct gendisk *crap)
#endif
static struct gendisk nftl_gendisk = {
- NFTL_MAJOR, /* Major number */
- "nftl", /* Major name */
+ MAJOR_NR, /* Major number */
+ "nftl", /* Major name */
4, /* Bits to shift to get real from partition */
15, /* Number of partitions per real */
#if LINUX_VERSION_CODE < 0x20328
@@ -138,281 +122,129 @@ static struct gendisk nftl_gendisk = {
NULL /* next */
};
-
struct NFTLrecord *NFTLs[MAX_NFTLS] = {NULL};
-static void NFTL_setup(struct mtd_info *mtd, unsigned long ofs,
- struct NFTLMediaHeader *hdr)
+static void NFTL_setup(struct mtd_info *mtd)
{
int i;
- struct NFTLrecord *thisNFTL;
+ struct NFTLrecord *nftl;
unsigned long temp;
int firstfree = -1;
- DEBUG(1,"NFTL_setup\n");
+ DEBUG(MTD_DEBUG_LEVEL1,"NFTL_setup\n");
- for (i=0; i < MAX_NFTLS; i++) {
- if (!NFTLs[i] && firstfree==-1)
+ for (i = 0; i < MAX_NFTLS; i++) {
+ if (!NFTLs[i] && firstfree == -1)
firstfree = i;
- else if (NFTLs[i] && NFTLs[i]->mtd == mtd &&
- NFTLs[i]->MediaHdr.FirstPhysicalEUN == hdr->FirstPhysicalEUN) {
+ else if (NFTLs[i] && NFTLs[i]->mtd == mtd) {
/* This is a Spare Media Header for an NFTL we've already found */
- DEBUG(1, "Spare Media Header for NFTL %d found at %lx\n",i, ofs);
- NFTLs[i]->SpareMediaUnit = ofs / mtd->erasesize;
+ DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n");
return;
}
}
-
-
- /* OK, it's a new one. Set up all the data structures. */
-#ifdef PSYCHO_DEBUG
- printk("Found new NFTL nftl%c at offset %lx\n",firstfree + 'a', ofs);
-#endif
- if (hdr->UnitSizeFactor != 0xff) {
- printk("Sorry, we don't support UnitSizeFactor of != 1 yet\n");
+ if (firstfree == -1) {
+ printk(KERN_WARNING "No more NFTL slot available\n");
return;
- }
-
- thisNFTL = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
- if (!thisNFTL) {
+ }
+
+ nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
+ if (!nftl) {
printk(KERN_WARNING "Out of memory for NFTL data structures\n");
return;
}
- init_MUTEX(&thisNFTL->mutex);
- thisNFTL->EraseSize = mtd->erasesize;
- memcpy(&thisNFTL->MediaHdr, hdr, sizeof(*hdr));
- thisNFTL->mtd = mtd;
- thisNFTL->MediaUnit = ofs / mtd->erasesize;
- thisNFTL->SpareMediaUnit = 0xffff;
- thisNFTL->numvunits = le32_to_cpu(thisNFTL->MediaHdr.FormattedSize) / 8192;
- thisNFTL->nr_sects = thisNFTL->numvunits * (thisNFTL->EraseSize / 512);
- thisNFTL->usecount = 0;
- thisNFTL->cylinders = 1024;
- thisNFTL->heads = 16;
+ init_MUTEX(&nftl->mutex);
- temp = thisNFTL->cylinders * thisNFTL->heads;
- thisNFTL->sectors = thisNFTL->nr_sects / temp;
+ /* get physical parameters */
+ nftl->EraseSize = mtd->erasesize;
+ nftl->nb_blocks = mtd->size / mtd->erasesize;
+ nftl->mtd = mtd;
- if (thisNFTL->nr_sects % temp) {
-
- thisNFTL->sectors++;
- temp = thisNFTL->cylinders * thisNFTL->sectors;
- thisNFTL->heads = thisNFTL->nr_sects / temp;
-
- if (thisNFTL->nr_sects & temp) {
- thisNFTL->heads++;
- temp = thisNFTL->heads * thisNFTL->sectors;
-
- thisNFTL->cylinders = thisNFTL->nr_sects / temp;
- }
- }
- if (thisNFTL->nr_sects != thisNFTL->heads * thisNFTL->cylinders *
- thisNFTL->sectors) {
- printk(KERN_WARNING "Cannot calculate an NFTL geometry to match size of 0x%lx.\n", thisNFTL->nr_sects);
- printk(KERN_WARNING "Using C:%d H:%d S:%d (== %lx sects)\n",
- thisNFTL->cylinders, thisNFTL->heads ,
- thisNFTL->sectors,
- (long)thisNFTL->cylinders * (long)thisNFTL->heads *
- (long)thisNFTL->sectors );
-
- /* Oh no we don't
- * thisNFTL->nr_sects = thisNFTL->heads * thisNFTL->cylinders * thisNFTL->sectors;
- */
- }
-
-
- thisNFTL->EUNtable = kmalloc( 2 * thisNFTL->numvunits,
- GFP_KERNEL);
- if (!thisNFTL->EUNtable) {
- printk("ENOMEM\n");
- kfree(thisNFTL);
+ if (NFTL_mount(nftl) < 0) {
+ printk(KERN_WARNING "Could not mount NFTL device\n");
+ kfree(nftl);
return;
- }
- memset(thisNFTL->EUNtable, 0xff, 2 * thisNFTL->numvunits);
-
- thisNFTL->VirtualUnitTable = kmalloc( 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) , GFP_KERNEL);
- if (!thisNFTL->VirtualUnitTable) {
- printk("ENOMEM\n");
- kfree(thisNFTL->EUNtable);
- kfree(thisNFTL);
- return;
- }
- memset(thisNFTL->VirtualUnitTable, 0xff, 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits));
-
- thisNFTL->ReplUnitTable = kmalloc( 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) , GFP_KERNEL);
- if (!thisNFTL->ReplUnitTable) {
- printk("ENOMEM\n");
- kfree(thisNFTL->VirtualUnitTable);
- kfree(thisNFTL->EUNtable);
- kfree(thisNFTL);
- return;
- }
- memset(thisNFTL->ReplUnitTable, 0xff, 2 *le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) );
-
- /* Ought to check the media header for bad blocks */
- thisNFTL->lastEUN = le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) +
- le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN) - 1;
- thisNFTL->numfreeEUNs = 0;
+ }
- /* Scan each physical Erase Unit for validity and to find the
- Virtual Erase Unit Chain to which it belongs */
-
- for (i=le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN);
- i <= thisNFTL->lastEUN; i++) {
-
- union nftl_uci uci;
- unsigned long ofs;
- size_t retlen;
- ofs = i * thisNFTL->EraseSize;
-
- MTD_READOOB(mtd, (i * thisNFTL->EraseSize) + 512 + 8, 8, &retlen, (char *)&uci);
-
- if (uci.b.EraseMark != cpu_to_le16(0x3c69) ||
- uci.b.EraseMark1 != cpu_to_le16(0x3c69)) {
- printk("EUN %d: EraseMark not 0x3c69 (0x%4.4x 0x%4.4x instead)\n",
- i, le16_to_cpu(uci.b.EraseMark), le16_to_cpu(uci.b.EraseMark1));
- thisNFTL->VirtualUnitTable[i] = 0x7fff;
- thisNFTL->ReplUnitTable[i] = 0xffff;
- continue;
- }
-
- MTD_READOOB(mtd, (i * thisNFTL->EraseSize) + 8, 8, &retlen, (u_char *)&uci);
-
- if (uci.a.VirtUnitNum != uci.a.SpareVirtUnitNum)
- printk("EUN %d: VirtualUnitNumber (%x) != SpareVirtualUnitNumber (%x)\n",
- i, le16_to_cpu(uci.a.VirtUnitNum),
- le16_to_cpu(uci.a.SpareVirtUnitNum));
-
- if (uci.a.ReplUnitNum != uci.a.SpareReplUnitNum)
- printk("EUN %d: ReplacementUnitNumber (%x) != SpareReplacementUnitNumber (%x)\n",
- i, le16_to_cpu(uci.a.ReplUnitNum),
- le16_to_cpu(uci.a.SpareReplUnitNum));
-
- /* We don't actually _do_ anything about the above, just whinge */
-
- thisNFTL->VirtualUnitTable[i] = le16_to_cpu(uci.a.VirtUnitNum);
- thisNFTL->ReplUnitTable[i] = le16_to_cpu(uci.a.ReplUnitNum);
-
- /* if (!(VUN & 0x8000) && VUN < (arraybounds)).. optimises to: */
- if (le16_to_cpu(uci.a.VirtUnitNum) < thisNFTL->numvunits)
- thisNFTL->EUNtable[le16_to_cpu(uci.a.VirtUnitNum) & 0x7fff] = i;
-
- if (uci.a.VirtUnitNum == 0xffff) {
- /* Free block */
- thisNFTL->LastFreeEUN = i;
- thisNFTL->numfreeEUNs++;
- }
-
- }
- NFTLs[firstfree] = thisNFTL;
- thisNFTL->LastFreeEUN = le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN);
-
- //#define PSYCHO_DEBUG
+ /* OK, it's a new one. Set up all the data structures. */
#ifdef PSYCHO_DEBUG
- for (i=0; i < 10/* thisNFTL->numvunits*/; i++) {
- u16 curEUN = thisNFTL->EUNtable[i];
- int sillycount=100;
-
- printk("Virtual Unit #%d: ",i);
- if (!curEUN || curEUN == 0xffff) {
- printk("Not present\n");
- continue;
- }
- printk("%d", curEUN);
-
- while ((curEUN = thisNFTL->ReplUnitTable[curEUN]) != 0xffff && --sillycount) {
- printk(", %d", curEUN & 0xffff);
-
+ printk("Found new NFTL nftl%c\n", firstfree + 'a');
+#endif
+
+ /* linux stuff */
+ nftl->usecount = 0;
+ nftl->cylinders = 1024;
+ nftl->heads = 16;
+
+ temp = nftl->cylinders * nftl->heads;
+ nftl->sectors = nftl->nr_sects / temp;
+ if (nftl->nr_sects % temp) {
+ nftl->sectors++;
+ temp = nftl->cylinders * nftl->sectors;
+ nftl->heads = nftl->nr_sects / temp;
+
+ if (nftl->nr_sects % temp) {
+ nftl->heads++;
+ temp = nftl->heads * nftl->sectors;
+ nftl->cylinders = nftl->nr_sects / temp;
}
- printk("\n");
}
-#endif
- /* OK. Now we deal with the fact that we're in the real world. Sometimes
- things don't actually happen the way they're supposed to. Find, fix,
- and whinge about the most common deviations from spec that we have
- been known to encounter.
- */
- /* Except that I haven't implemented that bit yet :) */
+ if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) {
+ printk(KERN_WARNING "Cannot calculate an NFTL geometry to "
+ "match size of 0x%lx.\n", nftl->nr_sects);
+ printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n",
+ nftl->cylinders, nftl->heads , nftl->sectors,
+ (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors );
+ /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */
+ }
+ NFTLs[firstfree] = nftl;
/* Finally, set up the block device sizes */
- nftl_sizes[firstfree * 16]=thisNFTL->nr_sects;
-// nftl_blocksizes[firstfree*16] = 512;
- part_table[firstfree * 16].nr_sects = thisNFTL->nr_sects;
+ nftl_sizes[firstfree * 16] = nftl->nr_sects;
+ //nftl_blocksizes[firstfree*16] = 512;
+ part_table[firstfree * 16].nr_sects = nftl->nr_sects;
+
+ /* partition check ... */
#if LINUX_VERSION_CODE < 0x20328
resetup_one_dev(&nftl_gendisk, firstfree);
#else
- grok_partitions(&nftl_gendisk, firstfree, 1<<4, thisNFTL->nr_sects);
+ grok_partitions(&nftl_gendisk, firstfree, 1<<4, nftl->nr_sects);
#endif
-
}
-
static void NFTL_unsetup(int i)
{
- struct NFTLrecord *thisNFTL = NFTLs[i];
+ struct NFTLrecord *nftl = NFTLs[i];
- DEBUG(1, "NFTL_unsetup %d\n", i);
+ DEBUG(MTD_DEBUG_LEVEL1, "NFTL_unsetup %d\n", i);
NFTLs[i] = NULL;
- if (thisNFTL->VirtualUnitTable)
- kfree(thisNFTL->VirtualUnitTable);
- if (thisNFTL->ReplUnitTable)
- kfree(thisNFTL->ReplUnitTable);
- if (thisNFTL->EUNtable)
- kfree(thisNFTL->EUNtable);
+ if (nftl->ReplUnitTable)
+ kfree(nftl->ReplUnitTable);
+ if (nftl->EUNtable)
+ kfree(nftl->EUNtable);
- kfree(thisNFTL);
+ kfree(nftl);
}
-
-
-
/* Search the MTD device for NFTL partitions */
static void NFTL_notify_add(struct mtd_info *mtd)
{
- int i;
- unsigned long ofs;
- struct NFTLMediaHeader hdr;
-
- DEBUG(1, "NFTL_notify_add for %s\n", mtd->name);
+ DEBUG(MTD_DEBUG_LEVEL1, "NFTL_notify_add for %s\n", mtd->name);
if (mtd) {
- if (!mtd->read_oob) /* If this MTD doesn't have out-of-band data,
- then there's no point continuing */
- {
- DEBUG(1, "No OOB data, quitting\n");
+ if (!mtd->read_oob) {
+ /* If this MTD doesn't have out-of-band data,
+ then there's no point continuing */
+ DEBUG(MTD_DEBUG_LEVEL1, "No OOB data, quitting\n");
return;
}
- DEBUG(3, "mtd->read = %p,size = %d, erasesize = %d\n",
- mtd->read, mtd->size, mtd->erasesize);
- for (ofs = 0; ofs < mtd->size ; ofs += mtd->erasesize) {
- size_t retlen = 0;
- MTD_READ(mtd, ofs, sizeof(hdr), &retlen, (u_char *)&hdr);
-
- if (retlen < sizeof(hdr))
- {
- continue;
- }
-
- if (!strncmp(hdr.DataOrgID, "ANAND", 6)) {
- DEBUG(2, "Valid NFTL partition at ofs %ld\n", ofs);
- NFTL_setup(mtd, ofs, &hdr);
- }
- else {
- DEBUG(3,"No valid NFTL Partition at ofs %d\n", ofs);
- for(i = 0; i < 6; i++) {
- DEBUG(3,"%x, ", hdr.DataOrgID[i]);
- }
- DEBUG(3," = %s\n", hdr.DataOrgID);
- DEBUG(3,"%d, %d, %d, %d\n", hdr.NumEraseUnits, hdr.FirstPhysicalEUN,
- hdr.FormattedSize, hdr.UnitSizeFactor);
+ DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n",
+ mtd->read, mtd->size, mtd->erasesize);
- }
- }
- return;
+ NFTL_setup(mtd);
}
}
@@ -420,100 +252,101 @@ static void NFTL_notify_remove(struct mtd_info *mtd)
{
int i;
- for (i=0; i< MAX_NFTLS; i++) {
+ for (i = 0; i < MAX_NFTLS; i++) {
if (NFTLs[i] && NFTLs[i]->mtd == mtd)
NFTL_unsetup(i);
}
}
-
#ifdef CONFIG_NFTL_RW
/* Actual NFTL access routines */
-
-
-static u16 NFTL_findfreeblock( struct NFTLrecord *thisNFTL, int desperate )
+/* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used
+ * when the give Virtual Unit Chain
+ */
+static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
{
/* For a given Virtual Unit Chain: find or create a free block and
add it to the chain */
/* We're passed the number of the last EUN in the chain, to save us from
having to look it up again */
-
- u16 pot = thisNFTL->LastFreeEUN;
+ u16 pot = nftl->LastFreeEUN;
int silly = -1;
/* Normally, we force a fold to happen before we run out of free blocks completely */
-
- if (!desperate && thisNFTL->numfreeEUNs < 2) {
- // printk("NFTL_findfreeblock: there are too few free EUNs\n");
+ if (!desperate && nftl->numfreeEUNs < 2) {
+ DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n");
return 0xffff;
}
/* Scan for a free block */
-
do {
- if (thisNFTL->VirtualUnitTable[pot] == 0xffff) {
- thisNFTL->LastFreeEUN = pot;
- thisNFTL->numfreeEUNs--;
+ if (nftl->ReplUnitTable[pot] == BLOCK_FREE) {
+ nftl->LastFreeEUN = pot;
+ nftl->numfreeEUNs--;
return pot;
}
- if (++pot > thisNFTL->lastEUN)
- pot = le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN);
+ /* This will probably point to the MediaHdr unit itself,
+ right at the beginning of the partition. But that unit
+ (and the backup unit too) should have the UCI set
+ up so that it's not selected for overwriting */
+ if (++pot > nftl->lastEUN)
+ pot = le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN);
if (!silly--) {
- printk("Tell Dave he fucked up. LastFreeEUN = %d, FirstEUN = %d\n",
- thisNFTL->LastFreeEUN, le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN));
+ printk("Argh! No free blocks found! LastFreeEUN = %d, "
+ "FirstEUN = %d\n", nftl->LastFreeEUN,
+ le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));
return 0xffff;
}
-
- } while (pot != thisNFTL->LastFreeEUN);
+ } while (pot != nftl->LastFreeEUN);
return 0xffff;
}
-
-
-
-
-static u16 NFTL_foldchain (struct NFTLrecord *thisNFTL, u16 thisVUC, unsigned pendingblock )
+static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
{
- u16 BlockMap[thisNFTL->EraseSize / 512];
- unsigned char BlockLastState[thisNFTL->EraseSize / 512];
- unsigned char BlockFreeFound[thisNFTL->EraseSize / 512];
- u16 thisEUN;
+ u16 BlockMap[MAX_SECTORS_PER_UNIT];
+ unsigned char BlockLastState[MAX_SECTORS_PER_UNIT];
+ unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT];
+ unsigned int thisEUN;
int block;
- int silly = -1;
- u16 targetEUN = 0xffff;
+ int silly;
+ unsigned int targetEUN;
struct nftl_oob oob;
int inplace = 1;
+ size_t retlen;
memset(BlockMap, 0xff, sizeof(BlockMap));
memset(BlockFreeFound, 0, sizeof(BlockFreeFound));
- thisEUN = thisNFTL->EUNtable[thisVUC];
+ thisEUN = nftl->EUNtable[thisVUC];
- if (thisEUN == 0xffff) {
- printk(KERN_WARNING "Trying to fold non-existent Virtual Unit Chain %d!\n", thisVUC);
- return 0xffff;
+ if (thisEUN == BLOCK_NIL) {
+ printk(KERN_WARNING "Trying to fold non-existent "
+ "Virtual Unit Chain %d!\n", thisVUC);
+ return BLOCK_NIL;
}
/* Scan to find the Erase Unit which holds the actual data for each
512-byte block within the Chain.
*/
+ silly = MAX_LOOPS;
+ targetEUN = BLOCK_NIL;
+ while (thisEUN <= nftl->lastEUN ) {
+ unsigned int status, foldmark;
- while( thisEUN <= thisNFTL->lastEUN ) {
- size_t retlen;
-
targetEUN = thisEUN;
-
- for (block = 0 ; block < thisNFTL->EraseSize / 512; block ++) {
-
- MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + (block * 512),16 , &retlen, (char *)&oob);
-
+ for (block = 0; block < nftl->EraseSize / 512; block ++) {
+ MTD_READOOB(nftl->mtd,
+ (thisEUN * nftl->EraseSize) + (block * 512),
+ 16 , &retlen, (char *)&oob);
if (block == 2) {
- if (oob.u.c.WriteInh != 0xffffffff) {
- printk("Write Inhibited on EUN %d\n", thisEUN);
+ foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
+ if (foldmark == FOLD_MARK_IN_PROGRESS) {
+ DEBUG(MTD_DEBUG_LEVEL1,
+ "Write Inhibited on EUN %d\n", thisEUN);
inplace = 0;
} else {
/* There's no other reason not to do inplace,
@@ -522,153 +355,139 @@ static u16 NFTL_foldchain (struct NFTLrecord *thisNFTL, u16 thisVUC, unsigned pe
inplace = 1;
}
}
+ status = oob.b.Status | oob.b.Status1;
+ BlockLastState[block] = status;
- BlockLastState[block] = (unsigned char) oob.b.Status & 0xff;
-
- switch(oob.b.Status) {
- case __constant_cpu_to_le16(BLOCK_FREE):
- BlockFreeFound[block]=1;
+ switch(status) {
+ case SECTOR_FREE:
+ BlockFreeFound[block] = 1;
break;
- case __constant_cpu_to_le16(BLOCK_USED):
+ case SECTOR_USED:
if (!BlockFreeFound[block])
BlockMap[block] = thisEUN;
else
- printk(KERN_WARNING "BLOCK_USED found after BLOCK_FREE in Virtual Unit Chain %d for block %d\n", thisVUC, block);
+ printk(KERN_WARNING
+ "SECTOR_USED found after SECTOR_FREE "
+ "in Virtual Unit Chain %d for block %d\n",
+ thisVUC, block);
break;
- case __constant_cpu_to_le16(BLOCK_IGNORE):
- case __constant_cpu_to_le16(BLOCK_DELETED):
+ case SECTOR_IGNORE:
+ case SECTOR_DELETED:
break;
default:
- printk("Unknown status for block %d in EUN %d: %x\n",block,thisEUN, oob.b.Status);
+ printk("Unknown status for block %d in EUN %d: %x\n",
+ block, thisEUN, status);
}
}
if (!silly--) {
- printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", thisVUC);
- return 0xffff;
+ printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",
+ thisVUC);
+ return BLOCK_NIL;
}
- thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff;
+ thisEUN = nftl->ReplUnitTable[thisEUN];
}
if (inplace) {
/* We're being asked to be a fold-in-place. Check
- that all blocks are either present or BLOCK_FREE
+ that all blocks are either present or SECTOR_FREE
in the target block. If not, we're going to have
to fold out-of-place anyway.
*/
-
- for (block = 0; block < thisNFTL->EraseSize / 512 ; block++) {
-
- if (BlockLastState[block] != (unsigned char) (cpu_to_le16(BLOCK_FREE) & 0xff) &&
+ for (block = 0; block < nftl->EraseSize / 512 ; block++) {
+ if (BlockLastState[block] != SECTOR_FREE &&
BlockMap[block] != targetEUN) {
- DEBUG(1, "Setting inplace to 0. VUC %d, block %d was %x lastEUN, and is in EUN %d (%s) %d\n",
- thisVUC, block, BlockLastState[block], BlockMap[block] , BlockMap[block]==targetEUN?"==":"!=", targetEUN);
-
+ DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, "
+ "block %d was %x lastEUN, "
+ "and is in EUN %d (%s) %d\n",
+ thisVUC, block, BlockLastState[block],
+ BlockMap[block],
+ BlockMap[block]== targetEUN ? "==" : "!=",
+ targetEUN);
inplace = 0;
break;
}
}
- if ( pendingblock >= (thisVUC * (thisNFTL->EraseSize / 512)) &&
- pendingblock < ((thisVUC + 1)* (thisNFTL->EraseSize / 512)) &&
- BlockLastState[ pendingblock - (thisVUC * (thisNFTL->EraseSize / 512))] !=
- (unsigned char) (cpu_to_le16(BLOCK_FREE) & 0xff)) {
- DEBUG(1, "Pending write not free in EUN %d. Folding out of place.\n", targetEUN);
+ if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) &&
+ pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) &&
+ BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] !=
+ SECTOR_FREE) {
+ DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. "
+ "Folding out of place.\n", targetEUN);
inplace = 0;
}
-
}
if (!inplace) {
- DEBUG(1, "Cannot fold Virtual Unit Chain %d in place. Trying out-of-place\n", thisVUC);
+ DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. "
+ "Trying out-of-place\n", thisVUC);
/* We need to find a targetEUN to fold into. */
- targetEUN = NFTL_findfreeblock(thisNFTL, 1);
- if (targetEUN == 0xffff) {
- /* Ouch. Now we're screwed. We need to do a
- fold-in-place of another chain to make room
- for this one. We need a better way of selecting
- which chain to fold, because makefreeblock will
- only ask us to fold the same one again.
- */
- printk(KERN_WARNING"NFTL_findfreeblock(desperate) returns 0xffff.\n");
- return 0xffff;
+ targetEUN = NFTL_findfreeblock(nftl, 1);
+ if (targetEUN == BLOCK_NIL) {
+ /* Ouch. Now we're screwed. We need to do a
+ fold-in-place of another chain to make room
+ for this one. We need a better way of selecting
+ which chain to fold, because makefreeblock will
+ only ask us to fold the same one again.
+ */
+ printk(KERN_WARNING
+ "NFTL_findfreeblock(desperate) returns 0xffff.\n");
+ return BLOCK_NIL;
}
-
- }
-
+ } else {
+ /* We put a fold mark in the chain we are folding only if
+ we fold in place to help the mount check code. If we do
+ not fold in place, it is possible to find the valid
+ chain by selecting the longer one */
+ oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
+ oob.u.c.unused = 0xffffffff;
+ MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
+ 8, &retlen, (char *)&oob.u);
+ }
/* OK. We now know the location of every block in the Virtual Unit Chain,
and the Erase Unit into which we are supposed to be copying.
Go for it.
*/
-
- DEBUG(1,"Folding chain %d into unit %d\n", thisVUC, targetEUN);
-
- for (block = 0; block < thisNFTL->EraseSize / 512 ; block++) {
+ DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN);
+ for (block = 0; block < nftl->EraseSize / 512 ; block++) {
unsigned char movebuf[512];
- struct nftl_oob oob;
- size_t retlen;
-
- memset(&oob, 0xff, sizeof(oob));
+ int ret;
/* If it's in the target EUN already, or if it's pending write, do nothing */
- if (BlockMap[block] == targetEUN ||(pendingblock == (thisVUC * (thisNFTL->EraseSize / 512) + block))) {
- /* Except if it's the first block, in which case we have to
- set the UnitNumbers */
- if (block == 0) {
-
- thisNFTL->mtd->read_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) ,
- 16, &retlen, (char *)&oob);
-
- // printk("Setting VirtUnitNum on EUN %d to %x, was %x\n", targetEUN, thisVUC,
- // le16_to_cpu(oob.u.a.VirtUnitNum));
-
- oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC & 0x7fff);
-
- thisNFTL->mtd->write_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) ,
- 16, &retlen, (char *)&oob);
- }
+ if (BlockMap[block] == targetEUN ||
+ (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) {
continue;
}
- oob.b.Status = BLOCK_USED;
-
- switch(block) {
- case 0:
- oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC & 0x7fff);
- // printk("Setting VirtUnitNum on EUN %d to %x\n", targetEUN, thisVUC);
-
- oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
- break;
-
- case 1:
- oob.u.b.WearInfo = cpu_to_le32(3); // We don't use this, but M-Systems' drivers do
- oob.u.b.EraseMark = oob.u.b.EraseMark1 = cpu_to_le16(0x3c69);
- break;
-
- case 2:
- default:
- oob.u.c.WriteInh = 0xffffffff;
- oob.u.c.unused = 0xffffffff;
- }
- if (thisNFTL->mtd->read_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * BlockMap[block]) + (block * 512),
- 512, &retlen, movebuf, (char *)&oob) == -EIO) {
- if (thisNFTL->mtd->read_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * BlockMap[block]) + (block * 512),
- 512, &retlen, movebuf, (char *)&oob) != -EIO)
- printk("Error went away on retry.\n");
- }
-
- thisNFTL->mtd->write_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) + (block * 512),
- 512, &retlen, movebuf, (char *)&oob);
-
-
- /* FIXME: Add some error checking.... */
- thisNFTL->mtd->write_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) + (block * 512),
- 16, &retlen, (char *)&oob);
-
+ /* copy only in non free block (free blocks can only
+ happen in case of media errors or deleted blocks) */
+ if (BlockMap[block] == BLOCK_NIL)
+ continue;
+
+ ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block])
+ + (block * 512), 512, &retlen, movebuf, (char *)&oob);
+ if (ret < 0) {
+ ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block])
+ + (block * 512), 512, &retlen,
+ movebuf, (char *)&oob);
+ if (ret != -EIO)
+ printk("Error went away on retry.\n");
+ }
+ MTD_WRITEECC(nftl->mtd, (nftl->EraseSize * targetEUN) + (block * 512),
+ 512, &retlen, movebuf, (char *)&oob);
}
+
+ /* add the header so that it is now a valid chain */
+ oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum
+ = cpu_to_le16(thisVUC);
+ oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
+
+ MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 8,
+ 8, &retlen, (char *)&oob.u);
/* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
@@ -677,78 +496,37 @@ static u16 NFTL_foldchain (struct NFTLrecord *thisNFTL, u16 thisVUC, unsigned pe
shouldn't actually lose data in this case. It's just that when we load up on a medium which
has duplicate chains, we need to free one of the chains because it's not necessary any more.
*/
-
-
- thisEUN = thisNFTL->EUNtable[thisVUC];
+ thisEUN = nftl->EUNtable[thisVUC];
+ DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n");
- DEBUG(1,"Want to erase\n");
/* For each block in the old chain (except the targetEUN of course),
free it and make it available for future use */
-
- while( thisEUN <= thisNFTL->lastEUN && thisEUN != targetEUN) {
- size_t retlen;
- struct erase_info *instr;
- u16 EUNtmp;
-
- instr = kmalloc(sizeof(struct erase_info), GFP_KERNEL);
- if (!instr) {
- printk(KERN_WARNING "Out of memory for struct erase_info\n");
-
- EUNtmp = thisEUN;
-
- thisEUN = thisNFTL->ReplUnitTable[EUNtmp] & 0x7fff;
- thisNFTL->VirtualUnitTable[EUNtmp] = 0x7fff;
- thisNFTL->ReplUnitTable[EUNtmp] = 0xffff;
- } else {
- memset(instr, 0, sizeof(struct erase_info));
- instr->addr = thisEUN * thisNFTL->EraseSize;
- instr->len = thisNFTL->EraseSize;
-
- MTD_ERASE(thisNFTL->mtd, instr);
- /* This is an async interface. Or will be. At which point
- this code will break. */
-
-#if 0
- MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + 512, 16, &retlen, (char *)&oob);
-
- printk("After erasing, EUN %d contains: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
- thisEUN, oob.b.ECCSig[0],
- oob.b.ECCSig[1],
- oob.b.ECCSig[2],
- oob.b.ECCSig[3],
- oob.b.ECCSig[4],
- oob.b.ECCSig[5]);
-#endif
- memset(&oob, 0xff, sizeof(oob));
- oob.u.b.WearInfo = cpu_to_le32(3);
- oob.u.b.EraseMark = oob.u.b.EraseMark1 = cpu_to_le16(0x3c69);
-
- MTD_WRITEOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + 512, 16, &retlen, (char *)&oob);
-
- EUNtmp = thisEUN;
-
- thisEUN = thisNFTL->ReplUnitTable[EUNtmp] & 0x7fff;
- thisNFTL->VirtualUnitTable[EUNtmp] = 0xffff;
- thisNFTL->ReplUnitTable[EUNtmp] = 0xffff;
-
- thisNFTL->numfreeEUNs++;
-
- }
-
- // shifted upwards: thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff;
-
+ while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {
+ unsigned int EUNtmp;
+
+ EUNtmp = nftl->ReplUnitTable[thisEUN];
+
+ if (NFTL_formatblock(nftl, thisEUN) < 0) {
+ /* could not erase : mark block as reserved
+ * FixMe: Update Bad Unit Table on disk
+ */
+ nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
+ } else {
+ /* correctly erased : mark it as free */
+ nftl->ReplUnitTable[thisEUN] = BLOCK_FREE;
+ nftl->numfreeEUNs++;
+ }
+ thisEUN = EUNtmp;
}
/* Make this the new start of chain for thisVUC */
- thisNFTL->VirtualUnitTable[targetEUN] = thisVUC;
- thisNFTL->ReplUnitTable[targetEUN] = 0xffff;
+ nftl->ReplUnitTable[targetEUN] = BLOCK_NIL;
+ nftl->EUNtable[thisVUC] = targetEUN;
- thisNFTL->EUNtable[thisVUC] = targetEUN;
return targetEUN;
-
}
-u16 NFTL_makefreeblock( struct NFTLrecord *thisNFTL , unsigned pendingblock)
+u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)
{
/* This is the part that needs some cleverness applied.
For now, I'm doing the minimum applicable to actually
@@ -757,23 +535,21 @@ u16 NFTL_makefreeblock( struct NFTLrecord *thisNFTL , unsigned pendingblock)
and we also need to do some assessment of the results when
the system loses power half-way through the routine.
*/
-
u16 LongestChain = 0;
u16 ChainLength = 0, thislen;
u16 chain, EUN;
-
- for (chain=0; chain < thisNFTL->MediaHdr.FormattedSize / thisNFTL->EraseSize; chain++) {
- EUN = thisNFTL->EUNtable[chain];
-
+ for (chain = 0; chain < nftl->MediaHdr.FormattedSize / nftl->EraseSize; chain++) {
+ EUN = nftl->EUNtable[chain];
thislen = 0;
- while (EUN <= thisNFTL->lastEUN) {
+ while (EUN <= nftl->lastEUN) {
thislen++;
- // printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN);
- EUN = thisNFTL->ReplUnitTable[EUN] & 0x7fff;
+ //printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN);
+ EUN = nftl->ReplUnitTable[EUN] & 0x7fff;
if (thislen > 0xff00) {
- printk("Endless loop in Virtual Chain %d: Unit %x\n", chain, EUN);
+ printk("Endless loop in Virtual Chain %d: Unit %x\n",
+ chain, EUN);
}
if (thislen > 0xff10) {
/* Actually, don't return failure. Just ignore this chain and
@@ -781,42 +557,38 @@ u16 NFTL_makefreeblock( struct NFTLrecord *thisNFTL , unsigned pendingblock)
thislen = 0;
break;
}
-
}
-
if (thislen > ChainLength) {
- // printk("New longest chain is %d with length %d\n", chain, thislen);
+ //printk("New longest chain is %d with length %d\n", chain, thislen);
ChainLength = thislen;
LongestChain = chain;
}
- }
+ }
if (ChainLength < 2) {
- printk(KERN_WARNING "No Virtual Unit Chains available for folding. Failing request\n");
+ printk(KERN_WARNING "No Virtual Unit Chains available for folding. "
+ "Failing request\n");
return 0xffff;
}
-
- return NFTL_foldchain (thisNFTL, LongestChain, pendingblock);
+
+ return NFTL_foldchain (nftl, LongestChain, pendingblock);
}
/* NFTL_findwriteunit: Return the unit number into which we can write
for this block. Make it available if it isn't already
*/
-
-static inline u16 NFTL_findwriteunit(struct NFTLrecord *thisNFTL, unsigned block)
+static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
{
u16 lastEUN;
- u16 thisVUC = block / (thisNFTL->EraseSize / 512);
- u16 writeEUN;
- unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1);
+ u16 thisVUC = block / (nftl->EraseSize / 512);
+ unsigned int writeEUN;
+ unsigned long blockofs = (block * 512) & (nftl->EraseSize -1);
size_t retlen;
- int silly = 0x10000, silly2 = 3;
+ int silly, silly2 = 3;
struct nftl_oob oob;
- int debug=0;
do {
-
/* Scan the media to find a unit in the VUC which has
a free space for the block in question.
*/
@@ -824,28 +596,30 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *thisNFTL, unsigned block
/* This condition catches the 0x[7f]fff cases, as well as
being a sanity check for past-end-of-media access
*/
- lastEUN = 0xffff;
- writeEUN = thisNFTL->EUNtable[thisVUC];
-
- while(writeEUN <= thisNFTL->lastEUN) {
+ lastEUN = BLOCK_NIL;
+ writeEUN = nftl->EUNtable[thisVUC];
+ silly = MAX_LOOPS;
+ while (writeEUN <= nftl->lastEUN) {
struct nftl_bci bci;
size_t retlen;
-
+ unsigned int status;
+
lastEUN = writeEUN;
+
+ MTD_READOOB(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs,
+ 8, &retlen, (char *)&bci);
- MTD_READOOB(thisNFTL->mtd, (writeEUN * thisNFTL->EraseSize)
- + blockofs,8, &retlen, (char *)&bci);
-
- if (debug)
- printk("Status of block %d in EUN %d is %x\n", block , writeEUN, le16_to_cpu(bci.Status));
+ DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
+ block , writeEUN, le16_to_cpu(bci.Status));
- switch(bci.Status) {
- case __constant_cpu_to_le16(BLOCK_FREE):
+ status = bci.Status | bci.Status1;
+ switch(status) {
+ case SECTOR_FREE:
return writeEUN;
- case __constant_cpu_to_le16(BLOCK_DELETED):
- case __constant_cpu_to_le16(BLOCK_USED):
- case __constant_cpu_to_le16(BLOCK_IGNORE):
+ case SECTOR_DELETED:
+ case SECTOR_USED:
+ case SECTOR_IGNORE:
break;
default:
// Invalid block. Don't use it any more. Must implement.
@@ -853,35 +627,35 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *thisNFTL, unsigned block
}
if (!silly--) {
- printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", thisVUC);
+ printk(KERN_WARNING
+ "Infinite loop in Virtual Unit Chain 0x%x\n",
+ thisVUC);
return 0xffff;
}
/* Skip to next block in chain */
-
- writeEUN = thisNFTL->ReplUnitTable[writeEUN] & 0x7fff;
+ writeEUN = nftl->ReplUnitTable[writeEUN];
}
/* OK. We didn't find one in the existing chain, or there
is no existing chain. */
/* Try to find an already-free block */
+ writeEUN = NFTL_findfreeblock(nftl, 0);
- writeEUN = NFTL_findfreeblock(thisNFTL, 0);
-
- if (writeEUN == 0xffff) {
+ if (writeEUN == BLOCK_NIL) {
/* That didn't work - there were no free blocks just
waiting to be picked up. We're going to have to fold
a chain to make room.
*/
/* First remember the start of this chain */
- // u16 startEUN = thisNFTL->EUNtable[thisVUC];
+ //u16 startEUN = nftl->EUNtable[thisVUC];
//printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);
- writeEUN = NFTL_makefreeblock(thisNFTL, block);
+ writeEUN = NFTL_makefreeblock(nftl, 0xffff);
- if (writeEUN == 0xffff) {
+ if (writeEUN == BLOCK_NIL) {
/* Ouch. This should never happen - we should
always be able to make some room somehow.
If we get here, we've allocated more storage
@@ -889,235 +663,223 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *thisNFTL, unsigned block
routine is missing something.
*/
printk(KERN_WARNING "Cannot make free space.\n");
- return 0xffff;
+ return BLOCK_NIL;
}
- // printk("Restarting scan\n");
- lastEUN = 0xffff;
- // debug = 1;
+ //printk("Restarting scan\n");
+ lastEUN = BLOCK_NIL;
continue;
-#if 0
- if (startEUN != thisNFTL->EUNtable[thisVUC]) {
- /* The fold operation has moved the chain
- that we're looking at. Start the scan again.
- */
- continue;
- }
-#endif
}
/* We've found a free block. Insert it into the chain. */
- if (lastEUN != 0xffff) {
- /* Addition to an existing chain. Make the previous
- last block in the chain point to this one.
- */
-
- //printk("Linking EUN %d to EUN %d in VUC %d\n",
- // lastEUN, writeEUN, thisVUC);
- /* Both in our cache... */
- thisNFTL->ReplUnitTable[lastEUN] = writeEUN;
-
-
- /* ... and on the flash itself */
- MTD_READOOB(thisNFTL->mtd, (lastEUN * thisNFTL->EraseSize), 16, &retlen,
- (char *)&oob);
+ if (lastEUN != BLOCK_NIL) {
+ thisVUC |= 0x8000; /* It's a replacement block */
+ } else {
+ /* The first block in a new chain */
+ nftl->EUNtable[thisVUC] = writeEUN;
+ }
- oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = cpu_to_le16(writeEUN);
+ /* set up the actual EUN we're writing into */
+ /* Both in our cache... */
+ nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
- MTD_WRITEOOB(thisNFTL->mtd, (lastEUN * thisNFTL->EraseSize), 16, &retlen,
- (char *)&oob);
+ /* ... and on the flash itself */
+ MTD_READOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8,
+ &retlen, (char *)&oob.u);
- thisVUC |= 0x8000; /* It's a replacement block */
- } else {
- /* The first block in a new chain */
- thisNFTL->EUNtable[thisVUC] = writeEUN;
- }
+ oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
- /* Now set up the actual EUN we're writing into */
+ MTD_WRITEOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8,
+ &retlen, (char *)&oob.u);
+ /* we link the new block to the chain only after the
+ block is ready. It avoids the case where the chain
+ could point to a free block */
+ if (lastEUN != BLOCK_NIL) {
/* Both in our cache... */
- thisNFTL->VirtualUnitTable[writeEUN] = thisVUC;
- thisNFTL->ReplUnitTable[writeEUN] = 0xffff;
-
+ nftl->ReplUnitTable[lastEUN] = writeEUN;
/* ... and on the flash itself */
- MTD_READOOB(thisNFTL->mtd, writeEUN * thisNFTL->EraseSize, 16,
- &retlen, (char *)&oob);
+ MTD_READOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8,
+ 8, &retlen, (char *)&oob.u);
- oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
+ oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
+ = cpu_to_le16(writeEUN);
- MTD_WRITEOOB(thisNFTL->mtd, writeEUN * thisNFTL->EraseSize, 16,
- &retlen, (char *)&oob);
+ MTD_WRITEOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8,
+ 8, &retlen, (char *)&oob.u);
+ }
return writeEUN;
} while (silly2--);
- printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", thisVUC);
+ printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n",
+ thisVUC);
return 0xffff;
}
-static int NFTL_writeblock(struct NFTLrecord *thisNFTL, unsigned block,
- char *buffer)
+static int NFTL_writeblock(struct NFTLrecord *nftl, unsigned block, char *buffer)
{
u16 writeEUN;
- unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1);
+ unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
size_t retlen;
- u16 eccbuf[8];
-
- // if (thisEUN == 0xffff) thisEUN = 0;
-
- writeEUN = NFTL_findwriteunit(thisNFTL, block);
+ u8 eccbuf[6];
-// printk("writeblock(%d): Write to Unit %d\n", block, writeEUN);
+ writeEUN = NFTL_findwriteunit(nftl, block);
- if (writeEUN == 0xffff) {
- printk(KERN_WARNING "NFTL_writeblock(): Cannot find block to write to\n");
+ if (writeEUN == BLOCK_NIL) {
+ printk(KERN_WARNING
+ "NFTL_writeblock(): Cannot find block to write to\n");
/* If we _still_ haven't got a block to use, we're screwed */
return 1;
}
-// printk("Writing block %lx to EUN %x\n",block, writeEUN);
-
- thisNFTL->mtd->write_ecc(thisNFTL->mtd,
- (writeEUN * thisNFTL->EraseSize) + blockofs,
- 512, &retlen, (char *)buffer, (char *)eccbuf);
- eccbuf[3] = BLOCK_USED;
- eccbuf[4] = eccbuf[5] = eccbuf[6] = eccbuf[7] = 0xffff;
-
- thisNFTL->mtd->write_oob(thisNFTL->mtd,
- (writeEUN * thisNFTL->EraseSize) + blockofs,
- 16, &retlen, (char *)eccbuf);
+ MTD_WRITEECC(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs,
+ 512, &retlen, (char *)buffer, (char *)eccbuf);
+ /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */
return 0;
}
-
#endif /* CONFIG_NFTL_RW */
-static int NFTL_readblock(struct NFTLrecord *thisNFTL,
- unsigned block, char *buffer)
+static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer)
{
- u16 lastgoodEUN = 0xffff;
- u16 thisEUN = thisNFTL->EUNtable[block / (thisNFTL->EraseSize / 512)];
- unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1);
-
- int silly = -1;
+ u16 lastgoodEUN;
+ u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)];
+ unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
+ unsigned int status;
+ int silly = MAX_LOOPS;
+ size_t retlen;
+ struct nftl_bci bci;
+
+ lastgoodEUN = BLOCK_NIL;
+
+ if (thisEUN != BLOCK_NIL) {
+ while (thisEUN < nftl->nb_blocks) {
+ if (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs,
+ 8, &retlen, (char *)&bci) < 0)
+ status = SECTOR_IGNORE;
+ else
+ status = bci.Status | bci.Status1;
+
+ switch (status) {
+ case SECTOR_FREE:
+ /* no modification of a sector should follow a free sector */
+ goto the_end;
+ case SECTOR_DELETED:
+ lastgoodEUN = BLOCK_NIL;
+ break;
+ case SECTOR_USED:
+ lastgoodEUN = thisEUN;
+ break;
+ case SECTOR_IGNORE:
+ break;
+ default:
+ printk("Unknown status for block %d in EUN %d: %x\n",
+ block, thisEUN, status);
+ break;
+ }
- if (thisEUN == 0xffff) thisEUN = 0;
-
- while(thisEUN && (thisEUN & 0x7fff) != 0x7fff) {
- struct nftl_bci bci;
- size_t retlen;
-
- MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + blockofs,8, &retlen, (char *)&bci);
-
- switch(bci.Status) {
- case __constant_cpu_to_le16(BLOCK_FREE):
- thisEUN = 0;
- break;
- case __constant_cpu_to_le16(BLOCK_USED):
- lastgoodEUN = thisEUN;
- break;
- case __constant_cpu_to_le16(BLOCK_IGNORE):
- case __constant_cpu_to_le16(BLOCK_DELETED):
- break;
- default:
- printk("Unknown status for block %d in EUN %d: %x\n",block,thisEUN, bci.Status);
+ if (!silly--) {
+ printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",
+ block / (nftl->EraseSize / 512));
+ return 1;
+ }
+ thisEUN = nftl->ReplUnitTable[thisEUN];
}
+ }
- if (!silly--) {
- printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",block / (thisNFTL->EraseSize / 512));
- return 1;
- }
- if (thisEUN)
- thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff;
- }
- if (lastgoodEUN == 0xffff) {
+ the_end:
+ if (lastgoodEUN == BLOCK_NIL) {
+ /* the requested block is not on the media, return all 0x00 */
memset(buffer, 0, 512);
} else {
- loff_t ptr = (lastgoodEUN * thisNFTL->EraseSize) + blockofs;
+ loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
size_t retlen;
u_char eccbuf[6];
- thisNFTL->mtd->read_ecc(thisNFTL->mtd, ptr, 512, &retlen, buffer, eccbuf);
+ if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf))
+ return -EIO;
}
return 0;
}
-
-static int nftl_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg)
+static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
{
- struct NFTLrecord *thisNFTL;
-
- thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16];
+ struct NFTLrecord *nftl;
- if (!thisNFTL) return -EINVAL;
+ nftl = NFTLs[MINOR(inode->i_rdev) / 16];
+ if (!nftl) return -EINVAL;
switch (cmd) {
case HDIO_GETGEO: {
struct hd_geometry g;
- g.heads = thisNFTL->heads;
- g.sectors = thisNFTL->sectors;
- g.cylinders = thisNFTL->cylinders;
+ g.heads = nftl->heads;
+ g.sectors = nftl->sectors;
+ g.cylinders = nftl->cylinders;
g.start = part_table[MINOR(inode->i_rdev)].start_sect;
return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
}
case BLKGETSIZE: /* Return device size */
- if (!arg) return -EINVAL;
+ if (!arg) return -EINVAL;
return put_user(part_table[MINOR(inode->i_rdev)].nr_sects,
(long *) arg);
case BLKFLSBUF:
- if(!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
- if (thisNFTL->mtd->sync)
- thisNFTL->mtd->sync(thisNFTL->mtd);
+ if (nftl->mtd->sync)
+ nftl->mtd->sync(nftl->mtd);
return 0;
case BLKRRPART:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- if (thisNFTL->usecount > 1) {
- // printk("Use count %d\n", thisNFTL->usecount);
- return -EBUSY;
- }
+ if (nftl->usecount > 1) return -EBUSY;
#if LINUX_VERSION_CODE < 0x20328
- resetup_one_dev(&nftl_gendisk, MINOR(inode->i_dev) / 16);
+ resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) / 16);
#else
- grok_partitions(&nftl_gendisk, MINOR(inode->i_dev) / 16, 1<<4, thisNFTL->nr_sects);
+ grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) / 16,
+ 1<<4, nftl->nr_sects);
#endif
return 0;
-
- // RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */
+
+#if (LINUX_VERSION_CODE < 0x20303)
+ RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */
+#else
+ case BLKROSET:
+ case BLKROGET:
+ case BLKSSZGET:
+ return blk_ioctl(inode->i_rdev, cmd, arg);
+#endif
+
default:
return -EINVAL;
}
}
-
void nftl_request(RQFUNC_ARG)
{
unsigned int dev, block, nsect;
- struct NFTLrecord *thisNFTL;
+ struct NFTLrecord *nftl;
char *buffer;
struct request *req;
int res;
while (1) {
INIT_REQUEST; /* blk.h */
-
- req = CURRENT;
-#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK
- blkdev_dequeue_request(req);
- spin_unlock_irq(&io_request_lock);
-#else
req = CURRENT;
-#endif
- DEBUG(2,"NFTL_request\n");
- DEBUG(3,"NFTL %d request, %lx, %lx", req->cmd,
- req->sector, req->current_nr_sectors);
+ /* We can do this because the generic code knows not to
+ touch the request at the head of the queue */
+ spin_unlock_irq(&io_request_lock);
+
+ DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n");
+ DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n",
+ (req->cmd == READ) ? "Read " : "Write",
+ req->sector, req->current_nr_sectors);
+
dev = MINOR(req->rq_dev);
block = req->sector;
nsect = req->current_nr_sectors;
@@ -1125,21 +887,23 @@ void nftl_request(RQFUNC_ARG)
res = 1; /* succeed */
if (dev >= MAX_NFTLS * 16) {
- printk("fl: bad minor number: device=%s\n",
+ /* there is no such partition */
+ printk("nftl: bad minor number: device = %s\n",
kdevname(req->rq_dev));
res = 0; /* fail */
goto repeat;
}
- thisNFTL = NFTLs[dev / 16];
- DEBUG(3,"Waiting for mutex\n");
- down(&thisNFTL->mutex);
- DEBUG(3,"Got mutex\n");
-
- if (block + nsect >= part_table[dev].nr_sects) {
- printk("nftl%c%d: bad access: block=%d, count=%d\n",
+ nftl = NFTLs[dev / 16];
+ DEBUG(MTD_DEBUG_LEVEL3, "Waiting for mutex\n");
+ down(&nftl->mutex);
+ DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n");
+
+ if (block + nsect > part_table[dev].nr_sects) {
+ /* access past the end of device */
+ printk("nftl%c%d: bad access: block = %d, count = %d\n",
(MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect);
- up(&thisNFTL->mutex);
+ up(&nftl->mutex);
res = 0; /* fail */
goto repeat;
}
@@ -1147,75 +911,80 @@ void nftl_request(RQFUNC_ARG)
block += part_table[dev].start_sect;
if (req->cmd == READ) {
- DEBUG(2,"NFTL read\n");
- for ( ; nsect > 0; nsect-- , block++, buffer+= 512) {
+ DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x "
+ "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors);
+
+ for ( ; nsect > 0; nsect-- , block++, buffer += 512) {
/* Read a single sector to req->buffer + (512 * i) */
-
- if (NFTL_readblock(thisNFTL, block, buffer)) {
- DEBUG(2,"NFTL read request failed\n");
- up(&thisNFTL->mutex);
+ if (NFTL_readblock(nftl, block, buffer)) {
+ DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n");
+ up(&nftl->mutex);
res = 0;
goto repeat;
}
}
- DEBUG(2,"NFTL read request completed OK\n");
- up(&thisNFTL->mutex);
+
+ DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n");
+ up(&nftl->mutex);
goto repeat;
- }
- else if (req->cmd == WRITE) {
- DEBUG(2,"NFTL write request of 0x%x sectors @ %x (req->nr_sectors == %lx\n",nsect, block, req->nr_sectors);
+ } else if (req->cmd == WRITE) {
+ DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x "
+ "(req->nr_sectors == %lx)\n", nsect, block,
+ req->nr_sectors);
#ifdef CONFIG_NFTL_RW
- for ( ; nsect > 0; nsect-- , block++, buffer+= 512) {
+ for ( ; nsect > 0; nsect-- , block++, buffer += 512) {
/* Read a single sector to req->buffer + (512 * i) */
-
- if (NFTL_writeblock(thisNFTL, block, buffer)) {
- DEBUG(1,"NFTL write request failed\n");
-
- up(&thisNFTL->mutex);
+ if (NFTL_writeblock(nftl, block, buffer)) {
+ DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n");
+ up(&nftl->mutex);
res = 0;
goto repeat;
}
}
- DEBUG(2,"NFTL write request completed OK\n");
+ DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n");
#else
- res=0; /* Writes always fail */
+ res = 0; /* Writes always fail */
#endif /* CONFIG_NFTL_RW */
- up(&thisNFTL->mutex);
+ up(&nftl->mutex);
goto repeat;
- }
- else {
- DEBUG(0,"NFTL ??? request\n");
- up(&thisNFTL->mutex);
+ } else {
+ DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n");
+ up(&nftl->mutex);
res = 0;
goto repeat;
}
repeat:
- DEBUG(3,"end_request(%d)\n", res);
-#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK
+ DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res);
spin_lock_irq(&io_request_lock);
- nftl_end_request(req, res);
-#else
end_request(res);
-#endif
}
}
static int nftl_open(struct inode *ip, struct file *fp)
{
+ int nftlnum = MINOR(ip->i_rdev) / 16;
struct NFTLrecord *thisNFTL;
- thisNFTL = NFTLs[MINOR(ip->i_rdev) / 16];
+ thisNFTL = NFTLs[nftlnum];
- DEBUG(2,"NFTL_open\n");
+ DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n");
+#ifdef CONFIG_KMOD
+ if (!thisNFTL && nftlnum == 0) {
+ request_module("docprobe");
+ thisNFTL = NFTLs[nftlnum];
+ }
+#endif
if (!thisNFTL) {
- DEBUG(2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n",
- MINOR(ip->i_rdev) / 16,ip->i_rdev,ip, fp);
+ DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n",
+ nftlnum, ip->i_rdev, ip, fp);
return -ENODEV;
}
+
#ifndef CONFIG_NFTL_RW
if (fp->f_mode & FMODE_WRITE)
- return -EROFS;
+ return -EROFS;
#endif /* !CONFIG_NFTL_RW */
+
thisNFTL->usecount++;
MOD_INC_USE_COUNT;
if (!get_mtd_device(thisNFTL->mtd, -1)) {
@@ -1233,8 +1002,8 @@ static int nftl_release(struct inode *inode, struct file *fp)
thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16];
- DEBUG(2, "NFTL_release\n");
-
+ DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n");
+
fsync_dev(inode->i_rdev);
if (sb)
invalidate_inodes(sb);
@@ -1251,19 +1020,19 @@ static int nftl_release(struct inode *inode, struct file *fp)
}
#if LINUX_VERSION_CODE < 0x20326
static struct file_operations nftl_fops = {
- read: block_read,
- write: block_write,
- ioctl: nftl_ioctl,
- open: nftl_open,
- release: nftl_release,
- fsync: block_fsync,
+ read: block_read,
+ write: block_write,
+ ioctl: nftl_ioctl,
+ open: nftl_open,
+ release: nftl_release,
+ fsync: block_fsync,
};
#else
static struct block_device_operations nftl_fops =
{
- open: nftl_open,
- release: nftl_release,
- ioctl: nftl_ioctl
+ open: nftl_open,
+ release: nftl_release,
+ ioctl: nftl_ioctl
};
#endif
@@ -1275,39 +1044,39 @@ static struct block_device_operations nftl_fops =
*
****************************************************************************/
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_nftl init_module
#define cleanup_nftl cleanup_module
#endif
-#define __exit
-#endif
static struct mtd_notifier nftl_notifier = {NFTL_notify_add, NFTL_notify_remove, NULL};
-
/* static int __init init_nftl(void) */
int __init init_nftl(void)
{
int i;
- printk(KERN_NOTICE "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n");
+ printk(KERN_NOTICE
+ "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n");
#ifdef PRERELEASE
- printk(KERN_INFO"$Id: nftl.c,v 1.36 2000/07/13 14:14:20 dwmw2 Exp $\n");
+ printk(KERN_INFO"$Id: nftl.c,v 1.57 2000/12/01 17:51:54 dwmw2 Exp $\n");
#endif
- if (register_blkdev(NFTL_MAJOR, "nftl", &nftl_fops)){
- printk("unable to register NFTL block device\n");
+ if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){
+ printk("unable to register NFTL block device on major %d\n", MAJOR_NR);
+ return -EBUSY;
} else {
#if LINUX_VERSION_CODE < 0x20320
- blk_dev[MAJOR_NR].request_fn = nftl_request;
+ blk_dev[MAJOR_NR].request_fn = nftl_request;
#else
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request);
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request);
#endif
- for (i=0; i < 256 ; i++) {
+ /* set block size to 1kB each */
+ for (i = 0; i < 256; i++) {
nftl_blocksizes[i] = 1024;
}
- blksize_size[NFTL_MAJOR] = nftl_blocksizes;
+ blksize_size[MAJOR_NR] = nftl_blocksizes;
+
nftl_gendisk.next = gendisk_head;
gendisk_head = &nftl_gendisk;
}
@@ -1319,25 +1088,25 @@ int __init init_nftl(void)
static void __exit cleanup_nftl(void)
{
- struct gendisk *gd, **gdp;
+ struct gendisk *gd, **gdp;
- unregister_mtd_user(&nftl_notifier);
-
- unregister_blkdev(NFTL_MAJOR, "nftl");
+ unregister_mtd_user(&nftl_notifier);
+ unregister_blkdev(MAJOR_NR, "nftl");
+
#if LINUX_VERSION_CODE < 0x20320
- blk_dev[MAJOR_NR].request_fn = 0;
+ blk_dev[MAJOR_NR].request_fn = 0;
#else
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
#endif
- for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
- if (*gdp == &nftl_gendisk) {
- gd = *gdp; *gdp = gd->next;
- break;
- }
-
+
+ /* remove ourself from generic harddisk list
+ FIXME: why can't I found this partition on /proc/partition */
+ for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
+ if (*gdp == &nftl_gendisk) {
+ gd = *gdp; *gdp = gd->next;
+ break;
+ }
}
-#if LINUX_VERSION_CODE > 0x20300
module_init(init_nftl);
module_exit(cleanup_nftl);
-#endif
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
new file mode 100644
index 000000000..d1f05930f
--- /dev/null
+++ b/drivers/mtd/nftlmount.c
@@ -0,0 +1,678 @@
+/*
+ * NFTL mount code with extensive checks
+ *
+ * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
+ * Copyright (C) 2000 Netgem S.A.
+ *
+ * $Id: nftlmount.c,v 1.11 2000/11/17 12:24:09 ollie Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the 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/kernel.h>
+#include <linux/module.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nftl.h>
+#include <linux/mtd/compatmac.h>
+
+#define SECTORSIZE 512
+
+/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
+ * various device information of the NFTL partition and Bad Unit Table. Update
+ * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
+ * is used for management of Erase Unit in other routines in nftl.c and nftlmount.c
+ */
+static int find_boot_record(struct NFTLrecord *nftl)
+{
+ struct nftl_uci1 h1;
+ struct nftl_oob oob;
+ unsigned int block, boot_record_count;
+ int retlen;
+ u8 buf[SECTORSIZE];
+ struct NFTLMediaHeader *mh = &nftl->MediaHdr;
+
+ nftl->MediaUnit = BLOCK_NIL;
+ nftl->SpareMediaUnit = BLOCK_NIL;
+ boot_record_count = 0;
+
+ /* search for a valid boot record */
+ for (block = 0; block < nftl->nb_blocks; block++) {
+ unsigned int erase_mark;
+
+ /* read ANAND header. To be safer with BIOS, also use erase mark as discriminant */
+ if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8,
+ 8, &retlen, (char *)&h1) < 0)
+ continue;
+
+ erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
+ if (erase_mark != ERASE_MARK)
+ continue;
+
+ if (MTD_READECC(nftl->mtd, block * nftl->EraseSize, SECTORSIZE,
+ &retlen, buf, (char *)&oob) < 0)
+ continue;
+
+ memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
+ if (memcmp(mh->DataOrgID, "ANAND", 6) == 0) {
+ /* first boot record */
+ if (boot_record_count == 0) {
+ unsigned int i;
+ /* header found : read the bad block table data */
+ if (mh->UnitSizeFactor != 0xff) {
+ printk("Sorry, we don't support UnitSizeFactor "
+ "of != 1 yet\n");
+ goto ReplUnitTable;
+ }
+
+ nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
+ if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks)
+ goto ReplUnitTable; /* small consistency check */
+
+ nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize;
+ if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2))
+ goto ReplUnitTable; /* small consistency check */
+
+ /* FixMe: with bad blocks, the total size available is not FormattedSize any
+ more !!! */
+ nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
+ nftl->MediaUnit = block;
+
+ /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
+ for (i = 0; i < nftl->nb_blocks; i++) {
+ if ((i & (SECTORSIZE - 1)) == 0) {
+ /* read one sector for every SECTORSIZE of blocks */
+ if (MTD_READECC(nftl->mtd, block * nftl->EraseSize +
+ i + SECTORSIZE, SECTORSIZE,
+ &retlen, buf, (char *)&oob) < 0)
+ goto ReplUnitTable;
+ }
+ /* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
+ if (buf[i & (SECTORSIZE - 1)] != 0xff)
+ nftl->ReplUnitTable[i] = BLOCK_RESERVED;
+ }
+
+ boot_record_count++;
+ } else if (boot_record_count == 1) {
+ nftl->SpareMediaUnit = block;
+ boot_record_count++;
+ break;
+ }
+ }
+ ReplUnitTable:
+ }
+
+ if (boot_record_count == 0) {
+ /* no boot record found */
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+static int memcmpb(void *a, int c, int n)
+{
+ int i;
+ for (i = 0; i < n; i++) {
+ if (c != ((unsigned char *)a)[i])
+ return 1;
+ }
+ return 0;
+}
+
+/* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */
+static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
+ int check_oob)
+{
+ int i, retlen;
+ u8 buf[SECTORSIZE];
+
+ for (i = 0; i < len; i += SECTORSIZE) {
+ /* we want to read the sector without ECC check here since a free
+ sector does not have ECC syndrome on it yet */
+ if (MTD_READ(nftl->mtd, address, SECTORSIZE, &retlen, buf) < 0)
+ return -1;
+ if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
+ return -1;
+
+ if (check_oob) {
+ if (MTD_READOOB(nftl->mtd, address, nftl->mtd->oobsize,
+ &retlen, buf) < 0)
+ return -1;
+ if (memcmpb(buf, 0xff, nftl->mtd->oobsize) != 0)
+ return -1;
+ }
+ address += SECTORSIZE;
+ }
+
+ return 0;
+}
+
+/* NFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase Unit and
+ * Update NFTL metadata. Each erase operation is checked with check_free_sectors
+ *
+ * Return: 0 when succeed, -1 on error.
+ *
+ * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
+ * 2. UnitSizeFactor != 0xFF
+ */
+int NFTL_formatblock(struct NFTLrecord *nftl, int block)
+{
+ int retlen;
+ unsigned int nb_erases, erase_mark;
+ struct nftl_uci1 uci;
+ struct erase_info *instr = &nftl->instr;
+
+ /* Read the Unit Control Information #1 for Wear-Leveling */
+ if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8,
+ 8, &retlen, (char *)&uci) < 0)
+ goto default_uci1;
+
+ erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1));
+ if (erase_mark != ERASE_MARK) {
+ default_uci1:
+ uci.EraseMark = cpu_to_le16(ERASE_MARK);
+ uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
+ uci.WearInfo = cpu_to_le32(0);
+ }
+
+ memset(instr, 0, sizeof(struct erase_info));
+
+ /* XXX: use async erase interface, XXX: test return code */
+ instr->addr = block * nftl->EraseSize;
+ instr->len = nftl->EraseSize;
+ MTD_ERASE(nftl->mtd, instr);
+
+ if (instr->state == MTD_ERASE_FAILED) {
+ /* could not format, FixMe: We should update the BadUnitTable
+ both in memory and on disk */
+ printk("Error while formatting block %d\n", block);
+ return -1;
+ } else {
+ /* increase and write Wear-Leveling info */
+ nb_erases = le32_to_cpu(uci.WearInfo);
+ nb_erases++;
+
+ /* wrap (almost impossible with current flashs) or free block */
+ if (nb_erases == 0)
+ nb_erases = 1;
+
+ /* check the "freeness" of Erase Unit before updating metadata
+ * FixMe: is this check really necessary ? since we have check the
+ * return code after the erase operation. */
+ if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
+ return -1;
+
+ uci.WearInfo = le32_to_cpu(nb_erases);
+ if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
+ &retlen, (char *)&uci) < 0)
+ return -1;
+ return 0;
+ }
+}
+
+/* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
+ * Mark as 'IGNORE' each incorrect sector. This check is only done if the chain
+ * was being folded when NFTL was interrupted.
+ *
+ * The check_free_sectors in this function is neceressary. There is a possible
+ * situation that after writing the Data area, the Block Control Information is
+ * not updated according (due to power failure or something) which leaves the block
+ * in an umconsistent state. So we have to check if a block is really FREE in this
+ * case. */
+static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
+{
+ unsigned int block, i, status;
+ struct nftl_bci bci;
+ int sectors_per_block, retlen;
+
+ sectors_per_block = nftl->EraseSize / SECTORSIZE;
+ block = first_block;
+ for (;;) {
+ for (i = 0; i < sectors_per_block; i++) {
+ if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i * SECTORSIZE,
+ 8, &retlen, (char *)&bci) < 0)
+ status = SECTOR_IGNORE;
+ else
+ status = bci.Status | bci.Status1;
+
+ switch(status) {
+ case SECTOR_FREE:
+ /* verify that the sector is really free. If not, mark
+ as ignore */
+ if (memcmpb(&bci, 0xff, 8) != 0 ||
+ check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
+ SECTORSIZE, 0) != 0) {
+ printk("Incorrect free sector %d in block %d: "
+ "marking it as ignored\n",
+ i, block);
+
+ /* sector not free actually : mark it as SECTOR_IGNORE */
+ bci.Status = SECTOR_IGNORE;
+ bci.Status1 = SECTOR_IGNORE;
+ MTD_WRITEOOB(nftl->mtd,
+ block * nftl->EraseSize + i * SECTORSIZE,
+ 8, &retlen, (char *)&bci);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* proceed to next Erase Unit on the chain */
+ block = nftl->ReplUnitTable[block];
+ if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
+ printk("incorrect ReplUnitTable[] : %d\n", block);
+ if (block == BLOCK_NIL || block >= nftl->nb_blocks)
+ break;
+ }
+}
+
+/* calc_chain_lenght: Walk through a Virtual Unit Chain and estimate chain length */
+static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
+{
+ unsigned int length = 0, block = first_block;
+
+ for (;;) {
+ length++;
+ /* avoid infinite loops, although this is guaranted not to
+ happen because of the previous checks */
+ if (length >= nftl->nb_blocks) {
+ printk("nftl: length too long %d !\n", length);
+ break;
+ }
+
+ block = nftl->ReplUnitTable[block];
+ if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
+ printk("incorrect ReplUnitTable[] : %d\n", block);
+ if (block == BLOCK_NIL || block >= nftl->nb_blocks)
+ break;
+ }
+ return length;
+}
+
+/* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a
+ * Virtual Unit Chain, i.e. all the units are disconnected.
+ *
+ * It is not stricly correct to begin from the first block of the chain because
+ * if we stop the code, we may see again a valid chain if there was a first_block
+ * flag in a block inside it. But is it really a problem ?
+ *
+ * FixMe: Figure out what the last statesment means. What if power failure when we are
+ * in the for (;;) loop formatting blocks ??
+ */
+static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
+{
+ unsigned int block = first_block, block1;
+
+ printk("Formatting chain at block %d\n", first_block);
+
+ for (;;) {
+ block1 = nftl->ReplUnitTable[block];
+
+ printk("Formatting block %d\n", block);
+ if (NFTL_formatblock(nftl, block) < 0) {
+ /* cannot format !!!! Mark it as Bad Unit,
+ FixMe: update the BadUnitTable on disk */
+ nftl->ReplUnitTable[block] = BLOCK_RESERVED;
+ } else {
+ nftl->ReplUnitTable[block] = BLOCK_FREE;
+ }
+
+ /* goto next block on the chain */
+ block = block1;
+
+ if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
+ printk("incorrect ReplUnitTable[] : %d\n", block);
+ if (block == BLOCK_NIL || block >= nftl->nb_blocks)
+ break;
+ }
+}
+
+/* check_and_mark_free_block: Verify that a block is free in the NFTL sense (valid erase mark) or
+ * totally free (only 0xff).
+ *
+ * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the
+ * following critia:
+ * 1. */
+static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
+{
+ struct nftl_uci1 h1;
+ unsigned int erase_mark;
+ int i, retlen;
+ unsigned char buf[SECTORSIZE];
+
+ /* check erase mark. */
+ if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
+ &retlen, (char *)&h1) < 0)
+ return -1;
+
+ erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
+ if (erase_mark != ERASE_MARK) {
+ /* if no erase mark, the block must be totally free. This is
+ possible in two cases : empty filsystem or interrupted erase (very unlikely) */
+ if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0)
+ return -1;
+
+ /* free block : write erase mark */
+ h1.EraseMark = cpu_to_le16(ERASE_MARK);
+ h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
+ h1.WearInfo = cpu_to_le32(0);
+ if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
+ &retlen, (char *)&h1) < 0)
+ return -1;
+ } else {
+#if 0
+ /* if erase mark present, need to skip it when doing check */
+ for (i = 0; i < nftl->EraseSize; i += SECTORSIZE) {
+ /* check free sector */
+ if (check_free_sectors (nftl, block * nftl->EraseSize + i,
+ SECTORSIZE, 0) != 0)
+ return -1;
+
+ if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i,
+ 16, &retlen, buf) < 0)
+ return -1;
+ if (i == SECTORSIZE) {
+ /* skip erase mark */
+ if (memcmpb(buf, 0xff, 8))
+ return -1;
+ } else {
+ if (memcmpb(buf, 0xff, 16))
+ return -1;
+ }
+ }
+#endif
+ }
+
+ return 0;
+}
+
+/* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS
+ * to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2
+ * is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted
+ * for some reason. A clean up/check of the VUC is neceressary in this case.
+ *
+ * WARNING: return 0 if read error
+ */
+static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
+{
+ struct nftl_uci2 uci;
+ int retlen;
+
+ if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
+ 8, &retlen, (char *)&uci) < 0)
+ return 0;
+
+ return le16_to_cpu((uci.FoldMark | uci.FoldMark1));
+}
+
+int NFTL_mount(struct NFTLrecord *s)
+{
+ int i;
+ unsigned int first_logical_block, logical_block, rep_block, nb_erases, erase_mark;
+ unsigned int block, first_block, is_first_block;
+ int chain_length, do_format_chain;
+ struct nftl_uci0 h0;
+ struct nftl_uci1 h1;
+ int retlen;
+
+ /* XXX: will be suppressed */
+ s->lastEUN = s->nb_blocks - 1;
+
+ /* memory alloc */
+ s->EUNtable = kmalloc(s->nb_blocks * sizeof(u16), GFP_KERNEL);
+ s->ReplUnitTable = kmalloc(s->nb_blocks * sizeof(u16), GFP_KERNEL);
+ if (!s->EUNtable || !s->ReplUnitTable) {
+ fail:
+ if (s->EUNtable)
+ kfree(s->EUNtable);
+ if (s->ReplUnitTable)
+ kfree(s->ReplUnitTable);
+ return -1;
+ }
+
+ /* mark all blocks as potentially containing data */
+ for (i = 0; i < s->nb_blocks; i++) {
+ s->ReplUnitTable[i] = BLOCK_NOTEXPLORED;
+ }
+
+ /* search for NFTL MediaHeader and Spare NFTL Media Header */
+ if (find_boot_record(s) < 0) {
+ printk("Could not find valid boot record\n");
+ goto fail;
+ }
+
+ /* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */
+ for (i = 0; i < s->nb_boot_blocks; i++)
+ s->ReplUnitTable[i] = BLOCK_RESERVED;
+
+ /* also mark the boot records (NFTL MediaHeader) blocks as reserved */
+ if (s->MediaUnit != BLOCK_NIL)
+ s->ReplUnitTable[s->MediaUnit] = BLOCK_RESERVED;
+ if (s->SpareMediaUnit != BLOCK_NIL)
+ s->ReplUnitTable[s->SpareMediaUnit] = BLOCK_RESERVED;
+
+ /* init the logical to physical table */
+ for (i = 0; i < s->nb_blocks; i++) {
+ s->EUNtable[i] = BLOCK_NIL;
+ }
+
+ /* first pass : explore each block chain */
+ first_logical_block = 0;
+ for (first_block = 0; first_block < s->nb_blocks; first_block++) {
+ /* if the block was not already explored, we can look at it */
+ if (s->ReplUnitTable[first_block] == BLOCK_NOTEXPLORED) {
+ block = first_block;
+ chain_length = 0;
+ do_format_chain = 0;
+
+ for (;;) {
+ /* read the block header. If error, we format the chain */
+ if (MTD_READOOB(s->mtd, block * s->EraseSize + 8, 8,
+ &retlen, (char *)&h0) < 0 ||
+ MTD_READOOB(s->mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
+ &retlen, (char *)&h1) < 0) {
+ s->ReplUnitTable[block] = BLOCK_NIL;
+ do_format_chain = 1;
+ break;
+ }
+
+ logical_block = le16_to_cpu ((h0.VirtUnitNum | h0.SpareVirtUnitNum));
+ rep_block = le16_to_cpu ((h0.ReplUnitNum | h0.SpareReplUnitNum));
+ nb_erases = le32_to_cpu (h1.WearInfo);
+ erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
+
+ is_first_block = !(logical_block >> 15);
+ logical_block = logical_block & 0x7fff;
+
+ /* invalid/free block test */
+ if (erase_mark != ERASE_MARK || logical_block >= s->nb_blocks) {
+ if (chain_length == 0) {
+ /* if not currently in a chain, we can handle it safely */
+ if (check_and_mark_free_block(s, block) < 0) {
+ /* not really free: format it */
+ printk("Formatting block %d\n", block);
+ if (NFTL_formatblock(s, block) < 0) {
+ /* could not format: reserve the block */
+ s->ReplUnitTable[block] = BLOCK_RESERVED;
+ } else {
+ s->ReplUnitTable[block] = BLOCK_FREE;
+ }
+ } else {
+ /* free block: mark it */
+ s->ReplUnitTable[block] = BLOCK_FREE;
+ }
+ /* directly examine the next block. */
+ goto examine_ReplUnitTable;
+ } else {
+ /* the block was in a chain : this is bad. We
+ must format all the chain */
+ printk("Block %d: free but referenced in chain %d\n",
+ block, first_block);
+ s->ReplUnitTable[block] = BLOCK_NIL;
+ do_format_chain = 1;
+ break;
+ }
+ }
+
+ /* we accept only first blocks here */
+ if (chain_length == 0) {
+ /* this block is not the first block in chain :
+ ignore it, it will be included in a chain
+ later, or marked as not explored */
+ if (!is_first_block)
+ goto examine_ReplUnitTable;
+ first_logical_block = logical_block;
+ } else {
+ if (logical_block != first_logical_block) {
+ printk("Block %d: incorrect logical block: %d expected: %d\n",
+ block, logical_block, first_logical_block);
+ /* the chain is incorrect : we must format it,
+ but we need to read it completly */
+ do_format_chain = 1;
+ }
+ if (is_first_block) {
+ /* we accept that a block is marked as first
+ block while being last block in a chain
+ only if the chain is being folded */
+ if (get_fold_mark(s, block) != FOLD_MARK_IN_PROGRESS ||
+ rep_block != 0xffff) {
+ printk("Block %d: incorrectly marked as first block in chain\n",
+ block);
+ /* the chain is incorrect : we must format it,
+ but we need to read it completly */
+ do_format_chain = 1;
+ } else {
+ printk("Block %d: folding in progress - ignoring first block flag\n",
+ block);
+ }
+ }
+ }
+ chain_length++;
+ if (rep_block == 0xffff) {
+ /* no more blocks after */
+ s->ReplUnitTable[block] = BLOCK_NIL;
+ break;
+ } else if (rep_block >= s->nb_blocks) {
+ printk("Block %d: referencing invalid block %d\n",
+ block, rep_block);
+ do_format_chain = 1;
+ s->ReplUnitTable[block] = BLOCK_NIL;
+ break;
+ } else if (s->ReplUnitTable[rep_block] != BLOCK_NOTEXPLORED) {
+ /* same problem as previous 'is_first_block' test:
+ we accept that the last block of a chain has
+ the first_block flag set if folding is in
+ progress. We handle here the case where the
+ last block appeared first */
+ if (s->ReplUnitTable[rep_block] == BLOCK_NIL &&
+ s->EUNtable[first_logical_block] == rep_block &&
+ get_fold_mark(s, first_block) == FOLD_MARK_IN_PROGRESS) {
+ /* EUNtable[] will be set after */
+ printk("Block %d: folding in progress - ignoring first block flag\n",
+ rep_block);
+ s->ReplUnitTable[block] = rep_block;
+ s->EUNtable[first_logical_block] = BLOCK_NIL;
+ } else {
+ printk("Block %d: referencing block %d already in another chain\n",
+ block, rep_block);
+ /* XXX: should handle correctly fold in progress chains */
+ do_format_chain = 1;
+ s->ReplUnitTable[block] = BLOCK_NIL;
+ }
+ break;
+ } else {
+ /* this is OK */
+ s->ReplUnitTable[block] = rep_block;
+ block = rep_block;
+ }
+ }
+
+ /* the chain was completely explored. Now we can decide
+ what to do with it */
+ if (do_format_chain) {
+ /* invalid chain : format it */
+ format_chain(s, first_block);
+ } else {
+ unsigned int first_block1, chain_to_format, chain_length1;
+ int fold_mark;
+
+ /* valid chain : get foldmark */
+ fold_mark = get_fold_mark(s, first_block);
+ if (fold_mark == 0) {
+ /* cannot get foldmark : format the chain */
+ printk("Could read foldmark at block %d\n", first_block);
+ format_chain(s, first_block);
+ } else {
+ if (fold_mark == FOLD_MARK_IN_PROGRESS)
+ check_sectors_in_chain(s, first_block);
+
+ /* now handle the case where we find two chains at the
+ same virtual address : we select the longer one,
+ because the shorter one is the one which was being
+ folded if the folding was not done in place */
+ first_block1 = s->EUNtable[first_logical_block];
+ if (first_block1 != BLOCK_NIL) {
+ /* XXX: what to do if same length ? */
+ chain_length1 = calc_chain_length(s, first_block1);
+ printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
+ first_block1, chain_length1, first_block, chain_length);
+
+ if (chain_length >= chain_length1) {
+ chain_to_format = first_block1;
+ s->EUNtable[first_logical_block] = first_block;
+ } else {
+ chain_to_format = first_block;
+ }
+ format_chain(s, chain_to_format);
+ } else {
+ s->EUNtable[first_logical_block] = first_block;
+ }
+ }
+ }
+ }
+ examine_ReplUnitTable:
+ }
+
+ /* second pass to format unreferenced blocks and init free block count */
+ s->numfreeEUNs = 0;
+ s->LastFreeEUN = BLOCK_NIL;
+
+ for (block = 0; block < s->nb_blocks; block++) {
+ if (s->ReplUnitTable[block] == BLOCK_NOTEXPLORED) {
+ printk("Unreferenced block %d, formatting it\n", block);
+ if (NFTL_formatblock(s, block) < 0)
+ s->ReplUnitTable[block] = BLOCK_RESERVED;
+ else
+ s->ReplUnitTable[block] = BLOCK_FREE;
+ }
+ if (s->ReplUnitTable[block] == BLOCK_FREE) {
+ s->numfreeEUNs++;
+ s->LastFreeEUN = block;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/mtd/nora.c b/drivers/mtd/nora.c
index 9304d7e62..48da299fc 100644
--- a/drivers/mtd/nora.c
+++ b/drivers/mtd/nora.c
@@ -1,5 +1,5 @@
/*
- * $Id: nora.c,v 1.12 2000/07/13 10:32:33 dwmw2 Exp $
+ * $Id: nora.c,v 1.17 2000/12/03 19:32:21 dwmw2 Exp $
*
* This is so simple I love it.
*/
@@ -58,19 +58,17 @@ void nora_copy_to(struct map_info *map, unsigned long to, const void *from, ssiz
}
struct map_info nora_map = {
- "NORA",
- WINDOW_SIZE,
- 2,
- nora_read8,
- nora_read16,
- nora_read32,
- nora_copy_from,
- nora_write8,
- nora_write16,
- nora_write32,
- nora_copy_to,
- 0,
- 0
+ name: "NORA",
+ size: WINDOW_SIZE,
+ buswidth: 2,
+ read8: nora_read8,
+ read16: nora_read16,
+ read32: nora_read32,
+ copy_from: nora_copy_from,
+ write8: nora_write8,
+ write16: nora_write16,
+ write32: nora_write32,
+ copy_to: nora_copy_to
};
@@ -140,7 +138,7 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */
{
type: MTD_NORFLASH,
flags: MTD_CAP_NORFLASH,
- size: 0xf00000,
+ size: 0x900000,
erasesize: 0x20000,
name: "NORA root filesystem",
module: THIS_MODULE,
@@ -155,9 +153,9 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */
{
type: MTD_NORFLASH,
flags: MTD_CAP_NORFLASH,
- size: 0x1000000,
+ size: 0x1600000,
erasesize: 0x20000,
- name: "NORA main filesystem",
+ name: "NORA second filesystem",
module: THIS_MODULE,
erase: nora_mtd_erase,
read: nora_mtd_read,
@@ -165,16 +163,15 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */
suspend: nora_mtd_suspend,
resume: nora_mtd_resume,
sync: nora_mtd_sync,
- priv: (void *)0x1000000
+ priv: (void *)0xa00000
}
};
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_nora init_module
#define cleanup_nora cleanup_module
#endif
-#endif
int __init init_nora(void)
{
@@ -186,10 +183,10 @@ int __init init_nora(void)
mymtd->module = &__this_module;
#endif
- add_mtd_device(&nora_mtds[3]);
+ add_mtd_device(&nora_mtds[2]);
add_mtd_device(&nora_mtds[0]);
add_mtd_device(&nora_mtds[1]);
- add_mtd_device(&nora_mtds[2]);
+ add_mtd_device(&nora_mtds[3]);
return 0;
}
@@ -199,10 +196,13 @@ int __init init_nora(void)
static void __exit cleanup_nora(void)
{
if (mymtd) {
- del_mtd_device(&nora_mtds[2]);
+ del_mtd_device(&nora_mtds[3]);
del_mtd_device(&nora_mtds[1]);
del_mtd_device(&nora_mtds[0]);
- del_mtd_device(&nora_mtds[3]);
+ del_mtd_device(&nora_mtds[2]);
map_destroy(mymtd);
}
}
+
+module_init(init_nora);
+module_exit(cleanup_nora);
diff --git a/drivers/mtd/octagon-5066.c b/drivers/mtd/octagon-5066.c
index b184cd0e7..70e78d7e9 100644
--- a/drivers/mtd/octagon-5066.c
+++ b/drivers/mtd/octagon-5066.c
@@ -1,4 +1,4 @@
-// $Id: octagon-5066.c,v 1.10 2000/07/13 14:04:23 dwmw2 Exp $
+// $Id: octagon-5066.c,v 1.12 2000/11/27 08:50:22 dwmw2 Exp $
/* ######################################################################
Octagon 5066 MTD Driver.
@@ -151,32 +151,32 @@ static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *
static struct map_info oct5066_map[2] = {
{
- "Octagon 5066 Socket",
- 512 * 1024,
- 1,
- oct5066_read8,
- oct5066_read16,
- oct5066_read32,
- oct5066_copy_from,
- oct5066_write8,
- oct5066_write16,
- oct5066_write32,
- oct5066_copy_to,
- 1<<6
+ name: "Octagon 5066 Socket",
+ size: 512 * 1024,
+ buswidth: 1,
+ read8: oct5066_read8,
+ read16: oct5066_read16,
+ read32: oct5066_read32,
+ copy_from: oct5066_copy_from,
+ write8: oct5066_write8,
+ write16: oct5066_write16,
+ write32: oct5066_write32,
+ copy_to: oct5066_copy_to,
+ map_priv_1: 1<<6
},
{
- "Octagon 5066 Internal Flash",
- 2 * 1024 * 1024,
- 1,
- oct5066_read8,
- oct5066_read16,
- oct5066_read32,
- oct5066_copy_from,
- oct5066_write8,
- oct5066_write16,
- oct5066_write32,
- oct5066_copy_to,
- 2<<6
+ name: "Octagon 5066 Internal Flash",
+ size: 2 * 1024 * 1024,
+ buswidth: 1,
+ read8: oct5066_read8,
+ read16: oct5066_read16,
+ read32: oct5066_read32,
+ copy_from: oct5066_copy_from,
+ write8: oct5066_write8,
+ write16: oct5066_write16,
+ write32: oct5066_write32,
+ copy_to: oct5066_copy_to,
+ map_priv_1: 2<<6
}
};
@@ -213,13 +213,10 @@ static int __init OctProbe()
return 0;
}
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_oct5066 init_module
#define cleanup_oct5066 cleanup_module
#endif
-#define __exit
-#endif
void cleanup_oct5066(void)
{
@@ -284,7 +281,5 @@ int __init init_oct5066(void)
return 0;
}
-#if LINUX_VERSION_CODE > 0x20300
module_init(init_oct5066);
module_exit(cleanup_oct5066);
-#endif
diff --git a/drivers/mtd/physmap.c b/drivers/mtd/physmap.c
index 658b8bf47..31ac39310 100644
--- a/drivers/mtd/physmap.c
+++ b/drivers/mtd/physmap.c
@@ -1,5 +1,5 @@
/*
- * $Id: physmap.c,v 1.2 2000/07/11 09:42:32 dwmw2 Exp $
+ * $Id: physmap.c,v 1.8 2000/11/27 08:50:22 dwmw2 Exp $
*
* Normal mappings of chips in physical memory
*/
@@ -15,6 +15,7 @@
#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START
#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN
+#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH
static struct mtd_info *mymtd;
@@ -59,32 +60,28 @@ void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, s
}
struct map_info physmap_map = {
- "Physically mapped flash",
- WINDOW_SIZE,
- 2,
- physmap_read8,
- physmap_read16,
- physmap_read32,
- physmap_copy_from,
- physmap_write8,
- physmap_write16,
- physmap_write32,
- physmap_copy_to,
- 0,
- 0
+ name: "Physically mapped flash",
+ size: WINDOW_SIZE,
+ buswidth: BUSWIDTH,
+ read8: physmap_read8,
+ read16: physmap_read16,
+ read32: physmap_read32,
+ copy_from: physmap_copy_from,
+ write8: physmap_write8,
+ write16: physmap_write16,
+ write32: physmap_write32,
+ copy_to: physmap_copy_to
};
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_physmap init_module
#define cleanup_physmap cleanup_module
#endif
-#endif
int __init init_physmap(void)
{
printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
- physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_SIZE, WINDOW_ADDR);
+ physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!physmap_map.map_priv_1) {
printk("Failed to ioremap\n");
@@ -99,6 +96,7 @@ int __init init_physmap(void)
return 0;
}
+ iounmap((void *)physmap_map.map_priv_1);
return -ENXIO;
}
@@ -113,3 +111,7 @@ static void __exit cleanup_physmap(void)
physmap_map.map_priv_1 = 0;
}
}
+
+module_init(init_physmap);
+module_exit(cleanup_physmap);
+
diff --git a/drivers/mtd/pmc551.c b/drivers/mtd/pmc551.c
index fdc80cbcf..ab9049356 100644
--- a/drivers/mtd/pmc551.c
+++ b/drivers/mtd/pmc551.c
@@ -1,17 +1,17 @@
/*
- * $Id: pmc551.c,v 1.8 2000/07/14 07:53:31 dwmw2 Exp $
+ * $Id: pmc551.c,v 1.11 2000/11/23 13:40:12 dwmw2 Exp $
*
* PMC551 PCI Mezzanine Ram Device
*
* Author:
- * Mark Ferrell
+ * Mark Ferrell <mferrell@mvista.com>
* Copyright 1999,2000 Nortel Networks
*
- * License:
+ * License:
* As part of this driver was derrived from the slram.c driver it falls
* under the same license, which is GNU General Public License v2
*
- * Description:
+ * Description:
* This driver is intended to support the PMC551 PCI Ram device from
* Ramix Inc. The PMC551 is a PMC Mezzanine module for cPCI embeded
* systems. The device contains a single SROM that initally programs the
@@ -24,6 +24,23 @@
* it as a block device allows us to use it as high speed swap or for a
* high speed disk device of some sort. Which becomes very usefull on
* diskless systems in the embeded market I might add.
+ *
+ * Notes:
+ * Due to what I assume is more buggy SROM, the 64M PMC551 I have
+ * available claims that all 4 of it's DRAM banks have 64M of ram
+ * configured (making a grand total of 256M onboard). This is slightly
+ * annoying since the BAR0 size reflects the aperture size, not the dram
+ * size, and the V370PDC supplies no other method for memory size
+ * discovery. This problem is mostly only relivant when compiled as a
+ * module, as the unloading of the module with an aperture size smaller
+ * then the ram will cause the driver to detect the onboard memory size
+ * to be equal to the aperture size when the module is reloaded. Soooo,
+ * to help, the module supports an msize option to allow the
+ * specification of the onboard memory, and an asize option, to allow the
+ * specification of the aperture size. The aperture must be equal to or
+ * less then the memory size, the driver will correct this if you screw
+ * it up. This problem is not relivant for compiled in drivers as
+ * compiled in drivers only init once.
*
* Credits:
* Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the initial
@@ -31,7 +48,7 @@
* questions I had concerning operation of the device.
*
* Most of the MTD code for this driver was originally written for the
- * slram.o module in the MTD drivers package written by David Hinds
+ * slram.o module in the MTD drivers package written by David Hinds
* <dhinds@allegro.stanford.edu> which allows the mapping of system
* memory into an mtd device. Since the PMC551 memory module is
* accessed in the same fashion as system memory, the slram.c code
@@ -44,9 +61,9 @@
* * Modified driver to utilize a sliding apature instead of mapping all
* memory into kernel space which turned out to be very wastefull.
* * Located a bug in the SROM's initialization sequence that made the
- * memory unussable, added a fix to code to touch up the DRAM some.
+ * memory unusable, added a fix to code to touch up the DRAM some.
*
- * Bugs/FIXME's:
+ * Bugs/FIXME's:
* * MUST fix the init function to not spin on a register
* waiting for it to set .. this does not safely handle busted devices
* that never reset the register correctly which will cause the system to
@@ -73,6 +90,10 @@
#include <stdarg.h>
#include <linux/pci.h>
+#ifndef CONFIG_PCI
+#error Enable PCI in your kernel config
+#endif
+
#include <linux/mtd/mtd.h>
#include <linux/mtd/pmc551.h>
#include <linux/mtd/compatmac.h>
@@ -347,14 +368,70 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
#ifdef CONFIG_MTD_PMC551_BUGFIX
u32 dram_data;
#endif
- u32 size, dcmd;
- u16 cmd, i;
+ u32 size, dcmd, cfg, dtmp;
+ u16 cmd, tmp, i;
+ u8 bcmd, counter;
/* Sanity Check */
if(!dev) {
return -ENODEV;
}
+ /*
+ * Attempt to reset the card
+ * FIXME: Stop Spinning registers
+ */
+ counter=0;
+ /* unlock registers */
+ pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 );
+ /* read in old data */
+ pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd );
+ /* bang the reset line up and down for a few */
+ for(i=0;i<10;i++) {
+ counter=0;
+ bcmd &= ~0x80;
+ while(counter++ < 100) {
+ pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
+ }
+ counter=0;
+ bcmd |= 0x80;
+ while(counter++ < 100) {
+ pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
+ }
+ }
+ bcmd |= (0x40|0x20);
+ pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
+
+ /*
+ * Take care and turn off the memory on the device while we
+ * tweak the configurations
+ */
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
+ pci_write_config_word(dev, PCI_COMMAND, tmp);
+
+ /*
+ * Disable existing aperture before probing memory size
+ */
+ pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
+ dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN);
+ pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
+ /*
+ * Grab old BAR0 config so that we can figure out memory size
+ * This is another bit of kludge going on. The reason for the
+ * redundancy is I am hoping to retain the original configuration
+ * previously assigned to the card by the BIOS or some previous
+ * fixup routine in the kernel. So we read the old config into cfg,
+ * then write all 1's to the memory space, read back the result into
+ * "size", and then write back all the old config.
+ */
+ pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg );
+#ifndef CONFIG_MTD_PMC551_BUGFIX
+ pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 );
+ pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size );
+ pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
+ size=~(size&PCI_BASE_ADDRESS_MEM_MASK)+1;
+#else
/*
* Get the size of the memory by reading all the DRAM size values
* and adding them up.
@@ -363,7 +440,6 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
* row mux values. We fix them here, but this will break other
* memory configurations.
*/
-#ifdef CONFIG_MTD_PMC551_BUGFIX
pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
@@ -387,7 +463,6 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
-#endif /* CONFIG_MTD_PMC551_BUGFIX */
/*
* Oops .. something went wrong
@@ -395,34 +470,14 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
return -ENODEV;
}
+#endif /* CONFIG_MTD_PMC551_BUGFIX */
- /*
- * Set to be prefetchable
- */
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dcmd );
- dcmd |= 0x8;
-
- /*
- * Put it back the way it was
- */
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dcmd );
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dcmd );
-
- /*
- * Some screen fun
- */
- printk(KERN_NOTICE "pmc551: %dM (0x%x) of %sprefetchable memory at 0x%lx\n",
- size/1024/1024, size, ((dcmd&0x8) == 0)?"non-":"",
- PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK );
-
- /*
- * Turn on PCI memory and I/O bus access just for kicks
- */
- pci_write_config_word( dev, PCI_COMMAND,
- PCI_COMMAND_MEMORY | PCI_COMMAND_IO );
+ if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
+ return -ENODEV;
+ }
/*
- * Config DRAM
+ * Precharge Dram
*/
pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 );
pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf );
@@ -431,11 +486,16 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
* Wait untill command has gone through
* FIXME: register spinning issue
*/
- do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd );
+ do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd );
+ if(counter++ > 100)break;
} while ( (PCI_COMMAND_IO) & cmd );
/*
- * Must be held high for some duration of time to take effect??
+ * Turn on auto refresh
+ * The loop is taken directly from Ramix's example code. I assume that
+ * this must be held high for some duration of time, but I can find no
+ * documentation refrencing the reasons why.
+ *
*/
for ( i = 1; i<=8 ; i++) {
pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df);
@@ -444,7 +504,9 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
* Make certain command has gone through
* FIXME: register spinning issue
*/
- do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
+ counter=0;
+ do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
+ if(counter++ > 100)break;
} while ( (PCI_COMMAND_IO) & cmd );
}
@@ -455,7 +517,9 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
* Wait until command completes
* FIXME: register spinning issue
*/
- do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd);
+ counter=0;
+ do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd);
+ if(counter++ > 100)break;
} while ( (PCI_COMMAND_IO) & cmd );
pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd);
@@ -481,54 +545,97 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
cmd &= ~PCI_STATUS_DEVSEL_MASK;
pci_write_config_word( dev, PCI_STATUS, cmd );
}
+ /*
+ * Set to be prefetchable and put everything back based on old cfg.
+ * it's possible that the reset of the V370PDC nuked the original
+ * settup
+ */
+ cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
+ pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
+
+ /*
+ * Turn PCI memory and I/O bus access back on
+ */
+ pci_write_config_word( dev, PCI_COMMAND,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_IO );
+#ifdef CONFIG_MTD_PMC551_DEBUG
+ /*
+ * Some screen fun
+ */
+ printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n",
+ (size<1024)?size:(size<1048576)?size/1024:size/1024/1024,
+ (size<1024)?'B':(size<1048576)?'K':'M',
+ size, ((dcmd&(0x1<<3)) == 0)?"non-":"",
+ PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK );
/*
* Check to see the state of the memory
- * FIXME: perhaps hide some of this around an #ifdef DEBUG as
- * it doesn't effect or enhance cards functionality
*/
- pci_read_config_dword( dev, 0x74, &dcmd );
- printk(KERN_NOTICE "pmc551: DRAM_BLK3 Flags: %s,%s\n",
- ((0x2&dcmd) == 0)?"RW":"RO",
- ((0x1&dcmd) == 0)?"Off":"On" );
-
- pci_read_config_dword( dev, 0x70, &dcmd );
- printk(KERN_NOTICE "pmc551: DRAM_BLK2 Flags: %s,%s\n",
- ((0x2&dcmd) == 0)?"RW":"RO",
- ((0x1&dcmd) == 0)?"Off":"On" );
-
- pci_read_config_dword( dev, 0x6C, &dcmd );
- printk(KERN_NOTICE "pmc551: DRAM_BLK1 Flags: %s,%s\n",
- ((0x2&dcmd) == 0)?"RW":"RO",
- ((0x1&dcmd) == 0)?"Off":"On" );
-
- pci_read_config_dword( dev, 0x68, &dcmd );
- printk(KERN_NOTICE "pmc551: DRAM_BLK0 Flags: %s,%s\n",
- ((0x2&dcmd) == 0)?"RW":"RO",
- ((0x1&dcmd) == 0)?"Off":"On" );
-
- pci_read_config_word( dev, 0x4, &cmd );
- printk( KERN_NOTICE "pmc551: Memory Access %s\n",
- ((0x2&cmd) == 0)?"off":"on" );
- printk( KERN_NOTICE "pmc551: I/O Access %s\n",
- ((0x1&cmd) == 0)?"off":"on" );
-
- pci_read_config_word( dev, 0x6, &cmd );
- printk( KERN_NOTICE "pmc551: Devsel %s\n",
+ pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd );
+ printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
+ "pmc551: DRAM_BLK0 Size: %d at %d\n"
+ "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
+ (((0x1<<1)&dcmd) == 0)?"RW":"RO",
+ (((0x1<<0)&dcmd) == 0)?"Off":"On",
+ PMC551_DRAM_BLK_GET_SIZE(dcmd),
+ ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
+
+ pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd );
+ printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
+ "pmc551: DRAM_BLK1 Size: %d at %d\n"
+ "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
+ (((0x1<<1)&dcmd) == 0)?"RW":"RO",
+ (((0x1<<0)&dcmd) == 0)?"Off":"On",
+ PMC551_DRAM_BLK_GET_SIZE(dcmd),
+ ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
+
+ pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd );
+ printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
+ "pmc551: DRAM_BLK2 Size: %d at %d\n"
+ "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
+ (((0x1<<1)&dcmd) == 0)?"RW":"RO",
+ (((0x1<<0)&dcmd) == 0)?"Off":"On",
+ PMC551_DRAM_BLK_GET_SIZE(dcmd),
+ ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
+
+ pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd );
+ printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
+ "pmc551: DRAM_BLK3 Size: %d at %d\n"
+ "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
+ (((0x1<<1)&dcmd) == 0)?"RW":"RO",
+ (((0x1<<0)&dcmd) == 0)?"Off":"On",
+ PMC551_DRAM_BLK_GET_SIZE(dcmd),
+ ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
+
+ pci_read_config_word( dev, PCI_COMMAND, &cmd );
+ printk( KERN_DEBUG "pmc551: Memory Access %s\n",
+ (((0x1<<1)&cmd) == 0)?"off":"on" );
+ printk( KERN_DEBUG "pmc551: I/O Access %s\n",
+ (((0x1<<0)&cmd) == 0)?"off":"on" );
+
+ pci_read_config_word( dev, PCI_STATUS, &cmd );
+ printk( KERN_DEBUG "pmc551: Devsel %s\n",
((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast":
((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium":
((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" );
- printk( KERN_NOTICE "pmc551: %sFast Back-to-Back\n",
+ printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" );
+ pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd );
+ printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n"
+ "pmc551: System Control Register is %slocked to PCI access\n"
+ "pmc551: System Control Register is %slocked to EEPROM access\n",
+ (bcmd&0x1)?"software":"hardware",
+ (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un");
+#endif
return size;
}
/*
* Kernel version specific module stuffages
*/
-#if LINUX_VERSION_CODE < 0x20300
+#if LINUX_VERSION_CODE < 0x20211
#ifdef MODULE
#define init_pmc551 init_module
#define cleanup_pmc551 cleanup_module
@@ -536,11 +643,27 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
#define __exit
#endif
+#if defined(MODULE)
+MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
+MODULE_DESCRIPTION(PMC551_VERSION);
+MODULE_PARM(msize, "i");
+MODULE_PARM_DESC(msize, "memory size, 6=32M, 7=64M, 8=128M, ect.. [32M-1024M]");
+MODULE_PARM(asize, "i");
+MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1M-1024M]");
+#endif
+/*
+ * Stuff these outside the ifdef so as to not bust compiled in driver support
+ */
+static int msize=0;
+#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
+static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE
+#else
+static int asize=0;
+#endif
/*
* PMC551 Card Initialization
*/
-//static int __init init_pmc551(void)
int __init init_pmc551(void)
{
struct pci_dev *PCI_Device = NULL;
@@ -549,9 +672,23 @@ int __init init_pmc551(void)
struct mtd_info *mtd;
u32 length = 0;
+ if(msize) {
+ if (msize < 6 || msize > 11 ) {
+ printk(KERN_NOTICE "pmc551: Invalid memory size\n");
+ return -ENODEV;
+ }
+ msize = (512*1024)<<msize;
+ }
- printk(KERN_NOTICE "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n");
- printk(KERN_INFO "$Id: pmc551.c,v 1.8 2000/07/14 07:53:31 dwmw2 Exp $\n");
+ if(asize) {
+ if (asize < 1 || asize > 11 ) {
+ printk(KERN_NOTICE "pmc551: Invalid aperture size\n");
+ return -ENODEV;
+ }
+ asize = (512*1024)<<asize;
+ }
+
+ printk(KERN_INFO PMC551_VERSION);
if(!pci_present()) {
printk(KERN_NOTICE "pmc551: PCI not enabled.\n");
@@ -583,6 +720,10 @@ int __init init_pmc551(void)
printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
break;
}
+ if(msize) {
+ length = msize;
+ printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length);
+ }
mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
if (!mtd) {
@@ -602,13 +743,44 @@ int __init init_pmc551(void)
mtd->priv = priv;
priv->dev = PCI_Device;
- priv->aperture_size = PMC551_APERTURE_SIZE;
+ if(asize) {
+ if(asize > length) {
+ asize=length;
+ printk(KERN_NOTICE "pmc551: reducing aperture size to fit memory [0x%x]\n",asize);
+ } else {
+ printk(KERN_NOTICE "pmc551: Using specified aperture size 0x%x\n", asize);
+ }
+ priv->aperture_size = asize;
+ } else {
+ priv->aperture_size = length;
+ }
priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device)
& PCI_BASE_ADDRESS_MEM_MASK),
priv->aperture_size);
- priv->mem_map0_base_val = (PMC551_APERTURE_VAL
- | PMC551_PCI_MEM_MAP_REG_EN
- | PMC551_PCI_MEM_MAP_ENABLE);
+
+ /*
+ * Due to the dynamic nature of the code, we need to figure
+ * this out in order to stuff the register to set the proper
+ * aperture size. If you know of an easier way to do this then
+ * PLEASE help yourself.
+ *
+ * Not with bloody floating point, you don't. Consider yourself
+ * duly LARTed. dwmw2.
+ */
+ {
+ u32 size;
+ u16 bits;
+ size = priv->aperture_size>>20;
+ for(bits=0;!(size&0x01)&&size>0;bits++,size=size>>1);
+ //size=((u32)((log10(priv->aperture_size)/.30103)-19)<<4);
+ priv->mem_map0_base_val = (PMC551_PCI_MEM_MAP_REG_EN
+ | PMC551_PCI_MEM_MAP_ENABLE
+ | size);
+#ifdef CONFIG_MTD_PMC551_DEBUG
+ printk(KERN_NOTICE "pmc551: aperture set to %d[%d]\n",
+ size, size>>4);
+#endif
+ }
priv->curr_mem_map0_val = priv->mem_map0_base_val;
pci_write_config_dword ( priv->dev,
@@ -641,7 +813,10 @@ int __init init_pmc551(void)
priv->aperture_size/1024/1024,
priv->start,
priv->start + priv->aperture_size);
- printk(KERN_NOTICE "Total memory is %dM\n", length/1024/1024);
+ printk(KERN_NOTICE "Total memory is %d%c\n",
+ (length<1024)?length:
+ (length<1048576)?length/1024:length/1024/1024,
+ (length<1024)?'B':(length<1048576)?'K':'M');
priv->nextpmc551 = pmc551list;
pmc551list = mtd;
found++;
@@ -651,8 +826,8 @@ int __init init_pmc551(void)
printk(KERN_NOTICE "pmc551: not detected,\n");
return -ENODEV;
} else {
- return 0;
printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
+ return 0;
}
}
@@ -669,7 +844,7 @@ static void __exit cleanup_pmc551(void)
priv = (struct mypriv *)mtd->priv;
pmc551list = priv->nextpmc551;
- if(priv->start)
+ if(priv->start)
iounmap(((struct mypriv *)mtd->priv)->start);
kfree (mtd->priv);
@@ -681,10 +856,7 @@ static void __exit cleanup_pmc551(void)
printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
}
-#if LINUX_VERSION_CODE > 0x20300
+#if LINUX_VERSION_CODE >= 0x20211
module_init(init_pmc551);
module_exit(cleanup_pmc551);
#endif
-
-
-
diff --git a/drivers/mtd/pnc2000.c b/drivers/mtd/pnc2000.c
index 4e4b052a7..a93dd3548 100644
--- a/drivers/mtd/pnc2000.c
+++ b/drivers/mtd/pnc2000.c
@@ -5,7 +5,7 @@
*
* This code is GPL
*
- * $Id: pnc2000.c,v 1.1 2000/07/12 09:34:32 dwmw2 Exp $
+ * $Id: pnc2000.c,v 1.4 2000/11/27 08:50:22 dwmw2 Exp $
*/
#include <linux/module.h>
@@ -14,6 +14,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
#define WINDOW_ADDR 0xbf000000
@@ -64,136 +65,60 @@ void pnc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize
}
struct map_info pnc_map = {
- "PNC-2000",
- WINDOW_SIZE,
- 4,
- pnc_read8,
- pnc_read16,
- pnc_read32,
- pnc_copy_from,
- pnc_write8,
- pnc_write16,
- pnc_write32,
- pnc_copy_to,
- 0,
- 0
+ name: "PNC-2000",
+ size: WINDOW_SIZE,
+ buswidth: 4,
+ read8: pnc_read8,
+ read16: pnc_read16,
+ read32: pnc_read32,
+ copy_from: pnc_copy_from,
+ write8: pnc_write8,
+ write16: pnc_write16,
+ write32: pnc_write32,
+ copy_to: pnc_copy_to
};
/*
* MTD 'PARTITIONING' STUFF
*/
-
-/*
- * This is the _real_ MTD device for which all the others are just
- * auto-relocating aliases.
- */
-static struct mtd_info *mymtd;
-
-/*
- * MTD methods which simply translate the effective address and pass through
- * to the _real_ device.
- */
-
-static int pnc_mtd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
-{
- return mymtd->read(mymtd, from + (unsigned long)mtd->priv, len, retlen, buf);
-}
-
-static int pnc_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
-{
- return mymtd->write(mymtd, to + (unsigned long)mtd->priv, len, retlen, buf);
-}
-
-static int pnc_mtd_erase (struct mtd_info *mtd, struct erase_info *instr)
-{
- instr->addr += (unsigned long)mtd->priv;
- return mymtd->erase(mymtd, instr);
-}
-
-static void pnc_mtd_sync (struct mtd_info *mtd)
-{
- mymtd->sync(mymtd);
-}
-
-static int pnc_mtd_suspend (struct mtd_info *mtd)
-{
- return mymtd->suspend(mymtd);
-}
-
-static void pnc_mtd_resume (struct mtd_info *mtd)
-{
- mymtd->resume(mymtd);
-}
-
-
-static struct mtd_info pnc_mtds[3] = { /* boot, kernel, fs */
+static struct mtd_partition pnc_partitions[3] = {
{
- type: MTD_NORFLASH,
- flags: MTD_CAP_NORFLASH,
- size: 0x20000,
- erasesize: 0x20000,
name: "PNC-2000 boot firmware",
- module: THIS_MODULE,
- erase: pnc_mtd_erase,
- read: pnc_mtd_read,
- write: pnc_mtd_write,
- suspend: pnc_mtd_suspend,
- resume: pnc_mtd_resume,
- sync: pnc_mtd_sync,
- priv: (void *)0
+ size: 0x20000,
+ offset: 0
},
{
- type: MTD_NORFLASH,
- flags: MTD_CAP_NORFLASH,
- size: 0x1a0000,
- erasesize: 0x20000,
name: "PNC-2000 kernel",
- module: THIS_MODULE,
- erase: pnc_mtd_erase,
- read: pnc_mtd_read,
- write: pnc_mtd_write,
- suspend: pnc_mtd_suspend,
- resume: pnc_mtd_resume,
- sync: pnc_mtd_sync,
- priv: (void *)0x20000
+ size: 0x1a0000,
+ offset: 0x20000
},
{
- type: MTD_NORFLASH,
- flags: MTD_CAP_NORFLASH,
- size: 0x240000,
- erasesize: 0x20000,
name: "PNC-2000 filesystem",
- module: THIS_MODULE,
- erase: pnc_mtd_erase,
- read: pnc_mtd_read,
- write: pnc_mtd_write,
- suspend: pnc_mtd_suspend,
- resume: pnc_mtd_resume,
- sync: pnc_mtd_sync,
- priv: (void *)0x1c0000
+ size: 0x240000,
+ offset: 0x1c0000
}
};
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+/*
+ * This is the master MTD device for which all the others are just
+ * auto-relocating aliases.
+ */
+static struct mtd_info *mymtd;
+
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_pnc init_module
#define cleanup_pnc cleanup_module
#endif
-#endif
int __init init_pnc(void)
{
- printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
+ printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
mymtd = do_cfi_probe(&pnc_map);
if (mymtd) {
mymtd->module = THIS_MODULE;
-
- add_mtd_device(&pnc_mtds[0]); /* boot */
- add_mtd_device(&pnc_mtds[1]); /* kernel */
- add_mtd_device(&pnc_mtds[2]); /* file system */
- return 0;
+ return add_mtd_partitions(mymtd, pnc_partitions, 3);
}
return -ENXIO;
@@ -202,9 +127,10 @@ int __init init_pnc(void)
static void __exit cleanup_pnc(void)
{
if (mymtd) {
- del_mtd_device(&pnc_mtds[2]);
- del_mtd_device(&pnc_mtds[1]);
- del_mtd_device(&pnc_mtds[0]);
+ del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
}
+
+module_init(init_pnc);
+module_exit(cleanup_pnc);
diff --git a/drivers/mtd/rpxlite.c b/drivers/mtd/rpxlite.c
index 783c863ac..51bcaf8a9 100644
--- a/drivers/mtd/rpxlite.c
+++ b/drivers/mtd/rpxlite.c
@@ -1,7 +1,7 @@
/*
- * $Id: rpxlite.c,v 1.2 2000/07/04 12:16:26 dwmw2 Exp $
+ * $Id: rpxlite.c,v 1.8 2000/12/09 22:00:31 dwmw2 Exp $
*
- * Handle the strange 16-in-32-bit mapping on the RPXLite board
+ * Handle mapping of the flash on the RPX Lite and CLLF boards
*/
#include <linux/module.h>
@@ -12,124 +12,74 @@
#include <linux/mtd/map.h>
-#define WINDOW_ADDR 0x8000000
-#define WINDOW_SIZE 0x2000000
-
-#define MAP_TO_ADR(x) ( ( ( x & ~1 ) << 1 ) | (x&1) )
+#define WINDOW_ADDR 0xfe000000
+#define WINDOW_SIZE 0x800000
static struct mtd_info *mymtd;
__u8 rpxlite_read8(struct map_info *map, unsigned long ofs)
{
- return readb(map->map_priv_1 + MAP_TO_ADR(ofs));
+ return readb(map->map_priv_1 * ofs);
}
__u16 rpxlite_read16(struct map_info *map, unsigned long ofs)
{
- return readw(map->map_priv_1 + MAP_TO_ADR(ofs));
+ return readw(map->map_priv_1 + ofs);
}
__u32 rpxlite_read32(struct map_info *map, unsigned long ofs)
{
- return readl(map->map_priv_1 + MAP_TO_ADR(ofs));
+ return readl(map->map_priv_1 + ofs);
}
void rpxlite_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
- if (from & 1) {
- *(__u8 *)to = readb(map->map_priv_1 + MAP_TO_ADR(from));
- from++;
- len--;
- }
- /* Can't do this if it's not aligned */
- if (!((unsigned long)to & 1)) {
- unsigned long fromadr = MAP_TO_ADR(from);
-
- while (len > 1) {
- *(__u16 *)to = readw(map->map_priv_1 + fromadr);
- to += 2;
- fromadr += 4;
- from += 2;
- len -= 2;
- }
- }
- while(len) {
- *(__u8 *)to = readb(map->map_priv_1 + MAP_TO_ADR(from));
- to++;
- from++;
- len--;
- }
+ memcpy_fromio(to, (void *)(map->map_priv_1 + from), len);
}
void rpxlite_write8(struct map_info *map, __u8 d, unsigned long adr)
{
- writeb(d, map->map_priv_1 + MAP_TO_ADR(adr));
+ writeb(d, map->map_priv_1 + adr);
}
void rpxlite_write16(struct map_info *map, __u16 d, unsigned long adr)
{
- writew(d, map->map_priv_1 + MAP_TO_ADR(adr));
+ writew(d, map->map_priv_1 + adr);
}
void rpxlite_write32(struct map_info *map, __u32 d, unsigned long adr)
{
- writel(d, map->map_priv_1 + MAP_TO_ADR(adr));
+ writel(d, map->map_priv_1 + adr);
}
void rpxlite_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
- if (to & 1) {
- writeb(*(__u8 *)from, map->map_priv_1 + MAP_TO_ADR(to));
- from++;
- len--;
- }
- /* Can't do this if it's not aligned */
- if (!((unsigned long)from & 1)) {
- unsigned long toadr = map->map_priv_1 + MAP_TO_ADR(to);
-
- while (len > 1) {
- writew(*(__u16 *)from, toadr);
- from += 2;
- toadr += 4;
- to += 2;
- len -= 2;
- }
- }
- while(len) {
- writeb(*(__u8 *)from, map->map_priv_1 + MAP_TO_ADR(to));
- to++;
- from++;
- len--;
- }
+ memcpy_toio((void *)(map->map_priv_1 + to), from, len);
}
struct map_info rpxlite_map = {
- "RPXLITE",
- WINDOW_SIZE,
- 2,
- rpxlite_read8,
- rpxlite_read16,
- rpxlite_read32,
- rpxlite_copy_from,
- rpxlite_write8,
- rpxlite_write16,
- rpxlite_write32,
- rpxlite_copy_to,
- 0,
- 0
+ name: "RPX",
+ size: WINDOW_SIZE,
+ buswidth: 4,
+ read8: rpxlite_read8,
+ read16: rpxlite_read16,
+ read32: rpxlite_read32,
+ copy_from: rpxlite_copy_from,
+ write8: rpxlite_write8,
+ write16: rpxlite_write16,
+ write32: rpxlite_write32,
+ copy_to: rpxlite_copy_to
};
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_rpxlite init_module
#define cleanup_rpxlite cleanup_module
#endif
-#endif
int __init init_rpxlite(void)
{
- printk(KERN_NOTICE "rpxlite flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
- rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 2);
+ printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR);
+ rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
if (!rpxlite_map.map_priv_1) {
printk("Failed to ioremap\n");
@@ -158,3 +108,6 @@ static void __exit cleanup_rpxlite(void)
rpxlite_map.map_priv_1 = 0;
}
}
+
+module_init(init_rpxlite);
+module_exit(cleanup_rpxlite);
diff --git a/drivers/mtd/vmax301.c b/drivers/mtd/vmax301.c
index 553beaad6..e694604e7 100644
--- a/drivers/mtd/vmax301.c
+++ b/drivers/mtd/vmax301.c
@@ -1,4 +1,4 @@
-// $Id: vmax301.c,v 1.13 2000/07/03 10:01:38 dwmw2 Exp $
+// $Id: vmax301.c,v 1.15 2000/11/27 08:50:22 dwmw2 Exp $
/* ######################################################################
Tempustech VMAX SBC301 MTD Driver.
@@ -142,46 +142,43 @@ static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *
static struct map_info vmax_map[2] = {
{
- "VMAX301 Internal Flash",
- 3*2*1024*1024,
- 1,
- vmax301_read8,
- vmax301_read16,
- vmax301_read32,
- vmax301_copy_from,
- vmax301_write8,
- vmax301_write16,
- vmax301_write32,
- vmax301_copy_to,
- WINDOW_START + WINDOW_LENGTH,
- 0xFFFFFFFF
+ name: "VMAX301 Internal Flash",
+ size: 3*2*1024*1024,
+ buswidth: 1,
+ read8: vmax301_read8,
+ read16: vmax301_read16,
+ read32: vmax301_read32,
+ copy_from: vmax301_copy_from,
+ write8: vmax301_write8,
+ write16: vmax301_write16,
+ write32: vmax301_write32,
+ copy_to: vmax301_copy_to,
+ map_priv_1: WINDOW_START + WINDOW_LENGTH,
+ map_priv_2: 0xFFFFFFFF
},
{
- "VMAX301 Socket",
- 0,
- 1,
- vmax301_read8,
- vmax301_read16,
- vmax301_read32,
- vmax301_copy_from,
- vmax301_write8,
- vmax301_write16,
- vmax301_write32,
- vmax301_copy_to,
- WINDOW_START + (3*WINDOW_LENGTH),
- 0xFFFFFFFF
+ name: "VMAX301 Socket",
+ size: 0,
+ buswidth: 1,
+ read8: vmax301_read8,
+ read16: vmax301_read16,
+ read32: vmax301_read32,
+ copy_from: vmax301_copy_from,
+ write8: vmax301_write8,
+ write16: vmax301_write16,
+ write32: vmax301_write32,
+ copy_to: vmax301_copy_to,
+ map_priv_1: WINDOW_START + (3*WINDOW_LENGTH),
+ map_priv_2: 0xFFFFFFFF
}
};
static struct mtd_info *vmax_mtd[2] = {NULL, NULL};
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_vmax301 init_module
#define cleanup_vmax301 cleanup_module
#endif
-#define __exit
-#endif
static void __exit cleanup_vmax301(void)
{
@@ -237,7 +234,5 @@ int __init init_vmax301(void)
return 0;
}
-#if LINUX_VERSION_CODE > 0x20300
module_init(init_vmax301);
module_exit(cleanup_vmax301);
-#endif
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 6db67d817..0a6609ecc 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -88,7 +88,7 @@ el2_probe(struct net_device *dev)
int base_addr = dev->base_addr;
SET_MODULE_OWNER(dev);
-
+
if (base_addr > 0x1ff) /* Check a single specified location. */
return el2_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
@@ -319,6 +319,7 @@ out:
static int
el2_open(struct net_device *dev)
{
+ int retval = -EAGAIN;
if (dev->irq < 2) {
int irqlist[] = {5, 9, 3, 4, 0};
@@ -331,18 +332,19 @@ el2_open(struct net_device *dev)
unsigned long cookie = probe_irq_on();
outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
outb_p(0x00, E33G_IDCFR);
- if (*irqp == probe_irq_off(cookie) /* It's a good IRQ line! */
- && request_irq (dev->irq = *irqp, ei_interrupt, 0, ei_status.name, dev) == 0)
+ if (*irqp == probe_irq_off(cookie) /* It's a good IRQ line! */
+ && ((retval = request_irq(dev->irq = *irqp,
+ ei_interrupt, 0, dev->name, dev)) == 0))
break;
}
} while (*++irqp);
if (*irqp == 0) {
outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */
- return -EAGAIN;
+ return retval;
}
} else {
- if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev)) {
- return -EAGAIN;
+ if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) {
+ return retval;
}
}
diff --git a/drivers/net/3c505.h b/drivers/net/3c505.h
index 1cbf41fae..23714facc 100644
--- a/drivers/net/3c505.h
+++ b/drivers/net/3c505.h
@@ -284,7 +284,7 @@ typedef struct {
/* flags */
unsigned long send_pcb_semaphore;
- unsigned int dmaing;
+ unsigned long dmaing;
unsigned long busy;
unsigned int rx_active; /* number of receive PCBs */
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index b26b06302..b66edcc44 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -134,6 +134,7 @@ an MMIO register read.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -141,18 +142,21 @@ an MMIO register read.
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
#include <linux/delay.h>
#include <asm/io.h>
-#define RTL8139_VERSION "0.9.11"
-#define RTL8139_MODULE_NAME "8139too"
-#define RTL8139_DRIVER_NAME RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION
-#define PFX RTL8139_MODULE_NAME ": "
+#define RTL8139_VERSION "0.9.12"
+#define MODNAME "8139too"
+#define RTL8139_DRIVER_NAME MODNAME " Fast Ethernet driver " RTL8139_VERSION
+#define PFX MODNAME ": "
-/* define to 1 to enable PIO instead of MMIO */
-#undef USE_IO_OPS
+/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */
+#ifdef CONFIG_8139TOO_PIO
+#define USE_IO_OPS 1
+#endif
/* define to 1 to enable copious debugging info */
#undef RTL8139_DEBUG
@@ -502,12 +506,11 @@ struct rtl8139_private {
int drv_flags;
struct pci_dev *pci_dev;
struct net_device_stats stats;
- struct timer_list timer; /* Media selection timer. */
unsigned char *rx_ring;
unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */
unsigned int tx_flag;
- atomic_t cur_tx;
- atomic_t dirty_tx;
+ unsigned int cur_tx;
+ unsigned int dirty_tx;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct ring_info tx_info[NUM_TX_DESC];
unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */
@@ -524,6 +527,9 @@ struct rtl8139_private {
unsigned int mediasense:1; /* Media sensing in progress. */
spinlock_t lock;
chip_t chipset;
+ pid_t thr_pid;
+ wait_queue_head_t thr_wait;
+ struct semaphore thr_exited;
};
MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
@@ -538,7 +544,7 @@ static int rtl8139_open (struct net_device *dev);
static int mdio_read (struct net_device *dev, int phy_id, int location);
static void mdio_write (struct net_device *dev, int phy_id, int location,
int val);
-static void rtl8139_timer (unsigned long data);
+static int rtl8139_thread (void *data);
static void rtl8139_tx_timeout (struct net_device *dev);
static void rtl8139_init_ring (struct net_device *dev);
static int rtl8139_start_xmit (struct sk_buff *skb,
@@ -552,7 +558,6 @@ static inline u32 ether_crc (int length, unsigned char *data);
static void rtl8139_set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
-
#ifdef USE_IO_OPS
#define RTL_R8(reg) inb (((unsigned long)ioaddr) + (reg))
@@ -648,6 +653,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
DPRINTK ("EXIT, returning -ENOMEM\n");
return -ENOMEM;
}
+ SET_MODULE_OWNER(dev);
tp = dev->priv;
pio_start = pci_resource_start (pdev, 0);
@@ -867,7 +873,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
tp->pci_dev = pdev;
tp->board = ent->driver_data;
tp->mmio_addr = ioaddr;
- tp->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init (&tp->lock);
+ init_waitqueue_head (&tp->thr_wait);
+ init_MUTEX_LOCKED (&tp->thr_exited);
pdev->driver_data = dev;
@@ -897,7 +905,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
RTL_W8_F (HltClk, 'H'); /* 'R' would leave the clock running. */
/* The lower four bits are the media type. */
- option = (board_idx > 7) ? 0 : media[board_idx];
+ option = (board_idx >= ARRAY_SIZE(media)) ? 0 : media[board_idx];
if (option > 0) {
tp->full_duplex = (option & 0x200) ? 1 : 0;
tp->default_port = option & 15;
@@ -1068,7 +1076,7 @@ static void mdio_sync (void *mdio_addr)
static int mdio_read (struct net_device *dev, int phy_id, int location)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *mdio_addr = tp->mmio_addr + Config4;
int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int retval = 0;
@@ -1111,7 +1119,7 @@ static int mdio_read (struct net_device *dev, int phy_id, int location)
static void mdio_write (struct net_device *dev, int phy_id, int location,
int value)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *mdio_addr = tp->mmio_addr + Config4;
int mii_cmd =
(0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
@@ -1154,7 +1162,7 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
static int rtl8139_open (struct net_device *dev)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
int retval;
#ifdef RTL8139_DEBUG
void *ioaddr = tp->mmio_addr;
@@ -1162,12 +1170,9 @@ static int rtl8139_open (struct net_device *dev)
DPRINTK ("ENTER\n");
- MOD_INC_USE_COUNT;
-
retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
if (retval) {
DPRINTK ("EXIT, returning %d\n", retval);
- MOD_DEC_USE_COUNT;
return retval;
}
@@ -1186,13 +1191,13 @@ static int rtl8139_open (struct net_device *dev)
tp->rx_ring, tp->rx_ring_dma);
DPRINTK ("EXIT, returning -ENOMEM\n");
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}
tp->full_duplex = tp->duplex_lock;
tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
+ tp->twistie = 1;
rtl8139_init_ring (dev);
rtl8139_hw_start (dev);
@@ -1203,13 +1208,10 @@ static int rtl8139_open (struct net_device *dev)
dev->irq, RTL_R8 (MediaStatus),
tp->full_duplex ? "full" : "half");
- /* Set the timer to switch to check for link beat and perhaps switch
- to an alternate media type. */
- init_timer (&tp->timer);
- tp->timer.expires = jiffies + 3 * HZ;
- tp->timer.data = (unsigned long) dev;
- tp->timer.function = &rtl8139_timer;
- add_timer (&tp->timer);
+ tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES);
+ if (tp->thr_pid < 0)
+ printk (KERN_WARNING "%s: unable to start kernel thread\n",
+ dev->name);
DPRINTK ("EXIT, returning 0\n");
return 0;
@@ -1219,7 +1221,7 @@ static int rtl8139_open (struct net_device *dev)
/* Start the hardware at open or resume. */
static void rtl8139_hw_start (struct net_device *dev)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u32 i;
u8 tmp;
@@ -1311,14 +1313,14 @@ static void rtl8139_hw_start (struct net_device *dev)
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void rtl8139_init_ring (struct net_device *dev)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
int i;
DPRINTK ("ENTER\n");
tp->cur_rx = 0;
- atomic_set (&tp->cur_tx, 0);
- atomic_set (&tp->dirty_tx, 0);
+ tp->cur_tx = 0;
+ tp->dirty_tx = 0;
for (i = 0; i < NUM_TX_DESC; i++) {
tp->tx_info[i].skb = NULL;
@@ -1330,7 +1332,10 @@ static void rtl8139_init_ring (struct net_device *dev)
}
-#ifndef RTL_TUNE_TWISTER
+/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */
+static int next_tick = 3 * HZ;
+
+#ifndef CONFIG_8139TOO_TUNE_TWISTER
static inline void rtl8139_tune_twister (struct net_device *dev,
struct rtl8139_private *tp) {}
#else
@@ -1338,6 +1343,7 @@ static void rtl8139_tune_twister (struct net_device *dev,
struct rtl8139_private *tp)
{
int linkcase;
+ void *ioaddr = tp->mmio_addr;
DPRINTK ("ENTER\n");
@@ -1421,15 +1427,13 @@ static void rtl8139_tune_twister (struct net_device *dev,
DPRINTK ("EXIT\n");
}
-#endif /* RTL_TUNE_TWISTER */
+#endif /* CONFIG_8139TOO_TUNE_TWISTER */
-static void rtl8139_timer (unsigned long data)
+static inline void rtl8139_thread_iter (struct net_device *dev,
+ struct rtl8139_private *tp,
+ void *ioaddr)
{
- struct net_device *dev = (struct net_device *) data;
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
- void *ioaddr = tp->mmio_addr;
- int next_tick = 60 * HZ;
int mii_reg5;
mii_reg5 = mdio_read (dev, tp->phys[0], 5);
@@ -1450,6 +1454,8 @@ static void rtl8139_timer (unsigned long data)
}
}
+ next_tick = HZ * 60;
+
rtl8139_tune_twister (dev, tp);
DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n",
@@ -1462,9 +1468,33 @@ static void rtl8139_timer (unsigned long data)
DPRINTK ("%s: Chip config %2.2x %2.2x.\n",
dev->name, RTL_R8 (Config0),
RTL_R8 (Config1));
+}
+
+
+static int rtl8139_thread (void *data)
+{
+ struct net_device *dev = data;
+ struct rtl8139_private *tp = dev->priv;
+ unsigned long timeout;
- tp->timer.expires = jiffies + next_tick;
- add_timer (&tp->timer);
+ daemonize ();
+ sprintf (current->comm, "k8139d-%s", dev->name);
+
+ while (1) {
+ timeout = next_tick;
+ do {
+ timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
+ } while (!signal_pending (current) && (timeout > 0));
+
+ if (signal_pending (current))
+ break;
+
+ rtnl_lock ();
+ rtl8139_thread_iter (dev, tp, tp->mmio_addr);
+ rtnl_unlock ();
+ }
+
+ up_and_exit (&tp->thr_exited, 0);
}
@@ -1472,8 +1502,8 @@ static void rtl8139_tx_clear (struct rtl8139_private *tp)
{
int i;
- atomic_set (&tp->cur_tx, 0);
- atomic_set (&tp->dirty_tx, 0);
+ tp->cur_tx = 0;
+ tp->dirty_tx = 0;
/* Dump the unsent Tx packets. */
for (i = 0; i < NUM_TX_DESC; i++) {
@@ -1494,11 +1524,10 @@ static void rtl8139_tx_clear (struct rtl8139_private *tp)
static void rtl8139_tx_timeout (struct net_device *dev)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
int i;
u8 tmp8;
- unsigned long flags;
DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "
"media %2.2x.\n", dev->name,
@@ -1516,20 +1545,17 @@ static void rtl8139_tx_timeout (struct net_device *dev)
/* Emit info to figure out what went wrong. */
printk (KERN_DEBUG "%s: Tx queue start entry %d dirty entry %d.\n",
- dev->name, atomic_read (&tp->cur_tx),
- atomic_read (&tp->dirty_tx));
+ dev->name, tp->cur_tx, tp->dirty_tx);
for (i = 0; i < NUM_TX_DESC; i++)
printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n",
dev->name, i, RTL_R32 (TxStatus0 + (i * 4)),
- i == atomic_read (&tp->dirty_tx) % NUM_TX_DESC ?
+ i == tp->dirty_tx % NUM_TX_DESC ?
" (queue head)" : "");
/* Stop a shared interrupt from scavenging while we are. */
- spin_lock_irqsave (&tp->lock, flags);
-
+ spin_lock_irq (&tp->lock);
rtl8139_tx_clear (tp);
-
- spin_unlock_irqrestore (&tp->lock, flags);
+ spin_unlock_irq (&tp->lock);
/* ...and finally, reset everything */
rtl8139_hw_start (dev);
@@ -1539,27 +1565,37 @@ static void rtl8139_tx_timeout (struct net_device *dev)
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
int entry;
/* Calculate the next Tx descriptor entry. */
- entry = atomic_read (&tp->cur_tx) % NUM_TX_DESC;
+ entry = tp->cur_tx % NUM_TX_DESC;
assert (tp->tx_info[entry].skb == NULL);
assert (tp->tx_info[entry].mapping == 0);
tp->tx_info[entry].skb = skb;
- /* tp->tx_info[entry].mapping = 0; */
- memcpy (tp->tx_buf[entry], skb->data, skb->len);
+ if ((long) skb->data & 3) { /* Must use alignment buffer. */
+ /* tp->tx_info[entry].mapping = 0; */
+ memcpy (tp->tx_buf[entry], skb->data, skb->len);
+ RTL_W32 (TxAddr0 + (entry * 4),
+ tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs));
+ } else {
+ tp->tx_info[entry].mapping =
+ pci_map_single (tp->pci_dev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ RTL_W32 (TxAddr0 + (entry * 4), tp->tx_info[entry].mapping);
+ }
/* Note: the chip doesn't have auto-pad! */
- RTL_W32 (TxStatus0 + (entry * sizeof(u32)),
+ RTL_W32 (TxStatus0 + (entry * sizeof (u32)),
tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
dev->trans_start = jiffies;
- atomic_inc (&tp->cur_tx);
- if ((atomic_read (&tp->cur_tx) - atomic_read (&tp->dirty_tx)) >= NUM_TX_DESC)
+ tp->cur_tx++;
+ mb();
+ if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
netif_stop_queue (dev);
DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n",
@@ -1573,16 +1609,14 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
struct rtl8139_private *tp,
void *ioaddr)
{
- int cur_tx, dirty_tx, tx_left;
+ unsigned int dirty_tx, tx_left;
assert (dev != NULL);
assert (tp != NULL);
assert (ioaddr != NULL);
- dirty_tx = atomic_read (&tp->dirty_tx);
-
- cur_tx = atomic_read (&tp->cur_tx);
- tx_left = cur_tx - dirty_tx;
+ dirty_tx = tp->dirty_tx;
+ tx_left = tp->cur_tx - dirty_tx;
while (tx_left > 0) {
int entry = dirty_tx % NUM_TX_DESC;
int txstatus;
@@ -1632,29 +1666,27 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
}
dev_kfree_skb_irq (tp->tx_info[entry].skb);
tp->tx_info[entry].skb = NULL;
- dirty_tx++;
- if (dirty_tx < 0) { /* handle signed int overflow */
- atomic_sub (cur_tx, &tp->cur_tx); /* XXX racy? */
- dirty_tx = cur_tx - tx_left + 1;
- }
- if (netif_queue_stopped (dev))
- netif_wake_queue (dev);
-
- cur_tx = atomic_read (&tp->cur_tx);
- tx_left = cur_tx - dirty_tx;
+ dirty_tx++;
+ tx_left--;
}
#ifndef RTL8139_NDEBUG
- if (atomic_read (&tp->cur_tx) - dirty_tx > NUM_TX_DESC) {
+ if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
printk (KERN_ERR
"%s: Out-of-sync dirty pointer, %d vs. %d.\n",
- dev->name, dirty_tx, atomic_read (&tp->cur_tx));
+ dev->name, dirty_tx, tp->cur_tx);
dirty_tx += NUM_TX_DESC;
}
#endif /* RTL8139_NDEBUG */
- atomic_set (&tp->dirty_tx, dirty_tx);
+ /* only wake the queue if we did work, and the queue is stopped */
+ if (tp->dirty_tx != dirty_tx) {
+ tp->dirty_tx = dirty_tx;
+ mb();
+ if (netif_queue_stopped (dev))
+ netif_wake_queue (dev);
+ }
}
@@ -1879,7 +1911,7 @@ static void rtl8139_interrupt (int irq, void *dev_instance,
struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_instance;
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
int boguscnt = max_interrupt_work;
void *ioaddr = tp->mmio_addr;
int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */
@@ -1962,20 +1994,27 @@ static void rtl8139_interrupt (int irq, void *dev_instance,
static int rtl8139_close (struct net_device *dev)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
- unsigned long flags;
+ int ret = 0;
DPRINTK ("ENTER\n");
netif_stop_queue (dev);
+ if (tp->thr_pid >= 0) {
+ ret = kill_proc (tp->thr_pid, SIGTERM, 1);
+ if (ret) {
+ printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
+ return ret;
+ }
+ down (&tp->thr_exited);
+ }
+
DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n",
dev->name, RTL_R16 (IntrStatus));
- del_timer_sync (&tp->timer);
-
- spin_lock_irqsave (&tp->lock, flags);
+ spin_lock_irq (&tp->lock);
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear));
@@ -1987,7 +2026,7 @@ static int rtl8139_close (struct net_device *dev)
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
RTL_W32 (RxMissed, 0);
- spin_unlock_irqrestore (&tp->lock, flags);
+ spin_unlock_irq (&tp->lock);
synchronize_irq ();
free_irq (dev->irq, dev);
@@ -2006,8 +2045,6 @@ static int rtl8139_close (struct net_device *dev)
RTL_W8 (Config1, 0x03);
RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */
- MOD_DEC_USE_COUNT;
-
DPRINTK ("EXIT\n");
return 0;
}
@@ -2015,9 +2052,8 @@ static int rtl8139_close (struct net_device *dev)
static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
u16 *data = (u16 *) & rq->ifr_data;
- unsigned long flags;
int rc = 0;
DPRINTK ("ENTER\n");
@@ -2028,9 +2064,7 @@ static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
/* Fall Through */
case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */
- spin_lock_irqsave (&tp->lock, flags);
data[3] = mdio_read (dev, data[0], data[1] & 0x1f);
- spin_unlock_irqrestore (&tp->lock, flags);
break;
case SIOCDEVPRIVATE + 2: /* Write the specified MII register */
@@ -2039,9 +2073,7 @@ static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
break;
}
- spin_lock_irqsave (&tp->lock, flags);
mdio_write (dev, data[0], data[1] & 0x1f, data[2]);
- spin_unlock_irqrestore (&tp->lock, flags);
break;
default:
@@ -2056,22 +2088,14 @@ static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
DPRINTK ("ENTER\n");
- assert (tp != NULL);
-
if (netif_running(dev)) {
- unsigned long flags;
-
- spin_lock_irqsave (&tp->lock, flags);
-
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
RTL_W32 (RxMissed, 0);
-
- spin_unlock_irqrestore (&tp->lock, flags);
}
DPRINTK ("EXIT\n");
@@ -2104,7 +2128,7 @@ static inline u32 ether_crc (int length, unsigned char *data)
static void rtl8139_set_rx_mode (struct net_device *dev)
{
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u32 mc_filter[2]; /* Multicast hash filter */
int i, rx_mode;
@@ -2160,7 +2184,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev)
static void rtl8139_suspend (struct pci_dev *pdev)
{
struct net_device *dev = pdev->driver_data;
- struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
unsigned long flags;
@@ -2190,7 +2214,7 @@ static void rtl8139_resume (struct pci_dev *pdev)
static struct pci_driver rtl8139_pci_driver = {
- name: RTL8139_MODULE_NAME,
+ name: MODNAME,
id_table: rtl8139_pci_tbl,
probe: rtl8139_init_one,
remove: rtl8139_remove_one,
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 9bbaf9631..a4ec3fb54 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -38,6 +38,7 @@
Paul Gortmaker : add kmod support for auto-loading of the 8390
module by all drivers that require it.
Alan Cox : Spinlocking work, added 'BUG_83C690'
+ Paul Gortmaker : Separate out Tx timeout code from Tx path.
Sources:
The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
@@ -105,6 +106,7 @@ int ei_debug = 1;
/* Index to functions. */
static void ei_tx_intr(struct net_device *dev);
static void ei_tx_err(struct net_device *dev);
+static void ei_tx_timeout(struct net_device *dev);
static void ei_receive(struct net_device *dev);
static void ei_rx_overrun(struct net_device *dev);
@@ -161,6 +163,13 @@ int ei_open(struct net_device *dev)
printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
return -ENXIO;
}
+
+ /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout
+ wrapper that does e.g. media check & then calls ei_tx_timeout. */
+ if (dev->tx_timeout == NULL)
+ dev->tx_timeout = ei_tx_timeout;
+ if (dev->watchdog_timeo <= 0)
+ dev->watchdog_timeo = TX_TIMEOUT;
/*
* Grab the page lock so we own the register set, then call
@@ -200,89 +209,66 @@ int ei_close(struct net_device *dev)
}
/**
- * ei_start_xmit - begin packet transmission
- * @skb: packet to be sent
- * @dev: network device to which packet is sent
+ * ei_tx_timeout - handle transmit time out condition
+ * @dev: network device which has apparently fallen asleep
*
- * Sends a packet to an 8390 network device.
+ * Called by kernel when device never acknowledges a transmit has
+ * completed (or failed) - i.e. never posted a Tx related interrupt.
*/
-
-static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+void ei_tx_timeout(struct net_device *dev)
{
long e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
- int length, send_length, output_page;
+ int txsr, isr, tickssofar = jiffies - dev->trans_start;
unsigned long flags;
- /*
- * If it has been too long since the last Tx, we assume the
- * board has died and kick it.
- */
-
- if (netif_queue_stopped(dev)) {
- /* Do timeouts, just like the 8003 driver. */
- int txsr;
- int isr;
- int tickssofar = jiffies - dev->trans_start;
-
- /*
- * Need the page lock. Now see what went wrong. This bit is
- * fast.
- */
-
- spin_lock_irqsave(&ei_local->page_lock, flags);
- txsr = inb(e8390_base+EN0_TSR);
- if (tickssofar < TX_TIMEOUT || (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX)))
- {
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
- return 1;
- }
-
- ei_local->stat.tx_errors++;
- isr = inb(e8390_base+EN0_ISR);
- if (!netif_running(dev)) {
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
- printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name);
- return 1;
- }
-
- /*
- * Note that if the Tx posted a TX_ERR interrupt, then the
- * error will have been handled from the interrupt handler
- * and not here. Error statistics are handled there as well.
- */
+ ei_local->stat.tx_errors++;
- printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
- dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
- (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ txsr = inb(e8390_base+EN0_TSR);
+ isr = inb(e8390_base+EN0_ISR);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
- if (!isr && !ei_local->stat.tx_packets)
- {
- /* The 8390 probably hasn't gotten on the cable yet. */
- ei_local->interface_num ^= 1; /* Try a different xcvr. */
- }
+ printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+ dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
+ (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
- /*
- * Play shuffle the locks, a reset on some chips takes a few
- * mS. We very rarely hit this point.
- */
-
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ if (!isr && !ei_local->stat.tx_packets)
+ {
+ /* The 8390 probably hasn't gotten on the cable yet. */
+ ei_local->interface_num ^= 1; /* Try a different xcvr. */
+ }
- /* Ugly but a reset can be slow, yet must be protected */
+ /* Ugly but a reset can be slow, yet must be protected */
- disable_irq_nosync(dev->irq);
- spin_lock(&ei_local->page_lock);
+ disable_irq_nosync(dev->irq);
+ spin_lock(&ei_local->page_lock);
- /* Try to restart the card. Perhaps the user has fixed something. */
- ei_reset_8390(dev);
- NS8390_init(dev, 1);
+ /* Try to restart the card. Perhaps the user has fixed something. */
+ ei_reset_8390(dev);
+ NS8390_init(dev, 1);
- spin_unlock(&ei_local->page_lock);
- enable_irq(dev->irq);
- dev->trans_start = jiffies;
- }
+ spin_unlock(&ei_local->page_lock);
+ enable_irq(dev->irq);
+ netif_wake_queue(dev);
+}
+/**
+ * ei_start_xmit - begin packet transmission
+ * @skb: packet to be sent
+ * @dev: network device to which packet is sent
+ *
+ * Sends a packet to an 8390 network device.
+ */
+
+static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ long e8390_base = dev->base_addr;
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+ int length, send_length, output_page;
+ unsigned long flags;
+
length = skb->len;
/* Mask interrupts from the ethercard.
@@ -1147,6 +1133,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
EXPORT_SYMBOL(ei_open);
EXPORT_SYMBOL(ei_close);
EXPORT_SYMBOL(ei_interrupt);
+EXPORT_SYMBOL(ei_tx_timeout);
EXPORT_SYMBOL(ethdev_init);
EXPORT_SYMBOL(NS8390_init);
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index f73af0828..19bf1ef0f 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -2223,7 +2223,7 @@ static int ace_open(struct net_device *dev)
/*
* Setup the bottom half rx ring refill handler
*/
- ap->immediate.next = NULL;
+ INIT_LIST_HEAD(&ap->immediate.list);
ap->immediate.sync = 0;
ap->immediate.routine = (void *)(void *)ace_bh;
ap->immediate.data = dev;
diff --git a/drivers/net/aironet4500.h b/drivers/net/aironet4500.h
index 92f2dd4c1..6a8956e85 100644
--- a/drivers/net/aironet4500.h
+++ b/drivers/net/aironet4500.h
@@ -1487,7 +1487,7 @@ struct awc_private {
volatile int ejected;
volatile int bh_running;
volatile int bh_active;
- volatile int tx_chain_active;
+ volatile long tx_chain_active;
volatile u16 enabled_interrupts;
volatile u16 waiting_interrupts;
volatile int interrupt_count;
diff --git a/drivers/net/aironet4500_core.c b/drivers/net/aironet4500_core.c
index 7d5e67b5c..5a06600f0 100644
--- a/drivers/net/aironet4500_core.c
+++ b/drivers/net/aironet4500_core.c
@@ -2868,7 +2868,7 @@ int awc_private_init(struct net_device * dev){
priv->command_semaphore_on = 0;
priv->unlock_command_postponed = 0;
- priv->immediate_bh.next = NULL;
+ INIT_LIST_HEAD(&priv->immediate_bh.list);
priv->immediate_bh.sync = 0;
priv->immediate_bh.routine = (void *)(void *)awc_bh;
priv->immediate_bh.data = dev;
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index fe24effde..ec318c974 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -384,9 +384,8 @@ apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_pa
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
return;
}
@@ -433,9 +432,8 @@ apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int rin
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
return;
}
ei_status.dmaing |= 0x01;
@@ -482,9 +480,8 @@ apne_block_output(struct net_device *dev, int count,
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
return;
}
ei_status.dmaing |= 0x01;
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 5c00406b4..7a4c1a1d6 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -50,7 +50,6 @@ static const char *version =
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -220,8 +219,10 @@ static struct net_device_stats *cops_get_stats (struct net_device *dev);
int __init cops_probe(struct net_device *dev)
{
int i;
- int base_addr = dev ? dev->base_addr : 0;
-
+ int base_addr = dev->base_addr;
+
+ SET_MODULE_OWNER(dev);
+
if(base_addr == 0 && io)
base_addr=io;
@@ -235,13 +236,9 @@ int __init cops_probe(struct net_device *dev)
* Dayna cards don't autoprobe well at all, but if your card is
* at IRQ 5 & IO 0x240 we find it every time. ;) JS
*/
- for(i=0; cops_portlist[i]; i++) {
- int ioaddr = cops_portlist[i];
- if(check_region(ioaddr, COPS_IO_EXTENT))
- continue;
- if(cops_probe1(dev, ioaddr) == 0)
+ for(i=0; cops_portlist[i]; i++)
+ if(cops_probe1(dev, cops_portlist[i]) == 0)
return 0;
- }
return -ENODEV;
}
@@ -254,13 +251,17 @@ int __init cops_probe(struct net_device *dev)
static int __init cops_probe1(struct net_device *dev, int ioaddr)
{
struct cops_local *lp;
- static unsigned version_printed = 0;
-
+ static unsigned version_printed;
int board = board_type;
+ int retval;
if(cops_debug && version_printed++ == 0)
printk("%s", version);
+ /* Grab the region so no one else tries to probe our ioports. */
+ if (!request_region(ioaddr, COPS_IO_EXTENT, dev->name))
+ return -EBUSY;
+
/*
* Since this board has jumpered interrupts, allocate the interrupt
* vector now. There is no point in waiting since no other device
@@ -273,13 +274,14 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
case 0:
/* COPS AutoIRQ routine */
dev->irq = cops_irq(ioaddr, board);
- if(!dev->irq)
- return -EINVAL; /* No IRQ found on this port */
- break;
+ if(!dev->irq) {
+ retval = -EINVAL; /* No IRQ found on this port */
+ goto err_out;
+ }
case 1:
- return -EINVAL;
- break;
+ retval = -EINVAL;
+ goto err_out;
/* Fixup for users that don't know that IRQ 2 is really
* IRQ 9, or don't know which one to set.
@@ -301,17 +303,22 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
}
/* Reserve any actual interrupt. */
- if(dev->irq && request_irq(dev->irq, &cops_interrupt, 0, cardname, dev))
- return -EINVAL;
+ if(dev->irq) {
+ retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev);
+ if (retval)
+ goto err_out;
+ }
- /* Grab the region so no one else tries to probe our ioports. */
- request_region(ioaddr, COPS_IO_EXTENT, cardname);
- dev->base_addr = ioaddr;
+ dev->base_addr = ioaddr;
/* Initialize the private device structure. */
dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL);
- if(dev->priv == NULL)
- return -ENOMEM;
+ if(dev->priv == NULL) {
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ retval = -ENOMEM;
+ goto err_out;
+ }
lp = (struct cops_local *)dev->priv;
memset(lp, 0, sizeof(struct cops_local));
@@ -347,6 +354,10 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
}
return 0;
+
+err_out:
+ release_region(ioaddr, COPS_IO_EXTENT);
+ return retval;
}
static int __init cops_irq (int ioaddr, int board)
@@ -426,10 +437,6 @@ static int cops_open(struct net_device *dev)
cops_jumpstart(dev); /* Start the card up. */
netif_start_queue(dev);
-#ifdef MODULE
- MOD_INC_USE_COUNT;
-#endif
-
return 0;
}
@@ -990,10 +997,6 @@ static int cops_close(struct net_device *dev)
del_timer(&cops_timer);
netif_stop_queue(dev);
-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
-
return 0;
}
@@ -1039,8 +1042,7 @@ void cleanup_module(void)
{
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
unregister_netdev(&cops0_dev);
- if(cops0_dev.priv)
- kfree(cops0_dev.priv);
+ kfree(cops0_dev.priv);
if(cops0_dev.irq)
free_irq(cops0_dev.irq, &cops0_dev);
release_region(cops0_dev.base_addr, COPS_IO_EXTENT);
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 503c66167..b7bca28da 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -62,22 +62,12 @@ static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt);
static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int ipddp_open(struct net_device *dev)
-{
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int ipddp_close(struct net_device *dev)
-{
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
static int __init ipddp_init(struct net_device *dev)
{
static unsigned version_printed = 0;
+ SET_MODULE_OWNER(dev);
+
if (ipddp_debug && version_printed++ == 0)
printk("%s", version);
@@ -100,8 +90,6 @@ static int __init ipddp_init(struct net_device *dev)
return -ENOMEM;
memset(dev->priv,0,sizeof(struct net_device_stats));
- dev->open = ipddp_open;
- dev->stop = ipddp_close;
dev->get_stats = ipddp_get_stats;
dev->do_ioctl = ipddp_ioctl;
@@ -298,7 +286,7 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
}
-static struct net_device dev_ipddp = { init: ipddp_init };
+static struct net_device dev_ipddp;
MODULE_PARM(ipddp_mode, "i");
@@ -306,6 +294,7 @@ static int __init ipddp_init_module(void)
{
int err;
+ dev_ipddp.init = ipddp_init;
err=dev_alloc_name(&dev_ipddp, "ipddp%d");
if(err < 0)
return err;
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index d9b818824..b55a37f28 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -206,11 +206,7 @@ static int io=0;
static int irq=0;
static int dma=0;
-#ifdef MODULE
#include <linux/module.h>
-#include <linux/version.h>
-#endif
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -710,22 +706,6 @@ static struct timer_list ltpc_timer;
static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev);
static struct net_device_stats *ltpc_get_stats(struct net_device *dev);
-static int ltpc_open(struct net_device *dev)
-{
-#ifdef MODULE
- MOD_INC_USE_COUNT;
-#endif
- return 0;
-}
-
-static int ltpc_close(struct net_device *dev)
-{
-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
- return 0;
-}
-
static int read_30 ( struct net_device *dev)
{
lt_command c;
@@ -921,9 +901,6 @@ static int ltpc_init(struct net_device *dev)
memset(dev->priv, 0, sizeof(struct ltpc_private));
dev->get_stats = ltpc_get_stats;
- dev->open = ltpc_open;
- dev->stop = ltpc_close;
-
/* add the ltpc-specific things */
dev->do_ioctl = &ltpc_ioctl;
@@ -1008,7 +985,7 @@ static struct net_device_stats *ltpc_get_stats(struct net_device *dev)
/* initialization stuff */
-int __init ltpc_probe_dma(int base)
+static int __init ltpc_probe_dma(int base)
{
int dma = 0;
int timeout;
@@ -1087,6 +1064,8 @@ int __init ltpc_probe(struct net_device *dev)
unsigned long flags;
unsigned long f;
+ SET_MODULE_OWNER(dev);
+
save_flags(flags);
/* probe for the I/O port address */
@@ -1273,11 +1252,7 @@ static int __init ltpc_setup(char *str)
__setup("ltpc=", ltpc_setup);
#endif /* MODULE */
-static struct net_device dev_ltpc = {
- "",
- 0, 0, 0, 0,
- 0x0, 0,
- 0, 0, 0, NULL, ltpc_probe };
+static struct net_device dev_ltpc;
#ifdef MODULE
MODULE_PARM(debug, "i");
@@ -1295,6 +1270,7 @@ int __init init_module(void)
"ltpc: Autoprobing is not recommended for modules\n");
/* Find a name for this unit */
+ dev_ltpc.init = ltpc_probe;
err=dev_alloc_name(&dev_ltpc,"lt%d");
if(err<0)
diff --git a/drivers/net/arlan.c b/drivers/net/arlan.c
index cec860fe0..aee2bcbdd 100644
--- a/drivers/net/arlan.c
+++ b/drivers/net/arlan.c
@@ -205,7 +205,7 @@ int arlan_command(struct net_device *dev, int command_p)
priv->card_polling_interval = 1;
if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
- printk(KERN_DEBUG "arlan_command, %lx lock %x commandByte %x waiting %x incoming %x \n",
+ printk(KERN_DEBUG "arlan_command, %lx lock %lx commandByte %x waiting %x incoming %x \n",
jiffies, priv->command_lock, READSHMB(arlan->commandByte),
priv->waiting_command_mask, command_p);
diff --git a/drivers/net/arlan.h b/drivers/net/arlan.h
index e28982bdb..0f3d5da3e 100644
--- a/drivers/net/arlan.h
+++ b/drivers/net/arlan.h
@@ -388,7 +388,7 @@ struct arlan_private {
volatile int tx_chain_active;
volatile int timer_chain_active;
volatile int interrupt_ack_requested;
- volatile int command_lock;
+ volatile long command_lock;
volatile int rx_command_needed;
volatile int tx_command_needed;
volatile int waiting_command_mask;
@@ -398,8 +398,8 @@ struct arlan_private {
volatile int under_reset;
volatile int under_config;
volatile int rx_command_given;
- volatile int tx_command_given;
- volatile int interrupt_processing_active;
+ volatile long tx_command_given;
+ volatile long interrupt_processing_active;
volatile long long last_tx_time;
volatile long long last_rx_time;
volatile long long last_rx_int_ack_time;
diff --git a/drivers/net/daynaport.c b/drivers/net/daynaport.c
index b7718aba5..ee4ba5876 100644
--- a/drivers/net/daynaport.c
+++ b/drivers/net/daynaport.c
@@ -44,8 +44,6 @@ static int version_printed;
#include <linux/etherdevice.h>
#include "8390.h"
-extern int console_loglevel;
-
int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
int prom, struct nubus_dev *ndev);
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index a947845d8..2de402944 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -130,6 +130,14 @@ typedef unsigned int bool;
#include "dgrs_asstruct.h"
#include "dgrs_bcomm.h"
+#if LINUX_VERSION_CODE >= 0x20400
+static struct pci_device_id dgrs_pci_tbl[] __initdata = {
+ { SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, dgrs_pci_tbl);
+#endif /* LINUX_VERSION_CODE >= 0x20400 */
+
/*
* Firmware. Compiled separately for local compilation,
* but #included for Linux distribution.
@@ -788,9 +796,6 @@ static int
dgrs_open( struct net_device *dev )
{
netif_start_queue(dev);
-
- MOD_INC_USE_COUNT;
-
return (0);
}
@@ -800,9 +805,6 @@ dgrs_open( struct net_device *dev )
static int dgrs_close( struct net_device *dev )
{
netif_stop_queue(dev);
-
- MOD_DEC_USE_COUNT;
-
return (0);
}
@@ -1268,6 +1270,7 @@ dgrs_found_device(
priv->devtbl[0] = dev;
dev->init = dgrs_probe1;
+ SET_MODULE_OWNER(dev);
ether_setup(dev);
priv->next_dev = dgrs_root_dev;
dgrs_root_dev = dev;
@@ -1303,6 +1306,7 @@ dgrs_found_device(
privN->chan = i+1;
priv->devtbl[i] = devN;
devN->init = dgrs_initclone;
+ SET_MODULE_OWNER(dev);
ether_setup(devN);
privN->next_dev = dgrs_root_dev;
dgrs_root_dev = devN;
diff --git a/drivers/net/dmfe.c b/drivers/net/dmfe.c
index c34472200..481b28700 100644
--- a/drivers/net/dmfe.c
+++ b/drivers/net/dmfe.c
@@ -393,6 +393,7 @@ static int __init dmfe_init_one (struct pci_dev *pdev,
dev = init_etherdev(NULL, sizeof(*db));
if (dev == NULL)
goto err_out;
+ SET_MODULE_OWNER(dev);
/* IO range check */
if (!request_region(pci_iobase, CHK_IO_SIZE(pdev, dev_rev), dev->name)) {
@@ -461,12 +462,14 @@ static void __exit dmfe_remove_one (struct pci_dev *pdev)
static int dmfe_open(struct net_device *dev)
{
+ int ret;
struct dmfe_board_info *db = dev->priv;
DMFE_DBUG(0, "dmfe_open", 0);
- if (request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev))
- return -EAGAIN;
+ ret = request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev);
+ if (ret)
+ return ret;
/* Allocated Tx/Rx descriptor memory */
db->desc_pool_ptr = kmalloc(sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, GFP_KERNEL | GFP_DMA);
@@ -511,9 +514,6 @@ static int dmfe_open(struct net_device *dev)
/* Initilize DM910X board */
dmfe_init_dm910x(dev);
- /* Active System Interface */
- MOD_INC_USE_COUNT;
-
/* set and active a timer process */
init_timer(&db->timer);
db->timer.expires = DMFE_TIMER_WUT;
@@ -657,7 +657,7 @@ static int dmfe_stop(struct net_device *dev)
DELAY_5US;
/* deleted timer */
- del_timer(&db->timer);
+ del_timer_sync(&db->timer);
/* free interrupt */
free_irq(dev->irq, dev);
@@ -669,8 +669,6 @@ static int dmfe_stop(struct net_device *dev)
kfree(db->desc_pool_ptr);
kfree(db->buf_pool_ptr);
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index bf3a376a2..1d974350c 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -39,18 +39,6 @@
static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
static struct net_device_stats *dummy_get_stats(struct net_device *dev);
-static int dummy_open(struct net_device *dev)
-{
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int dummy_close(struct net_device *dev)
-{
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
/* fake multicast ability */
static void set_multicast_list(struct net_device *dev)
{
@@ -74,8 +62,6 @@ static int __init dummy_init(struct net_device *dev)
memset(dev->priv, 0, sizeof(struct net_device_stats));
dev->get_stats = dummy_get_stats;
- dev->open = dummy_open;
- dev->stop = dummy_close;
dev->set_multicast_list = set_multicast_list;
/* Fill in the fields of the device structure with ethernet-generic values. */
@@ -107,12 +93,17 @@ static struct net_device_stats *dummy_get_stats(struct net_device *dev)
return dev->priv;
}
-static struct net_device dev_dummy = { init: dummy_init };
+static struct net_device dev_dummy;
static int __init dummy_init_module(void)
{
+ int err;
+
+ dev_dummy.init = dummy_init;
+ SET_MODULE_OWNER(&dev_dummy);
+
/* Find a name for this unit */
- int err=dev_alloc_name(&dev_dummy,"dummy%d");
+ err=dev_alloc_name(&dev_dummy,"dummy%d");
if(err<0)
return err;
if (register_netdev(&dev_dummy) != 0)
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 3d632145c..680f043eb 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -96,7 +96,7 @@ extern inline void mem_off(short port)
#define E21_TX_START_PG E21_RX_STOP_PG /* First page of TX buffer */
int e2100_probe(struct net_device *dev);
-int e21_probe1(struct net_device *dev, int ioaddr);
+static int e21_probe1(struct net_device *dev, int ioaddr);
static int e21_open(struct net_device *dev);
static void e21_reset_8390(struct net_device *dev);
@@ -122,6 +122,8 @@ int __init e2100_probe(struct net_device *dev)
int *port;
int base_addr = dev->base_addr;
+ SET_MODULE_OWNER(dev);
+
if (base_addr > 0x1ff) /* Check a single specified location. */
return e21_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
@@ -134,14 +136,14 @@ int __init e2100_probe(struct net_device *dev)
return -ENODEV;
}
-int __init e21_probe1(struct net_device *dev, int ioaddr)
+static int __init e21_probe1(struct net_device *dev, int ioaddr)
{
int i, status, retval;
unsigned char *station_addr = dev->dev_addr;
static unsigned version_printed = 0;
- if (!request_region(ioaddr, E21_IO_EXTENT, "e2100"))
- return -ENODEV;
+ if (!request_region(ioaddr, E21_IO_EXTENT, dev->name))
+ return -EBUSY;
/* First check the station address for the Ctron prefix. */
if (inb(ioaddr + E21_SAPROM + 0) != 0x00
@@ -255,10 +257,10 @@ static int
e21_open(struct net_device *dev)
{
short ioaddr = dev->base_addr;
+ int retval;
- if (request_irq(dev->irq, ei_interrupt, 0, "e2100", dev)) {
- return -EBUSY;
- }
+ if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
+ return retval;
/* Set the interrupt line and memory base on the hardware. */
inb(ioaddr + E21_IRQ_LOW);
@@ -270,7 +272,6 @@ e21_open(struct net_device *dev)
outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -369,8 +370,6 @@ e21_close(struct net_device *dev)
really bad things happen if it isn't. */
mem_off(ioaddr);
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index cff64211b..6943b7f87 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -533,8 +533,9 @@ static unsigned eeprom_reg = EEPROM_REG_PRO;
int __init eepro_probe(struct net_device *dev)
{
int i;
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev->base_addr;
+ SET_MODULE_OWNER(dev);
#ifdef PnPWakeup
/* XXXX for multiple cards should this only be run once? */
@@ -643,7 +644,7 @@ void printEEPROMInfo(short ioaddr, struct net_device *dev)
probes on the ISA bus. A good device probe avoids doing writes, and
verifies that the correct device exists and functions. */
-int eepro_probe1(struct net_device *dev, short ioaddr)
+static int eepro_probe1(struct net_device *dev, short ioaddr)
{
unsigned short station_addr[6], id, counter;
int i,j, irqMask;
@@ -1078,7 +1079,6 @@ static int eepro_open(struct net_device *dev)
/* enabling rx */
eepro_en_rx(ioaddr);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -1234,7 +1234,6 @@ static int eepro_close(struct net_device *dev)
/* Update the statistics here. What statistics? */
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1732,7 +1731,7 @@ eepro_transmit_interrupt(struct net_device *dev)
static struct net_device dev_eepro[MAX_EEPRO];
static int io[MAX_EEPRO];
-static int irq[MAX_EEPRO] = { [0 ... MAX_EEPRO-1] = 0 };
+static int irq[MAX_EEPRO];
static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */
[0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024
};
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 6ba26b3b9..298a317e2 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -29,21 +29,25 @@
static const char *version =
"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
-"eepro100.c: $Revision: 1.33 $ 2000/05/24 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
+"eepro100.c: $Revision: 1.35 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
/* A few user-configurable values that apply to all boards.
First set is undocumented and spelled per Intel recommendations. */
-static int congenb; /* Enable congestion control in the DP83840. */
+static int congenb /* = 0 */; /* Enable congestion control in the DP83840. */
static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */
static int txdmacount = 128;
-static int rxdmacount;
+static int rxdmacount /* = 0 */;
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
Lower values use more memory, but are faster. */
+#if defined(__alpha__) || defined(__sparc__)
+static int rx_copybreak = 1518;
+#else
static int rx_copybreak = 200;
+#endif
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 20;
@@ -136,26 +140,6 @@ static inline int null_set_power_state(struct pci_dev *dev, int state)
}
#endif /* CONFIG_EEPRO100_PM */
-#ifndef pci_resource_start
-#define pci_resource_start(p, n) (p)->resource[n].start
-#define pci_resource_len(p, n) ((p)->resource[n].end - (p)->resource[n].start)
-#endif
-
-/* Because of changes in this area the driver may not compile for kernels
- 2.3.43 - 2.3.47. --SAW */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
-#define netif_wake_queue(dev) do { \
- clear_bit(0, (void*)&dev->tbusy); \
- mark_bh(NET_BH); \
- } while(0)
-#define netif_start_queue(dev) clear_bit(0, (void*)&dev->tbusy)
-#define netif_stop_queue(dev) set_bit(0, (void*)&dev->tbusy)
-#define netif_running(dev) dev->start
-#define netdevice_start(dev) dev->start = 1
-#define netdevice_stop(dev) dev->start = 0
-#define netif_set_tx_timeout(dev, tf, tm)
-#define dev_kfree_skb_irq(x) dev_kfree_skb(x)
-#else
#define netdevice_start(dev)
#define netdevice_stop(dev)
#define netif_set_tx_timeout(dev, tf, tm) \
@@ -163,51 +147,8 @@ static inline int null_set_power_state(struct pci_dev *dev, int state)
(dev)->tx_timeout = (tf); \
(dev)->watchdog_timeo = (tm); \
} while(0)
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47)
#define netif_device_attach(dev) netif_start_queue(dev)
#define netif_device_detach(dev) netif_stop_queue(dev)
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
-typedef u32 dma_addr_t;
-static void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle)
-{
- void *ret;
- ret = kmalloc(size, GFP_ATOMIC);
- if (ret != NULL) {
- *dma_handle = virt_to_bus(ret);
- }
- return ret;
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- kfree(vaddr);
-}
-
-#define PCI_DMA_FROMDEVICE 0
-#define PCI_DMA_TODEVICE 0
-
-extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
- size_t size, int direction)
-{
- return virt_to_bus(ptr);
-}
-
-extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
- size_t size, int direction)
-{
-}
-
-extern inline void pci_dma_sync_single(struct pci_dev *hwdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
-{
-}
-#endif
#ifndef PCI_DEVICE_ID_INTEL_ID1029
#define PCI_DEVICE_ID_INTEL_ID1029 0x1029
@@ -450,6 +391,7 @@ enum RxFD_bits {
TxUnderrun=0x1000, StatusComplete=0x8000,
};
+#define CONFIG_DATA_SIZE 22
struct TxFD { /* Transmit frame descriptor set. */
s32 status;
u32 link; /* void * */
@@ -461,6 +403,8 @@ struct TxFD { /* Transmit frame descriptor set. */
s32 tx_buf_size0; /* Length of Tx frame. */
u32 tx_buf_addr1; /* void *, frame to be transmitted. */
s32 tx_buf_size1; /* Length of Tx frame. */
+ /* the structure must have space for at least CONFIG_DATA_SIZE starting
+ * from tx_desc_addr field */
};
/* Multicast filter setting block. --SAW */
@@ -546,12 +490,12 @@ struct speedo_private {
/* The parameters for a CmdConfigure operation.
There are so many options that it would be difficult to document each bit.
We mostly use the default or recommended settings. */
-const char i82557_config_cmd[22] = {
+const char i82557_config_cmd[CONFIG_DATA_SIZE] = {
22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */
0, 0x2E, 0, 0x60, 0,
0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */
0x3f, 0x05, };
-const char i82558_config_cmd[22] = {
+const char i82558_config_cmd[CONFIG_DATA_SIZE] = {
22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */
0, 0x2E, 0, 0x60, 0x08, 0x88,
0x68, 0, 0x40, 0xf2, 0x84, /* Disable FC */
@@ -571,11 +515,10 @@ static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
static int eepro100_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void eepro100_remove_one (struct pci_dev *pdev);
-
#ifdef CONFIG_EEPRO100_PM
static void eepro100_suspend (struct pci_dev *pdev);
static void eepro100_resume (struct pci_dev *pdev);
-#endif /* CONFIG_EEPRO100_PM */
+#endif
static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
static int mdio_read(long ioaddr, int phy_id, int location);
@@ -611,9 +554,9 @@ static int __devinit eepro100_init_one (struct pci_dev *pdev,
unsigned long ioaddr;
int irq;
int acpi_idle_state = 0, pm;
- static int cards_found;
+ static int cards_found /* = 0 */;
- static int did_version; /* Already printed version info. */
+ static int did_version /* = 0 */; /* Already printed version info. */
if (speedo_debug > 0 && did_version++ == 0)
printk(version);
@@ -755,6 +698,7 @@ static int speedo_found1(struct pci_dev *pdev,
This takes less than 10usec and will easily finish before the next
action. */
outl(PortReset, ioaddr + SCBPort);
+ udelay(10);
if (eeprom[3] & 0x0100)
product = "OEM i82557/i82558 10/100 Ethernet";
@@ -841,6 +785,7 @@ static int speedo_found1(struct pci_dev *pdev,
#endif /* kernel_bloat */
outl(PortReset, ioaddr + SCBPort);
+ udelay(10);
/* Return the chip to its original power state. */
pci_set_power_state(pdev, acpi_idle_state);
@@ -856,7 +801,8 @@ static int speedo_found1(struct pci_dev *pdev,
sp->tx_ring = tx_ring_space;
sp->tx_ring_dma = tx_ring_dma;
sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
- sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
+ sp->lstats_dma = cpu_to_le32(TX_RING_ELEM_DMA(sp, TX_RING_SIZE));
+ init_timer(&sp->timer); /* used in ioctl() */
sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
if (card_idx >= 0) {
@@ -921,7 +867,7 @@ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
io_outw(EE_ENB, ee_addr); udelay(2);
/* Terminate the EEPROM access. */
- io_outw(EE_ENB & ~EE_CS, ee_addr); udelay(4);
+ io_outw(EE_ENB & ~EE_CS, ee_addr);
return retval;
}
@@ -960,6 +906,7 @@ speedo_open(struct net_device *dev)
{
struct speedo_private *sp = (struct speedo_private *)dev->priv;
long ioaddr = dev->base_addr;
+ int retval;
if (speedo_debug > 1)
printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
@@ -977,9 +924,10 @@ speedo_open(struct net_device *dev)
sp->in_interrupt = 0;
/* .. we can safely take handler calls during init. */
- if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) {
+ retval = request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev);
+ if (retval) {
MOD_DEC_USE_COUNT;
- return -EBUSY;
+ return retval;
}
dev->if_port = sp->default_port;
@@ -1030,7 +978,6 @@ speedo_open(struct net_device *dev)
to an alternate media type
2) to monitor Rx activity, and restart the Rx process if the receiver
hangs. */
- init_timer(&sp->timer);
sp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
sp->timer.data = (unsigned long)dev;
sp->timer.function = &speedo_timer; /* timer handler */
@@ -1055,29 +1002,32 @@ static void speedo_resume(struct net_device *dev)
/* Set the segment registers to '0'. */
wait_for_cmd_done(ioaddr + SCBCmd);
outl(0, ioaddr + SCBPointer);
+ inl(ioaddr + SCBPointer); /* XXX */
outb(RxAddrLoad, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
outb(CUCmdBase, ioaddr + SCBCmd);
- wait_for_cmd_done(ioaddr + SCBCmd);
/* Load the statistics block and rx ring addresses. */
+ wait_for_cmd_done(ioaddr + SCBCmd);
outl(sp->lstats_dma, ioaddr + SCBPointer);
+ inl(ioaddr + SCBPointer); /* XXX */
outb(CUStatsAddr, ioaddr + SCBCmd);
sp->lstats->done_marker = 0;
- wait_for_cmd_done(ioaddr + SCBCmd);
if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) {
if (speedo_debug > 2)
printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n",
dev->name);
} else {
+ wait_for_cmd_done(ioaddr + SCBCmd);
outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
ioaddr + SCBPointer);
outb(RxStart, ioaddr + SCBCmd);
- wait_for_cmd_done(ioaddr + SCBCmd);
}
+ wait_for_cmd_done(ioaddr + SCBCmd);
outb(CUDumpStats, ioaddr + SCBCmd);
+ udelay(30);
/* Fill the first command with our physical address. */
{
@@ -1143,14 +1093,19 @@ static void speedo_timer(unsigned long data)
/* We haven't received a packet in a Long Time. We might have been
bitten by the receiver hang bug. This can be cleared by sending
a set multicast list command. */
- if (speedo_debug > 2)
+ if (speedo_debug > 3)
printk(KERN_DEBUG "%s: Sending a multicast list set command"
- " from a timer routine.\n", dev->name);
+ " from a timer routine,"
+ " m=%d, j=%ld, l=%ld.\n",
+ dev->name, sp->rx_mode, jiffies, sp->last_rx_time);
set_rx_mode(dev);
}
/* We must continue to monitor the media. */
sp->timer.expires = RUN_AT(2*HZ); /* 2.0 sec. */
add_timer(&sp->timer);
+#if defined(timer_exit)
+ timer_exit(&sp->timer);
+#endif
}
static void speedo_show_state(struct net_device *dev)
@@ -1182,13 +1137,15 @@ static void speedo_show_state(struct net_device *dev)
(unsigned)sp->rx_ringp[i]->status : 0);
#if 0
- long ioaddr = dev->base_addr;
- int phy_num = sp->phy[0] & 0x1f;
- for (i = 0; i < 16; i++) {
- /* FIXME: what does it mean? --SAW */
- if (i == 6) i = 21;
- printk(KERN_DEBUG "%s: PHY index %d register %d is %4.4x.\n",
- dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i));
+ {
+ long ioaddr = dev->base_addr;
+ int phy_num = sp->phy[0] & 0x1f;
+ for (i = 0; i < 16; i++) {
+ /* FIXME: what does it mean? --SAW */
+ if (i == 6) i = 21;
+ printk(KERN_DEBUG "%s: PHY index %d register %d is %4.4x.\n",
+ dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i));
+ }
}
#endif
@@ -1200,6 +1157,7 @@ speedo_init_rx_ring(struct net_device *dev)
{
struct speedo_private *sp = (struct speedo_private *)dev->priv;
struct RxFD *rxf, *last_rxf = NULL;
+ dma_addr_t last_rxf_dma = 0 /* to shut up the compiler */;
int i;
sp->cur_rx = 0;
@@ -1214,26 +1172,31 @@ speedo_init_rx_ring(struct net_device *dev)
rxf = (struct RxFD *)skb->tail;
sp->rx_ringp[i] = rxf;
sp->rx_ring_dma[i] =
- pci_map_single(sp->pdev, rxf, PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
+ pci_map_single(sp->pdev, rxf,
+ PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_BIDIRECTIONAL);
skb_reserve(skb, sizeof(struct RxFD));
if (last_rxf) {
last_rxf->link = cpu_to_le32(sp->rx_ring_dma[i]);
- pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[i-1], sizeof(struct RxFD), PCI_DMA_TODEVICE);
+ pci_dma_sync_single(sp->pdev, last_rxf_dma,
+ sizeof(struct RxFD), PCI_DMA_TODEVICE);
}
last_rxf = rxf;
+ last_rxf_dma = sp->rx_ring_dma[i];
rxf->status = cpu_to_le32(0x00000001); /* '1' is flag value only. */
rxf->link = 0; /* None yet. */
/* This field unused by i82557. */
rxf->rx_buf_addr = 0xffffffff;
rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
- pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[i], sizeof(struct RxFD), PCI_DMA_TODEVICE);
+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[i],
+ sizeof(struct RxFD), PCI_DMA_TODEVICE);
}
sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
/* Mark the last entry as end-of-list. */
last_rxf->status = cpu_to_le32(0xC0000002); /* '2' is flag value only. */
- pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[RX_RING_SIZE-1], sizeof(struct RxFD), PCI_DMA_TODEVICE);
+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[RX_RING_SIZE-1],
+ sizeof(struct RxFD), PCI_DMA_TODEVICE);
sp->last_rxf = last_rxf;
- sp->last_rxf_dma = sp->rx_ring_dma[RX_RING_SIZE-1];
+ sp->last_rxf_dma = last_rxf_dma;
}
static void speedo_purge_tx(struct net_device *dev)
@@ -1304,9 +1267,6 @@ static void speedo_tx_timeout(struct net_device *dev)
sp->dirty_tx, sp->cur_tx,
sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
- /* Trigger a stats dump to give time before the reset. */
- speedo_get_stats(dev);
-
speedo_show_state(dev);
#if 0
if ((status & 0x00C0) != 0x0080
@@ -1322,14 +1282,7 @@ static void speedo_tx_timeout(struct net_device *dev)
#else
{
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
- start_bh_atomic();
- /* Ensure that timer routine doesn't run! */
- del_timer(&sp->timer);
- end_bh_atomic();
-#else /* LINUX_VERSION_CODE */
del_timer_sync(&sp->timer);
-#endif /* LINUX_VERSION_CODE */
/* Reset the Tx and Rx units. */
outl(PortReset, ioaddr + SCBPort);
/* We may get spurious interrupts here. But I don't think that they
@@ -1367,25 +1320,6 @@ speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
long ioaddr = dev->base_addr;
int entry;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
- if (test_bit(0, (void*)&dev->tbusy) != 0) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < TX_TIMEOUT - 2)
- return 1;
- if (tickssofar < TX_TIMEOUT) {
- /* Reap sent packets from the full Tx queue. */
- unsigned long flags;
- spin_lock_irqsave(&sp->lock, flags);
- wait_for_cmd_done(ioaddr + SCBCmd);
- outw(SCBTriggerIntr, ioaddr + SCBCmd);
- spin_unlock_irqrestore(&sp->lock, flags);
- return 1;
- }
- speedo_tx_timeout(dev);
- return 1;
- }
-#endif
-
{ /* Prevent interrupts from changing the Tx ring from underneath us. */
unsigned long flags;
@@ -1636,7 +1570,7 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
/* Clear all interrupt sources. */
/* Will change from 0xfc00 to 0xff00 when we start handling
FCP and ER interrupts --Dragan */
- outl(0xfc00, ioaddr + SCBStatus);
+ outw(0xfc00, ioaddr + SCBStatus);
break;
}
} while (1);
@@ -1668,7 +1602,8 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
skb->dev = dev;
skb_reserve(skb, sizeof(struct RxFD));
rxf->rx_buf_addr = 0xffffffff;
- pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], sizeof(struct RxFD), PCI_DMA_TODEVICE);
+ pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry],
+ sizeof(struct RxFD), PCI_DMA_TODEVICE);
return rxf;
}
@@ -1681,7 +1616,8 @@ static inline void speedo_rx_link(struct net_device *dev, int entry,
rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
sp->last_rxf->link = cpu_to_le32(rxf_dma);
sp->last_rxf->status &= cpu_to_le32(~0xC0000000);
- pci_dma_sync_single(sp->pdev, sp->last_rxf_dma, sizeof(struct RxFD), PCI_DMA_TODEVICE);
+ pci_dma_sync_single(sp->pdev, sp->last_rxf_dma,
+ sizeof(struct RxFD), PCI_DMA_TODEVICE);
sp->last_rxf = rxf;
sp->last_rxf_dma = rxf_dma;
}
@@ -1742,7 +1678,6 @@ speedo_rx(struct net_device *dev)
{
struct speedo_private *sp = (struct speedo_private *)dev->priv;
int entry = sp->cur_rx % RX_RING_SIZE;
- int status;
int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx;
int alloc_ok = 1;
@@ -1750,16 +1685,16 @@ speedo_rx(struct net_device *dev)
printk(KERN_DEBUG " In speedo_rx().\n");
/* If we own the next entry, it's a new packet. Send it up. */
while (sp->rx_ringp[entry] != NULL) {
+ int status;
int pkt_len;
pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry],
sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
+ status = le32_to_cpu(sp->rx_ringp[entry]->status);
+ pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff;
- if(!((status = le32_to_cpu(sp->rx_ringp[entry]->status)) & RxComplete)) {
+ if (!(status & RxComplete))
break;
- }
-
- pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff;
if (--rx_work_limit < 0)
break;
@@ -1812,7 +1747,6 @@ speedo_rx(struct net_device *dev)
pkt_len);
#endif
} else {
- void *temp;
/* Pass up the already-filled skbuff. */
skb = sp->rx_skbuff[entry];
if (skb == NULL) {
@@ -1821,7 +1755,7 @@ speedo_rx(struct net_device *dev)
break;
}
sp->rx_skbuff[entry] = NULL;
- temp = skb_put(skb, pkt_len);
+ skb_put(skb, pkt_len);
sp->rx_ringp[entry] = NULL;
pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry],
PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
@@ -1862,7 +1796,7 @@ speedo_close(struct net_device *dev)
dev->name, inw(ioaddr + SCBStatus));
/* Shut off the media monitoring timer. */
- del_timer(&sp->timer);
+ del_timer_sync(&sp->timer);
/* Shutting down the chip nicely fails to disable flow control. So.. */
outl(PortPartialReset, ioaddr + SCBPort);
@@ -1922,10 +1856,6 @@ speedo_close(struct net_device *dev)
update the stats with the previous dump results, and then trigger a
new dump.
- These problems are mitigated by the current /proc implementation, which
- calls this routine first to judge the output length, and then to emit the
- output.
-
Oh, and incoming frames are dropped while executing dump-stats!
*/
static struct net_device_stats *
@@ -1968,6 +1898,7 @@ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
u16 *data = (u16 *)&rq->ifr_data;
int phy = sp->phy[0] & 0x1f;
int saved_acpi;
+ int t;
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
@@ -1978,30 +1909,20 @@ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
They are currently serialized only with MDIO access from the
timer routine. 2000/05/09 SAW */
saved_acpi = pci_set_power_state(sp->pdev, 0);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
- start_bh_atomic();
+ t = del_timer_sync(&sp->timer);
data[3] = mdio_read(ioaddr, data[0], data[1]);
- end_bh_atomic();
-#else /* LINUX_VERSION_CODE */
- del_timer_sync(&sp->timer);
- data[3] = mdio_read(ioaddr, data[0], data[1]);
- add_timer(&sp->timer); /* may be set to the past --SAW */
-#endif /* LINUX_VERSION_CODE */
+ if (t)
+ add_timer(&sp->timer); /* may be set to the past --SAW */
pci_set_power_state(sp->pdev, saved_acpi);
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
saved_acpi = pci_set_power_state(sp->pdev, 0);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
- start_bh_atomic();
- mdio_write(ioaddr, data[0], data[1], data[2]);
- end_bh_atomic();
-#else /* LINUX_VERSION_CODE */
- del_timer_sync(&sp->timer);
+ t = del_timer_sync(&sp->timer);
mdio_write(ioaddr, data[0], data[1], data[2]);
- add_timer(&sp->timer); /* may be set to the past --SAW */
-#endif /* LINUX_VERSION_CODE */
+ if (t)
+ add_timer(&sp->timer); /* may be set to the past --SAW */
pci_set_power_state(sp->pdev, saved_acpi);
return 0;
default:
@@ -2060,7 +1981,7 @@ static void set_rx_mode(struct net_device *dev)
cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr;
/* Construct a full CmdConfig frame. */
- memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd));
+ memcpy(config_cmd_data, i82558_config_cmd, CONFIG_DATA_SIZE);
config_cmd_data[1] = (txfifo << 4) | rxfifo;
config_cmd_data[4] = rxdmacount;
config_cmd_data[5] = txdmacount + 0x80;
@@ -2186,7 +2107,8 @@ static void set_rx_mode(struct net_device *dev)
mc_setup_frm->link =
cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
- pci_dma_sync_single(sp->pdev, mc_blk->frame_dma, mc_blk->len, PCI_DMA_TODEVICE);
+ pci_dma_sync_single(sp->pdev, mc_blk->frame_dma,
+ mc_blk->len, PCI_DMA_TODEVICE);
wait_for_cmd_done(ioaddr + SCBCmd);
clear_suspend(last_cmd);
@@ -2207,9 +2129,7 @@ static void set_rx_mode(struct net_device *dev)
sp->rx_mode = new_rx_mode;
}
-
#ifdef CONFIG_EEPRO100_PM
-
static void eepro100_suspend(struct pci_dev *pdev)
{
struct net_device *dev = pdev->driver_data;
@@ -2241,7 +2161,6 @@ static void eepro100_resume(struct pci_dev *pdev)
sp->flow_ctrl = sp->partner = 0;
set_rx_mode(dev);
}
-
#endif /* CONFIG_EEPRO100_PM */
static void __devexit eepro100_remove_one (struct pci_dev *pdev)
@@ -2284,7 +2203,6 @@ static struct pci_driver eepro100_driver = {
id_table: eepro100_pci_tbl,
probe: eepro100_init_one,
remove: eepro100_remove_one,
-
#ifdef CONFIG_EEPRO100_PM
suspend: eepro100_suspend,
resume: eepro100_resume,
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 5f1f697bc..102704b0c 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -344,6 +344,8 @@ int __init express_probe(struct net_device *dev)
static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 };
unsigned short ioaddr = dev->base_addr;
+ SET_MODULE_OWNER(dev);
+
dev->if_port = 0xff; /* not set */
#ifdef CONFIG_MCA
@@ -420,7 +422,7 @@ int __init express_probe(struct net_device *dev)
static int eexp_open(struct net_device *dev)
{
- int irq = dev->irq;
+ int ret;
unsigned short ioaddr = dev->base_addr;
struct net_local *lp = (struct net_local *)dev->priv;
@@ -428,11 +430,11 @@ static int eexp_open(struct net_device *dev)
printk(KERN_DEBUG "%s: eexp_open()\n", dev->name);
#endif
- if (!irq || !irqrmap[irq])
+ if (!dev->irq || !irqrmap[dev->irq])
return -ENXIO;
- if (request_irq(irq,&eexp_irq,0,"EtherExpress",dev))
- return -EAGAIN;
+ ret = request_irq(dev->irq,&eexp_irq,0,dev->name,dev);
+ if (ret) return ret;
request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress");
request_region(ioaddr+0x4000, 16, "EtherExpress shadow");
@@ -445,7 +447,6 @@ static int eexp_open(struct net_device *dev)
}
eexp_hw_init586(dev);
- MOD_INC_USE_COUNT;
netif_start_queue(dev);
#if NET_DEBUG > 6
printk(KERN_DEBUG "%s: leaving eexp_open()\n", dev->name);
@@ -477,7 +478,6 @@ static int eexp_close(struct net_device *dev)
release_region(ioaddr+0x8000, 16);
release_region(ioaddr+0xc000, 16);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1625,14 +1625,9 @@ eexp_set_multicast(struct net_device *dev)
#define EEXP_MAX_CARDS 4 /* max number of cards to support */
-static struct net_device dev_eexp[EEXP_MAX_CARDS] =
-{
- { "",
- 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe },
-};
-
-static int irq[EEXP_MAX_CARDS] = {0, };
-static int io[EEXP_MAX_CARDS] = {0, };
+static struct net_device dev_eexp[EEXP_MAX_CARDS];
+static int irq[EEXP_MAX_CARDS];
+static int io[EEXP_MAX_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(EEXP_MAX_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(EEXP_MAX_CARDS) "i");
@@ -1649,6 +1644,7 @@ int init_module(void)
struct net_device *dev = &dev_eexp[this_dev];
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
+ dev->init = express_probe;
if (io[this_dev] == 0) {
if (this_dev) break;
printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n");
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 112e0afba..e281511dc 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -201,6 +201,8 @@ static int __init eql_init(struct net_device *dev)
/* static unsigned num_masters = 0; */
equalizer_t *eql = 0;
+ SET_MODULE_OWNER(dev);
+
if ( version_printed++ == 0 && eql_debug > 0)
printk(version);
/*
@@ -259,8 +261,6 @@ static int eql_open(struct net_device *dev)
equalizer_t *eql = (equalizer_t *) dev->priv;
slave_queue_t *new_queue;
- MOD_INC_USE_COUNT;
-
#ifdef EQL_DEBUG
if (eql_debug >= 5)
printk ("%s: open\n", dev->name);
@@ -284,7 +284,6 @@ static int eql_open(struct net_device *dev)
return 0;
}
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}
@@ -310,7 +309,6 @@ static int eql_close(struct net_device *dev)
eql_delete_slave_queue (eql->queue);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -985,14 +983,12 @@ static void eql_timer(unsigned long param)
}
}
-static struct net_device dev_eql =
-{
- name: "eql",
- init: eql_init,
-};
+static struct net_device dev_eql;
static int __init eql_init_module(void)
{
+ strcpy(dev_eql.name, "eql");
+ dev_eql.init = eql_init;
if (register_netdev(&dev_eql) != 0) {
printk("eql: register_netdev() returned non-zero.\n");
return -EIO;
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 86a09b4d4..0c4c241ac 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -62,7 +62,7 @@ static const char *version =
#include "8390.h"
int es_probe(struct net_device *dev);
-int es_probe1(struct net_device *dev, int ioaddr);
+static int es_probe1(struct net_device *dev, int ioaddr);
static int es_open(struct net_device *dev);
static int es_close(struct net_device *dev);
@@ -128,6 +128,8 @@ int __init es_probe(struct net_device *dev)
{
unsigned short ioaddr = dev->base_addr;
+ SET_MODULE_OWNER(dev);
+
if (ioaddr > 0x1ff) /* Check a single specified location. */
return es_probe1(dev, ioaddr);
else if (ioaddr > 0) /* Don't probe at all. */
@@ -148,7 +150,7 @@ int __init es_probe(struct net_device *dev)
return -ENODEV;
}
-int __init es_probe1(struct net_device *dev, int ioaddr)
+static int __init es_probe1(struct net_device *dev, int ioaddr)
{
int i, retval;
unsigned long eisa_id;
@@ -357,9 +359,6 @@ static void es_block_output(struct net_device *dev, int count,
static int es_open(struct net_device *dev)
{
ei_open(dev);
-
- MOD_INC_USE_COUNT;
-
return 0;
}
@@ -370,24 +369,13 @@ static int es_close(struct net_device *dev)
printk("%s: Shutting down ethercard.\n", dev->name);
ei_close(dev);
-
- MOD_DEC_USE_COUNT;
-
return 0;
}
#ifdef MODULE
#define MAX_ES_CARDS 4 /* Max number of ES3210 cards per module */
#define NAMELEN 8 /* # of chars for storing dev->name */
-static struct net_device dev_es3210[MAX_ES_CARDS] = {
- {
- "", /* device name is inserted by net_init.c */
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, NULL
- },
-};
-
+static struct net_device dev_es3210[MAX_ES_CARDS];
static int io[MAX_ES_CARDS];
static int irq[MAX_ES_CARDS];
static int mem[MAX_ES_CARDS];
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index c8cab2062..a70ab61a3 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -440,8 +440,10 @@ int __init eth16i_probe(struct net_device *dev)
{
int i;
int ioaddr;
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev->base_addr;
+ SET_MODULE_OWNER(dev);
+
if(eth16i_debug > 4)
printk(KERN_DEBUG "Probing started for %s\n", cardname);
@@ -979,8 +981,6 @@ static int eth16i_open(struct net_device *dev)
outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
netif_start_queue(dev);
- MOD_INC_USE_COUNT;
-
return 0;
}
@@ -1007,8 +1007,6 @@ static int eth16i_close(struct net_device *dev)
outb(0x00, ioaddr + CONFIG_REG_1);
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/ethertap.c b/drivers/net/ethertap.c
index a4cfce6ae..5863998cb 100644
--- a/drivers/net/ethertap.c
+++ b/drivers/net/ethertap.c
@@ -67,6 +67,8 @@ struct net_local
int __init ethertap_probe(struct net_device *dev)
{
+ SET_MODULE_OWNER(dev);
+
memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6);
if (dev->mem_start & 0xf)
ethertap_debug = dev->mem_start & 0x7;
@@ -116,13 +118,9 @@ static int ethertap_open(struct net_device *dev)
if (ethertap_debug > 2)
printk("%s: Doing ethertap_open()...", dev->name);
- MOD_INC_USE_COUNT;
-
lp->nl = netlink_kernel_create(dev->base_addr, ethertap_rx);
- if (lp->nl == NULL) {
- MOD_DEC_USE_COUNT;
+ if (lp->nl == NULL)
return -ENOBUFS;
- }
netif_start_queue(dev);
return 0;
}
@@ -324,7 +322,6 @@ static int ethertap_close(struct net_device *dev)
sock_release(sk->socket);
}
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index 60cef746f..b10fe9490 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -350,6 +350,8 @@ int __init ewrk3_probe(struct net_device *dev)
int tmp = num_ewrk3s, status = -ENODEV;
u_long iobase = dev->base_addr;
+ SET_MODULE_OWNER(dev);
+
if ((iobase == 0) && loading_module) {
printk("Autoprobing is not supported when loading a module based driver.\n");
status = -EIO;
@@ -681,8 +683,6 @@ static int ewrk3_open(struct net_device *dev)
return -EINVAL;
}
- MOD_INC_USE_COUNT;
-
return status;
}
@@ -1132,8 +1132,6 @@ static int ewrk3_close(struct net_device *dev)
if (!lp->hard_strapped) {
free_irq(dev->irq, dev);
}
- MOD_DEC_USE_COUNT;
-
return 0;
}
@@ -1860,15 +1858,7 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
#ifdef MODULE
-static char devicename[9] =
-{0,};
-static struct net_device thisEthwrk =
-{
- devicename, /* device name is inserted by /linux/drivers/net/net_init.c */
- 0, 0, 0, 0,
- 0x300, 5, /* I/O address, IRQ */
- 0, 0, 0, NULL, ewrk3_probe};
-
+static struct net_device thisEthwrk;
static int io = 0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
static int irq = 5; /* or use the insmod io= irq= options */
@@ -1879,6 +1869,7 @@ int init_module(void)
{
thisEthwrk.base_addr = io;
thisEthwrk.irq = irq;
+ thisEthwrk.init = ewrk3_probe;
if (register_netdev(&thisEthwrk) != 0)
return -EIO;
return 0;
diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
index 9c1423965..14265574d 100644
--- a/drivers/net/fmv18x.c
+++ b/drivers/net/fmv18x.c
@@ -134,6 +134,8 @@ int __init fmv18x_probe(struct net_device *dev)
int i;
int base_addr = dev->base_addr;
+ SET_MODULE_OWNER(dev);
+
if (base_addr > 0x1ff) /* Check a single specified location. */
return fmv18x_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
@@ -319,8 +321,6 @@ static int net_open(struct net_device *dev)
/* Enable both Tx and Rx interrupts */
outw(0x8182, ioaddr+TX_INTR);
- MOD_INC_USE_COUNT;
-
return 0;
}
@@ -569,8 +569,6 @@ static int net_close(struct net_device *dev)
/* Power-down the chip. Green, green, green! */
outb(0x00, ioaddr + CONFIG_1);
- MOD_DEC_USE_COUNT;
-
/* Set the ethernet adaptor disable IRQ */
outb(0x00, ioaddr + FJ_CONFIG1);
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index dda42edd8..d4b8e8e37 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -580,6 +580,7 @@ static int __init hamachi_init_one (struct pci_dev *pdev,
iounmap((char *)ioaddr);
return -ENOMEM;
}
+ SET_MODULE_OWNER(dev);
#ifdef TX_CHECKSUM
printk("check that skbcopy in ip_queue_xmit isn't happening\n");
@@ -787,12 +788,9 @@ static int hamachi_open(struct net_device *dev)
u_int32_t rx_int_var, tx_int_var;
u_int16_t fifo_info;
- MOD_INC_USE_COUNT;
-
- if (request_irq(dev->irq, &hamachi_interrupt, SA_SHIRQ, dev->name, dev)) {
- MOD_DEC_USE_COUNT;
- return -EAGAIN;
- }
+ i = request_irq(dev->irq, &hamachi_interrupt, SA_SHIRQ, dev->name, dev);
+ if (i)
+ return i;
if (hamachi_debug > 1)
printk(KERN_DEBUG "%s: hamachi_open() irq %d.\n",
@@ -1754,8 +1752,6 @@ static int hamachi_close(struct net_device *dev)
writeb(0x00, ioaddr + LEDCtrl);
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/hamradio/6pack.h b/drivers/net/hamradio/6pack.h
index b929c83a6..08cee0485 100644
--- a/drivers/net/hamradio/6pack.h
+++ b/drivers/net/hamradio/6pack.h
@@ -101,7 +101,8 @@ struct sixpack {
int mtu; /* Our mtu (to spot changes!) */
int buffsize; /* Max buffers sizes */
- unsigned char flags; /* Flag values/ mode etc */
+ unsigned long flags; /* Flag values/ mode etc */
+ /* long req'd for set_bit --RR */
unsigned char mode; /* 6pack mode */
/* 6pack stuff */
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 263ae384e..0e41265fe 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -1023,7 +1023,8 @@ static int epp_open(struct net_device *dev)
struct baycom_state *bc;
struct parport *pp;
const struct tq_struct run_bh = {
- 0, 0, (void *)(void *)epp_bh, dev
+ routine: (void *)(void *)epp_bh,
+ data: dev
};
unsigned int i, j;
unsigned char tmp[128];
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index 9ccc0d1b4..3ec7b1c1d 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -287,7 +287,7 @@ void hdlcdrv_receiver(struct net_device *dev, struct hdlcdrv_state *s)
/* ---------------------------------------------------------------------- */
-static void inline do_kiss_params(struct hdlcdrv_state *s,
+static inline void do_kiss_params(struct hdlcdrv_state *s,
unsigned char *data, unsigned long len)
{
@@ -889,14 +889,7 @@ EXPORT_SYMBOL(hdlcdrv_unregister_hdlcdrv);
/* --------------------------------------------------------------------- */
-#ifdef MODULE
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
-
-/* --------------------------------------------------------------------- */
-
-int __init init_module(void)
+static int __init hdlcdrv_init_driver(void)
{
printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n");
printk(KERN_INFO "hdlcdrv: version 0.8 compiled " __TIME__ " " __DATE__ "\n");
@@ -905,10 +898,16 @@ int __init init_module(void)
/* --------------------------------------------------------------------- */
-void cleanup_module(void)
+static void __exit hdlcdrv_cleanup_driver(void)
{
printk(KERN_INFO "hdlcdrv: cleanup\n");
}
-#endif /* MODULE */
+/* --------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
+MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
+module_init(hdlcdrv_init_driver);
+module_exit(hdlcdrv_cleanup_driver);
+
/* --------------------------------------------------------------------- */
diff --git a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h
index c24c27819..4a3d700cb 100644
--- a/drivers/net/hamradio/mkiss.h
+++ b/drivers/net/hamradio/mkiss.h
@@ -42,7 +42,8 @@ struct ax_disp {
int buffsize; /* Max buffers sizes */
- unsigned char flags; /* Flag values/ mode etc */
+ unsigned long flags; /* Flag values/ mode etc */
+ /* long req'd: used by set_bit --RR */
#define AXF_INUSE 0 /* Channel in use */
#define AXF_ESCAPE 1 /* ESC received */
#define AXF_ERROR 2 /* Parity, etc. error */
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 68fb88261..9dbade427 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -120,7 +120,9 @@ static void hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hd
int __init hp_plus_probe(struct net_device *dev)
{
int i;
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev->base_addr;
+
+ SET_MODULE_OWNER(dev);
if (base_addr > 0x1ff) /* Check a single specified location. */
return hpp_probe1(dev, base_addr);
@@ -270,7 +272,6 @@ hpp_open(struct net_device *dev)
outw(Perf_Page, ioaddr + HP_PAGING);
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -285,7 +286,6 @@ hpp_close(struct net_device *dev)
outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
ioaddr + HPP_OPTION);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -402,17 +402,9 @@ hpp_mem_block_output(struct net_device *dev, int count,
#ifdef MODULE
#define MAX_HPP_CARDS 4 /* Max number of HPP cards per module */
-static struct net_device dev_hpp[MAX_HPP_CARDS] = {
- {
- "",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, NULL
- },
-};
-
-static int io[MAX_HPP_CARDS] = { 0, };
-static int irq[MAX_HPP_CARDS] = { 0, };
+static struct net_device dev_hpp[MAX_HPP_CARDS];
+static int io[MAX_HPP_CARDS];
+static int irq[MAX_HPP_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HPP_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_HPP_CARDS) "i");
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 26b92b8c6..60b723bfa 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -57,7 +57,7 @@ static unsigned int hppclan_portlist[] __initdata =
#define HP_16BSTOP_PG 0xFF /* Same, for 16 bit cards. */
int hp_probe(struct net_device *dev);
-int hp_probe1(struct net_device *dev, int ioaddr);
+static int hp_probe1(struct net_device *dev, int ioaddr);
static int hp_open(struct net_device *dev);
static int hp_close(struct net_device *dev);
@@ -83,7 +83,9 @@ static char irqmap[16] __initdata= { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0}
int __init hp_probe(struct net_device *dev)
{
int i;
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev->base_addr;
+
+ SET_MODULE_OWNER(dev);
if (base_addr > 0x1ff) /* Check a single specified location. */
return hp_probe1(dev, base_addr);
@@ -97,14 +99,14 @@ int __init hp_probe(struct net_device *dev)
return -ENODEV;
}
-int __init hp_probe1(struct net_device *dev, int ioaddr)
+static int __init hp_probe1(struct net_device *dev, int ioaddr)
{
int i, retval, board_id, wordmode;
const char *name;
static unsigned version_printed;
if (!request_region(ioaddr, HP_IO_EXTENT, dev->name))
- return -ENODEV;
+ return -EBUSY;
/* Check for the HP physical address, 08 00 09 xx xx xx. */
/* This really isn't good enough: we may pick up HP LANCE boards
@@ -206,7 +208,6 @@ static int
hp_open(struct net_device *dev)
{
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -214,7 +215,6 @@ static int
hp_close(struct net_device *dev)
{
ei_close(dev);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -373,17 +373,9 @@ hp_init_card(struct net_device *dev)
#ifdef MODULE
#define MAX_HP_CARDS 4 /* Max number of HP cards per module */
-static struct net_device dev_hp[MAX_HP_CARDS] = {
- {
- "",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, NULL
- },
-};
-
-static int io[MAX_HP_CARDS] = { 0, };
-static int irq[MAX_HP_CARDS] = { 0, };
+static struct net_device dev_hp[MAX_HP_CARDS];
+static int io[MAX_HP_CARDS];
+static int irq[MAX_HP_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HP_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_HP_CARDS) "i");
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 74938f954..6a052e543 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -274,6 +274,17 @@ static struct hp100_pci_id hp100_pci_ids[] = {
#define HP100_PCI_IDS_SIZE (sizeof(hp100_pci_ids)/sizeof(struct hp100_pci_id))
+#if LINUX_VERSION_CODE >= 0x20400
+static struct pci_device_id hp100_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_COMPEX2, PCI_DEVICE_ID_COMPEX2_100VG, PCI_ANY_ID, PCI_ANY_ID, },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, hp100_pci_tbl);
+#endif /* LINUX_VERSION_CODE >= 0x20400 */
+
static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO;
static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX;
static int hp100_mode = 1;
@@ -761,6 +772,7 @@ static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus,
/* Reset statistics (counters) */
hp100_clear_stats( lp, ioaddr );
+ SET_MODULE_OWNER(dev);
ether_setup( dev );
/* If busmaster mode is wanted, a dma-capable memory area is needed for
@@ -1154,8 +1166,6 @@ static int hp100_open( struct net_device *dev )
return -EAGAIN;
}
- MOD_INC_USE_COUNT;
-
dev->trans_start = jiffies;
netif_start_queue(dev);
@@ -1201,7 +1211,6 @@ static int hp100_close( struct net_device *dev )
printk( "hp100: %s: close LSW = 0x%x\n", dev->name, hp100_inw(OPTION_LSW) );
#endif
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c
index 63fdd734b..d80e5c9c0 100644
--- a/drivers/net/hplance.c
+++ b/drivers/net/hplance.c
@@ -116,6 +116,7 @@ static int __init hplance_init(struct net_device *dev, int scode)
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct hplance_private));
#endif
+ SET_MODULE_OWNER(dev);
printk("%s: HP LANCE; select code %d, addr", dev->name, scode);
@@ -212,7 +213,6 @@ static int hplance_open(struct net_device *dev)
/* enable interrupts at board level. */
writeb(LE_IE, &(hpregs->status));
- MOD_INC_USE_COUNT;
return 0;
}
@@ -222,7 +222,6 @@ static int hplance_close(struct net_device *dev)
struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
writeb(0,&(hpregs->status)); /* disable interrupts at boardlevel */
lance_close(dev);
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 8f05bb5a0..5f2052feb 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -87,9 +87,7 @@ History:
#include <asm/bitops.h>
#include <asm/io.h>
-#ifdef MODULE
#include <linux/module.h>
-#endif
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -877,9 +875,6 @@ static int ibmlana_open(struct IBMLANA_NETDEV *dev)
dev->interrupt = 0;
dev->tbusy = 0;
dev->start = 1;
-#endif
-
-#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
@@ -897,7 +892,7 @@ static int ibmlana_close(struct IBMLANA_NETDEV *dev)
free_irq(dev->irq, dev);
dev->irq = 0;
-#ifdef MODULE
+#if (LINUX_VERSION_CODE < 0x02032a)
MOD_DEC_USE_COUNT;
#endif
@@ -1043,6 +1038,10 @@ int ibmlana_probe(struct IBMLANA_NETDEV *dev)
ibmlana_priv *priv;
ibmlana_medium medium;
+#if (LINUX_VERSION_CODE >= 0x02032a)
+ SET_MODULE_OWNER(dev);
+#endif
+
/* can't work without an MCA bus ;-) */
if (MCA_bus == 0)
@@ -1192,14 +1191,11 @@ int ibmlana_probe(struct IBMLANA_NETDEV *dev)
#define DEVMAX 5
-static struct IBMLANA_NETDEV moddevs[DEVMAX] = {
- { init: ibmlana_probe }, { init: ibmlana_probe },
- { init: ibmlana_probe }, { init: ibmlana_probe },
- { init: ibmlana_probe }
-};
-
-int irq = 0;
-int io = 0;
+static struct IBMLANA_NETDEV moddevs[DEVMAX];
+static int irq;
+static int io;
+MODULE_PARM(irq, "i");
+MODULE_PARM(io, "i");
int init_module(void)
{
@@ -1207,7 +1203,9 @@ int init_module(void)
startslot = 0;
for (z = 0; z < DEVMAX; z++) {
- strcpy(moddevs[z].name, " ");
+ moddevs[z].init = ibmlana_probe;
+ moddevs[z].irq = irq;
+ moddevs[z].base_addr = io;
res = register_netdev(moddevs + z);
if (res != 0)
return (z > 0) ? 0 : -EIO;
diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
index 614c5e200..a2e6147cb 100644
--- a/drivers/net/irda/irtty.c
+++ b/drivers/net/irda/irtty.c
@@ -960,7 +960,7 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRTTY_MAGIC, return -1;);
- IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+ IRDA_DEBUG(3, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 245442ff2..a63e865b7 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -708,9 +708,12 @@ static int nsc_ircc_setup(chipio_t *info)
switch_bank(iobase, BANK0);
/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
- switch_bank(iobase, BANK0);
+ switch_bank(iobase, BANK0);
outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
-
+
+ outb(0x03, iobase+LCR); /* 8 bit word length */
+ outb(MCR_SIR, iobase+MCR); /* Start at SIR-mode, also clears LSR*/
+
/* Set FIFO size to 32 */
switch_bank(iobase, BANK2);
outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
@@ -723,7 +726,7 @@ static int nsc_ircc_setup(chipio_t *info)
switch_bank(iobase, BANK6);
outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
outb(0x0a, iobase+1); /* Set MIR pulse width */
- outb(0x0d, iobase+2); /* Set SIR pulse width */
+ outb(0x0d, iobase+2); /* Set SIR pulse width to 1.6us */
outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
@@ -804,8 +807,6 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
dongle_types[dongle_id]);
break;
case 0x04: /* Sharp RY5HD01 */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
- dongle_types[dongle_id]);
break;
case 0x05: /* Reserved, but this is what the Thinkpad reports */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
@@ -892,8 +893,7 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
dongle_types[dongle_id]);
break;
case 0x04: /* Sharp RY5HD01 */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
- dongle_types[dongle_id]);
+ break;
case 0x05: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
index c39defcd3..99093299c 100644
--- a/drivers/net/isa-skeleton.c
+++ b/drivers/net/isa-skeleton.c
@@ -121,8 +121,8 @@ static void net_tx_timeout(struct net_device *dev);
/* Example routines you must write ;->. */
#define tx_done(dev) 1
-extern void hardware_send_packet(short ioaddr, char *buf, int length);
-extern void chipset_init(struct net_device *dev, int startp);
+static void hardware_send_packet(short ioaddr, char *buf, int length);
+static void chipset_init(struct net_device *dev, int startp);
/*
* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -135,7 +135,9 @@ int __init
netcard_probe(struct net_device *dev)
{
int i;
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev->base_addr;
+
+ SET_MODULE_OWNER(dev);
if (base_addr > 0x1ff) /* Check a single specified location. */
return netcard_probe1(dev, base_addr);
@@ -360,8 +362,6 @@ net_open(struct net_device *dev)
*/
netif_start_queue(dev);
- MOD_INC_USE_COUNT;
-
return 0;
}
@@ -574,8 +574,6 @@ net_close(struct net_device *dev)
/* Update the statistics here. */
- MOD_DEC_USE_COUNT;
-
return 0;
}
@@ -589,11 +587,8 @@ static struct net_device_stats *net_get_stats(struct net_device *dev)
struct net_local *lp = (struct net_local *)dev->priv;
short ioaddr = dev->base_addr;
- cli();
/* Update the statistics from the device registers. */
lp->stats.rx_missed_errors = inw(ioaddr+1);
- sti();
-
return &lp->stats;
}
@@ -633,7 +628,7 @@ set_multicast_list(struct net_device *dev)
#ifdef MODULE
-static struct net_device this_device = { init: netcard_probe };
+static struct net_device this_device;
static int io = 0x300;
static int irq;
static int dma;
@@ -652,6 +647,7 @@ int init_module(void)
this_device.irq = irq;
this_device.dma = dma;
this_device.mem_start = mem;
+ this_device.init = netcard_probe;
if ((result = register_netdev(&this_device)) != 0)
return result;
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 6a6745704..435144291 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -37,7 +37,6 @@
static const char *version = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
new file mode 100644
index 000000000..0fe5f5c25
--- /dev/null
+++ b/drivers/net/lasi_82596.c
@@ -0,0 +1,1549 @@
+/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
+ munged into HPPA boxen .
+
+ This driver is based upon 82596.c, original credits are below...
+ but there were too many hoops which HP wants jumped through to
+ keep this code in there in a sane manner.
+
+ 3 primary sources of the mess --
+ 1) hppa needs *lots* of cacheline flushing to keep this kind of
+ MMIO running.
+
+ 2) The 82596 needs to see all of its pointers as their physical
+ address. Thus virt_to_bus/bus_to_virt are *everywhere*.
+
+ 3) The implementation HP is using seems to be significantly pickier
+ about when and how the command and RX units are started. some
+ command ordering was changed.
+
+ Examination of the mach driver leads one to believe that there
+ might be a saner way to pull this off... anyone who feels like a
+ full rewrite can be my guest.
+
+ Split 02/13/2000 Sam Creasey (sammy@oh.verio.com)
+
+ 02/01/2000 Initial modifications for parisc by Helge Deller (deller@gmx.de)
+ 03/02/2000 changes for better/correct(?) cache-flushing (deller)
+*/
+
+/* 82596.c: A generic 82596 ethernet driver for linux. */
+/*
+ Based on Apricot.c
+ Written 1994 by Mark Evans.
+ This driver is for the Apricot 82596 bus-master interface
+
+ Modularised 12/94 Mark Evans
+
+
+ Modified to support the 82596 ethernet chips on 680x0 VME boards.
+ by Richard Hirst <richard@sleepie.demon.co.uk>
+ Renamed to be 82596.c
+
+ 980825: Changed to receive directly in to sk_buffs which are
+ allocated at open() time. Eliminates copy on incoming frames
+ (small ones are still copied). Shared data now held in a
+ non-cached page, so we can run on 68060 in copyback mode.
+
+ TBD:
+ * look at deferring rx frames rather than discarding (as per tulip)
+ * handle tx ring full as per tulip
+ * performace test to tune rx_copybreak
+
+ Most of my modifications relate to the braindead big-endian
+ implementation by Intel. When the i596 is operating in
+ 'big-endian' mode, it thinks a 32 bit value of 0x12345678
+ should be stored as 0x56781234. This is a real pain, when
+ you have linked lists which are shared by the 680x0 and the
+ i596.
+
+ Driver skeleton
+ Written 1993 by Donald Becker.
+ Copyright 1993 United States Government as represented by the Director,
+ National Security Agency. This software may only be used and distributed
+ according to the terms of the GNU Public License as modified by SRC,
+ incorporated herein by reference.
+
+ The author may be reached as becker@super.org or
+ C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+
+ */
+
+static const char *version = "82596.c $Revision: 1.14 $\n";
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/irq.h>
+
+#include <asm/pdc.h>
+#include <asm/gsc.h>
+#include <asm/cache.h>
+
+/* DEBUG flags
+ */
+
+#define DEB_INIT 0x0001
+#define DEB_PROBE 0x0002
+#define DEB_SERIOUS 0x0004
+#define DEB_ERRORS 0x0008
+#define DEB_MULTI 0x0010
+#define DEB_TDR 0x0020
+#define DEB_OPEN 0x0040
+#define DEB_RESET 0x0080
+#define DEB_ADDCMD 0x0100
+#define DEB_STATUS 0x0200
+#define DEB_STARTTX 0x0400
+#define DEB_RXADDR 0x0800
+#define DEB_TXADDR 0x1000
+#define DEB_RXFRAME 0x2000
+#define DEB_INTS 0x4000
+#define DEB_STRUCT 0x8000
+#define DEB_ANY 0xffff
+
+
+#define DEB(x,y) if (i596_debug & (x)) y
+
+
+#define CHECK_WBACK(addr,len) \
+ do { if (!dma_consistent) dma_cache_wback((unsigned long)addr,len); } while (0)
+
+#define CHECK_INV(addr,len) \
+ do { if (!dma_consistent) dma_cache_inv((unsigned long)addr,len); } while(0)
+
+#define CHECK_WBACK_INV(addr,len) \
+ do { if (!dma_consistent) dma_cache_wback_inv((unsigned long)addr,len); } while (0)
+
+
+#define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/
+#define PA_CPU_PORT_L_ACCESS 4
+#define PA_CHANNEL_ATTENTION 8
+
+
+/*
+ * Define various macros for Channel Attention, word swapping etc., dependent
+ * on architecture. MVME and BVME are 680x0 based, otherwise it is Intel.
+ */
+
+#ifdef __BIG_ENDIAN
+#define WSWAPrfd(x) ((struct i596_rfd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPrbd(x) ((struct i596_rbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPiscp(x) ((struct i596_iscp *)(((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPscb(x) ((struct i596_scb *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPcmd(x) ((struct i596_cmd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPtbd(x) ((struct i596_tbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define WSWAPchar(x) ((char *) (((u32)(x)<<16) | ((((u32)(x)))>>16)))
+#define ISCP_BUSY 0x00010000
+#define MACH_IS_APRICOT 0
+#else
+#define WSWAPrfd(x) ((struct i596_rfd *)(x))
+#define WSWAPrbd(x) ((struct i596_rbd *)(x))
+#define WSWAPiscp(x) ((struct i596_iscp *)(x))
+#define WSWAPscb(x) ((struct i596_scb *)(x))
+#define WSWAPcmd(x) ((struct i596_cmd *)(x))
+#define WSWAPtbd(x) ((struct i596_tbd *)(x))
+#define WSWAPchar(x) ((char *)(x))
+#define ISCP_BUSY 0x0001
+#define MACH_IS_APRICOT 1
+#endif
+
+/*
+ * The MPU_PORT command allows direct access to the 82596. With PORT access
+ * the following commands are available (p5-18). The 32-bit port command
+ * must be word-swapped with the most significant word written first.
+ * This only applies to VME boards.
+ */
+#define PORT_RESET 0x00 /* reset 82596 */
+#define PORT_SELFTEST 0x01 /* selftest */
+#define PORT_ALTSCP 0x02 /* alternate SCB address */
+#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */
+
+static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+
+MODULE_AUTHOR("Richard Hirst");
+MODULE_DESCRIPTION("i82596 driver");
+MODULE_PARM(i596_debug, "i");
+
+
+/* Copy frames shorter than rx_copybreak, otherwise pass on up in
+ * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha).
+ */
+static int rx_copybreak = 100;
+
+#define PKT_BUF_SZ 1536
+#define MAX_MC_CNT 64
+
+#define I596_TOTAL_SIZE 17
+
+#define I596_NULL ((void *)0xffffffff)
+
+#define CMD_EOL 0x8000 /* The last command of the list, stop. */
+#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */
+#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */
+
+#define CMD_FLEX 0x0008 /* Enable flexible memory model */
+
+enum commands {
+ CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
+ CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
+};
+
+#define STAT_C 0x8000 /* Set to 0 after execution */
+#define STAT_B 0x4000 /* Command being executed */
+#define STAT_OK 0x2000 /* Command executed ok */
+#define STAT_A 0x1000 /* Command aborted */
+
+#define CUC_START 0x0100
+#define CUC_RESUME 0x0200
+#define CUC_SUSPEND 0x0300
+#define CUC_ABORT 0x0400
+#define RX_START 0x0010
+#define RX_RESUME 0x0020
+#define RX_SUSPEND 0x0030
+#define RX_ABORT 0x0040
+
+#define TX_TIMEOUT 5
+
+#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */
+
+
+struct i596_reg {
+ unsigned short porthi;
+ unsigned short portlo;
+ unsigned long ca;
+};
+
+#define EOF 0x8000
+#define SIZE_MASK 0x3fff
+
+struct i596_tbd {
+ unsigned short size;
+ unsigned short pad;
+ struct i596_tbd *next;
+ char *data;
+ long cache_pad[5]; /* Total 32 bytes... */
+};
+
+/* The command structure has two 'next' pointers; v_next is the address of
+ * the next command as seen by the CPU, b_next is the address of the next
+ * command as seen by the 82596. The b_next pointer, as used by the 82596
+ * always references the status field of the next command, rather than the
+ * v_next field, because the 82596 is unaware of v_next. It may seem more
+ * logical to put v_next at the end of the structure, but we cannot do that
+ * because the 82596 expects other fields to be there, depending on command
+ * type.
+ */
+
+struct i596_cmd {
+ struct i596_cmd *v_next; /* Address from CPUs viewpoint */
+ unsigned short status;
+ unsigned short command;
+ struct i596_cmd *b_next; /* Address from i596 viewpoint */
+};
+
+struct tx_cmd {
+ struct i596_cmd cmd;
+ struct i596_tbd *tbd;
+ unsigned short size;
+ unsigned short pad;
+ struct sk_buff *skb; /* So we can free it after tx */
+ dma_addr_t dma_addr;
+ long cache_pad[1]; /* Total 32 bytes... */
+};
+
+struct tdr_cmd {
+ struct i596_cmd cmd;
+ unsigned short status;
+ unsigned short pad;
+};
+
+struct mc_cmd {
+ struct i596_cmd cmd;
+ short mc_cnt;
+ char mc_addrs[MAX_MC_CNT*6];
+};
+
+struct sa_cmd {
+ struct i596_cmd cmd;
+ char eth_addr[8];
+};
+
+struct cf_cmd {
+ struct i596_cmd cmd;
+ char i596_config[16];
+};
+
+struct i596_rfd {
+ unsigned short stat;
+ unsigned short cmd;
+ struct i596_rfd *b_next; /* Address from i596 viewpoint */
+ struct i596_rbd *rbd;
+ unsigned short count;
+ unsigned short size;
+ struct i596_rfd *v_next; /* Address from CPUs viewpoint */
+ struct i596_rfd *v_prev;
+ long cache_pad[2]; /* Total 32 bytes... */
+};
+
+struct i596_rbd {
+ unsigned short count;
+ unsigned short zero1;
+ struct i596_rbd *b_next;
+ unsigned char *b_data; /* Address from i596 viewpoint */
+ unsigned short size;
+ unsigned short zero2;
+ struct sk_buff *skb;
+ struct i596_rbd *v_next;
+ struct i596_rbd *b_addr; /* This rbd addr from i596 view */
+ unsigned char *v_data; /* Address from CPUs viewpoint */
+ /* Total 32 bytes... */
+};
+
+/* These values as chosen so struct i596_private fits in one page... */
+
+#define TX_RING_SIZE 32
+#define RX_RING_SIZE 16
+
+struct i596_scb {
+ unsigned short status;
+ unsigned short command;
+ struct i596_cmd *cmd;
+ struct i596_rfd *rfd;
+ unsigned long crc_err;
+ unsigned long align_err;
+ unsigned long resource_err;
+ unsigned long over_err;
+ unsigned long rcvdt_err;
+ unsigned long short_err;
+ unsigned short t_on;
+ unsigned short t_off;
+};
+
+struct i596_iscp {
+ unsigned long stat;
+ struct i596_scb *scb;
+};
+
+struct i596_scp {
+ unsigned long sysbus;
+ unsigned long pad;
+ struct i596_iscp *iscp;
+};
+
+struct i596_private {
+ volatile struct i596_scp scp __attribute__((aligned(32)));
+ volatile struct i596_iscp iscp __attribute__((aligned(32)));
+ volatile struct i596_scb scb __attribute__((aligned(32)));
+ struct sa_cmd sa_cmd __attribute__((aligned(32)));
+ struct cf_cmd cf_cmd __attribute__((aligned(32)));
+ struct tdr_cmd tdr_cmd __attribute__((aligned(32)));
+ struct mc_cmd mc_cmd __attribute__((aligned(32)));
+ struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32)));
+ struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32)));
+ struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32)));
+ struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32)));
+ unsigned long stat;
+ int last_restart;
+ struct i596_rfd *rfd_head;
+ struct i596_rbd *rbd_head;
+ struct i596_cmd *cmd_tail;
+ struct i596_cmd *cmd_head;
+ int cmd_backlog;
+ unsigned long last_cmd;
+ struct net_device_stats stats;
+ int next_tx_cmd;
+ int options;
+ spinlock_t lock;
+ dma_addr_t dma_addr;
+};
+
+char init_setup[] =
+{
+ 0x8E, /* length, prefetch on */
+ 0xC8, /* fifo to 8, monitor off */
+ 0x80, /* don't save bad frames */
+ 0x2E, /* No source address insertion, 8 byte preamble */
+ 0x00, /* priority and backoff defaults */
+ 0x60, /* interframe spacing */
+ 0x00, /* slot time LSB */
+ 0xf2, /* slot time and retries */
+ 0x00, /* promiscuous mode */
+ 0x00, /* collision detect */
+ 0x40, /* minimum frame length */
+ 0xff,
+ 0x00,
+ 0x7f /* *multi IA */ };
+
+static int dma_consistent = 1; /* Zero if pci_alloc_consistent() fails */
+
+static int i596_open(struct net_device *dev);
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int i596_close(struct net_device *dev);
+static struct net_device_stats *i596_get_stats(struct net_device *dev);
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
+static void i596_tx_timeout (struct net_device *dev);
+static void print_eth(unsigned char *buf, char *str);
+static void set_multicast_list(struct net_device *dev);
+
+static int rx_ring_size = RX_RING_SIZE;
+static int ticks_limit = 100;
+static int max_cmd_backlog = TX_RING_SIZE-1;
+
+
+static inline void CA(struct net_device *dev)
+{
+ gsc_writel(0, (void*)(dev->base_addr + PA_CHANNEL_ATTENTION));
+}
+
+
+static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+
+ u32 v = (u32) (c) | (u32) (x);
+
+ if (lp->options & OPT_SWAP_PORT)
+ v = ((u32) (v) << 16) | ((u32) (v) >> 16);
+
+ gsc_writel(v & 0xffff, (void*)(dev->base_addr + PA_CPU_PORT_L_ACCESS));
+ udelay(1);
+ gsc_writel(v >> 16, (void*)(dev->base_addr + PA_CPU_PORT_L_ACCESS));
+}
+
+
+static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
+{
+ CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp));
+ while (--delcnt && lp->iscp.stat) {
+ udelay(10);
+ CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp));
+ }
+ if (!delcnt) {
+ printk("%s: %s, iscp.stat %04lx, didn't clear\n",
+ dev->name, str, lp->iscp.stat);
+ return -1;
+ }
+ else
+ return 0;
+}
+
+
+static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
+{
+ CHECK_INV(&(lp->scb), sizeof(struct i596_scb));
+ while (--delcnt && lp->scb.command) {
+ udelay(10);
+ CHECK_INV(&(lp->scb), sizeof(struct i596_scb));
+ }
+ if (!delcnt) {
+ printk("%s: %s, status %4.4x, cmd %4.4x.\n",
+ dev->name, str, lp->scb.status, lp->scb.command);
+ return -1;
+ }
+ else
+ return 0;
+}
+
+
+static void i596_display_data(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ struct i596_cmd *cmd;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+
+ printk("lp and scp at %p, .sysbus = %08lx, .iscp = %p\n",
+ &lp->scp, lp->scp.sysbus, lp->scp.iscp);
+ printk("iscp at %p, iscp.stat = %08lx, .scb = %p\n",
+ &lp->iscp, lp->iscp.stat, lp->iscp.scb);
+ printk("scb at %p, scb.status = %04x, .command = %04x,"
+ " .cmd = %p, .rfd = %p\n",
+ &lp->scb, lp->scb.status, lp->scb.command,
+ lp->scb.cmd, lp->scb.rfd);
+ printk(" errors: crc %lx, align %lx, resource %lx,"
+ " over %lx, rcvdt %lx, short %lx\n",
+ lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err,
+ lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err);
+ cmd = lp->cmd_head;
+ while (cmd != I596_NULL) {
+ printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %p\n",
+ cmd, cmd->status, cmd->command, cmd->b_next);
+ cmd = cmd->v_next;
+ }
+ rfd = lp->rfd_head;
+ printk("rfd_head = %p\n", rfd);
+ do {
+ printk (" %p .stat %04x, .cmd %04x, b_next %p, rbd %p,"
+ " count %04x\n",
+ rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd,
+ rfd->count);
+ rfd = rfd->v_next;
+ } while (rfd != lp->rfd_head);
+ rbd = lp->rbd_head;
+ printk("rbd_head = %p\n", rbd);
+ do {
+ printk(" %p .count %04x, b_next %p, b_data %p, size %04x\n",
+ rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
+ rbd = rbd->v_next;
+ } while (rbd != lp->rbd_head);
+ CHECK_INV(lp, sizeof(struct i596_private));
+}
+
+
+#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
+static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
+
+ pcc2[0x28] = 1;
+ pcc2[0x2b] = 0x1d;
+ printk("%s: Error interrupt\n", dev->name);
+ i596_display_data(dev);
+}
+#endif
+
+#define virt_to_dma(lp,v) ((char *)(v)-(char *)(lp)+(char *)((lp)->dma_addr))
+
+static inline void init_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *)dev->priv;
+ int i;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+
+ /* First build the Receive Buffer Descriptor List */
+
+ for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
+ dma_addr_t dma_addr;
+ struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4);
+
+ if (skb == NULL)
+ panic("82596: alloc_skb() failed");
+ skb_reserve(skb, 2);
+ dma_addr = pci_map_single(NULL, skb->tail,PKT_BUF_SZ,
+ PCI_DMA_FROMDEVICE);
+ skb->dev = dev;
+ rbd->v_next = rbd+1;
+ rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1));
+ rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd));
+ rbd->skb = skb;
+ rbd->v_data = skb->tail;
+ rbd->b_data = WSWAPchar(dma_addr);
+ rbd->size = PKT_BUF_SZ;
+ }
+ lp->rbd_head = lp->rbds;
+ rbd = lp->rbds + rx_ring_size - 1;
+ rbd->v_next = lp->rbds;
+ rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds));
+
+ /* Now build the Receive Frame Descriptor List */
+
+ for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
+ rfd->rbd = I596_NULL;
+ rfd->v_next = rfd+1;
+ rfd->v_prev = rfd-1;
+ rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1));
+ rfd->cmd = CMD_FLEX;
+ }
+ lp->rfd_head = lp->rfds;
+ lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
+ rfd = lp->rfds;
+ rfd->rbd = lp->rbd_head;
+ rfd->v_prev = lp->rfds + rx_ring_size - 1;
+ rfd = lp->rfds + rx_ring_size - 1;
+ rfd->v_next = lp->rfds;
+ rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds));
+ rfd->cmd = CMD_EOL|CMD_FLEX;
+
+ CHECK_WBACK_INV(lp, sizeof(struct i596_private));
+}
+
+static inline void remove_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *)dev->priv;
+ struct i596_rbd *rbd;
+ int i;
+
+ for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
+ if (rbd->skb == NULL)
+ break;
+ pci_unmap_single(NULL,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(rbd->skb);
+ }
+}
+
+
+static void rebuild_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ int i;
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+
+ for (i = 0; i < rx_ring_size; i++) {
+ lp->rfds[i].rbd = I596_NULL;
+ lp->rfds[i].cmd = CMD_FLEX;
+ }
+ lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
+ lp->rfd_head = lp->rfds;
+ lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
+ lp->rbd_head = lp->rbds;
+ lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds));
+
+ CHECK_WBACK_INV(lp, sizeof(struct i596_private));
+}
+
+
+static int init_i596_mem(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ unsigned long flags;
+
+ disable_irq(dev->irq); /* disable IRQs from LAN */
+ DEB(DEB_INIT,
+ printk("RESET 82596 port: %08lX (with IRQ%d disabled)\n",
+ dev->base_addr + PA_I82596_RESET,
+ dev->irq));
+
+ gsc_writel(0, (void*)(dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
+ udelay(100); /* Wait 100us - seems to help */
+
+ /* change the scp address */
+
+ lp->last_cmd = jiffies;
+
+
+ lp->scp.sysbus = 0x0000006c;
+ lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp)));
+ lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb)));
+ lp->iscp.stat = ISCP_BUSY;
+ lp->cmd_backlog = 0;
+
+ lp->cmd_head = lp->scb.cmd = I596_NULL;
+
+ DEB(DEB_INIT,printk("%s: starting i82596.\n", dev->name));
+
+ CHECK_WBACK(&(lp->scp), sizeof(struct i596_scp));
+ CHECK_WBACK(&(lp->iscp), sizeof(struct i596_iscp));
+
+ MPU_PORT(dev, PORT_ALTSCP, (void *)virt_to_dma(lp,&lp->scp));
+
+ CA(dev);
+
+ if (wait_istat(dev,lp,1000,"initialization timed out"))
+ goto failed;
+ DEB(DEB_INIT,printk("%s: i82596 initialization successful\n", dev->name));
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+ rebuild_rx_bufs(dev);
+
+ lp->scb.command = 0;
+ CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+
+ enable_irq(dev->irq); /* enable IRQs from LAN */
+
+ DEB(DEB_INIT,printk("%s: queuing CmdConfigure\n", dev->name));
+ memcpy(lp->cf_cmd.i596_config, init_setup, 14);
+ lp->cf_cmd.cmd.command = CmdConfigure;
+ CHECK_WBACK(&(lp->cf_cmd), sizeof(struct cf_cmd));
+ i596_add_cmd(dev, &lp->cf_cmd.cmd);
+
+ DEB(DEB_INIT,printk("%s: queuing CmdSASetup\n", dev->name));
+ memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
+ lp->sa_cmd.cmd.command = CmdSASetup;
+ CHECK_WBACK(&(lp->sa_cmd), sizeof(struct sa_cmd));
+ i596_add_cmd(dev, &lp->sa_cmd.cmd);
+
+ DEB(DEB_INIT,printk("%s: queuing CmdTDR\n", dev->name));
+ lp->tdr_cmd.cmd.command = CmdTDR;
+ CHECK_WBACK(&(lp->tdr_cmd), sizeof(struct tdr_cmd));
+ i596_add_cmd(dev, &lp->tdr_cmd.cmd);
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ if (wait_cmd(dev,lp,1000,"timed out waiting to issue RX_START")) {
+ spin_unlock_irqrestore (&lp->lock, flags);
+ goto failed;
+ }
+ DEB(DEB_INIT,printk("%s: Issuing RX_START\n", dev->name));
+ lp->scb.command = RX_START;
+ lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
+ CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+
+ CA(dev);
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ if (wait_cmd(dev,lp,1000,"RX_START not processed"))
+ goto failed;
+ DEB(DEB_INIT,printk("%s: Receive unit started OK\n", dev->name));
+
+ return 0;
+
+failed:
+ printk("%s: Failed to initialise 82596\n", dev->name);
+ MPU_PORT(dev, PORT_RESET, 0);
+ return -1;
+}
+
+
+static inline int i596_rx(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *)dev->priv;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+ int frames = 0;
+
+ DEB(DEB_RXFRAME,printk ("i596_rx(), rfd_head %p, rbd_head %p\n",
+ lp->rfd_head, lp->rbd_head));
+
+
+ rfd = lp->rfd_head; /* Ref next frame to check */
+
+ CHECK_INV(rfd, sizeof(struct i596_rfd));
+ while ((rfd->stat) & STAT_C) { /* Loop while complete frames */
+ if (rfd->rbd == I596_NULL)
+ rbd = I596_NULL;
+ else if (rfd->rbd == lp->rbd_head->b_addr) {
+ rbd = lp->rbd_head;
+ CHECK_INV(rbd, sizeof(struct i596_rbd));
+ }
+ else {
+ printk("%s: rbd chain broken!\n", dev->name);
+ /* XXX Now what? */
+ rbd = I596_NULL;
+ }
+ DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %p, rfd.stat %04x\n",
+ rfd, rfd->rbd, rfd->stat));
+
+ if (rbd != I596_NULL && ((rfd->stat) & STAT_OK)) {
+ /* a good frame */
+ int pkt_len = rbd->count & 0x3fff;
+ struct sk_buff *skb = rbd->skb;
+ int rx_in_place = 0;
+
+ DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));
+ frames++;
+
+ /* Check if the packet is long enough to just accept
+ * without copying to a properly sized skbuff.
+ */
+
+ if (pkt_len > rx_copybreak) {
+ struct sk_buff *newskb;
+ dma_addr_t dma_addr;
+
+ pci_unmap_single(NULL,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ /* Get fresh skbuff to replace filled one. */
+ newskb = dev_alloc_skb(PKT_BUF_SZ + 4);
+ if (newskb == NULL) {
+ skb = NULL; /* drop pkt */
+ goto memory_squeeze;
+ }
+ skb_reserve(newskb, 2);
+
+ /* Pass up the skb already on the Rx ring. */
+ skb_put(skb, pkt_len);
+ rx_in_place = 1;
+ rbd->skb = newskb;
+ newskb->dev = dev;
+ dma_addr = pci_map_single(NULL, newskb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ rbd->v_data = newskb->tail;
+ rbd->b_data = WSWAPchar(dma_addr);
+ CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd));
+ }
+ else
+ skb = dev_alloc_skb(pkt_len + 2);
+memory_squeeze:
+ if (skb == NULL) {
+ /* XXX tulip.c can defer packets here!! */
+ printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
+ lp->stats.rx_dropped++;
+ }
+ else {
+ skb->dev = dev;
+ if (!rx_in_place) {
+ /* 16 byte align the data fields */
+ pci_dma_sync_single(NULL, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);
+ }
+ skb->len = pkt_len;
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes+=pkt_len;
+ }
+ }
+ else {
+ DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n",
+ dev->name, rfd->stat));
+ lp->stats.rx_errors++;
+ if ((rfd->stat) & 0x0001)
+ lp->stats.collisions++;
+ if ((rfd->stat) & 0x0080)
+ lp->stats.rx_length_errors++;
+ if ((rfd->stat) & 0x0100)
+ lp->stats.rx_over_errors++;
+ if ((rfd->stat) & 0x0200)
+ lp->stats.rx_fifo_errors++;
+ if ((rfd->stat) & 0x0400)
+ lp->stats.rx_frame_errors++;
+ if ((rfd->stat) & 0x0800)
+ lp->stats.rx_crc_errors++;
+ if ((rfd->stat) & 0x1000)
+ lp->stats.rx_length_errors++;
+ }
+
+ /* Clear the buffer descriptor count and EOF + F flags */
+
+ if (rbd != I596_NULL && (rbd->count & 0x4000)) {
+ rbd->count = 0;
+ lp->rbd_head = rbd->v_next;
+ CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd));
+ }
+
+ /* Tidy the frame descriptor, marking it as end of list */
+
+ rfd->rbd = I596_NULL;
+ rfd->stat = 0;
+ rfd->cmd = CMD_EOL|CMD_FLEX;
+ rfd->count = 0;
+
+ /* Remove end-of-list from old end descriptor */
+
+ rfd->v_prev->cmd = CMD_FLEX;
+
+ /* Update record of next frame descriptor to process */
+
+ lp->scb.rfd = rfd->b_next;
+ lp->rfd_head = rfd->v_next;
+ CHECK_WBACK_INV(rfd->v_prev, sizeof(struct i596_rfd));
+ CHECK_WBACK_INV(rfd, sizeof(struct i596_rfd));
+ rfd = lp->rfd_head;
+ CHECK_INV(rfd, sizeof(struct i596_rfd));
+ }
+
+ DEB(DEB_RXFRAME,printk ("frames %d\n", frames));
+
+ return 0;
+}
+
+
+static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+{
+ struct i596_cmd *ptr;
+
+ while (lp->cmd_head != I596_NULL) {
+ ptr = lp->cmd_head;
+ lp->cmd_head = ptr->v_next;
+ lp->cmd_backlog--;
+
+ switch ((ptr->command) & 0x7) {
+ case CmdTx:
+ {
+ struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+ struct sk_buff *skb = tx_cmd->skb;
+ pci_unmap_single(NULL, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE);
+
+ dev_kfree_skb(skb);
+
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+
+ ptr->v_next = ptr->b_next = I596_NULL;
+ tx_cmd->cmd.command = 0; /* Mark as free */
+ break;
+ }
+ default:
+ ptr->v_next = ptr->b_next = I596_NULL;
+ }
+ CHECK_WBACK_INV(ptr, sizeof(struct i596_cmd));
+ }
+
+ wait_cmd(dev,lp,100,"i596_cleanup_cmd timed out");
+ lp->scb.cmd = I596_NULL;
+ CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+}
+
+
+static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr)
+{
+ unsigned long flags;
+
+ DEB(DEB_RESET,printk("i596_reset\n"));
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ wait_cmd(dev,lp,100,"i596_reset timed out");
+
+ netif_stop_queue(dev);
+
+ /* FIXME: this command might cause an lpmc */
+ lp->scb.command = CUC_ABORT | RX_ABORT;
+ CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+ CA(dev);
+
+ /* wait for shutdown */
+ wait_cmd(dev,lp,1000,"i596_reset 2 timed out");
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ i596_cleanup_cmd(dev,lp);
+ i596_rx(dev);
+
+ netif_start_queue(dev);
+ init_i596_mem(dev);
+}
+
+
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ int ioaddr = dev->base_addr;
+ unsigned long flags;
+
+ DEB(DEB_ADDCMD,printk("i596_add_cmd cmd_head %p\n", lp->cmd_head));
+
+ cmd->status = 0;
+ cmd->command |= (CMD_EOL | CMD_INTR);
+ cmd->v_next = cmd->b_next = I596_NULL;
+ CHECK_WBACK(cmd, sizeof(struct i596_cmd));
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ if (lp->cmd_head != I596_NULL) {
+ lp->cmd_tail->v_next = cmd;
+ lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status));
+ CHECK_WBACK(lp->cmd_tail, sizeof(struct i596_cmd));
+ } else {
+ lp->cmd_head = cmd;
+ wait_cmd(dev,lp,100,"i596_add_cmd timed out");
+ lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status));
+ lp->scb.command = CUC_START;
+ CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb));
+ CA(dev);
+ }
+ lp->cmd_tail = cmd;
+ lp->cmd_backlog++;
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ if (lp->cmd_backlog > max_cmd_backlog) {
+ unsigned long tickssofar = jiffies - lp->last_cmd;
+
+ if (tickssofar < ticks_limit)
+ return;
+
+ printk("%s: command unit timed out, status resetting.\n", dev->name);
+#if 1
+ i596_reset(dev, lp, ioaddr);
+#endif
+ }
+}
+
+#if 0
+/* this function makes a perfectly adequate probe... but we have a
+ device list */
+static int i596_test(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ volatile int *tint;
+ u32 data;
+
+ tint = (volatile int *)(&(lp->scp));
+ data = virt_to_dma(lp,tint);
+
+ tint[1] = -1;
+ CHECK_WBACK(tint,PAGE_SIZE);
+
+ MPU_PORT(dev, 1, data);
+
+ for(data = 1000000; data; data--) {
+ CHECK_INV(tint,PAGE_SIZE);
+ if(tint[1] != -1)
+ break;
+
+ }
+
+ printk("i596_test result %d\n", tint[1]);
+
+}
+#endif
+
+
+static int i596_open(struct net_device *dev)
+{
+ int res = 0;
+
+ DEB(DEB_OPEN,printk("%s: i596_open() irq %d.\n", dev->name, dev->irq));
+
+ if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
+ printk("%s: IRQ %d not free\n", dev->name, dev->irq);
+ return -EAGAIN;
+ }
+
+ request_region(dev->base_addr, 12, dev->name);
+
+ init_rx_bufs(dev);
+
+ netif_start_queue(dev);
+
+ MOD_INC_USE_COUNT;
+
+ /* Initialize the 82596 memory */
+ if (init_i596_mem(dev)) {
+ res = -EAGAIN;
+ free_irq(dev->irq, dev);
+ }
+
+ return res;
+}
+
+static void i596_tx_timeout (struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ int ioaddr = dev->base_addr;
+
+ /* Transmitter timeout, serious problems. */
+ DEB(DEB_ERRORS,printk("%s: transmit timed out, status resetting.\n",
+ dev->name));
+
+ lp->stats.tx_errors++;
+
+ /* Try to restart the adaptor */
+ if (lp->last_restart == lp->stats.tx_packets) {
+ DEB(DEB_ERRORS,printk ("Resetting board.\n"));
+ /* Shutdown and restart */
+ i596_reset (dev, lp, ioaddr);
+ } else {
+ /* Issue a channel attention signal */
+ DEB(DEB_ERRORS,printk ("Kicking board.\n"));
+ lp->scb.command = CUC_START | RX_START;
+ CHECK_WBACK_INV(&(lp->scb), sizeof(struct i596_scb));
+ CA (dev);
+ lp->last_restart = lp->stats.tx_packets;
+ }
+
+ dev->trans_start = jiffies;
+ netif_wake_queue (dev);
+}
+
+
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ struct tx_cmd *tx_cmd;
+ struct i596_tbd *tbd;
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ dev->trans_start = jiffies;
+
+ DEB(DEB_STARTTX,printk("%s: i596_start_xmit(%x,%x) called\n", dev->name,
+ skb->len, (unsigned int)skb->data));
+
+ netif_stop_queue(dev);
+
+ tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
+ tbd = lp->tbds + lp->next_tx_cmd;
+
+ if (tx_cmd->cmd.command) {
+ DEB(DEB_ERRORS,printk ("%s: xmit ring full, dropping packet.\n",
+ dev->name));
+ lp->stats.tx_dropped++;
+
+ dev_kfree_skb(skb);
+ } else {
+ if (++lp->next_tx_cmd == TX_RING_SIZE)
+ lp->next_tx_cmd = 0;
+ tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd));
+ tbd->next = I596_NULL;
+
+ tx_cmd->cmd.command = CMD_FLEX | CmdTx;
+ tx_cmd->skb = skb;
+
+ tx_cmd->pad = 0;
+ tx_cmd->size = 0;
+ tbd->pad = 0;
+ tbd->size = EOF | length;
+
+ tx_cmd->dma_addr = pci_map_single(NULL, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ tbd->data = WSWAPchar(tx_cmd->dma_addr);
+
+ DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
+ CHECK_WBACK_INV(tx_cmd, sizeof(struct tx_cmd));
+ CHECK_WBACK_INV(tbd, sizeof(struct i596_tbd));
+ i596_add_cmd(dev, &tx_cmd->cmd);
+
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += length;
+ }
+
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static void print_eth(unsigned char *add, char *str)
+{
+ int i;
+
+ printk("i596 0x%p, ", add);
+ for (i = 0; i < 6; i++)
+ printk(" %02X", add[i + 6]);
+ printk(" -->");
+ for (i = 0; i < 6; i++)
+ printk(" %02X", add[i]);
+ printk(" %02X%02X, %s\n", add[12], add[13], str);
+}
+
+
+#define LAN_PROM_ADDR 0xF0810000
+
+static int __init i82596_probe(struct net_device *dev, int options)
+{
+ int i;
+ struct i596_private *lp;
+ char eth_addr[6];
+ dma_addr_t dma_addr;
+
+ /* This lot is ensure things have been cache line aligned. */
+ if (sizeof(struct i596_rfd) != 32) {
+ printk("82596: sizeof(struct i596_rfd) = %d\n",
+ sizeof(struct i596_rfd));
+ return -ENODEV;
+ }
+ if (sizeof(struct i596_rbd) != 32) {
+ printk("82596: sizeof(struct i596_rbd) = %d\n",
+ sizeof(struct i596_rbd));
+ return -ENODEV;
+ }
+ if (sizeof(struct tx_cmd) != 32) {
+ printk("82596: sizeof(struct tx_cmd) = %d\n",
+ sizeof(struct tx_cmd));
+ return -ENODEV;
+ }
+ if (sizeof(struct i596_tbd) != 32) {
+ printk("82596: sizeof(struct i596_tbd) = %d\n",
+ sizeof(struct i596_tbd));
+ return -ENODEV;
+ }
+ if (sizeof(struct i596_private) > 4096) {
+ printk("82596: sizeof(struct i596_private) = %d\n",
+ sizeof(struct i596_private));
+ return -ENODEV;
+ }
+
+ /* FIXME:
+ Currently this works only, if set-up from lasi.c.
+ This should be changed to use probing too !
+ */
+
+ if (!dev->base_addr || !dev->irq)
+ return -ENODEV;
+
+ if (!pdc_lan_station_id( (char*)&eth_addr, (void*)dev->base_addr)) {
+ for(i=0;i<6;i++)
+ eth_addr[i] = gsc_readb(LAN_PROM_ADDR+i);
+ printk("82596.c: MAC of HP700 LAN blindely read from the prom!\n");
+ }
+
+ dev->mem_start = (int)pci_alloc_consistent( NULL,
+ sizeof(struct i596_private), &dma_addr);
+ if (!dev->mem_start) {
+ printk("%s: Couldn't get consistent shared memory\n", dev->name);
+ dma_consistent = 0;
+ dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0);
+ if (!dev->mem_start) {
+ printk("%s: Couldn't get shared memory\n", dev->name);
+#ifdef ENABLE_APRICOT
+ release_region(dev->base_addr, I596_TOTAL_SIZE);
+#endif
+ return -ENOMEM;
+ }
+ dma_addr = virt_to_bus(dev->mem_start);
+ }
+
+ ether_setup(dev);
+ DEB(DEB_PROBE,printk("%s: 82596 at %#3lx,", dev->name, dev->base_addr));
+
+ for (i = 0; i < 6; i++)
+ DEB(DEB_PROBE,printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]));
+
+ DEB(DEB_PROBE,printk(" IRQ %d.\n", dev->irq));
+
+ DEB(DEB_PROBE,printk(version));
+
+ /* The 82596-specific entries in the device structure. */
+ dev->open = i596_open;
+ dev->stop = i596_close;
+ dev->hard_start_xmit = i596_start_xmit;
+ dev->get_stats = i596_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->tx_timeout = i596_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ dev->priv = (void *)(dev->mem_start);
+
+ lp = (struct i596_private *) dev->priv;
+ DEB(DEB_INIT,printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n",
+ dev->name, (unsigned long)lp,
+ sizeof(struct i596_private), (unsigned long)&lp->scb));
+ memset((void *) lp, 0, sizeof(struct i596_private));
+
+#if 0
+ kernel_set_cachemode((void *)(dev->mem_start), 4096, IOMAP_NOCACHE_SER);
+#endif
+ lp->options = options;
+ lp->scb.command = 0;
+ lp->scb.cmd = I596_NULL;
+ lp->scb.rfd = I596_NULL;
+ lp->lock = SPIN_LOCK_UNLOCKED;
+ lp->dma_addr = dma_addr;
+
+ CHECK_WBACK_INV(dev->mem_start, sizeof(struct i596_private));
+
+ return 0;
+}
+
+
+int __init lasi_i82596_probe(struct net_device *dev)
+{
+ return i82596_probe(dev, 0);
+}
+
+
+int __init asp_i82596_probe(struct net_device *dev)
+{
+ return i82596_probe(dev, OPT_SWAP_PORT);
+}
+
+
+static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct i596_private *lp;
+ unsigned short status, ack_cmd = 0;
+
+ if (dev == NULL) {
+ printk("i596_interrupt(): irq %d for unknown device.\n", irq);
+ return;
+ }
+
+ lp = (struct i596_private *) dev->priv;
+
+ spin_lock (&lp->lock);
+
+ wait_cmd(dev,lp,100,"i596 interrupt, timeout");
+ status = lp->scb.status;
+
+ DEB(DEB_INTS,printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n",
+ dev->name, irq, status));
+
+ ack_cmd = status & 0xf000;
+
+ if (!ack_cmd) {
+ DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name));
+ spin_unlock (&lp->lock);
+ return;
+ }
+
+ if ((status & 0x8000) || (status & 0x2000)) {
+ struct i596_cmd *ptr;
+
+ if ((status & 0x8000))
+ DEB(DEB_INTS,printk("%s: i596 interrupt completed command.\n", dev->name));
+ if ((status & 0x2000))
+ DEB(DEB_INTS,printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
+
+ while (lp->cmd_head != I596_NULL) {
+ CHECK_INV(lp->cmd_head, sizeof(struct i596_cmd));
+ if (!(lp->cmd_head->status & STAT_C))
+ break;
+
+ ptr = lp->cmd_head;
+
+ DEB(DEB_STATUS,printk("cmd_head->status = %04x, ->command = %04x\n",
+ lp->cmd_head->status, lp->cmd_head->command));
+ lp->cmd_head = ptr->v_next;
+ lp->cmd_backlog--;
+
+ switch ((ptr->command) & 0x7) {
+ case CmdTx:
+ {
+ struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+ struct sk_buff *skb = tx_cmd->skb;
+
+ if ((ptr->status) & STAT_OK) {
+ DEB(DEB_TXADDR,print_eth(skb->data, "tx-done"));
+ } else {
+ lp->stats.tx_errors++;
+ if ((ptr->status) & 0x0020)
+ lp->stats.collisions++;
+ if (!((ptr->status) & 0x0040))
+ lp->stats.tx_heartbeat_errors++;
+ if ((ptr->status) & 0x0400)
+ lp->stats.tx_carrier_errors++;
+ if ((ptr->status) & 0x0800)
+ lp->stats.collisions++;
+ if ((ptr->status) & 0x1000)
+ lp->stats.tx_aborted_errors++;
+ }
+ pci_unmap_single(NULL, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(skb);
+
+ tx_cmd->cmd.command = 0; /* Mark free */
+ break;
+ }
+ case CmdTDR:
+ {
+ unsigned short status = ((struct tdr_cmd *)ptr)->status;
+
+ if (status & 0x8000) {
+ DEB(DEB_ANY,printk("%s: link ok.\n", dev->name));
+ } else {
+ if (status & 0x4000)
+ printk("%s: Transceiver problem.\n", dev->name);
+ if (status & 0x2000)
+ printk("%s: Termination problem.\n", dev->name);
+ if (status & 0x1000)
+ printk("%s: Short circuit.\n", dev->name);
+
+ DEB(DEB_TDR,printk("%s: Time %d.\n", dev->name, status & 0x07ff));
+ }
+ break;
+ }
+ case CmdConfigure:
+ /* Zap command so set_multicast_list() knows it is free */
+ ptr->command = 0;
+ break;
+ }
+ ptr->v_next = ptr->b_next = I596_NULL;
+ CHECK_WBACK(ptr, sizeof(struct i596_cmd));
+ lp->last_cmd = jiffies;
+ }
+
+ /* This mess is arranging that only the last of any outstanding
+ * commands has the interrupt bit set. Should probably really
+ * only add to the cmd queue when the CU is stopped.
+ */
+ ptr = lp->cmd_head;
+ while ((ptr != I596_NULL) && (ptr != lp->cmd_tail)) {
+ struct i596_cmd *prev = ptr;
+
+ ptr->command &= 0x1fff;
+ ptr = ptr->v_next;
+ CHECK_WBACK_INV(prev, sizeof(struct i596_cmd));
+ }
+
+ if ((lp->cmd_head != I596_NULL))
+ ack_cmd |= CUC_START;
+ lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status));
+ CHECK_WBACK_INV(&lp->scb, sizeof(struct i596_scb));
+ }
+ if ((status & 0x1000) || (status & 0x4000)) {
+ if ((status & 0x4000))
+ DEB(DEB_INTS,printk("%s: i596 interrupt received a frame.\n", dev->name));
+ i596_rx(dev);
+ /* Only RX_START if stopped - RGH 07-07-96 */
+ if (status & 0x1000) {
+ if (netif_running(dev)) {
+ DEB(DEB_ERRORS,printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status));
+ ack_cmd |= RX_START;
+ lp->stats.rx_errors++;
+ lp->stats.rx_fifo_errors++;
+ rebuild_rx_bufs(dev);
+ }
+ }
+ }
+ wait_cmd(dev,lp,100,"i596 interrupt, timeout");
+ lp->scb.command = ack_cmd;
+ CHECK_WBACK(&lp->scb, sizeof(struct i596_scb));
+
+ /* DANGER: I suspect that some kind of interrupt
+ acknowledgement aside from acking the 82596 might be needed
+ here... but it's running acceptably without */
+
+ CA(dev);
+
+ wait_cmd(dev,lp,100,"i596 interrupt, exit timeout");
+ DEB(DEB_INTS,printk("%s: exiting interrupt.\n", dev->name));
+
+ spin_unlock (&lp->lock);
+ return;
+}
+
+static int i596_close(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+
+ DEB(DEB_INIT,printk("%s: Shutting down ethercard, status was %4.4x.\n",
+ dev->name, lp->scb.status));
+
+ save_flags(flags);
+ cli();
+
+ wait_cmd(dev,lp,100,"close1 timed out");
+ lp->scb.command = CUC_ABORT | RX_ABORT;
+ CHECK_WBACK(&lp->scb, sizeof(struct i596_scb));
+
+ CA(dev);
+
+ wait_cmd(dev,lp,100,"close2 timed out");
+ restore_flags(flags);
+ DEB(DEB_STRUCT,i596_display_data(dev));
+ i596_cleanup_cmd(dev,lp);
+
+ disable_irq(dev->irq);
+
+ free_irq(dev->irq, dev);
+ remove_rx_bufs(dev);
+
+ release_region(dev->base_addr, 12);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+static struct net_device_stats *
+ i596_get_stats(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+
+ return &lp->stats;
+}
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
+ int config = 0, cnt;
+
+ DEB(DEB_MULTI,printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
+
+ if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) {
+ lp->cf_cmd.i596_config[8] |= 0x01;
+ config = 1;
+ }
+ if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) {
+ lp->cf_cmd.i596_config[8] &= ~0x01;
+ config = 1;
+ }
+ if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) {
+ lp->cf_cmd.i596_config[11] &= ~0x20;
+ config = 1;
+ }
+ if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) {
+ lp->cf_cmd.i596_config[11] |= 0x20;
+ config = 1;
+ }
+ if (config) {
+ if (lp->cf_cmd.cmd.command)
+ printk("%s: config change request already queued\n",
+ dev->name);
+ else {
+ lp->cf_cmd.cmd.command = CmdConfigure;
+ CHECK_WBACK_INV(&lp->cf_cmd, sizeof(struct cf_cmd));
+ i596_add_cmd(dev, &lp->cf_cmd.cmd);
+ }
+ }
+
+ cnt = dev->mc_count;
+ if (cnt > MAX_MC_CNT)
+ {
+ cnt = MAX_MC_CNT;
+ printk("%s: Only %d multicast addresses supported",
+ dev->name, cnt);
+ }
+
+ if (dev->mc_count > 0) {
+ struct dev_mc_list *dmi;
+ unsigned char *cp;
+ struct mc_cmd *cmd;
+
+ cmd = &lp->mc_cmd;
+ cmd->cmd.command = CmdMulticastList;
+ cmd->mc_cnt = dev->mc_count * 6;
+ cp = cmd->mc_addrs;
+ for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
+ memcpy(cp, dmi->dmi_addr, 6);
+ if (i596_debug > 1)
+ DEB(DEB_MULTI,printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5]));
+ }
+ CHECK_WBACK_INV(&lp->mc_cmd, sizeof(struct mc_cmd));
+ i596_add_cmd(dev, &cmd->cmd);
+ }
+}
+
+#ifdef HAVE_DEVLIST
+static unsigned int i596_portlist[] __initdata =
+{0x300, 0};
+struct netdev_entry i596_drv =
+{"lasi_i82596", lasi_i82596_probe, I596_TOTAL_SIZE, i596_portlist};
+#endif
+
+#ifdef MODULE
+static char devicename[9] =
+{0,};
+static struct net_device dev_82596 =
+{
+ devicename, /* device name inserted by drivers/net/net_init.c */
+ 0, 0, 0, 0,
+ 0, 0, /* base, irq */
+ 0, 0, 0, NULL, lasi_i82596_probe};
+
+
+MODULE_PARM(debug, "i");
+static int debug = -1;
+
+int init_module(void)
+{
+ if (debug >= 0)
+ i596_debug = debug;
+ if (register_netdev(&dev_82596) != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ unregister_netdev(&dev_82596);
+ lp = (struct i596_private *) dev_82596.priv;
+
+ if (dma_consistent)
+ pci_free_consistent( NULL, sizeof( struct i596_private),
+ dev_82596.mem_start, lp->dma_addr);
+ else
+ free_page ((u32)(dev_82596.mem_start));
+
+ dev_82596.priv = NULL;
+}
+
+#endif /* MODULE */
+
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index d524b5ef6..59ce4f9b7 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -50,7 +50,7 @@ static const char *version =
#include "8390.h"
int lne390_probe(struct net_device *dev);
-int lne390_probe1(struct net_device *dev, int ioaddr);
+static int lne390_probe1(struct net_device *dev, int ioaddr);
static int lne390_open(struct net_device *dev);
static int lne390_close(struct net_device *dev);
@@ -108,8 +108,10 @@ int __init lne390_probe(struct net_device *dev)
unsigned short ioaddr = dev->base_addr;
int ret;
+ SET_MODULE_OWNER(dev);
+
if (ioaddr > 0x1ff) { /* Check a single specified location. */
- if (!request_region(ioaddr, LNE390_IO_EXTENT, "lne390"))
+ if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name))
return -EBUSY;
ret = lne390_probe1(dev, ioaddr);
if (ret)
@@ -128,7 +130,7 @@ int __init lne390_probe(struct net_device *dev)
/* EISA spec allows for up to 16 slots, but 8 is typical. */
for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
- if (!request_region(ioaddr, LNE390_IO_EXTENT, "lne390"))
+ if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name))
continue;
if (lne390_probe1(dev, ioaddr) == 0)
return 0;
@@ -138,7 +140,7 @@ int __init lne390_probe(struct net_device *dev)
return -ENODEV;
}
-int __init lne390_probe1(struct net_device *dev, int ioaddr)
+static int __init lne390_probe1(struct net_device *dev, int ioaddr)
{
int i, revision, ret;
unsigned long eisa_id;
@@ -195,11 +197,11 @@ int __init lne390_probe1(struct net_device *dev, int ioaddr)
}
printk(" IRQ %d,", dev->irq);
- if (request_irq(dev->irq, ei_interrupt, 0, "lne390", dev)) {
+ if ((ret = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) {
printk (" unable to get IRQ %d.\n", dev->irq);
kfree(dev->priv);
dev->priv = NULL;
- return -EAGAIN;
+ return ret;
}
if (dev->mem_start == 0) {
@@ -356,7 +358,6 @@ static void lne390_block_output(struct net_device *dev, int count,
static int lne390_open(struct net_device *dev)
{
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -367,21 +368,12 @@ static int lne390_close(struct net_device *dev)
printk("%s: Shutting down ethercard.\n", dev->name);
ei_close(dev);
- MOD_DEC_USE_COUNT;
return 0;
}
#ifdef MODULE
#define MAX_LNE_CARDS 4 /* Max number of LNE390 cards per module */
-static struct net_device dev_lne[MAX_LNE_CARDS] = {
- {
- "",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, NULL
- },
-};
-
+static struct net_device dev_lne[MAX_LNE_CARDS];
static int io[MAX_LNE_CARDS];
static int irq[MAX_LNE_CARDS];
static int mem[MAX_LNE_CARDS];
diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c
index fd6744284..1d2d4c47b 100644
--- a/drivers/net/mvme147.c
+++ b/drivers/net/mvme147.c
@@ -79,9 +79,11 @@ int __init mvme147lance_probe(struct net_device *dev)
u_long address;
if (!MACH_IS_MVME147 || called)
- return(ENODEV);
+ return(-ENODEV);
called++;
+ SET_MODULE_OWNER(dev);
+
dev->priv = kmalloc(sizeof(struct m147lance_private), GFP_KERNEL);
if (dev->priv == NULL)
return -ENOMEM;
@@ -173,7 +175,6 @@ static int m147lance_open(struct net_device *dev)
m147_pcc->lan_cntrl=0; /* clear the interrupts (if any) */
m147_pcc->lan_cntrl=0x08 | 0x04; /* Enable irq 4 */
- MOD_INC_USE_COUNT;
return 0;
}
@@ -182,7 +183,6 @@ static int m147lance_close(struct net_device *dev)
/* disable interrupts at boardlevel */
m147_pcc->lan_cntrl=0x0; /* disable interrupts */
lance_close(dev);
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 254b42880..34d050f71 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -386,6 +386,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
dev = init_etherdev(NULL, sizeof (struct netdev_private));
if (!dev)
return -ENOMEM;
+ SET_MODULE_OWNER(dev);
{
void *mmio;
@@ -559,12 +560,8 @@ static int netdev_open(struct net_device *dev)
/* Do we need to reset the chip??? */
- MOD_INC_USE_COUNT;
-
- if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) {
- MOD_DEC_USE_COUNT;
- return -EAGAIN;
- }
+ i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
+ if (i) return i;
if (debug > 1)
printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
@@ -1179,8 +1176,6 @@ static int netdev_close(struct net_device *dev)
writel(0x0200, ioaddr + ChipConfig); /* Power down Xcvr. */
#endif
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 133e8d1a1..5292c4a35 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -157,7 +157,9 @@ static void ne_block_output(struct net_device *dev, const int count,
int __init ne_probe(struct net_device *dev)
{
- unsigned int base_addr = dev ? dev->base_addr : 0;
+ unsigned int base_addr = dev->base_addr;
+
+ SET_MODULE_OWNER(dev);
/* First check any supplied i/o locations. User knows best. <cough> */
if (base_addr > 0x1ff) /* Check a single specified location. */
@@ -469,7 +471,6 @@ err_out:
static int ne_open(struct net_device *dev)
{
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -478,7 +479,6 @@ static int ne_close(struct net_device *dev)
if (ei_debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
ei_close(dev);
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 3ff0ef141..9bb252dc5 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -152,6 +152,8 @@ int __init ne2_probe(struct net_device *dev)
int i;
int adapter_found = 0;
+ SET_MODULE_OWNER(dev);
+
/* Do not check any supplied i/o locations.
POS registers usually don't fail :) */
@@ -371,7 +373,6 @@ out:
static int ne_open(struct net_device *dev)
{
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -380,7 +381,6 @@ static int ne_close(struct net_device *dev)
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
ei_close(dev);
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 3ba20f197..b404574fe 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -244,6 +244,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
printk (KERN_ERR "ne2k-pci: cannot allocate ethernet device\n");
goto err_out_free_res;
}
+ SET_MODULE_OWNER(dev);
/* Reset card. Who knows what dain-bramaged state it was left in. */
{
@@ -358,11 +359,10 @@ err_out_free_res:
static int ne2k_pci_open(struct net_device *dev)
{
- MOD_INC_USE_COUNT;
- if (request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev)) {
- MOD_DEC_USE_COUNT;
- return -EAGAIN;
- }
+ int ret = request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev);
+ if (ret)
+ return ret;
+
/* Set full duplex for the chips that we know about. */
if (ei_status.ne2k_flags & FORCE_FDX) {
long ioaddr = dev->base_addr;
@@ -380,7 +380,6 @@ static int ne2k_pci_close(struct net_device *dev)
{
ei_close(dev);
free_irq(dev->irq, dev);
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index e57551271..eae50f902 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -99,6 +99,8 @@ int __init ne3210_probe(struct net_device *dev)
{
unsigned short ioaddr = dev->base_addr;
+ SET_MODULE_OWNER(dev);
+
if (ioaddr > 0x1ff) /* Check a single specified location. */
return ne3210_probe1(dev, ioaddr);
else if (ioaddr > 0) /* Don't probe at all. */
@@ -345,7 +347,6 @@ static void ne3210_block_output(struct net_device *dev, int count,
static int ne3210_open(struct net_device *dev)
{
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -356,7 +357,6 @@ static int ne3210_close(struct net_device *dev)
printk("%s: Shutting down ethercard.\n", dev->name);
ei_close(dev);
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index a2c4802c0..ccb92e8a5 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -491,7 +491,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_INFO "pcnet32_probe_pci: found device %#08x.%#08x\n", ent->vendor, ent->device);
ioaddr = pci_resource_start (pdev, 0);
- printk(KERN_INFO " ioaddr=%#08lx resource_flags=%#08lx\n", ioaddr, pci_resource_flags (pdev, 0));
+ printk(KERN_INFO " ioaddr=%#08lx resource_flags=%#08lx\n", ioaddr, pci_resource_flags (pdev, 0));
if (!ioaddr) {
printk (KERN_ERR "no PCI IO resources, aborting\n");
return -ENODEV;
@@ -637,29 +637,29 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car
/* There is a 16 byte station address PROM at the base address.
The first six bytes are the station address. */
for (i = 0; i < 6; i++)
- printk( KERN_INFO " %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
+ printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 or 0x2624 */
i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */
- printk(KERN_INFO"\n tx_start_pt(0x%04x):",i);
+ printk("\n" KERN_INFO " tx_start_pt(0x%04x):",i);
switch(i>>10) {
- case 0: printk(KERN_INFO " 20 bytes,"); break;
- case 1: printk(KERN_INFO " 64 bytes,"); break;
- case 2: printk(KERN_INFO " 128 bytes,"); break;
- case 3: printk(KERN_INFO "~220 bytes,"); break;
+ case 0: printk(" 20 bytes,"); break;
+ case 1: printk(" 64 bytes,"); break;
+ case 2: printk(" 128 bytes,"); break;
+ case 3: printk("~220 bytes,"); break;
}
i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */
- printk(KERN_INFO" BCR18(%x):",i&0xffff);
- if (i & (1<<5)) printk(KERN_INFO "BurstWrEn ");
- if (i & (1<<6)) printk(KERN_INFO "BurstRdEn ");
- if (i & (1<<7)) printk(KERN_INFO "DWordIO ");
- if (i & (1<<11)) printk(KERN_INFO"NoUFlow ");
+ printk(" BCR18(%x):",i&0xffff);
+ if (i & (1<<5)) printk("BurstWrEn ");
+ if (i & (1<<6)) printk("BurstRdEn ");
+ if (i & (1<<7)) printk("DWordIO ");
+ if (i & (1<<11)) printk("NoUFlow ");
i = a->read_bcr(ioaddr, 25);
- printk(KERN_INFO "\n SRAMSIZE=0x%04x,",i<<8);
+ printk("\n" KERN_INFO " SRAMSIZE=0x%04x,",i<<8);
i = a->read_bcr(ioaddr, 26);
- printk(KERN_INFO " SRAM_BND=0x%04x,",i<<8);
+ printk(" SRAM_BND=0x%04x,",i<<8);
i = a->read_bcr(ioaddr, 27);
- if (i & (1<<14)) printk(KERN_INFO "LowLatRx,");
+ if (i & (1<<14)) printk("LowLatRx");
}
dev->base_addr = ioaddr;
@@ -672,7 +672,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car
memset(lp, 0, sizeof(*lp));
lp->dma_addr = lp_dma_addr;
lp->pci_dev = pdev;
- printk(KERN_INFO "pcnet32: pcnet32_private lp=%p lp_dma_addr=%#08x\n", lp, lp_dma_addr);
+ printk("\n" KERN_INFO "pcnet32: pcnet32_private lp=%p lp_dma_addr=%#08x", lp, lp_dma_addr);
spin_lock_init(&lp->lock);
@@ -723,7 +723,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car
}
if (dev->irq >= 2)
- printk(KERN_INFO " assigned IRQ %d.\n", dev->irq);
+ printk(" assigned IRQ %d.\n", dev->irq);
else {
unsigned long irq_mask = probe_irq_on();
@@ -738,9 +738,9 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car
dev->irq = probe_irq_off (irq_mask);
if (dev->irq)
- printk(KERN_INFO ", probed IRQ %d.\n", dev->irq);
+ printk(", probed IRQ %d.\n", dev->irq);
else {
- printk(KERN_ERR ", failed to detect IRQ line.\n");
+ printk(", failed to detect IRQ line.\n");
return -ENODEV;
}
}
@@ -988,14 +988,14 @@ pcnet32_tx_timeout (struct net_device *dev)
lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
lp->cur_rx);
for (i = 0 ; i < RX_RING_SIZE; i++)
- printk(KERN_DEBUG "%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
+ printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
lp->rx_ring[i].base, -lp->rx_ring[i].buf_length,
lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status);
for (i = 0 ; i < TX_RING_SIZE; i++)
- printk(KERN_DEBUG "%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
+ printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
lp->tx_ring[i].base, -lp->tx_ring[i].length,
lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status);
- printk(KERN_DEBUG "\n");
+ printk("\n");
}
pcnet32_restart(dev, 0x0042);
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index ee7ef1578..61cdd84d6 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -286,6 +286,7 @@ plip_init_dev(struct net_device *dev, struct parport *pb)
struct net_local *nl;
struct pardevice *pardev;
+ SET_MODULE_OWNER(dev);
dev->irq = pb->irq;
dev->base_addr = pb->base;
@@ -348,18 +349,18 @@ plip_init_dev(struct net_device *dev, struct parport *pb)
nl->nibble = PLIP_NIBBLE_WAIT;
/* Initialize task queue structures */
- nl->immediate.next = NULL;
+ INIT_LIST_HEAD(&nl->immediate.list);
nl->immediate.sync = 0;
nl->immediate.routine = (void (*)(void *))plip_bh;
nl->immediate.data = dev;
- nl->deferred.next = NULL;
+ INIT_LIST_HEAD(&nl->deferred.list);
nl->deferred.sync = 0;
nl->deferred.routine = (void (*)(void *))plip_kick_bh;
nl->deferred.data = dev;
if (dev->irq == -1) {
- nl->timer.next = NULL;
+ INIT_LIST_HEAD(&nl->timer.list);
nl->timer.sync = 0;
nl->timer.routine = (void (*)(void *))plip_timer_bh;
nl->timer.data = dev;
@@ -1164,7 +1165,6 @@ plip_open(struct net_device *dev)
netif_start_queue (dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -1212,7 +1212,6 @@ plip_close(struct net_device *dev)
/* Reset. */
outb(0x00, PAR_CONTROL(dev));
#endif
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 98b7db0f8..8fc567262 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -2207,7 +2207,7 @@ ppp_create_interface(int unit, int *retp)
dev->init = ppp_net_init;
sprintf(dev->name, "ppp%d", unit);
dev->priv = ppp;
- dev->new_style = 1;
+ dev->features |= NETIF_F_DYNALLOC;
rtnl_lock();
ret = register_netdevice(dev);
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index feb723651..8744f6186 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -785,8 +785,7 @@ int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
skb_reserve(skb, dev->hard_header_len);
skb->nh.raw = skb->data;
- skb->rx_dev = skb->dev = dev;
- dev_hold(skb->rx_dev);
+ skb->dev = dev;
skb->priority = sk->priority;
skb->protocol = __constant_htons(ETH_P_PPP_SES);
@@ -869,11 +868,7 @@ int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
skb->nh.raw = skb->data;
- /* Change device of skb, update reference counts */
- if(skb->rx_dev)
- dev_put(skb->rx_dev);
- skb->rx_dev = skb->dev = dev;
- dev_hold(skb->rx_dev);
+ skb->dev = dev;
dev->hard_header(skb, dev, ETH_P_PPP_SES,
sk->protinfo.pppox->pppoe_pa.remote,
diff --git a/drivers/net/rclanmtl.c b/drivers/net/rclanmtl.c
index 2721cb05e..1a5f13672 100644
--- a/drivers/net/rclanmtl.c
+++ b/drivers/net/rclanmtl.c
@@ -1561,7 +1561,7 @@ RC_RETURN
RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
{
unsigned long off;
- unsigned long *pMsg;
+ PU32 pMsg;
PPAB pPab;
int i;
long timeout = 0;
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index 793af1577..95a7c864e 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -210,6 +210,9 @@ sb1000_probe(struct net_device *dev)
dev->rmem_end, serial_number, dev->irq);
dev = init_etherdev(dev, 0);
+ if (!dev)
+ return -ENOMEM;
+ SET_MODULE_OWNER(dev);
/* Make up a SB1000-specific-data structure. */
dev->priv = kmalloc(sizeof(struct sb1000_private), GFP_KERNEL);
@@ -1004,7 +1007,6 @@ sb1000_open(struct net_device *dev)
netif_start_queue(dev);
- MOD_INC_USE_COUNT;
return 0; /* Always succeed */
}
@@ -1195,7 +1197,6 @@ static int sb1000_close(struct net_device *dev)
dev_kfree_skb(lp->rx_skb[i]);
}
}
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1205,14 +1206,9 @@ MODULE_DESCRIPTION("General Instruments SB1000 driver");
MODULE_PARM(io, "1-2i");
MODULE_PARM(irq, "i");
-static struct net_device dev_sb1000 = {
- "",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, sb1000_probe };
-
-static int io[2] = {0, 0};
-static int irq = 0;
+static struct net_device dev_sb1000;
+static int io[2];
+static int irq;
int
init_module(void)
@@ -1226,6 +1222,7 @@ init_module(void)
printk(KERN_ERR "sb1000: can't register any device cm<n>\n");
return -ENFILE;
}
+ dev_sb1000.init = sb1000_probe;
dev_sb1000.base_addr = io[0];
/* rmem_end holds the second I/O address - fv */
dev_sb1000.rmem_end = io[1];
diff --git a/drivers/net/setup.c b/drivers/net/setup.c
index a8c9e5e46..823836cbb 100644
--- a/drivers/net/setup.c
+++ b/drivers/net/setup.c
@@ -31,9 +31,7 @@ extern int sdla_c_setup(void);
extern int comx_init(void);
extern int lmc_setup(void);
-extern int abyss_probe(void);
extern int madgemc_probe(void);
-extern int tms_pci_probe(void);
/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */
#define __PAD6 "\0\0\0\0\0\0\0\0\0"
@@ -115,16 +113,9 @@ struct net_probe pci_probes[] __initdata = {
/*
* Token Ring Drivers
*/
-#ifdef CONFIG_ABYSS
- {abyss_probe, 0},
-#endif
#ifdef CONFIG_MADGEMC
{madgemc_probe, 0},
#endif
-#ifdef CONFIG_TMSPCI
- {tms_pci_probe, 0},
-#endif
-
{NULL, 0},
};
diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c
index b476e290c..1be9f6561 100644
--- a/drivers/net/shaper.c
+++ b/drivers/net/shaper.c
@@ -406,7 +406,6 @@ static int shaper_open(struct net_device *dev)
return -ENODEV;
if(shaper->bitspersec==0)
return -EINVAL;
- MOD_INC_USE_COUNT;
return 0;
}
@@ -419,7 +418,6 @@ static int shaper_close(struct net_device *dev)
struct shaper *shaper=dev->priv;
shaper_flush(shaper);
del_timer_sync(&shaper->timer);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -618,34 +616,31 @@ static int shaper_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
}
-static struct shaper *shaper_alloc(struct net_device *dev)
+static void shaper_init_priv(struct net_device *dev)
{
- struct shaper *sh=kmalloc(sizeof(struct shaper), GFP_KERNEL);
- if(sh==NULL)
- return NULL;
- memset(sh,0,sizeof(*sh));
+ struct shaper *sh = dev->priv;
+
skb_queue_head_init(&sh->sendq);
init_timer(&sh->timer);
sh->timer.function=shaper_timer;
sh->timer.data=(unsigned long)sh;
init_waitqueue_head(&sh->wait_queue);
- return sh;
}
/*
* Add a shaper device to the system
*/
-int __init shaper_probe(struct net_device *dev)
+static int __init shaper_probe(struct net_device *dev)
{
/*
* Set up the shaper.
*/
-
- dev->priv = shaper_alloc(dev);
- if(dev->priv==NULL)
- return -ENOMEM;
-
+
+ SET_MODULE_OWNER(dev);
+
+ shaper_init_priv(dev);
+
dev->open = shaper_open;
dev->stop = shaper_close;
dev->hard_start_xmit = shaper_start_xmit;
@@ -685,89 +680,68 @@ int __init shaper_probe(struct net_device *dev)
return 0;
}
+static int shapers = 1;
#ifdef MODULE
-static struct net_device dev_shape =
-{
- "",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, shaper_probe
-};
+MODULE_PARM(shapers, "i");
-int init_module(void)
-{
- int err=dev_alloc_name(&dev_shape,"shaper%d");
- if(err<0)
- return err;
- printk(SHAPER_BANNER);
- if (register_netdev(&dev_shape) != 0)
- return -EIO;
- printk("Traffic shaper initialised.\n");
- return 0;
-}
+#else /* MODULE */
-void cleanup_module(void)
+static int __init set_num_shapers(char *str)
{
- struct shaper *sh=dev_shape.priv;
+ shapers = simple_strtol(str, NULL, 0);
+ return 1;
+}
- /*
- * No need to check MOD_IN_USE, as sys_delete_module() checks.
- * To be unloadable we must be closed and detached so we don't
- * need to flush things.
- */
-
- unregister_netdev(&dev_shape);
+__setup("shapers=", set_num_shapers);
- /*
- * Free up the private structure, or leak memory :-)
- */
- kfree(sh);
- dev_shape.priv = NULL;
-}
+#endif /* MODULE */
-#else
+static struct net_device *devs;
-static struct net_device dev_sh0 =
+static int __init shaper_init(void)
{
- "shaper0",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, shaper_probe
-};
+ int i, err;
+ size_t alloc_size;
+ struct shaper *sp;
+ unsigned int shapers_registered = 0;
+ if (shapers < 1)
+ return -ENODEV;
-static struct net_device dev_sh1 =
-{
- "shaper1",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, shaper_probe
-};
+ alloc_size = (sizeof(*devs) * shapers) +
+ (sizeof(struct shaper) * shapers);
+ devs = kmalloc(alloc_size, GFP_KERNEL);
+ if (!devs)
+ return -ENOMEM;
+ memset(devs, 0, alloc_size);
+ sp = (struct shaper *) &devs[shapers];
+ for (i = 0; i < shapers; i++) {
+ err = dev_alloc_name(&devs[i], "shaper%d");
+ if (err < 0)
+ break;
+ devs[i].init = shaper_probe;
+ devs[i].priv = &sp[i];
+ if (register_netdev(&devs[i]))
+ break;
+ shapers_registered++;
+ }
-static struct net_device dev_sh2 =
-{
- "shaper2",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, shaper_probe
-};
+ if (!shapers_registered) {
+ kfree(devs);
+ devs = NULL;
+ }
-static struct net_device dev_sh3 =
-{
- "shaper3",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, shaper_probe
-};
+ return (shapers_registered ? 0 : -ENODEV);
+}
-void shaper_init(void)
+static void __exit shaper_exit (void)
{
- register_netdev(&dev_sh0);
- register_netdev(&dev_sh1);
- register_netdev(&dev_sh2);
- register_netdev(&dev_sh3);
+ kfree(devs);
+ devs = NULL;
}
-#endif /* MODULE */
+module_init(shaper_init);
+module_exit(shaper_exit);
+
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index cc0eae214..72949ff74 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -241,6 +241,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev
net_dev = init_etherdev(NULL, sizeof(struct sis900_private));
if (!net_dev)
return -ENOMEM;
+ SET_MODULE_OWNER(net_dev);
if (!request_region(ioaddr, SIS900_TOTAL_SIZE, net_dev->name)) {
printk(KERN_ERR "sis900.c: can't allocate I/O space at 0x%lX\n", ioaddr);
@@ -530,8 +531,7 @@ sis900_open(struct net_device *net_dev)
struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
long ioaddr = net_dev->base_addr;
u8 revision;
-
- MOD_INC_USE_COUNT;
+ int ret;
/* Soft reset the chip. */
sis900_reset(net_dev);
@@ -541,10 +541,9 @@ sis900_open(struct net_device *net_dev)
if (revision == SIS630E_REV || revision == SIS630EA1_REV)
sis630e_set_eq(net_dev);
- if (request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev)) {
- MOD_DEC_USE_COUNT;
- return -EAGAIN;
- }
+ ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev);
+ if (ret)
+ return ret;
sis900_init_rxfilter(net_dev);
@@ -1279,8 +1278,6 @@ sis900_close(struct net_device *net_dev)
/* Green! Put the chip in low-power mode. */
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
index 51688271a..49823291a 100644
--- a/drivers/net/sk_mca.c
+++ b/drivers/net/sk_mca.c
@@ -879,9 +879,6 @@ static int skmca_open(struct SKMCA_NETDEV *dev)
dev->interrupt = 0;
dev->tbusy = 0;
dev->start = 0;
-#endif
-
-#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
@@ -900,7 +897,7 @@ static int skmca_close(struct SKMCA_NETDEV *dev)
free_irq(dev->irq, dev);
dev->irq = 0;
-#ifdef MODULE
+#if (LINUX_VERSION_CODE < 0x02032a)
MOD_DEC_USE_COUNT;
#endif
@@ -1087,6 +1084,8 @@ int skmca_probe(struct SKMCA_NETDEV *dev)
if (MCA_bus == 0)
return -ENODEV;
+ SET_MODULE_OWNER(dev);
+
/* start address of 1 --> forced detection */
if (dev->mem_start == 1)
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 7420e5691..6e8427a3b 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -549,7 +549,6 @@ sl_close(struct net_device *dev)
sl->xleft = 0;
spin_unlock_bh(&sl->lock);
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -564,7 +563,6 @@ static int sl_open(struct net_device *dev)
sl->flags &= (1 << SLF_INUSE);
netif_start_queue(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -647,6 +645,8 @@ static int sl_init(struct net_device *dev)
dev->type = ARPHRD_SLIP + sl->mode;
dev->tx_queue_len = 10;
+ SET_MODULE_OWNER(dev);
+
dev_init_buffers(dev);
/* New-style flags. */
diff --git a/drivers/net/slip.h b/drivers/net/slip.h
index c9f064b1d..bbd82fda5 100644
--- a/drivers/net/slip.h
+++ b/drivers/net/slip.h
@@ -91,7 +91,7 @@ struct slip {
int xdata, xbits; /* 6 bit slip controls */
#endif
- unsigned int flags; /* Flag values/ mode etc */
+ unsigned long flags; /* Flag values/ mode etc */
#define SLF_INUSE 0 /* Channel in use */
#define SLF_ESCAPE 1 /* ESC received */
#define SLF_ERROR 2 /* Parity, etc. error */
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index af2050833..2b5fb3fc4 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -91,7 +91,7 @@ struct smc_mca_adapters_t {
char *name;
};
-const struct smc_mca_adapters_t smc_mca_adapters[] = {
+static const struct smc_mca_adapters_t smc_mca_adapters[] = {
{ 0x61c8, "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)" },
{ 0x61c9, "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)" },
{ 0x6fc0, "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)" },
@@ -114,13 +114,15 @@ int __init ultramca_probe(struct net_device *dev)
int adapter = 0;
int tbase = 0;
int tirq = 0;
- int base_addr = dev ? dev->base_addr : 0;
- int irq = dev ? dev->irq : 0;
+ int base_addr = dev->base_addr;
+ int irq = dev->irq;
if (!MCA_bus) {
return -ENODEV;
}
+ SET_MODULE_OWNER(dev);
+
if (base_addr || irq) {
printk(KERN_INFO "Probing for SMC MCA adapter");
if (base_addr) {
@@ -340,7 +342,6 @@ static int ultramca_open(struct net_device *dev)
*/
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -424,8 +425,6 @@ static int ultramca_close_card(struct net_device *dev)
* "just in case"...
*/
- MOD_DEC_USE_COUNT;
-
return 0;
}
@@ -435,18 +434,9 @@ static int ultramca_close_card(struct net_device *dev)
#define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */
-static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS] =
-{
- {
- "",
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, NULL
- },
-};
-
-static int io[MAX_ULTRAMCA_CARDS] = { 0, };
-static int irq[MAX_ULTRAMCA_CARDS] = { 0, };
+static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS];
+static int io[MAX_ULTRAMCA_CARDS];
+static int irq[MAX_ULTRAMCA_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 5e7c7aeae..ebd3ab2b7 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -105,7 +105,9 @@ static int ultra_close_card(struct net_device *dev);
int __init ultra_probe(struct net_device *dev)
{
int i;
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev->base_addr;
+
+ SET_MODULE_OWNER(dev);
if (base_addr > 0x1ff) /* Check a single specified location. */
return ultra_probe1(dev, base_addr);
@@ -272,7 +274,6 @@ ultra_open(struct net_device *dev)
outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
outb(0xff, dev->base_addr + EN0_ERWCNT);
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -412,8 +413,6 @@ ultra_close_card(struct net_device *dev)
/* We should someday disable shared memory and change to 8-bit mode
"just in case"... */
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index ba387049c..3978433b5 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -61,7 +61,7 @@ static const char *version = "smc-ultra32.c: 06/97 v1.00\n";
#include "8390.h"
int ultra32_probe(struct net_device *dev);
-int ultra32_probe1(struct net_device *dev, int ioaddr);
+static int ultra32_probe1(struct net_device *dev, int ioaddr);
static int ultra32_open(struct net_device *dev);
static void ultra32_reset_8390(struct net_device *dev);
static void ultra32_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
@@ -105,48 +105,64 @@ static int ultra32_close(struct net_device *dev);
int __init ultra32_probe(struct net_device *dev)
{
- const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
- int ioaddr, edge, media;
+ int ioaddr;
if (!EISA_bus) return -ENODEV;
+ SET_MODULE_OWNER(dev);
+
/* EISA spec allows for up to 16 slots, but 8 is typical. */
for (ioaddr = 0x1000 + ULTRA32_BASE; ioaddr < 0x9000; ioaddr += 0x1000)
- if (check_region(ioaddr, ULTRA32_IO_EXTENT) == 0 &&
- inb(ioaddr + ULTRA32_IDPORT) != 0xff &&
- inl(ioaddr + ULTRA32_IDPORT) == ULTRA32_ID) {
- media = inb(ioaddr + ULTRA32_CFG7) & 0x03;
- edge = inb(ioaddr + ULTRA32_CFG5) & 0x08;
- printk("SMC Ultra32 in EISA Slot %d, Media: %s, %s IRQs.\n",
- ioaddr >> 12, ifmap[media],
- (edge ? "Edge Triggered" : "Level Sensitive"));
if (ultra32_probe1(dev, ioaddr) == 0)
- return 0;
- }
+ return 0;
+
return -ENODEV;
}
-int __init ultra32_probe1(struct net_device *dev, int ioaddr)
+static int __init ultra32_probe1(struct net_device *dev, int ioaddr)
{
- int i;
+ int i, edge, media, retval;
int checksum = 0;
const char *model_name;
- static unsigned version_printed = 0;
+ static unsigned version_printed;
/* Values from various config regs. */
- unsigned char idreg = inb(ioaddr + 7);
- unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
+ unsigned char idreg;
+ unsigned char reg4;
+ const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
+
+ if (!request_region(ioaddr, ULTRA32_IO_EXTENT, dev->name))
+ return -EBUSY;
+
+ if (inb(ioaddr + ULTRA32_IDPORT) == 0xff ||
+ inl(ioaddr + ULTRA32_IDPORT) != ULTRA32_ID) {
+ retval = -ENODEV;
+ goto out;
+ }
+
+ media = inb(ioaddr + ULTRA32_CFG7) & 0x03;
+ edge = inb(ioaddr + ULTRA32_CFG5) & 0x08;
+ printk("SMC Ultra32 in EISA Slot %d, Media: %s, %s IRQs.\n",
+ ioaddr >> 12, ifmap[media],
+ (edge ? "Edge Triggered" : "Level Sensitive"));
+
+ idreg = inb(ioaddr + 7);
+ reg4 = inb(ioaddr + 4) & 0x7f;
/* Check the ID nibble. */
- if ((idreg & 0xf0) != 0x20) /* SMC Ultra */
- return -ENODEV;
+ if ((idreg & 0xf0) != 0x20) { /* SMC Ultra */
+ retval = -ENODEV;
+ goto out;
+ }
/* Select the station address register set. */
outb(reg4, ioaddr + 4);
for (i = 0; i < 8; i++)
checksum += inb(ioaddr + 8 + i);
- if ((checksum & 0xff) != 0xff)
- return -ENODEV;
+ if ((checksum & 0xff) != 0xff) {
+ retval = -ENODEV;
+ goto out;
+ }
if (ei_debug && version_printed++ == 0)
printk(version);
@@ -175,7 +191,8 @@ int __init ultra32_probe1(struct net_device *dev, int ioaddr)
if ((inb(ioaddr + ULTRA32_CFG5) & 0x40) == 0) {
printk("\nsmc-ultra32: Card RAM is disabled! "
"Run EISA config utility.\n");
- return -ENODEV;
+ retval = -ENODEV;
+ goto out;
}
if ((inb(ioaddr + ULTRA32_CFG2) & 0x04) == 0)
printk("\nsmc-ultra32: Ignoring Bus-Master enable bit. "
@@ -186,7 +203,8 @@ int __init ultra32_probe1(struct net_device *dev, int ioaddr)
int irq = irqmap[inb(ioaddr + ULTRA32_CFG5) & 0x07];
if (irq == 0) {
printk(", failed to detect IRQ line.\n");
- return -EAGAIN;
+ retval = -EAGAIN;
+ goto out;
}
dev->irq = irq;
}
@@ -194,12 +212,10 @@ int __init ultra32_probe1(struct net_device *dev, int ioaddr)
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk (", no memory for dev->priv.\n");
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto out;
}
- /* OK, we are certain this is going to work. Setup the device. */
- request_region(ioaddr, ULTRA32_IO_EXTENT, model_name);
-
/* The 8390 isn't at the base address, so fake the offset */
dev->base_addr = ioaddr + ULTRA32_NIC_OFFSET;
@@ -229,15 +245,20 @@ int __init ultra32_probe1(struct net_device *dev, int ioaddr)
NS8390_init(dev, 0);
return 0;
+out:
+ release_region(ioaddr, ULTRA32_IO_EXTENT);
+ return retval;
}
static int ultra32_open(struct net_device *dev)
{
int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC addr */
int irq_flags = (inb(ioaddr + ULTRA32_CFG5) & 0x08) ? 0 : SA_SHIRQ;
+ int retval;
- if (request_irq(dev->irq, ei_interrupt, irq_flags, ei_status.name, dev))
- return -EAGAIN;
+ retval = request_irq(dev->irq, ei_interrupt, irq_flags, dev->name, dev);
+ if (retval)
+ return retval;
outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */
outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */
@@ -248,7 +269,6 @@ static int ultra32_open(struct net_device *dev)
outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
outb(0xff, dev->base_addr + EN0_ERWCNT);
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -267,8 +287,6 @@ static int ultra32_close(struct net_device *dev)
NS8390_init(dev, 0);
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index 201b259f7..199553971 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -256,15 +256,7 @@ inline static void smc_tx( struct net_device * dev );
. Test if a given location contains a chip, trying to cause as
. little damage as possible if it's not a SMC chip.
*/
-static int smc_probe( int ioaddr );
-
-/*
- . this routine initializes the cards hardware, prints out the configuration
- . to the system log as well as the vanity message, and handles the setup
- . of a device parameter.
- . It will give an error if it can't initialize the card.
-*/
-static int smc_initcard( struct net_device *, int ioaddr );
+static int smc_probe(struct net_device *dev, int ioaddr);
/*
. A rather simple routine to print out a packet for debugging purposes.
@@ -714,35 +706,20 @@ static void smc_hardware_send_packet( struct net_device * dev )
int __init smc_init(struct net_device *dev)
{
int i;
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev->base_addr;
+
+ SET_MODULE_OWNER(dev);
/* try a specific location */
- if (base_addr > 0x1ff) {
- int error;
- error = smc_probe(base_addr);
- if ( 0 == error ) {
- return smc_initcard( dev, base_addr );
- }
- return error;
- } else {
- if ( 0 != base_addr ) {
- return -ENXIO;
- }
- }
+ if (base_addr > 0x1ff)
+ return smc_probe(dev, base_addr);
+ else if (base_addr != 0)
+ return -ENXIO;
/* check every ethernet address */
- for (i = 0; smc_portlist[i]; i++) {
- int ioaddr = smc_portlist[i];
-
- /* check if the area is available */
- if (check_region( ioaddr , SMC_IO_EXTENT))
- continue;
-
- /* check this specific address */
- if ( smc_probe( ioaddr ) == 0) {
- return smc_initcard( dev, ioaddr );
- }
- }
+ for (i = 0; smc_portlist[i]; i++)
+ if (smc_probe(dev, smc_portlist[i]) == 0)
+ return 0;
/* couldn't find anything */
return -ENODEV;
@@ -837,23 +814,53 @@ int __init smc_findirq( int ioaddr )
.---------------------------------------------------------------------
*/
-static int __init smc_probe( int ioaddr )
+/*---------------------------------------------------------------
+ . Here I do typical initialization tasks.
+ .
+ . o Initialize the structure if needed
+ . o print out my vanity message if not done so already
+ . o print out what type of hardware is detected
+ . o print out the ethernet address
+ . o find the IRQ
+ . o set up my private data
+ . o configure the dev structure with my subroutines
+ . o actually GRAB the irq.
+ . o GRAB the region
+ .-----------------------------------------------------------------
+*/
+static int __init smc_probe(struct net_device *dev, int ioaddr)
{
- unsigned int bank;
- word revision_register;
- word base_address_register;
+ int i, memory, retval;
+ static unsigned version_printed;
+ unsigned int bank;
+
+ const char *version_string;
+ const char *if_string;
+
+ /* registers */
+ word revision_register;
+ word base_address_register;
+ word configuration_register;
+ word memory_info_register;
+ word memory_cfg_register;
+
+ /* Grab the region so that no one else tries to probe our ioports. */
+ if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
+ return -EBUSY;
/* First, see if the high byte is 0x33 */
bank = inw( ioaddr + BANK_SELECT );
if ( (bank & 0xFF00) != 0x3300 ) {
- return -ENODEV;
+ retval = -ENODEV;
+ goto err_out;
}
/* The above MIGHT indicate a device, but I need to write to further
test this. */
outw( 0x0, ioaddr + BANK_SELECT );
bank = inw( ioaddr + BANK_SELECT );
if ( (bank & 0xFF00 ) != 0x3300 ) {
- return -ENODEV;
+ retval = -ENODEV;
+ goto err_out;
}
/* well, we've already written once, so hopefully another time won't
hurt. This time, I need to switch the bank register to bank 1,
@@ -866,7 +873,8 @@ static int __init smc_probe( int ioaddr )
ioaddr, base_address_register >> 3 & 0x3E0 );
/* well, the base address register didn't match. Must not have
been a SMC chip after all. */
- return -ENODEV;
+ retval = -ENODEV;
+ goto err_out;
}
/* check if the revision register is something that I recognize.
@@ -879,46 +887,13 @@ static int __init smc_probe( int ioaddr )
printk(CARDNAME ": IO %x: Unrecognized revision register:"
" %x, Contact author. \n", ioaddr, revision_register );
- return -ENODEV;
+ retval = -ENODEV;
+ goto err_out;
}
/* at this point I'll assume that the chip is an SMC9xxx.
It might be prudent to check a listing of MAC addresses
against the hardware address, or do some other tests. */
- return 0;
-}
-
-/*---------------------------------------------------------------
- . Here I do typical initialization tasks.
- .
- . o Initialize the structure if needed
- . o print out my vanity message if not done so already
- . o print out what type of hardware is detected
- . o print out the ethernet address
- . o find the IRQ
- . o set up my private data
- . o configure the dev structure with my subroutines
- . o actually GRAB the irq.
- . o GRAB the region
- .-----------------------------------------------------------------
-*/
-static int __init smc_initcard(struct net_device *dev, int ioaddr)
-{
- int i;
-
- static unsigned version_printed = 0;
-
- /* registers */
- word revision_register;
- word configuration_register;
- word memory_info_register;
- word memory_cfg_register;
-
- const char * version_string;
- const char * if_string;
- int memory;
-
- int irqval;
if (version_printed++ == 0)
printk("%s", version);
@@ -956,7 +931,8 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ];
if ( !version_string ) {
/* I shouldn't get here because this call was done before.... */
- return -ENODEV;
+ retval = -ENODEV;
+ goto err_out;
}
/* is it using AUI or 10BaseT ? */
@@ -1003,7 +979,8 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
}
if (dev->irq == 0 ) {
printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n");
- return -ENODEV;
+ retval = -ENODEV;
+ goto err_out;
}
if (dev->irq == 2) {
/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
@@ -1014,7 +991,7 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
/* now, print out the card info, in a short format.. */
- printk(CARDNAME ": %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ",
+ printk("%s: %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
version_string, revision_register & 0xF, ioaddr, dev->irq,
if_string, memory );
/*
@@ -1029,8 +1006,10 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
/* Initialize the private structure. */
if (dev->priv == NULL) {
dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
+ if (dev->priv == NULL) {
+ retval = -ENOMEM;
+ goto err_out;
+ }
}
/* set the private data to zero by default */
memset(dev->priv, 0, sizeof(struct smc_local));
@@ -1039,16 +1018,15 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
ether_setup(dev);
/* Grab the IRQ */
- irqval = request_irq(dev->irq, &smc_interrupt, 0, CARDNAME, dev);
- if (irqval) {
- printk(CARDNAME": unable to get IRQ %d (irqval=%d).\n",
- dev->irq, irqval);
- return -EAGAIN;
+ retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
+ if (retval) {
+ printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
+ dev->irq, retval);
+ kfree(dev->priv);
+ dev->priv = NULL;
+ goto err_out;
}
- /* Grab the region so that no one else tries to probe our ioports. */
- request_region(ioaddr, SMC_IO_EXTENT, CARDNAME);
-
dev->open = smc_open;
dev->stop = smc_close;
dev->hard_start_xmit = smc_wait_to_send_packet;
@@ -1058,6 +1036,10 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
dev->set_multicast_list = smc_set_multicast_list;
return 0;
+
+err_out:
+ release_region(ioaddr, SMC_IO_EXTENT);
+ return retval;
}
#if SMC_DEBUG > 2
@@ -1112,8 +1094,6 @@ static int smc_open(struct net_device *dev)
/* clear out all the junk that was put here before... */
memset(dev->priv, 0, sizeof(struct smc_local));
- MOD_INC_USE_COUNT;
-
/* reset the hardware */
smc_reset( ioaddr );
@@ -1504,7 +1484,6 @@ static int smc_close(struct net_device *dev)
smc_shutdown( dev->base_addr );
/* Update the statistics here. */
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -1577,8 +1556,7 @@ static void smc_set_multicast_list(struct net_device *dev)
#ifdef MODULE
-static struct net_device devSMC9194 = { init: smc_init };
-
+static struct net_device devSMC9194;
static int io;
static int irq;
static int ifport;
@@ -1599,6 +1577,7 @@ int init_module(void)
devSMC9194.base_addr = io;
devSMC9194.irq = irq;
devSMC9194.if_port = ifport;
+ devSMC9194.init = smc_init;
if ((result = register_netdev(&devSMC9194)) != 0)
return result;
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index a6535df79..085270494 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -390,6 +390,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
dev = init_etherdev(NULL, sizeof(*np));
if (!dev)
return -ENOMEM;
+ SET_MODULE_OWNER(dev);
#ifdef USE_IO_OPS
ioaddr = pci_resource_start(pdev, 0);
@@ -609,12 +610,9 @@ static int netdev_open(struct net_device *dev)
/* Do we need to reset the chip??? */
- MOD_INC_USE_COUNT;
-
- if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) {
- MOD_DEC_USE_COUNT;
- return -EAGAIN;
- }
+ i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
+ if (i)
+ return i;
if (debug > 1)
printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
@@ -1224,8 +1222,6 @@ static int netdev_close(struct net_device *dev)
np->tx_skbuff[i] = 0;
}
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index bfb0f57df..ba436a12b 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1,4 +1,4 @@
-/* $Id: sunhme.c,v 1.104 2000/11/17 01:40:00 davem Exp $
+/* $Id: sunhme.c,v 1.105 2000/12/05 02:00:36 anton Exp $
* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
* auto carrier detecting ethernet driver. Also known as the
* "Happy Meal Ethernet" found on SunSwift SBUS cards.
@@ -1492,18 +1492,18 @@ static int happy_meal_init(struct happy_meal *hp, int from_irq)
/* Shut up the MIF. */
HMD(("happy_meal_init: Disable all MIF irqs (old[%08x]), ",
- hme_read32(hp, &tregs->int_mask)));
+ hme_read32(hp, tregs + TCVR_IMASK)));
hme_write32(hp, tregs + TCVR_IMASK, 0xffff);
/* See if we can enable the MIF frame on this card to speak to the DP83840. */
if (hp->happy_flags & HFLAG_FENABLE) {
HMD(("use frame old[%08x], ",
- hme_read32(hp, &tregs->cfg)));
+ hme_read32(hp, tregs + TCVR_CFG)));
hme_write32(hp, tregs + TCVR_CFG,
hme_read32(hp, tregs + TCVR_CFG) & ~(TCV_CFG_BENABLE));
} else {
HMD(("use bitbang old[%08x], ",
- hme_read32(hp, &tregs->cfg)));
+ hme_read32(hp, tregs + TCVR_CFG)));
hme_write32(hp, tregs + TCVR_CFG,
hme_read32(hp, tregs + TCVR_CFG) | TCV_CFG_BENABLE);
}
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 33e98c23e..e3aae9111 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -474,6 +474,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");
return -ENOMEM;
}
+ SET_MODULE_OWNER(dev);
priv = dev->priv;
@@ -814,14 +815,11 @@ static int TLan_Open( struct net_device *dev )
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
int err;
- MOD_INC_USE_COUNT;
-
priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev );
if ( err ) {
printk(KERN_ERR "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq );
- MOD_DEC_USE_COUNT;
return err;
}
@@ -1098,8 +1096,6 @@ static int TLan_Close(struct net_device *dev)
TLan_FreeLists( dev );
TLAN_DBG( TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name );
- MOD_DEC_USE_COUNT;
-
return 0;
} /* TLan_Close */
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 3db04bdee..a020b21dd 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -15,6 +15,7 @@
* Modification History:
* 30-Dec-99 AF Split off from the tms380tr driver.
* 22-Jan-00 AF Updated to use indirect read/writes
+ * 23-Nov-00 JG New PCI API, cleanups
*
*
* TODO:
@@ -23,7 +24,6 @@
* config registers)
*
*/
-static const char *version = "abyss.c: v1.01 22/01/2000 by Adam Fritzler\n";
#include <linux/module.h>
#include <linux/kernel.h>
@@ -41,9 +41,18 @@ static const char *version = "abyss.c: v1.01 22/01/2000 by Adam Fritzler\n";
#include "tms380tr.h"
#include "abyss.h" /* Madge-specific constants */
+static char version[] __initdata =
+"abyss.c: v1.02 23/11/2000 by Adam Fritzler\n";
+
#define ABYSS_IO_EXTENT 64
-int abyss_probe(void);
+static struct pci_device_id abyss_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_MK2,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_TOKEN_RING << 8, 0x00ffffff, },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, abyss_pci_tbl);
+
static int abyss_open(struct net_device *dev);
static int abyss_close(struct net_device *dev);
static void abyss_enable(struct net_device *dev);
@@ -51,17 +60,16 @@ static int abyss_chipset_init(struct net_device *dev);
static void abyss_read_eeprom(struct net_device *dev);
static unsigned short abyss_setnselout_pins(struct net_device *dev);
-void at24_writedatabyte(unsigned long regaddr, unsigned char byte);
-int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr);
-int at24_sendcmd(unsigned long regaddr, unsigned char cmd);
-unsigned char at24_readdatabit(unsigned long regaddr);
-unsigned char at24_readdatabyte(unsigned long regaddr);
-int at24_waitforack(unsigned long regaddr);
-int at24_waitfornack(unsigned long regaddr);
-void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data);
-void at24_start(unsigned long regaddr);
-void at24_stop(unsigned long regaddr);
-unsigned char at24_readb(unsigned long regaddr, unsigned char addr);
+static void at24_writedatabyte(unsigned long regaddr, unsigned char byte);
+static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr);
+static int at24_sendcmd(unsigned long regaddr, unsigned char cmd);
+static unsigned char at24_readdatabit(unsigned long regaddr);
+static unsigned char at24_readdatabyte(unsigned long regaddr);
+static int at24_waitforack(unsigned long regaddr);
+static int at24_waitfornack(unsigned long regaddr);
+static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data);
+static void at24_start(unsigned long regaddr);
+static unsigned char at24_readb(unsigned long regaddr, unsigned char addr);
static unsigned short abyss_sifreadb(struct net_device *dev, unsigned short reg)
{
@@ -83,129 +91,100 @@ static void abyss_sifwritew(struct net_device *dev, unsigned short val, unsigned
outw(val, dev->base_addr + reg);
}
-struct tms_abyss_card {
- struct net_device *dev;
- struct pci_dev *pci_dev;
- struct tms_abyss_card *next;
-};
-static struct tms_abyss_card *abyss_card_list = NULL;
-
-int __init abyss_probe(void)
+static int __init abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int versionprinted = 0;
- struct pci_dev *pdev = NULL ;
+ static int versionprinted;
struct net_device *dev;
struct net_local *tp;
- int i;
-
- if (!pci_present())
- return (-1); /* No PCI present. */
+ int i, ret, pci_irq_line;
+ unsigned long pci_ioaddr;
- while ( (pdev=pci_find_class(PCI_CLASS_NETWORK_TOKEN_RING<<8, pdev))) {
- unsigned int pci_irq_line;
- unsigned long pci_ioaddr;
- struct tms_abyss_card *card;
-
- /* We only support Madge Smart 16/4 PCI Mk2 (Abyss) cards */
- if ( (pdev->vendor != PCI_VENDOR_ID_MADGE) ||
- (pdev->device != PCI_DEVICE_ID_MADGE_MK2) )
- continue;
-
- if (versionprinted++ == 0)
- printk("%s", version);
+ if (versionprinted++ == 0)
+ printk("%s", version);
- if (pci_enable_device(pdev))
- continue;
+ if (pci_enable_device(pdev))
+ return -EIO;
- /* Remove I/O space marker in bit 0. */
- pci_irq_line = pdev->irq;
- pci_ioaddr = pci_resource_start (pdev, 0);
-
- if(!request_region(pci_ioaddr, ABYSS_IO_EXTENT, "abyss"))
- continue;
+ /* Remove I/O space marker in bit 0. */
+ pci_irq_line = pdev->irq;
+ pci_ioaddr = pci_resource_start (pdev, 0);
- /* At this point we have found a valid card. */
+ /* At this point we have found a valid card. */
- dev = init_trdev(NULL, 0);
- if (!dev) {
- release_region(pci_ioaddr, ABYSS_IO_EXTENT);
- continue;
- }
+ dev = init_trdev(NULL, 0);
+ if (!dev)
+ return -ENOMEM;
+ SET_MODULE_OWNER(dev);
+
+ if (!request_region(pci_ioaddr, ABYSS_IO_EXTENT, dev->name)) {
+ ret = -EBUSY;
+ goto err_out_trdev;
+ }
- if(request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
- "abyss", dev)) {
- release_region(pci_ioaddr, ABYSS_IO_EXTENT) ;
- /* XXX free trdev */
- continue; /*return (-ENODEV);*/ /* continue; ?? */
- }
+ ret = request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
+ dev->name, dev);
+ if (ret)
+ goto err_out_region;
- /*
- if (load_tms380_module("abyss.c")) {
- return 0;
- }
- */
-
- dev->base_addr = pci_ioaddr;
- dev->irq = pci_irq_line;
- dev->dma = 0;
+ dev->base_addr = pci_ioaddr;
+ dev->irq = pci_irq_line;
- printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name);
- printk("%s: IO: %#4lx IRQ: %d\n",
- dev->name, pci_ioaddr, dev->irq);
- /*
- * The TMS SIF registers lay 0x10 above the card base address.
- */
- dev->base_addr += 0x10;
+ printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name);
+ printk("%s: IO: %#4lx IRQ: %d\n",
+ dev->name, pci_ioaddr, dev->irq);
+ /*
+ * The TMS SIF registers lay 0x10 above the card base address.
+ */
+ dev->base_addr += 0x10;
- if (tmsdev_init(dev)) {
- printk("%s: unable to get memory for dev->priv.\n",
- dev->name);
- return 0;
- }
+ ret = tmsdev_init(dev);
+ if (ret) {
+ printk("%s: unable to get memory for dev->priv.\n",
+ dev->name);
+ goto err_out_irq;
+ }
- abyss_read_eeprom(dev);
+ abyss_read_eeprom(dev);
- printk("%s: Ring Station Address: ", dev->name);
- printk("%2.2x", dev->dev_addr[0]);
- for (i = 1; i < 6; i++)
- printk(":%2.2x", dev->dev_addr[i]);
- printk("\n");
-
- tp = (struct net_local *)dev->priv;
- tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */
- tp->setnselout = abyss_setnselout_pins;
- tp->sifreadb = abyss_sifreadb;
- tp->sifreadw = abyss_sifreadw;
- tp->sifwriteb = abyss_sifwriteb;
- tp->sifwritew = abyss_sifwritew;
-
- memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1);
+ printk("%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (i = 1; i < 6; i++)
+ printk(":%2.2x", dev->dev_addr[i]);
+ printk("\n");
+
+ tp = dev->priv;
+ tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */
+ tp->setnselout = abyss_setnselout_pins;
+ tp->sifreadb = abyss_sifreadb;
+ tp->sifreadw = abyss_sifreadw;
+ tp->sifwriteb = abyss_sifwriteb;
+ tp->sifwritew = abyss_sifwritew;
+
+ memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1);
- dev->open = abyss_open;
- dev->stop = abyss_close;
-
- if (register_trdev(dev) == 0) {
- /* Enlist in the card list */
- card = kmalloc(sizeof(struct tms_abyss_card),
- GFP_KERNEL);
- card->next = abyss_card_list;
- abyss_card_list = card;
- card->dev = dev;
- card->pci_dev = pdev;
- } else {
- printk("abyss: register_trdev() returned non-zero.\n");
- kfree(dev->priv);
- kfree(dev);
- return -1;
- }
- }
-
- if (abyss_card_list)
- return 0;
- return (-1);
+ dev->open = abyss_open;
+ dev->stop = abyss_close;
+
+ ret = register_trdev(dev);
+ if (ret)
+ goto err_out_tmsdev;
+
+ pci_set_drvdata(pdev, dev);
+ return 0;
+
+err_out_tmsdev:
+ kfree(dev->priv);
+err_out_irq:
+ free_irq(pdev->irq, dev);
+err_out_region:
+ release_region(pci_ioaddr, ABYSS_IO_EXTENT);
+err_out_trdev:
+ unregister_netdev(dev);
+ kfree(dev);
+ return ret;
}
-unsigned short abyss_setnselout_pins(struct net_device *dev)
+static unsigned short abyss_setnselout_pins(struct net_device *dev)
{
unsigned short val = 0;
struct net_local *tp = (struct net_local *)dev->priv;
@@ -228,7 +207,7 @@ unsigned short abyss_setnselout_pins(struct net_device *dev)
* These access an Atmel AT24 SEEPROM using their glue chip registers.
*
*/
-void at24_writedatabyte(unsigned long regaddr, unsigned char byte)
+static void at24_writedatabyte(unsigned long regaddr, unsigned char byte)
{
int i;
@@ -239,7 +218,7 @@ void at24_writedatabyte(unsigned long regaddr, unsigned char byte)
}
}
-int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr)
+static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr)
{
if (at24_sendcmd(regaddr, cmd)) {
at24_writedatabyte(regaddr, addr);
@@ -248,7 +227,7 @@ int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char add
return 0;
}
-int at24_sendcmd(unsigned long regaddr, unsigned char cmd)
+static int at24_sendcmd(unsigned long regaddr, unsigned char cmd)
{
int i;
@@ -261,7 +240,7 @@ int at24_sendcmd(unsigned long regaddr, unsigned char cmd)
return 0;
}
-unsigned char at24_readdatabit(unsigned long regaddr)
+static unsigned char at24_readdatabit(unsigned long regaddr)
{
unsigned char val;
@@ -273,7 +252,7 @@ unsigned char at24_readdatabit(unsigned long regaddr)
return val;
}
-unsigned char at24_readdatabyte(unsigned long regaddr)
+static unsigned char at24_readdatabyte(unsigned long regaddr)
{
unsigned char data = 0;
int i;
@@ -286,7 +265,7 @@ unsigned char at24_readdatabyte(unsigned long regaddr)
return data;
}
-int at24_waitforack(unsigned long regaddr)
+static int at24_waitforack(unsigned long regaddr)
{
int i;
@@ -297,7 +276,7 @@ int at24_waitforack(unsigned long regaddr)
return 0;
}
-int at24_waitfornack(unsigned long regaddr)
+static int at24_waitfornack(unsigned long regaddr)
{
int i;
for (i = 0; i < 10; i++) {
@@ -307,10 +286,9 @@ int at24_waitfornack(unsigned long regaddr)
return 0;
}
-void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data)
+static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data)
{
- unsigned char val;
- val = AT24_ENABLE;
+ unsigned char val = AT24_ENABLE;
if (clock)
val |= AT24_CLOCK;
if (data)
@@ -320,25 +298,15 @@ void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char dat
tms380tr_wait(20); /* Very necessary. */
}
-void at24_start(unsigned long regaddr)
+static void at24_start(unsigned long regaddr)
{
at24_setlines(regaddr, 0, 1);
at24_setlines(regaddr, 1, 1);
at24_setlines(regaddr, 1, 0);
at24_setlines(regaddr, 0, 1);
- return;
}
-void at24_stop(unsigned long regaddr)
-{
- at24_setlines(regaddr, 0, 0);
- at24_setlines(regaddr, 1, 0);
- at24_setlines(regaddr, 1, 1);
- at24_setlines(regaddr, 0, 1);
- return;
-}
-
-unsigned char at24_readb(unsigned long regaddr, unsigned char addr)
+static unsigned char at24_readb(unsigned long regaddr, unsigned char addr)
{
unsigned char data = 0xff;
@@ -367,7 +335,6 @@ static void abyss_enable(struct net_device *dev)
reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
tms380tr_wait(100);
- return;
}
/*
@@ -411,14 +378,12 @@ static int abyss_chipset_init(struct net_device *dev)
return 0;
}
-void abyss_chipset_close(struct net_device *dev)
+static inline void abyss_chipset_close(struct net_device *dev)
{
unsigned long ioaddr;
ioaddr = dev->base_addr;
outb(0, ioaddr + PCIBM2_RESET_REG);
-
- return;
}
/*
@@ -451,15 +416,12 @@ static void abyss_read_eeprom(struct net_device *dev)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,
PCIBM2_SEEPROM_BIA+i);
-
- return;
}
static int abyss_open(struct net_device *dev)
{
abyss_chipset_init(dev);
tms380tr_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -467,41 +429,49 @@ static int abyss_close(struct net_device *dev)
{
tms380tr_close(dev);
abyss_chipset_close(dev);
- MOD_DEC_USE_COUNT;
return 0;
}
-#ifdef MODULE
+static void __exit abyss_detach (struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (!dev)
+ BUG();
+ unregister_netdev(dev);
+ release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ kfree(dev->priv);
+ kfree(dev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_driver abyss_driver = {
+ name: "abyss",
+ id_table: abyss_pci_tbl,
+ probe: abyss_attach,
+ remove: abyss_detach,
+};
-int init_module(void)
+static int __init abyss_init (void)
{
- /* Probe for cards. */
- if (abyss_probe()) {
- printk(KERN_NOTICE "abyss.c: No cards found.\n");
+ int rc = pci_register_driver (&abyss_driver);
+ if (rc < 0)
+ return rc;
+ if (rc == 0) {
+ pci_unregister_driver (&abyss_driver);
+ return -ENODEV;
}
- /* lock_tms380_module(); */
- return (0);
+ return 0;
}
-void cleanup_module(void)
+static void __exit abyss_rmmod (void)
{
- struct net_device *dev;
- struct tms_abyss_card *this_card;
-
- while (abyss_card_list) {
- dev = abyss_card_list->dev;
- unregister_netdev(dev);
- release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
- free_irq(dev->irq, dev);
- kfree(dev->priv);
- kfree(dev);
- this_card = abyss_card_list;
- abyss_card_list = this_card->next;
- kfree(this_card);
- }
- /* unlock_tms380_module(); */
+ pci_unregister_driver (&abyss_driver);
}
-#endif /* MODULE */
+
+module_init(abyss_init);
+module_exit(abyss_rmmod);
/*
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index b8784bb29..c42f3f6eb 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -101,6 +101,13 @@
static char *version =
"Olympic.c v0.5.0 3/10/00 - Peter De Schrijver & Mike Phillips" ;
+static struct pci_device_id olympic_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, PCI_ANY_ID, PCI_ANY_ID, },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, olympic_pci_tbl);
+
+
static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion",
"Address Verification", "Neighbor Notification (Ring Poll)",
"Request Parameters","FDX Registration Request",
diff --git a/drivers/net/tokenring/tms380tr_microcode.h b/drivers/net/tokenring/tms380tr_microcode.h
index 3c03f1f6f..c05adebc1 100644
--- a/drivers/net/tokenring/tms380tr_microcode.h
+++ b/drivers/net/tokenring/tms380tr_microcode.h
@@ -27,7 +27,7 @@
#if defined(CONFIG_TMS380TR) || defined(CONFIG_TMS380TR_MODULE)
-unsigned char tms380tr_code[] = {
+static unsigned char tms380tr_code[] = {
0x00, 0x00, 0x00, 0xA0, 0x00, 0x20, 0x68, 0x54,
0x73, 0x69, 0x63, 0x20, 0x64, 0x6F, 0x20, 0x65,
0x73, 0x69, 0x72, 0x20, 0x6C, 0x65, 0x61, 0x65,
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
index 029e0cdfa..216154db5 100644
--- a/drivers/net/tokenring/tmspci.c
+++ b/drivers/net/tokenring/tmspci.c
@@ -19,12 +19,12 @@
* Modification History:
* 30-Dec-99 AF Split off from the tms380tr driver.
* 22-Jan-00 AF Updated to use indirect read/writes
+ * 23-Nov-00 JG New PCI API, cleanups
*
* TODO:
* 1. See if we can use MMIO instead of port accesses
*
*/
-static const char *version = "tmspci.c: v1.01 22/01/2000 by Adam Fritzler\n";
#include <linux/module.h>
#include <linux/kernel.h>
@@ -41,33 +41,32 @@ static const char *version = "tmspci.c: v1.01 22/01/2000 by Adam Fritzler\n";
#include <linux/trdevice.h>
#include "tms380tr.h"
+static char version[] __initdata =
+"tmspci.c: v1.02 23/11/2000 by Adam Fritzler\n";
+
#define TMS_PCI_IO_EXTENT 32
-struct cardinfo_table {
- int vendor_id; /* PCI info */
- int device_id;
- int registeroffset; /* SIF offset from dev->base_addr */
+struct card_info {
unsigned char nselout[2]; /* NSELOUT vals for 4mb([0]) and 16mb([1]) */
char *name;
};
-struct cardinfo_table probelist[] = {
- { 0, 0,
- 0x0000, {0x00, 0x00}, "Unknown TMS380 Token Ring Adapter"},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TOKENRING,
- 0x0000, {0x03, 0x01}, "Compaq 4/16 TR PCI"},
- { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_TR,
- 0x0000, {0x03, 0x01}, "SK NET TR 4/16 PCI"},
- { PCI_VENDOR_ID_TCONRAD, PCI_DEVICE_ID_TCONRAD_TOKENRING,
- 0x0000, {0x03, 0x01}, "Thomas-Conrad TC4048 PCI 4/16"},
- { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C339,
- 0x0000, {0x03, 0x01}, "3Com Token Link Velocity"},
- { 0, 0, 0, {0x00, 0x00}, NULL}
+static struct card_info card_info_table[] = {
+ { {0x03, 0x01}, "Compaq 4/16 TR PCI"},
+ { {0x03, 0x01}, "SK NET TR 4/16 PCI"},
+ { {0x03, 0x01}, "Thomas-Conrad TC4048 PCI 4/16"},
+ { {0x03, 0x01}, "3Com Token Link Velocity"},
+};
+
+static struct pci_device_id tmspci_pci_tbl[] __initdata = {
+ { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TOKENRING, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_TR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
+ { PCI_VENDOR_ID_TCONRAD, PCI_DEVICE_ID_TCONRAD_TOKENRING, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
+ { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C339, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
+ { } /* Terminating entry */
};
+MODULE_DEVICE_TABLE(pci, tmspci_pci_tbl);
-int tms_pci_probe(void);
-static int tms_pci_open(struct net_device *dev);
-static int tms_pci_close(struct net_device *dev);
static void tms_pci_read_eeprom(struct net_device *dev);
static unsigned short tms_pci_setnselout_pins(struct net_device *dev);
@@ -91,145 +90,97 @@ static void tms_pci_sifwritew(struct net_device *dev, unsigned short val, unsign
outw(val, dev->base_addr + reg);
}
-struct tms_pci_card {
- struct net_device *dev;
- struct pci_dev *pci_dev;
- struct cardinfo_table *cardinfo;
- struct tms_pci_card *next;
-};
-static struct tms_pci_card *tms_pci_card_list = NULL;
-
-
-struct cardinfo_table * __init tms_pci_getcardinfo(unsigned short vendor,
- unsigned short device)
-{
- int cur;
- for (cur = 1; probelist[cur].name != NULL; cur++) {
- if ((probelist[cur].vendor_id == vendor) &&
- (probelist[cur].device_id == device))
- return &probelist[cur];
- }
-
- return NULL;
-}
-
-int __init tms_pci_probe(void)
+static int __init tms_pci_attach(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int versionprinted = 0;
- struct pci_dev *pdev = NULL ;
+ static int versionprinted;
struct net_device *dev;
struct net_local *tp;
- int i;
-
- if (!pci_present())
- return (-1); /* No PCI present. */
-
- while ( (pdev=pci_find_class(PCI_CLASS_NETWORK_TOKEN_RING<<8, pdev))) {
- unsigned int pci_irq_line;
- unsigned long pci_ioaddr;
- struct tms_pci_card *card;
- struct cardinfo_table *cardinfo;
+ int i, ret;
+ unsigned int pci_irq_line;
+ unsigned long pci_ioaddr;
+ struct card_info *cardinfo = &card_info_table[ent->driver_data];
- if ((cardinfo =
- tms_pci_getcardinfo(pdev->vendor, pdev->device)) == NULL)
- continue;
+ if (versionprinted++ == 0)
+ printk("%s", version);
- if (versionprinted++ == 0)
- printk("%s", version);
+ if (pci_enable_device(pdev))
+ return -EIO;
- if (pci_enable_device(pdev))
- continue;
+ /* Remove I/O space marker in bit 0. */
+ pci_irq_line = pdev->irq;
+ pci_ioaddr = pci_resource_start (pdev, 0);
- /* Remove I/O space marker in bit 0. */
- pci_irq_line = pdev->irq;
- pci_ioaddr = pci_resource_start (pdev, 0);
+ /* At this point we have found a valid card. */
+ dev = init_trdev(NULL, 0);
+ if (!dev)
+ return -ENOMEM;
+ SET_MODULE_OWNER(dev);
- if(check_region(pci_ioaddr, TMS_PCI_IO_EXTENT))
- continue;
-
- /* At this point we have found a valid card. */
-
- dev = init_trdev(NULL, 0);
- if (!dev) {
- continue; /*return (-ENOMEM);*/ /* continue; ?? */
- }
-
- request_region(pci_ioaddr, TMS_PCI_IO_EXTENT, cardinfo->name); /* XXX check return */
- if(request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
- cardinfo->name, dev)) {
- release_region(pci_ioaddr, TMS_PCI_IO_EXTENT);
- /* XXX free trdev */
- continue; /*return (-ENODEV);*/ /* continue; ?? */
- }
-
- /*
- if (load_tms380_module("tmspci.c")) {
- return 0;
- }
- */
-
- pci_ioaddr &= ~3 ;
- dev->base_addr = pci_ioaddr;
- dev->irq = pci_irq_line;
- dev->dma = 0;
-
- printk("%s: %s\n", dev->name, cardinfo->name);
- printk("%s: IO: %#4lx IRQ: %d\n",
- dev->name, dev->base_addr, dev->irq);
- /*
- * Some cards have their TMS SIF registers offset from
- * their given base address. Account for that here.
- */
- dev->base_addr += cardinfo->registeroffset;
+ if (!request_region(pci_ioaddr, TMS_PCI_IO_EXTENT, dev->name)) {
+ ret = -EBUSY;
+ goto err_out_trdev;
+ }
+
+ ret = request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
+ dev->name, dev);
+ if (ret)
+ goto err_out_region;
+
+ dev->base_addr = pci_ioaddr;
+ dev->irq = pci_irq_line;
+ dev->dma = 0;
+
+ printk("%s: %s\n", dev->name, cardinfo->name);
+ printk("%s: IO: %#4lx IRQ: %d\n",
+ dev->name, dev->base_addr, dev->irq);
- tms_pci_read_eeprom(dev);
+ tms_pci_read_eeprom(dev);
- printk("%s: Ring Station Address: ", dev->name);
- printk("%2.2x", dev->dev_addr[0]);
- for (i = 1; i < 6; i++)
- printk(":%2.2x", dev->dev_addr[i]);
- printk("\n");
+ printk("%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (i = 1; i < 6; i++)
+ printk(":%2.2x", dev->dev_addr[i]);
+ printk("\n");
- if (tmsdev_init(dev)) {
- printk("%s: unable to get memory for dev->priv.\n", dev->name);
- return 0;
- }
-
- tp = (struct net_local *)dev->priv;
- tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */
- tp->setnselout = tms_pci_setnselout_pins;
+ ret = tmsdev_init(dev);
+ if (ret) {
+ printk("%s: unable to get memory for dev->priv.\n", dev->name);
+ goto err_out_irq;
+ }
+
+ tp = dev->priv;
+ tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */
+ tp->setnselout = tms_pci_setnselout_pins;
- tp->sifreadb = tms_pci_sifreadb;
- tp->sifreadw = tms_pci_sifreadw;
- tp->sifwriteb = tms_pci_sifwriteb;
- tp->sifwritew = tms_pci_sifwritew;
+ tp->sifreadb = tms_pci_sifreadb;
+ tp->sifreadw = tms_pci_sifreadw;
+ tp->sifwriteb = tms_pci_sifwriteb;
+ tp->sifwritew = tms_pci_sifwritew;
- memcpy(tp->ProductID, cardinfo->name, PROD_ID_SIZE + 1);
-
- tp->tmspriv = cardinfo;
-
- dev->open = tms_pci_open;
- dev->stop = tms_pci_close;
-
- if (register_trdev(dev) == 0) {
- /* Enlist in the card list */
- card = kmalloc(sizeof(struct tms_pci_card), GFP_KERNEL);
- card->next = tms_pci_card_list;
- tms_pci_card_list = card;
- card->dev = dev;
- card->pci_dev = pdev;
- card->cardinfo = cardinfo;
- } else {
- printk("%s: register_trdev() returned non-zero.\n", dev->name);
- kfree(dev->priv);
- kfree(dev);
- return -1;
- }
- }
+ memcpy(tp->ProductID, cardinfo->name, PROD_ID_SIZE + 1);
+
+ tp->tmspriv = cardinfo;
+
+ dev->open = tms380tr_open;
+ dev->stop = tms380tr_close;
+
+ ret = register_trdev(dev);
+ if (!ret)
+ goto err_out_tmsdev;
- if (tms_pci_card_list)
- return 0;
- return (-1);
+ pci_set_drvdata(pdev, dev);
+ return 0;
+
+err_out_tmsdev:
+ kfree(dev->priv);
+err_out_irq:
+ free_irq(pdev->irq, dev);
+err_out_region:
+ release_region(pci_ioaddr, TMS_PCI_IO_EXTENT);
+err_out_trdev:
+ unregister_netdev(dev);
+ kfree(dev);
+ return ret;
}
/*
@@ -255,11 +206,11 @@ static void tms_pci_read_eeprom(struct net_device *dev)
dev->dev_addr[i] = tms_pci_sifreadw(dev, SIFINC) >> 8;
}
-unsigned short tms_pci_setnselout_pins(struct net_device *dev)
+static unsigned short tms_pci_setnselout_pins(struct net_device *dev)
{
unsigned short val = 0;
- struct net_local *tp = (struct net_local *)dev->priv;
- struct cardinfo_table *cardinfo = (struct cardinfo_table *)tp->tmspriv;
+ struct net_local *tp = dev->priv;
+ struct card_info *cardinfo = tp->tmspriv;
if(tp->DataRate == SPEED_4)
val |= cardinfo->nselout[0]; /* Set 4Mbps */
@@ -268,65 +219,46 @@ unsigned short tms_pci_setnselout_pins(struct net_device *dev)
return val;
}
-static int tms_pci_open(struct net_device *dev)
-{
- tms380tr_open(dev);
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int tms_pci_close(struct net_device *dev)
+static void __exit tms_pci_detach (struct pci_dev *pdev)
{
- tms380tr_close(dev);
- MOD_DEC_USE_COUNT;
- return 0;
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (!dev)
+ BUG();
+ unregister_netdev(dev);
+ release_region(dev->base_addr, TMS_PCI_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ kfree(dev->priv);
+ kfree(dev);
+ pci_set_drvdata(pdev, NULL);
}
-#ifdef MODULE
+static struct pci_driver tms_pci_driver = {
+ name: "tmspci",
+ id_table: tmspci_pci_tbl,
+ probe: tms_pci_attach,
+ remove: tms_pci_detach,
+};
-int init_module(void)
+static int __init tms_pci_init (void)
{
- /* Probe for cards. */
- if (tms_pci_probe()) {
- printk(KERN_NOTICE "tmspci.c: No cards found.\n");
+ int rc = pci_register_driver (&tms_pci_driver);
+ if (rc < 0)
+ return rc;
+ if (rc == 0) {
+ pci_unregister_driver (&tms_pci_driver);
+ return -ENODEV;
}
- /* lock_tms380_module(); */
- return (0);
+ return 0;
}
-void cleanup_module(void)
+static void __exit tms_pci_rmmod (void)
{
- struct net_device *dev;
- struct tms_pci_card *this_card;
-
- while (tms_pci_card_list) {
- dev = tms_pci_card_list->dev;
-
- /*
- * If we used a register offset, revert here.
- */
- if (dev->priv)
- {
- struct net_local *tp;
- struct cardinfo_table *cardinfo;
-
- tp = (struct net_local *)dev->priv;
- cardinfo = (struct cardinfo_table *)tp->tmspriv;
-
- dev->base_addr -= cardinfo->registeroffset;
- }
- unregister_netdev(dev);
- release_region(dev->base_addr, TMS_PCI_IO_EXTENT);
- free_irq(dev->irq, dev);
- kfree(dev->priv);
- kfree(dev);
- this_card = tms_pci_card_list;
- tms_pci_card_list = this_card->next;
- kfree(this_card);
- }
- /* unlock_tms380_module(); */
+ pci_unregister_driver (&tms_pci_driver);
}
-#endif /* MODULE */
+
+module_init(tms_pci_init);
+module_exit(tms_pci_rmmod);
/*
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c
index 17d81a534..e23ad7a6e 100644
--- a/drivers/net/tulip/eeprom.c
+++ b/drivers/net/tulip/eeprom.c
@@ -237,6 +237,7 @@ subsequent_board:
printk(KERN_INFO "%s: Index #%d - Media %s (#%d) described "
"by a %s (%d) block.\n",
dev->name, i, medianame[leaf->media], leaf->media,
+ leaf->type >= ARRAY_SIZE(block_name) ? "UNKNOWN" :
block_name[leaf->type], leaf->type);
}
if (new_advertise)
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index de4af6890..f5d261027 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -52,7 +52,7 @@ const char * const medianame[] = {
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
- || defined(__sparc_)
+ || defined(__sparc_) || defined(__ia64__)
static int rx_copybreak = 1518;
#else
static int rx_copybreak = 100;
@@ -71,11 +71,11 @@ static int rx_copybreak = 100;
ToDo: Non-Intel setting could be better.
*/
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__ia64__)
static int csr0 = 0x01A00000 | 0xE000;
-#elif defined(__i386__) || defined(__powerpc__) || defined(__hppa__)
+#elif defined(__i386__) || defined(__powerpc__)
static int csr0 = 0x01A00000 | 0x8000;
-#elif defined(__sparc__)
+#elif defined(__sparc__) || defined(__hppa__)
/* The UltraSparc PCI controllers will disconnect at every 64-byte
* crossing anyways so it makes no sense to tell Tulip to burst
* any more than that.
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 8a80813aa..0a44dcf9f 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -130,6 +130,7 @@ int tun_net_init(struct net_device *dev)
DBG(KERN_INFO "%s: tun_net_init\n", tun->name);
+ SET_MODULE_OWNER(dev);
dev->open = tun_net_open;
dev->hard_start_xmit = tun_net_xmit;
dev->stop = tun_net_close;
@@ -454,8 +455,6 @@ static int tun_chr_open(struct inode *inode, struct file * file)
tun->dev.init = tun_net_init;
tun->dev.priv = tun;
- MOD_INC_USE_COUNT;
-
return 0;
}
@@ -479,7 +478,6 @@ static int tun_chr_close(struct inode *inode, struct file *file)
kfree(tun);
file->private_data = NULL;
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 9d0947b05..a1d4629af 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -508,6 +508,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
card_idx);
goto err_out_free_dma;
}
+ SET_MODULE_OWNER(dev);
/* request all PIO and MMIO regions just to make sure
* noone else attempts to use any portion of our I/O space */
@@ -694,15 +695,12 @@ static int via_rhine_open(struct net_device *dev)
long ioaddr = dev->base_addr;
int i;
- MOD_INC_USE_COUNT;
-
/* Reset the chip. */
writew(CmdReset, ioaddr + ChipCmd);
- if (request_irq(dev->irq, &via_rhine_interrupt, SA_SHIRQ, dev->name, dev)) {
- MOD_DEC_USE_COUNT;
- return -EBUSY;
- }
+ i = request_irq(dev->irq, &via_rhine_interrupt, SA_SHIRQ, dev->name, dev);
+ if (i)
+ return i;
if (debug > 1)
printk(KERN_DEBUG "%s: via_rhine_open() irq %d.\n",
@@ -712,7 +710,6 @@ static int via_rhine_open(struct net_device *dev)
&np->tx_bufs_dma);
if (np->tx_bufs == NULL) {
free_irq(dev->irq, dev);
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}
@@ -1403,8 +1400,6 @@ static int via_rhine_close(struct net_device *dev)
pci_free_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE,
np->tx_bufs, np->tx_bufs_dma);
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/wan/comx-hw-mixcom.c b/drivers/net/wan/comx-hw-mixcom.c
index 2bf564aba..e6a2837b8 100644
--- a/drivers/net/wan/comx-hw-mixcom.c
+++ b/drivers/net/wan/comx-hw-mixcom.c
@@ -76,7 +76,7 @@ static unsigned char* hscx_versions[]={"A1", NULL, "A2", NULL, "A3", "2.1"};
struct mixcom_privdata {
u16 clock;
char channel;
- char txbusy;
+ long txbusy;
struct sk_buff *sending;
unsigned tx_ptr;
struct sk_buff *recving;
diff --git a/drivers/net/wan/comx.h b/drivers/net/wan/comx.h
index b343eb4ca..1461d5fb1 100644
--- a/drivers/net/wan/comx.h
+++ b/drivers/net/wan/comx.h
@@ -55,12 +55,12 @@ struct comx_channel {
unsigned char line_status;
struct timer_list lineup_timer; // against line jitter
- int lineup_pending;
+ long int lineup_pending;
unsigned char lineup_delay;
#if 0
struct timer_list reset_timer; // for board resetting
- int reset_pending;
+ long reset_pending;
int reset_timeout;
#endif
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
index 520b1341a..4ab0de121 100644
--- a/drivers/net/wan/sdlamain.c
+++ b/drivers/net/wan/sdlamain.c
@@ -106,14 +106,7 @@ static int active; /* number of active cards */
static sdla_t* card_array; /* adapter data space */
/* Task queue element for creating a 'thread' */
-static struct tq_struct sdla_tq =
-{
- NULL, /* .next */
- 0, /* .sync */
- &sdla_poll, /* .routine */
- NULL /* .data */
-};
-
+static struct tq_struct sdla_tq = { routine: sdla_poll };
/******* Kernel Loadable Module Entry Points ********************************/
@@ -480,8 +473,11 @@ static int setup (wan_device_t* wandev, wandev_conf_t* conf)
if(card->hw.type != SDLA_S514 && !card->wandev.piggyback)
request_region(card->hw.port, card->hw.io_range, wandev->name);
- if (++active == 1)
- queue_task(&sdla_tq, &tq_scheduler);
+ if (++active == 1) {
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&sdla_tq) == 0)
+ MOD_DEC_USE_COUNT;
+ }
wandev->critical = 0;
return 0;
@@ -859,8 +855,12 @@ STATIC void sdla_poll (void* data)
card->poll(card);
}
}
- if (active)
- queue_task(&sdla_tq, &tq_scheduler);
+ if (active) {
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&sdla_tq) == 0) /* Surely not? */
+ MOD_DEC_USE_COUNT;
+ }
+ MOD_DEC_USE_COUNT;
}
/*============================================================================
diff --git a/drivers/net/wan/x25_asy.h b/drivers/net/wan/x25_asy.h
index 5abeceb20..c54e2ed18 100644
--- a/drivers/net/wan/x25_asy.h
+++ b/drivers/net/wan/x25_asy.h
@@ -42,7 +42,7 @@ struct x25_asy {
int mtu; /* Our mtu (to spot changes!) */
int buffsize; /* Max buffers sizes */
- unsigned int flags; /* Flag values/ mode etc */
+ unsigned long flags; /* Flag values/ mode etc */
#define SLF_INUSE 0 /* Channel in use */
#define SLF_ESCAPE 1 /* ESC received */
#define SLF_ERROR 2 /* Parity, etc. error */
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index e46844b59..26a26506d 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -86,7 +86,9 @@ int __init wd_probe(struct net_device *dev)
{
int i;
struct resource *r;
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev->base_addr;
+
+ SET_MODULE_OWNER(dev);
if (base_addr > 0x1ff) { /* Check a user specified location. */
r = request_region(base_addr, WD_IO_EXTENT, "wd-probe");
@@ -96,7 +98,7 @@ int __init wd_probe(struct net_device *dev)
if (i != 0)
release_resource(r);
else
- r->name = ei_status.name;
+ r->name = dev->name;
return i;
}
else if (base_addr != 0) /* Don't probe at all. */
@@ -108,7 +110,7 @@ int __init wd_probe(struct net_device *dev)
if (r == NULL)
continue;
if (wd_probe1(dev, ioaddr) == 0) {
- r->name = ei_status.name;
+ r->name = dev->name;
return 0;
}
release_resource(r);
@@ -263,11 +265,12 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
/* Snarf the interrupt now. There's no point in waiting since we cannot
share and the board will usually be enabled. */
- if (request_irq(dev->irq, ei_interrupt, 0, model_name, dev)) {
+ i = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
+ if (i) {
printk (" unable to get IRQ %d.\n", dev->irq);
kfree(dev->priv);
dev->priv = NULL;
- return -EAGAIN;
+ return i;
}
/* OK, were are certain this is going to work. Setup the device. */
@@ -324,7 +327,6 @@ wd_open(struct net_device *dev)
outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
ei_open(dev);
- MOD_INC_USE_COUNT;
return 0;
}
@@ -431,8 +433,6 @@ wd_close(struct net_device *dev)
/* And disable the shared memory. */
outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg);
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/winbond-840.c b/drivers/net/winbond-840.c
index 03f79ca2e..2996fb6f9 100644
--- a/drivers/net/winbond-840.c
+++ b/drivers/net/winbond-840.c
@@ -367,6 +367,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
dev = init_etherdev(NULL, sizeof(*np));
if (!dev)
return -ENOMEM;
+ SET_MODULE_OWNER(dev);
#ifdef USE_IO_OPS
ioaddr = pci_resource_start(pdev, 0);
@@ -623,12 +624,9 @@ static int netdev_open(struct net_device *dev)
writel(0x00000001, ioaddr + PCIBusCfg); /* Reset */
- MOD_INC_USE_COUNT;
-
- if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) {
- MOD_DEC_USE_COUNT;
- return -EAGAIN;
- }
+ i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
+ if (i)
+ return i;
if (debug > 1)
printk(KERN_DEBUG "%s: w89c840_open() irq %d.\n",
@@ -1305,8 +1303,6 @@ static int netdev_close(struct net_device *dev)
np->tx_skbuff[i] = 0;
}
- MOD_DEC_USE_COUNT;
-
return 0;
}
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 4e2d6435e..9cda23333 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -305,9 +305,6 @@ struct yellowfin_private {
for status. */
struct yellowfin_desc rx_ring[RX_RING_SIZE];
struct yellowfin_desc tx_ring[TX_RING_SIZE*2];
- const char *product_name;
- struct net_device *next_module;
- void *priv_addr; /* Unaligned address for kfree */
/* The addresses of receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
@@ -426,8 +423,6 @@ static int yellowfin_open(struct net_device *dev)
printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n",
dev->name, dev->irq);
- MOD_INC_USE_COUNT;
-
yellowfin_init_ring(dev);
YF_OUTL(virt_to_bus(yp->rx_ring), ioaddr + RxPtr);
@@ -1110,8 +1105,6 @@ static int yellowfin_close(struct net_device *dev)
dev->name, bogus_rx);
}
#endif
- MOD_DEC_USE_COUNT;
-
return 0;
}
@@ -1230,24 +1223,19 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
chip_idx = ent->driver_data;
flags = chip_info[chip_idx].flags;
- dev = init_etherdev(NULL, 0);
+ dev = init_etherdev(NULL, sizeof(*yp));
if (!dev) {
printk (KERN_ERR PFX "cannot allocate ethernet device\n");
return -ENOMEM;
}
+ SET_MODULE_OWNER(dev);
- dev->priv = kmalloc(sizeof(*yp) + PRIV_ALIGN, GFP_KERNEL);
- if (!dev->priv)
- goto err_out_free_netdev;
- yp = (void *)(((long)dev->priv + PRIV_ALIGN) & ~PRIV_ALIGN);
- memset(yp, 0, sizeof(*yp));
- yp->priv_addr = dev->priv; /* store real addr for kfree */
- dev->priv = yp; /* use aligned addr */
+ yp = dev->priv;
if (!request_region (pci_resource_start (pdev, 0),
YELLOWFIN_SIZE, YELLOWFIN_MODULE_NAME)) {
printk (KERN_ERR PFX "cannot obtain I/O port region\n");
- goto err_out_free_priv;
+ goto err_out_free_netdev;
}
if (!request_mem_region (pci_resource_start (pdev, 1),
YELLOWFIN_SIZE, YELLOWFIN_MODULE_NAME)) {
@@ -1255,8 +1243,8 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
goto err_out_free_pio_region;
}
- /* XXX check enable_device for failure */
- pci_enable_device (pdev);
+ if (pci_enable_device (pdev))
+ goto err_out_free_mmio_region;
pci_set_master (pdev);
#ifdef USE_IO_OPS
@@ -1264,7 +1252,8 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
#else
real_ioaddr = ioaddr = pci_resource_start (pdev, 1);
ioaddr = (long) ioremap(ioaddr, YELLOWFIN_SIZE);
- /* XXX check for failure */
+ if (!ioaddr)
+ goto err_out_free_mmio_region;
#endif
irq = pdev->irq;
@@ -1348,10 +1337,10 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
return 0;
+err_out_free_mmio_region:
+ release_mem_region (pci_resource_start (pdev, 1), YELLOWFIN_SIZE);
err_out_free_pio_region:
release_region (pci_resource_start (pdev, 0), YELLOWFIN_SIZE);
-err_out_free_priv:
- kfree (dev->priv);
err_out_free_netdev:
unregister_netdev (dev);
kfree (dev);
@@ -1363,23 +1352,18 @@ static void __devexit yellowfin_remove_one (struct pci_dev *pdev)
struct net_device *dev = pdev->driver_data;
struct yellowfin_private *np;
- if (!dev) {
- printk (KERN_ERR "remove non-existent device\n");
- return;
- }
- np = (struct yellowfin_private *) dev->priv;
+ if (!dev)
+ BUG();
+ np = dev->priv;
unregister_netdev (dev);
-#ifdef USE_IO_OPS
release_region (dev->base_addr, YELLOWFIN_SIZE);
-#else
- iounmap ((void *) dev->base_addr);
release_mem_region (dev->base_addr, YELLOWFIN_SIZE);
-#endif
- if (np->priv_addr)
- kfree (np->priv_addr);
+#ifndef USE_IO_OPS
+ iounmap ((void *) dev->base_addr);
+#endif
kfree (dev);
}
@@ -1398,11 +1382,7 @@ static int __init yellowfin_init (void)
if (debug) /* Emit version even if no cards detected. */
printk(KERN_INFO "%s", version);
- if (pci_register_driver (&yellowfin_driver) > 0)
- return 0;
-
- pci_unregister_driver (&yellowfin_driver);
- return -ENODEV;
+ return pci_module_init (&yellowfin_driver);
}
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 47b3d88fe..b07d83358 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -27,8 +27,6 @@
extern void via_nubus_init(void);
extern void oss_nubus_init(void);
-extern int console_loglevel;
-
/* Constants */
/* This is, of course, the size in bytelanes, rather than the size in
@@ -967,8 +965,9 @@ static int nubus_read_proc(char *buf, char **start, off_t off,
int count, int *eof, void *data)
{
int nprinted, len, begin = 0;
- int slot;
-
+ int slot,size;
+ struct nubus_board* board;
+
len = sprintf(buf, "Nubus devices found:\n");
/* Walk the list of NuBus boards */
for (board = nubus_boards; board != NULL; board = board->next)
@@ -987,7 +986,7 @@ static int nubus_read_proc(char *buf, char **start, off_t off,
if (slot==16 || len+begin < off)
*eof = 1;
off -= begin;
- *strat = buf + off;
+ *start = buf + off;
len -= off;
if (len>count)
len = count;
diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog
index 1314e9f9d..8d3c572ab 100644
--- a/drivers/parport/ChangeLog
+++ b/drivers/parport/ChangeLog
@@ -1,3 +1,9 @@
+2000-11-21 Tim Waugh <twaugh@redhat.com>
+
+ * parport_pc.c (parport_pc_ecp_write_block_pio): Fix
+ reverse-to-forward logic. Spotted by Roland Kuck
+ <rci@cityweb.de>.
+
2000-09-16 Cesar Eduardo Barros <cesarb@nitnet.com.br>
* parport_pc.c (sio_via_686a_probe): Handle case
diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile
index 95a778e96..f2f7b1d70 100644
--- a/drivers/parport/Makefile
+++ b/drivers/parport/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_PARPORT_AMIGA) += parport_amiga.o
obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o
obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o
obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o
+obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o
# Extract lists of the multi-part drivers.
# The 'int-*' lists are the intermediate files used to build the multi's.
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index 3c675b88e..e5314cec9 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -1,4 +1,4 @@
-/* Low-level parallel port routines for the Amiga buildin port
+/* Low-level parallel port routines for the Amiga built-in port
*
* Author: Joerg Dorchain <joerg@dorchain.net>
*
@@ -6,9 +6,9 @@
* lp_intern. code.
*
* The built-in Amiga parallel port provides one port at a fixed address
- * with 8 bisdirecttional data lines (D0 - D7) and 3 bidirectional status
- * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically in
- * hardware when the data register is accessed), and 1 input control line
+ * with 8 bidirectional data lines (D0 - D7) and 3 bidirectional status
+ * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically
+ * in hardware when the data register is accessed), and 1 input control line
* /ACK, able to cause an interrupt, but both not directly settable by
* software.
*/
@@ -20,22 +20,24 @@
#include <asm/setup.h>
#include <asm/amigahw.h>
#include <asm/irq.h>
+#include <asm/io.h>
#include <asm/amigaints.h>
#undef DEBUG
#ifdef DEBUG
#define DPRINTK printk
#else
-static inline void DPRINTK(void *nothing, ...) {}
+#define DPRINTK(x...) do { } while (0)
#endif
static struct parport *this_port = NULL;
static void amiga_write_data(struct parport *p, unsigned char data)
{
-DPRINTK("write_data %c\n",data);
+ DPRINTK("write_data %c\n",data);
/* Triggers also /STROBE. This behavior cannot be changed */
ciaa.prb = data;
+ mb();
}
static unsigned char amiga_read_data(struct parport *p)
@@ -71,13 +73,13 @@ static unsigned char control_amiga_to_pc(unsigned char control)
static void amiga_write_control(struct parport *p, unsigned char control)
{
-DPRINTK("write_control %02x\n",control);
+ DPRINTK("write_control %02x\n",control);
/* No implementation possible */
}
static unsigned char amiga_read_control( struct parport *p)
{
-DPRINTK("read_control \n");
+ DPRINTK("read_control \n");
return control_amiga_to_pc(0);
}
@@ -85,7 +87,7 @@ static unsigned char amiga_frob_control( struct parport *p, unsigned char mask,
{
unsigned char old;
-DPRINTK("frob_control mask %02x, value %02x\n",mask,val);
+ DPRINTK("frob_control mask %02x, value %02x\n",mask,val);
old = amiga_read_control(p);
amiga_write_control(p, (old & ~mask) ^ val);
return old;
@@ -130,7 +132,7 @@ static unsigned char amiga_read_status(struct parport *p)
unsigned char status;
status = status_amiga_to_pc(ciab.pra & 7);
-DPRINTK("read_status %02x\n", status);
+ DPRINTK("read_status %02x\n", status);
return status;
}
@@ -154,12 +156,14 @@ static void amiga_data_forward(struct parport *p)
{
DPRINTK("forward\n");
ciaa.ddrb = 0xff; /* all pins output */
+ mb();
}
static void amiga_data_reverse(struct parport *p)
{
DPRINTK("reverse\n");
ciaa.ddrb = 0; /* all pins input */
+ mb();
}
static void amiga_init_state(struct pardevice *dev, struct parport_state *s)
@@ -172,18 +176,22 @@ static void amiga_init_state(struct pardevice *dev, struct parport_state *s)
static void amiga_save_state(struct parport *p, struct parport_state *s)
{
+ mb();
s->u.amiga.data = ciaa.prb;
s->u.amiga.datadir = ciaa.ddrb;
s->u.amiga.status = ciab.pra & 7;
s->u.amiga.statusdir = ciab.ddra & 7;
+ mb();
}
static void amiga_restore_state(struct parport *p, struct parport_state *s)
{
+ mb();
ciaa.prb = s->u.amiga.data;
ciaa.ddrb = s->u.amiga.datadir;
ciab.pra |= (ciab.pra & 0xf8) | s->u.amiga.status;
ciab.ddra |= (ciab.ddra & 0xf8) | s->u.amiga.statusdir;
+ mb();
}
static void amiga_inc_use_count(void)
@@ -238,56 +246,58 @@ static struct parport_operations pp_amiga_ops = {
int __init parport_amiga_init(void)
{
struct parport *p;
+ int err;
- if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) {
- if (!request_mem_region(CIAA_PHYSADDR+0x100, 1, "parallel"))
- return 0;
- ciaa.ddrb = 0xff;
- ciab.ddra &= 0xf8;
- if (!(p = parport_register_port((unsigned long)&ciaa.prb,
- IRQ_AMIGA_CIAA_FLG, PARPORT_DMA_NONE,
- &pp_amiga_ops))) {
- release_mem_region(CIAA_PHYSADDR+0x100, 1);
- return 0;
- }
- if (!request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p)) {
- parport_unregister_port (p);
- release_mem_region(CIAA_PHYSADDR+0x100, 1);
- return 0;
- }
-
- this_port = p;
- printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
- /* XXX: set operating mode */
- parport_proc_register(p);
-
- parport_announce_port(p);
-
- return 1;
-
- }
- return 0;
-}
+ if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL))
+ return -ENODEV;
-#ifdef MODULE
+ err = -EBUSY;
+ if (!request_mem_region(CIAA_PHYSADDR-1+0x100, 0x100, "parallel"))
+ goto out_mem;
-MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
-MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
-MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port");
+ ciaa.ddrb = 0xff;
+ ciab.ddra &= 0xf8;
+ mb();
-int init_module(void)
-{
- return ! parport_amiga_init();
+ p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG,
+ PARPORT_DMA_NONE, &pp_amiga_ops);
+ if (!p)
+ goto out_port;
+
+ err = request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p);
+ if (err)
+ goto out_irq;
+
+ this_port = p;
+ printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
+ /* XXX: set operating mode */
+ parport_proc_register(p);
+
+ parport_announce_port(p);
+
+ return 0;
+
+out_irq:
+ parport_unregister_port(p);
+out_port:
+ release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
+out_mem:
+ return err;
}
-void cleanup_module(void)
+void __exit parport_amiga_exit(void)
{
if (this_port->irq != PARPORT_IRQ_NONE)
free_irq(IRQ_AMIGA_CIAA_FLG, this_port);
parport_proc_unregister(this_port);
parport_unregister_port(this_port);
- release_mem_region(CIAA_PHYSADDR+0x100, 1);
+ release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
}
-#endif
+MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
+MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
+MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port");
+
+module_init(parport_amiga_init)
+module_exit(parport_amiga_exit)
diff --git a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c
index 8df0e5a33..c6ee0ac4b 100644
--- a/drivers/parport/parport_atari.c
+++ b/drivers/parport/parport_atari.c
@@ -113,6 +113,46 @@ parport_atari_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
static void
+parport_atari_enable_irq(struct parport *p)
+{
+ enable_irq(IRQ_MFP_BUSY);
+}
+
+static void
+parport_atari_disable_irq(struct parport *p)
+{
+ disable_irq(IRQ_MFP_BUSY);
+}
+
+static void
+parport_atari_data_forward(struct parport *p)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ /* Soundchip port B as output. */
+ sound_ym.rd_data_reg_sel = 7;
+ sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x40;
+ restore_flags(flags);
+}
+
+static void
+parport_atari_data_reverse(struct parport *p)
+{
+#if 0 /* too dangerous, can kill sound chip */
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ /* Soundchip port B as input. */
+ sound_ym.rd_data_reg_sel = 7;
+ sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~0x40;
+ restore_flags(flags);
+#endif
+}
+
+static void
parport_atari_inc_use_count(void)
{
MOD_INC_USE_COUNT;
@@ -134,11 +174,11 @@ static struct parport_operations parport_atari_ops = {
parport_atari_read_status,
- NULL, /* enable_irq - FIXME */
- NULL, /* disable_irq - FIXME */
+ parport_atari_enable_irq,
+ parport_atari_disable_irq,
- NULL, /* data_forward - FIXME */
- NULL, /* data_reverse - FIXME */
+ parport_atari_data_forward,
+ parport_atari_data_reverse,
parport_atari_init_state,
parport_atari_save_state,
@@ -147,18 +187,18 @@ static struct parport_operations parport_atari_ops = {
parport_atari_inc_use_count,
parport_atari_dec_use_count,
- NULL, /* epp_write_data */
- NULL, /* epp_read_data */
- NULL, /* epp_write_addr */
- NULL, /* epp_read_addr */
+ parport_ieee1284_epp_write_data,
+ parport_ieee1284_epp_read_data,
+ parport_ieee1284_epp_write_addr,
+ parport_ieee1284_epp_read_addr,
- NULL, /* ecp_write_data */
- NULL, /* ecp_read_data */
- NULL, /* ecp_write_addr */
+ parport_ieee1284_ecp_write_data,
+ parport_ieee1284_ecp_read_data,
+ parport_ieee1284_ecp_write_addr,
- NULL, /* compat_write_data */
- NULL, /* nibble_read_data */
- NULL, /* byte_read_data */
+ parport_ieee1284_write_compat,
+ parport_ieee1284_read_nibble,
+ parport_ieee1284_read_byte,
};
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
new file mode 100644
index 000000000..8e4b177e3
--- /dev/null
+++ b/drivers/parport/parport_gsc.c
@@ -0,0 +1,573 @@
+/*
+ * Low-level parallel-support for PC-style hardware integrated in the
+ * LASI-Controller (on GSC-Bus) for HP-PARISC Workstations
+ *
+ * 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.
+ *
+ * by Helge Deller <deller@gmx.de>
+ *
+ *
+ * based on parport_pc.c by
+ * Grant Guenther <grant@torque.net>
+ * Phil Blundell <Philip.Blundell@pobox.com>
+ * Tim Waugh <tim@cyberelk.demon.co.uk>
+ * Jose Renau <renau@acm.org>
+ * David Campbell <campbell@torque.net>
+ * Andrea Arcangeli
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/pci.h>
+#include <linux/sysctl.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+#include <linux/parport.h>
+#include <asm/gsc.h>
+#include <asm/pdc.h>
+#include <asm/hardware.h>
+#include <asm/parport_gsc.h>
+
+
+#undef DEBUG /* undef for production */
+
+#ifdef DEBUG
+#define DPRINTK printk
+#else
+#define DPRINTK(stuff...)
+#endif
+
+
+/*
+ * Clear TIMEOUT BIT in EPP MODE
+ *
+ * This is also used in SPP detection.
+ */
+static int clear_epp_timeout(struct parport *pb)
+{
+ unsigned char r;
+
+ if (!(parport_gsc_read_status(pb) & 0x01))
+ return 1;
+
+ /* To clear timeout some chips require double read */
+ parport_gsc_read_status(pb);
+ r = parport_gsc_read_status(pb);
+ parport_writeb (r | 0x01, STATUS (pb)); /* Some reset by writing 1 */
+ parport_writeb (r & 0xfe, STATUS (pb)); /* Others by writing 0 */
+ r = parport_gsc_read_status(pb);
+
+ return !(r & 0x01);
+}
+
+/*
+ * Access functions.
+ *
+ * Most of these aren't static because they may be used by the
+ * parport_xxx_yyy macros. extern __inline__ versions of several
+ * of these are in parport_gsc.h.
+ */
+
+static void parport_gsc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ DPRINTK(__FILE__ ": got IRQ\n");
+ parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
+void parport_gsc_write_data(struct parport *p, unsigned char d)
+{
+ DPRINTK(__FILE__ ": write (0x%02x) %c \n", d, d);
+ parport_writeb (d, DATA (p));
+}
+
+unsigned char parport_gsc_read_data(struct parport *p)
+{
+#ifdef DEBUG
+ unsigned char c = parport_readb (DATA (p));
+ DPRINTK(__FILE__ ": read (0x%02x) %c\n", c,c);
+ return c;
+#else
+ return parport_readb (DATA (p));
+#endif
+}
+
+void parport_gsc_write_control(struct parport *p, unsigned char d)
+{
+ const unsigned char wm = (PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_INIT |
+ PARPORT_CONTROL_SELECT);
+
+ /* Take this out when drivers have adapted to the newer interface. */
+ if (d & 0x20) {
+ printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
+ p->name, p->cad->name);
+ parport_gsc_data_reverse (p);
+ }
+
+ __parport_gsc_frob_control (p, wm, d & wm);
+}
+
+unsigned char parport_gsc_read_control(struct parport *p)
+{
+ const unsigned char wm = (PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_INIT |
+ PARPORT_CONTROL_SELECT);
+ const struct parport_gsc_private *priv = p->physport->private_data;
+ return priv->ctr & wm; /* Use soft copy */
+}
+
+unsigned char parport_gsc_frob_control (struct parport *p, unsigned char mask,
+ unsigned char val)
+{
+ const unsigned char wm = (PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_INIT |
+ PARPORT_CONTROL_SELECT);
+
+ /* Take this out when drivers have adapted to the newer interface. */
+ if (mask & 0x20) {
+ printk (KERN_DEBUG "%s (%s): use data_%s for this!\n",
+ p->name, p->cad->name,
+ (val & 0x20) ? "reverse" : "forward");
+ if (val & 0x20)
+ parport_gsc_data_reverse (p);
+ else
+ parport_gsc_data_forward (p);
+ }
+
+ /* Restrict mask and val to control lines. */
+ mask &= wm;
+ val &= wm;
+
+ return __parport_gsc_frob_control (p, mask, val);
+}
+
+unsigned char parport_gsc_read_status(struct parport *p)
+{
+ return parport_readb (STATUS (p));
+}
+
+void parport_gsc_disable_irq(struct parport *p)
+{
+ __parport_gsc_frob_control (p, 0x10, 0);
+}
+
+void parport_gsc_enable_irq(struct parport *p)
+{
+ __parport_gsc_frob_control (p, 0x10, 0x10);
+}
+
+void parport_gsc_data_forward (struct parport *p)
+{
+ __parport_gsc_frob_control (p, 0x20, 0);
+}
+
+void parport_gsc_data_reverse (struct parport *p)
+{
+ __parport_gsc_frob_control (p, 0x20, 0x20);
+}
+
+void parport_gsc_init_state(struct pardevice *dev, struct parport_state *s)
+{
+ s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
+}
+
+void parport_gsc_save_state(struct parport *p, struct parport_state *s)
+{
+ s->u.pc.ctr = parport_readb (CONTROL (p));
+}
+
+void parport_gsc_restore_state(struct parport *p, struct parport_state *s)
+{
+ parport_writeb (s->u.pc.ctr, CONTROL (p));
+}
+
+void parport_gsc_inc_use_count(void)
+{
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif
+}
+
+void parport_gsc_dec_use_count(void)
+{
+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
+
+struct parport_operations parport_gsc_ops =
+{
+ write_data: parport_gsc_write_data,
+ read_data: parport_gsc_read_data,
+
+ write_control: parport_gsc_write_control,
+ read_control: parport_gsc_read_control,
+ frob_control: parport_gsc_frob_control,
+
+ read_status: parport_gsc_read_status,
+
+ enable_irq: parport_gsc_enable_irq,
+ disable_irq: parport_gsc_disable_irq,
+
+ data_forward: parport_gsc_data_forward,
+ data_reverse: parport_gsc_data_reverse,
+
+ init_state: parport_gsc_init_state,
+ save_state: parport_gsc_save_state,
+ restore_state: parport_gsc_restore_state,
+
+ inc_use_count: parport_gsc_inc_use_count,
+ dec_use_count: parport_gsc_dec_use_count,
+
+ epp_write_data: parport_ieee1284_epp_write_data,
+ epp_read_data: parport_ieee1284_epp_read_data,
+ epp_write_addr: parport_ieee1284_epp_write_addr,
+ epp_read_addr: parport_ieee1284_epp_read_addr,
+
+ ecp_write_data: parport_ieee1284_ecp_write_data,
+ ecp_read_data: parport_ieee1284_ecp_read_data,
+ ecp_write_addr: parport_ieee1284_ecp_write_addr,
+
+ compat_write_data: parport_ieee1284_write_compat,
+ nibble_read_data: parport_ieee1284_read_nibble,
+ byte_read_data: parport_ieee1284_read_byte,
+};
+
+/* --- Mode detection ------------------------------------- */
+
+/*
+ * Checks for port existence, all ports support SPP MODE
+ */
+static int __devinit parport_SPP_supported(struct parport *pb)
+{
+ unsigned char r, w;
+
+ /*
+ * first clear an eventually pending EPP timeout
+ * I (sailer@ife.ee.ethz.ch) have an SMSC chipset
+ * that does not even respond to SPP cycles if an EPP
+ * timeout is pending
+ */
+ clear_epp_timeout(pb);
+
+ /* Do a simple read-write test to make sure the port exists. */
+ w = 0xc;
+ parport_writeb (w, CONTROL (pb));
+
+ /* Is there a control register that we can read from? Some
+ * ports don't allow reads, so read_control just returns a
+ * software copy. Some ports _do_ allow reads, so bypass the
+ * software copy here. In addition, some bits aren't
+ * writable. */
+ r = parport_readb (CONTROL (pb));
+ if ((r & 0xf) == w) {
+ w = 0xe;
+ parport_writeb (w, CONTROL (pb));
+ r = parport_readb (CONTROL (pb));
+ parport_writeb (0xc, CONTROL (pb));
+ if ((r & 0xf) == w)
+ return PARPORT_MODE_PCSPP;
+ }
+
+ /* Try the data register. The data lines aren't tri-stated at
+ * this stage, so we expect back what we wrote. */
+ w = 0xaa;
+ parport_gsc_write_data (pb, w);
+ r = parport_gsc_read_data (pb);
+ if (r == w) {
+ w = 0x55;
+ parport_gsc_write_data (pb, w);
+ r = parport_gsc_read_data (pb);
+ if (r == w)
+ return PARPORT_MODE_PCSPP;
+ }
+
+ return 0;
+}
+
+/* Detect PS/2 support.
+ *
+ * Bit 5 (0x20) sets the PS/2 data direction; setting this high
+ * allows us to read data from the data lines. In theory we would get back
+ * 0xff but any peripheral attached to the port may drag some or all of the
+ * lines down to zero. So if we get back anything that isn't the contents
+ * of the data register we deem PS/2 support to be present.
+ *
+ * Some SPP ports have "half PS/2" ability - you can't turn off the line
+ * drivers, but an external peripheral with sufficiently beefy drivers of
+ * its own can overpower them and assert its own levels onto the bus, from
+ * where they can then be read back as normal. Ports with this property
+ * and the right type of device attached are likely to fail the SPP test,
+ * (as they will appear to have stuck bits) and so the fact that they might
+ * be misdetected here is rather academic.
+ */
+
+static int __devinit parport_PS2_supported(struct parport *pb)
+{
+ int ok = 0;
+
+ clear_epp_timeout(pb);
+
+ /* try to tri-state the buffer */
+ parport_gsc_data_reverse (pb);
+
+ parport_gsc_write_data(pb, 0x55);
+ if (parport_gsc_read_data(pb) != 0x55) ok++;
+
+ parport_gsc_write_data(pb, 0xaa);
+ if (parport_gsc_read_data(pb) != 0xaa) ok++;
+
+ /* cancel input mode */
+ parport_gsc_data_forward (pb);
+
+ if (ok) {
+ pb->modes |= PARPORT_MODE_TRISTATE;
+ } else {
+ struct parport_gsc_private *priv = pb->private_data;
+ priv->ctr_writable &= ~0x20;
+ }
+
+ return ok;
+}
+
+
+/* --- Initialisation code -------------------------------- */
+
+struct parport *__devinit parport_gsc_probe_port (unsigned long base,
+ unsigned long base_hi,
+ int irq, int dma,
+ struct pci_dev *dev)
+{
+ struct parport_gsc_private *priv;
+ struct parport_operations *ops;
+ struct parport tmp;
+ struct parport *p = &tmp;
+
+ if (check_region(base, 3))
+ return NULL;
+
+ priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL);
+ if (!priv) {
+ printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
+ return NULL;
+ }
+ ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
+ if (!ops) {
+ printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
+ base);
+ kfree (priv);
+ return NULL;
+ }
+ memcpy (ops, &parport_gsc_ops, sizeof (struct parport_operations));
+ priv->ctr = 0xc;
+ priv->ctr_writable = 0xff;
+ priv->dma_buf = 0;
+ priv->dma_handle = 0;
+ priv->dev = dev;
+ p->base = base;
+ p->base_hi = base_hi;
+ p->irq = irq;
+ p->dma = dma;
+ p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
+ p->ops = ops;
+ p->private_data = priv;
+ p->physport = p;
+ if (!parport_SPP_supported (p)) {
+ /* No port. */
+ kfree (priv);
+ return NULL;
+ }
+ parport_PS2_supported (p);
+
+ if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
+ PARPORT_DMA_NONE, ops))) {
+ kfree (priv);
+ kfree (ops);
+ return NULL;
+ }
+
+ p->base_hi = base_hi;
+ p->modes = tmp.modes;
+ p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
+ p->private_data = priv;
+
+ printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
+ p->irq = irq;
+ if (p->irq == PARPORT_IRQ_AUTO) {
+ p->irq = PARPORT_IRQ_NONE;
+ }
+ if (p->irq != PARPORT_IRQ_NONE) {
+ printk(", irq %d", p->irq);
+
+ if (p->dma == PARPORT_DMA_AUTO) {
+ p->dma = PARPORT_DMA_NONE;
+ }
+ }
+ if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq
+ is mandatory (see above) */
+ p->dma = PARPORT_DMA_NONE;
+
+ printk(" [");
+#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}
+ {
+ int f = 0;
+ printmode(PCSPP);
+ printmode(TRISTATE);
+ printmode(COMPAT)
+ printmode(EPP);
+// printmode(ECP);
+// printmode(DMA);
+ }
+#undef printmode
+ printk("]\n");
+ parport_proc_register(p);
+
+ request_region (p->base, 3, p->name);
+ if (p->size > 3)
+ request_region (p->base + 3, p->size - 3, p->name);
+ if (p->modes & PARPORT_MODE_ECP)
+ request_region (p->base_hi, 3, p->name);
+
+ if (p->irq != PARPORT_IRQ_NONE) {
+ if (request_irq (p->irq, parport_gsc_interrupt,
+ 0, p->name, p)) {
+ printk (KERN_WARNING "%s: irq %d in use, "
+ "resorting to polled operation\n",
+ p->name, p->irq);
+ p->irq = PARPORT_IRQ_NONE;
+ p->dma = PARPORT_DMA_NONE;
+ }
+ }
+
+ /* Done probing. Now put the port into a sensible start-up state. */
+
+ parport_gsc_write_data(p, 0);
+ parport_gsc_data_forward (p);
+
+ /* Now that we've told the sharing engine about the port, and
+ found out its characteristics, let the high-level drivers
+ know about it. */
+ parport_announce_port (p);
+
+ return p;
+}
+
+
+#define PARPORT_GSC_OFFSET 0x800
+
+static int __initdata parport_count;
+
+static int __init
+parport_init_chip(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ unsigned long port;
+ int irq;
+
+ irq = busdevice_alloc_irq(d);
+
+ if (!irq) {
+ printk("IRQ not found for parallel device at 0x%p\n", d->hpa);
+ return -ENODEV;
+ }
+
+ port = ((unsigned long) d->hpa) + PARPORT_GSC_OFFSET;
+
+ /*
+ some older machines with ASP-chip don't support the enhanced parport modes
+ */
+ if (!pdc_add_valid( (void *)(port+4))) {
+ /* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */
+ printk("%s: initialize bidirectional-mode.\n", __FUNCTION__);
+ parport_writeb ( (0x10 + 0x20), port + 4);
+ } else {
+ printk("%s: enhanced parport-modes not supported.\n", __FUNCTION__);
+ }
+
+ if (parport_gsc_probe_port(port, 0,
+ irq, /* PARPORT_IRQ_NONE */
+ PARPORT_DMA_NONE, NULL))
+ parport_count++;
+
+ return 0;
+}
+
+static struct pa_iodc_driver parport_drivers_for[] __initdata = {
+ {HPHW_FIO, 0x0, 0x0, 0x74, 0x0, 0, /* 715/64 */
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ "parallel device", "HP 7xx - Series", (void *) parport_init_chip},
+ { 0 }
+};
+
+int __init
+parport_gsc_init ( void )
+{
+ parport_count = 0;
+
+ register_driver(parport_drivers_for);
+
+ return parport_count;
+}
+
+/* Exported symbols. */
+EXPORT_NO_SYMBOLS;
+
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Helge Deller <deller@gmx.de>");
+MODULE_DESCRIPTION("HP-PARISC PC-style parallel port driver");
+MODULE_SUPPORTED_DEVICE("integrated PC-style parallel port");
+
+int init_module(void)
+{
+ return !parport_gsc_init ();
+}
+
+void cleanup_module(void)
+{
+ struct parport *p = parport_enumerate(), *tmp;
+ while (p) {
+ tmp = p->next;
+ if (p->modes & PARPORT_MODE_PCSPP) {
+ struct parport_gsc_private *priv = p->private_data;
+ struct parport_operations *ops = p->ops;
+ if (p->dma != PARPORT_DMA_NONE)
+ free_dma(p->dma);
+ if (p->irq != PARPORT_IRQ_NONE)
+ free_irq(p->irq, p);
+ release_region(p->base, 3);
+ if (p->size > 3)
+ release_region(p->base + 3, p->size - 3);
+ if (p->modes & PARPORT_MODE_ECP)
+ release_region(p->base_hi, 3);
+ parport_proc_unregister(p);
+ if (priv->dma_buf)
+ pci_free_consistent(priv->dev, PAGE_SIZE,
+ priv->dma_buf,
+ priv->dma_handle);
+ kfree (p->private_data);
+ parport_unregister_port(p);
+ kfree (ops); /* hope no-one cached it */
+ }
+ p = tmp;
+ }
+}
+#endif
diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c
index 19045439e..51e80b4ce 100644
--- a/drivers/parport/parport_mfc3.c
+++ b/drivers/parport/parport_mfc3.c
@@ -332,75 +332,83 @@ static struct parport_operations pp_mfc3_ops = {
int __init parport_mfc3_init(void)
{
struct parport *p;
- int pias = 0;
+ int pias;
struct pia *pp;
struct zorro_dev *z = NULL;
if (!MACH_IS_AMIGA)
- return 0;
+ return -ENODEV;
while ((z = zorro_find_device(ZORRO_PROD_BSC_MULTIFACE_III, z))) {
unsigned long piabase = z->resource.start+PIABASE;
if (!request_mem_region(piabase, sizeof(struct pia), "PIA"))
continue;
+
pp = (struct pia *)ZTWO_VADDR(piabase);
- if (pias < MAX_MFC) {
- pp->crb = 0;
- pp->pddrb = 255; /* all data pins output */
- pp->crb = PIA_DDR|32|8;
- dummy = pp->pddrb; /* reading clears interrupt */
- pp->cra = 0;
- pp->pddra = 0xe0; /* /RESET, /DIR ,/AUTO-FEED output */
- pp->cra = PIA_DDR;
- pp->ppra = 0; /* reset printer */
- udelay(10);
- pp->ppra = 128;
- if ((p = parport_register_port((unsigned long)pp,
- IRQ_AMIGA_PORTS, PARPORT_DMA_NONE,
- &pp_mfc3_ops))) {
- this_port[pias++] = p;
- printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
- /* XXX: set operating mode */
- parport_proc_register(p);
-
- if (p->irq != PARPORT_IRQ_NONE)
- if (use_cnt++ == 0)
- if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, SA_SHIRQ, p->name, &pp_mfc3_ops))
- use_cnt--;
-
- p->private_data = (void *)piabase;
- parport_announce_port (p);
- }
+ pp->crb = 0;
+ pp->pddrb = 255; /* all data pins output */
+ pp->crb = PIA_DDR|32|8;
+ dummy = pp->pddrb; /* reading clears interrupt */
+ pp->cra = 0;
+ pp->pddra = 0xe0; /* /RESET, /DIR ,/AUTO-FEED output */
+ pp->cra = PIA_DDR;
+ pp->ppra = 0; /* reset printer */
+ udelay(10);
+ pp->ppra = 128;
+ p = parport_register_port((unsigned long)pp, IRQ_AMIGA_PORTS,
+ PARPORT_DMA_NONE, &pp_mfc3_ops);
+ if (!p)
+ goto out_port;
+
+ if (p->irq != PARPORT_IRQ_NONE) {
+ if (use_cnt++ == 0)
+ if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, SA_SHIRQ, p->name, &pp_mfc3_ops))
+ goto out_irq;
}
- }
- return pias;
-}
-#ifdef MODULE
+ this_port[pias++] = p;
+ printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
+ /* XXX: set operating mode */
+ parport_proc_register(p);
-MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
-MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Paralllel Port");
-MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port");
+ p->private_data = (void *)piabase;
+ parport_announce_port (p);
-int init_module(void)
-{
- return ! parport_mfc3_init();
+ if (pias >= MAX_MFC)
+ break;
+ continue;
+
+ out_irq:
+ parport_unregister_port(p);
+ out_port:
+ release_mem_region(piabase, sizeof(struct pia));
+ }
+
+ return pias ? 0 : -ENODEV;
}
-void cleanup_module(void)
+void __exit parport_mfc3_exit(void)
{
int i;
- for (i = 0; i < MAX_MFC; i++)
- if (this_port[i] != NULL) {
- if (p->irq != PARPORT_IRQ_NONE)
- if (--use_cnt == 0)
- free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);
- parport_proc_unregister(this_port[i]);
- parport_unregister_port(this_port[i]);
- release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia));
+ for (i = 0; i < MAX_MFC; i++) {
+ if (!this_port[i])
+ continue;
+ if (!this_port[i]->irq != PARPORT_IRQ_NONE) {
+ if (--use_cnt == 0)
+ free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);
}
+ parport_proc_unregister(this_port[i]);
+ parport_unregister_port(this_port[i]);
+ release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia));
+ }
}
-#endif
+MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
+MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Paralllel Port");
+MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port");
+
+module_init(parport_mfc3_init)
+module_exit(parport_mfc3_exit)
+
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 952eaec41..fe6721c34 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -778,9 +778,13 @@ size_t parport_pc_ecp_write_block_pio (struct parport *port,
/* Switch to forward mode if necessary. */
if (port->physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) {
/* Event 47: Set nInit high. */
- parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
+ parport_frob_control (port,
+ PARPORT_CONTROL_INIT
+ | PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_INIT
+ | PARPORT_CONTROL_AUTOFD);
- /* Event 40: PError goes high. */
+ /* Event 49: PError goes high. */
r = parport_wait_peripheral (port,
PARPORT_STATUS_PAPEROUT,
PARPORT_STATUS_PAPEROUT);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f90c23520..a6dc39f43 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -300,18 +300,25 @@ static int
pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
{
const struct pci_device_id *id;
+ int ret = 0;
if (drv->id_table) {
id = pci_match_device(drv->id_table, dev);
- if (!id)
- return 0;
+ if (!id) {
+ ret = 0;
+ goto out;
+ }
} else
id = NULL;
+
+ dev_probe_lock();
if (drv->probe(dev, id) >= 0) {
dev->driver = drv;
- return 1;
+ ret = 1;
}
- return 0;
+ dev_probe_unlock();
+out:
+ return ret;
}
int
@@ -354,16 +361,16 @@ static void
run_sbin_hotplug(struct pci_dev *pdev, int insert)
{
int i;
- char *argv[3], *envp[7];
- char id[20], sub_id[24], bus_id[64], class_id[20];
+ char *argv[3], *envp[8];
+ char id[20], sub_id[24], bus_id[24], class_id[20];
if (!hotplug_path[0])
return;
- sprintf(class_id, "PCI_CLASS=%X", pdev->class >> 8);
- sprintf(id, "PCI_ID=%X/%X", pdev->vendor, pdev->device);
- sprintf(sub_id, "PCI_SUBSYS_ID=%X/%X", pdev->subsystem_vendor, pdev->subsystem_device);
- sprintf(bus_id, "PCI_BUS_ID=%s", pdev->slot_name);
+ sprintf(class_id, "PCI_CLASS=%04X", pdev->class);
+ sprintf(id, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device);
+ sprintf(sub_id, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, pdev->subsystem_device);
+ sprintf(bus_id, "PCI_SLOT_NAME=%s", pdev->slot_name);
i = 0;
argv[i++] = hotplug_path;
@@ -376,6 +383,7 @@ run_sbin_hotplug(struct pci_dev *pdev, int insert)
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
/* other stuff we want to pass to /sbin/hotplug */
+ envp[i++] = class_id;
envp[i++] = id;
envp[i++] = sub_id;
envp[i++] = bus_id;
@@ -539,15 +547,9 @@ static u32 pci_size(u32 base, unsigned long mask)
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
{
unsigned int pos, reg, next;
- u32 l, sz, tmp;
- u16 cmd;
+ u32 l, sz;
struct resource *res;
- /* Disable IO and memory while we fiddle */
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
- pci_write_config_word(dev, PCI_COMMAND, tmp);
-
for(pos=0; pos<howmany; pos = next) {
next = pos+1;
res = &dev->resource[pos];
@@ -578,10 +580,11 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
res->start |= ((unsigned long) l) << 32;
res->end = res->start + sz;
pci_write_config_dword(dev, reg+4, ~0);
- pci_read_config_dword(dev, reg+4, &tmp);
+ pci_read_config_dword(dev, reg+4, &sz);
pci_write_config_dword(dev, reg+4, l);
- if (l)
- res->end = res->start + (((unsigned long) ~l) << 32);
+ if (~sz)
+ res->end = res->start + 0xffffffff +
+ (((unsigned long) ~sz) << 32);
#else
if (l) {
printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", dev->slot_name);
@@ -610,7 +613,6 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
}
res->name = dev->name;
}
- pci_write_config_word(dev, PCI_COMMAND, cmd);
}
void __init pci_read_bridge_bases(struct pci_bus *child)
@@ -710,6 +712,7 @@ static struct pci_bus * __init pci_alloc_bus(void)
static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
{
struct pci_bus *child;
+ int i;
/*
* Allocate a new bus, and inherit stuff from the parent..
@@ -731,6 +734,10 @@ static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pc
child->primary = parent->secondary;
child->subordinate = 0xff;
+ /* Set up default resource pointers.. */
+ for (i = 0; i < 4; i++)
+ child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
+
return child;
}
@@ -755,7 +762,7 @@ static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass);
- if ((buses & 0xffffff) && !pcibios_assign_all_busses()) {
+ if ((buses & 0xffff00) && !pcibios_assign_all_busses()) {
/*
* Bus already configured by firmware, process it in the first
* pass and just note the configuration.
@@ -771,9 +778,8 @@ static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int
unsigned int cmax = pci_do_scan_bus(child);
if (cmax > max) max = cmax;
} else {
- int i;
- for (i = 0; i < 4; i++)
- child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
+ unsigned int cmax = child->subordinate;
+ if (cmax > max) max = cmax;
}
} else {
/*
@@ -786,6 +792,7 @@ static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int
pci_read_config_word(dev, PCI_COMMAND, &cr);
pci_write_config_word(dev, PCI_COMMAND, 0x0000);
pci_write_config_word(dev, PCI_STATUS, 0xffff);
+
child = pci_add_new_bus(bus, dev, ++max);
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
@@ -799,15 +806,12 @@ static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int
/* Now we can scan all subordinate buses... */
max = pci_do_scan_bus(child);
} else {
- int i;
/*
* For CardBus bridges, we leave 4 bus numbers
* as cards with a PCI-to-PCI bridge can be
* inserted later.
*/
max += 3;
- for (i = 0; i < 4; i++)
- child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
}
/*
* Set the subordinate bus number to its real value.
@@ -1086,6 +1090,9 @@ static int pci_pm_resume_device(struct pci_dev *dev)
return 0;
}
+
+/* take care to suspend/resume bridges only once */
+
static int pci_pm_suspend_bus(struct pci_bus *bus)
{
struct list_head *list;
@@ -1097,9 +1104,6 @@ static int pci_pm_suspend_bus(struct pci_bus *bus)
/* Walk the device children list */
list_for_each(list, &bus->devices)
pci_pm_suspend_device(pci_dev_b(list));
-
- /* Suspend the bus controller.. */
- pci_pm_suspend_device(bus->self);
return 0;
}
@@ -1107,8 +1111,6 @@ static int pci_pm_resume_bus(struct pci_bus *bus)
{
struct list_head *list;
- pci_pm_resume_device(bus->self);
-
/* Walk the device children list */
list_for_each(list, &bus->devices)
pci_pm_resume_device(pci_dev_b(list));
@@ -1122,18 +1124,26 @@ static int pci_pm_resume_bus(struct pci_bus *bus)
static int pci_pm_suspend(void)
{
struct list_head *list;
+ struct pci_bus *bus;
- list_for_each(list, &pci_root_buses)
- pci_pm_suspend_bus(pci_bus_b(list));
+ list_for_each(list, &pci_root_buses) {
+ bus = pci_bus_b(list);
+ pci_pm_suspend_bus(bus);
+ pci_pm_suspend_device(bus->self);
+ }
return 0;
}
static int pci_pm_resume(void)
{
struct list_head *list;
+ struct pci_bus *bus;
- list_for_each(list, &pci_root_buses)
- pci_pm_resume_bus(pci_bus_b(list));
+ list_for_each(list, &pci_root_buses) {
+ bus = pci_bus_b(list);
+ pci_pm_resume_device(bus->self);
+ pci_pm_resume_bus(bus);
+ }
return 0;
}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 401185890..ace49456b 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -9,148 +9,241 @@
* Support routines for initializing a PCI subsystem.
*/
+/*
+ * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+ * PCI-PCI bridges cleanup, sorted resource allocation
+ */
+
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/cache.h>
+#include <linux/slab.h>
-#define DEBUG_CONFIG 0
+#define DEBUG_CONFIG 1
#if DEBUG_CONFIG
# define DBGC(args) printk args
#else
# define DBGC(args)
#endif
-
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
-#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
-static void __init
-pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
+static int __init
+pbus_assign_resources_sorted(struct pci_bus *bus,
+ struct pbus_set_ranges_data *ranges)
{
- struct pbus_set_ranges_data inner;
- struct pci_dev *dev;
struct list_head *ln;
+ struct resource *res;
+ struct resource_list head_io, head_mem, *list, *tmp;
+ unsigned long io_reserved = 0, mem_reserved = 0;
+ int idx, found_vga = 0;
- inner.found_vga = 0;
- inner.mem_start = inner.io_start = ~0UL;
- inner.mem_end = inner.io_end = 0;
-
- /* Collect information about how our direct children are layed out. */
+ head_io.next = head_mem.next = NULL;
for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
- int i;
- dev = pci_dev_b(ln);
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *res = &dev->resource[i];
- if (res->flags & IORESOURCE_IO) {
- if (res->start < inner.io_start)
- inner.io_start = res->start;
- if (res->end > inner.io_end)
- inner.io_end = res->end;
- } else if (res->flags & IORESOURCE_MEM) {
- if (res->start < inner.mem_start)
- inner.mem_start = res->start;
- if (res->end > inner.mem_end)
- inner.mem_end = res->end;
- }
+ struct pci_dev *dev = pci_dev_b(ln);
+ u16 class = dev->class >> 8;
+ u16 cmd;
+
+ /* First, disable the device to avoid side
+ effects of possibly overlapping I/O and
+ memory ranges.
+ Leave VGA enabled - for obvious reason. :-)
+ Same with all sorts of bridges - they may
+ have VGA behind them. */
+ if (class == PCI_CLASS_DISPLAY_VGA
+ || class == PCI_CLASS_NOT_DEFINED_VGA)
+ found_vga = 1;
+ else if (class >> 8 != PCI_BASE_CLASS_BRIDGE) {
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY
+ | PCI_COMMAND_MASTER);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
}
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- inner.found_vga = 1;
+
+ /* Reserve some resources for CardBus.
+ Are these values reasonable? */
+ if (class == PCI_CLASS_BRIDGE_CARDBUS) {
+ io_reserved += 8*1024;
+ mem_reserved += 32*1024*1024;
+ continue;
+ }
+
+ pdev_sort_resources(dev, &head_io, IORESOURCE_IO);
+ pdev_sort_resources(dev, &head_mem, IORESOURCE_MEM);
}
- /* And for all of the sub-busses. */
- for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
- pbus_set_ranges(pci_bus_b(ln), &inner);
-
- /* Align the values. */
- inner.io_start = ROUND_DOWN(inner.io_start, 4*1024);
- inner.io_end = ROUND_UP(inner.io_end, 4*1024);
-
- inner.mem_start = ROUND_DOWN(inner.mem_start, 1*1024*1024);
- inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024);
-
- pcibios_fixup_pbus_ranges(bus, &inner);
-
- /* Configure the bridge, if possible. */
- if (bus->self) {
- struct pci_dev *bridge = bus->self;
- u32 l;
-
- /* Set up the top and bottom of the PCI I/O segment
- for this bus. */
- pci_read_config_dword(bridge, PCI_IO_BASE, &l);
- l &= 0xffff0000;
- l |= (inner.io_start >> 8) & 0x00f0;
- l |= (inner.io_end - 1) & 0xf000;
- pci_write_config_dword(bridge, PCI_IO_BASE, l);
-
- /*
- * Clear out the upper 16 bits of IO base/limit.
- * Clear out the upper 32 bits of PREF base/limit.
- */
- pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0);
- pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
- pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
-
- /* Set up the top and bottom of the PCI Memory segment
- for this bus. */
- l = (inner.mem_start & 0xfff00000) >> 16;
- l |= (inner.mem_end - 1) & 0xfff00000;
- pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
-
- /*
- * Turn off downstream PF memory address range, unless
- * there is a VGA behind this bridge, in which case, we
- * enable the PREFETCH range to include BIOS ROM at C0000.
- *
- * NOTE: this is a bit of a hack, done with PREFETCH for
- * simplicity, rather than having to add it into the above
- * non-PREFETCH range, which could then be bigger than we want.
- * We might assume that we could relocate the BIOS ROM, but
- * that would depend on having it found by those who need it
- * (the DEC BIOS emulator would find it, but I do not know
- * about the Xservers). So, we do it this way for now... ;-)
- */
- l = (inner.found_vga) ? 0 : 0x0000ffff;
- pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
-
- /*
- * Tell bridge that there is an ISA bus in the system,
- * and (possibly) a VGA as well.
- */
- l = (inner.found_vga) ? 0x0c : 0x04;
- pci_write_config_byte(bridge, PCI_BRIDGE_CONTROL, l);
-
- /*
- * Clear status bits,
- * turn on I/O enable (for downstream I/O),
- * turn on memory enable (for downstream memory),
- * turn on master enable (for upstream memory and I/O).
- */
- pci_write_config_dword(bridge, PCI_COMMAND, 0xffff0007);
+ for (list = head_io.next; list;) {
+ res = list->res;
+ idx = res - &list->dev->resource[0];
+ if (pci_assign_resource(list->dev, idx) == 0
+ && ranges->io_end < res->end)
+ ranges->io_end = res->end;
+ tmp = list;
+ list = list->next;
+ kfree(tmp);
+ }
+ for (list = head_mem.next; list;) {
+ res = list->res;
+ idx = res - &list->dev->resource[0];
+ if (pci_assign_resource(list->dev, idx) == 0
+ && ranges->mem_end < res->end)
+ ranges->mem_end = res->end;
+ tmp = list;
+ list = list->next;
+ kfree(tmp);
+ }
+
+ ranges->io_end += io_reserved;
+ ranges->mem_end += mem_reserved;
+
+ /* PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
+ requires that if there is no I/O ports or memory behind the
+ bridge, corresponding range must be turned off by writing base
+ value greater than limit to the bridge's base/limit registers. */
+#if 1
+ /* But assuming that some hardware designed before 1998 might
+ not support this (very unlikely - at least all DEC bridges
+ are ok and I believe that was standard de-facto. -ink), we
+ must allow for at least one unit. */
+ if (ranges->io_end == ranges->io_start)
+ ranges->io_end += 1;
+ if (ranges->mem_end == ranges->mem_start)
+ ranges->mem_end += 1;
+#endif
+ ranges->io_end = ROUND_UP(ranges->io_end, 4*1024);
+ ranges->mem_end = ROUND_UP(ranges->mem_end, 1024*1024);
+
+ return found_vga;
+}
+
+/* Initialize bridges with base/limit values we have collected */
+static void __init
+pci_setup_bridge(struct pci_bus *bus)
+{
+ struct pbus_set_ranges_data ranges;
+ struct pci_dev *bridge = bus->self;
+ u32 l;
+
+ if (!bridge || (bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ return;
+ ranges.io_start = bus->resource[0]->start;
+ ranges.io_end = bus->resource[0]->end;
+ ranges.mem_start = bus->resource[1]->start;
+ ranges.mem_end = bus->resource[1]->end;
+ pcibios_fixup_pbus_ranges(bus, &ranges);
+
+ DBGC(("PCI: Bus %d, bridge: %s\n", bus->number, bridge->name));
+ DBGC((" IO window: %04lx-%04lx\n", ranges.io_start, ranges.io_end));
+ DBGC((" MEM window: %08lx-%08lx\n", ranges.mem_start, ranges.mem_end));
+
+ /* Set up the top and bottom of the PCI I/O segment for this bus. */
+ pci_read_config_dword(bridge, PCI_IO_BASE, &l);
+ l &= 0xffff0000;
+ l |= (ranges.io_start >> 8) & 0x00f0;
+ l |= ranges.io_end & 0xf000;
+ pci_write_config_dword(bridge, PCI_IO_BASE, l);
+
+ /* Clear upper 16 bits of I/O base/limit. */
+ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0);
+
+ /* Clear out the upper 32 bits of PREF base/limit. */
+ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
+ pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
+
+ /* Set up the top and bottom of the PCI Memory segment
+ for this bus. */
+ l = (ranges.mem_start >> 16) & 0xfff0;
+ l |= ranges.mem_end & 0xfff00000;
+ pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
+
+ /* Set up PREF base/limit. */
+ l = (bus->resource[2]->start >> 16) & 0xfff0;
+ l |= bus->resource[2]->end & 0xfff00000;
+ pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
+
+ /* Check if we have VGA behind the bridge.
+ Enable ISA in either case. */
+ l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
+ pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
+}
+
+static void __init
+pbus_assign_resources(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
+{
+ struct list_head *ln;
+ int found_vga = pbus_assign_resources_sorted(bus, ranges);
+
+ if (!ranges->found_vga && found_vga) {
+ struct pci_bus *b;
+
+ ranges->found_vga = 1;
+ /* Propogate presence of the VGA to upstream bridges */
+ for (b = bus; b->parent; b = b->parent) {
+#if 0
+ /* ? Do we actually need to enable PF memory? */
+ b->resource[2]->start = 0;
+#endif
+ b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA;
+ }
}
+ for (ln=bus->children.next; ln != &bus->children; ln=ln->next) {
+ struct pci_bus *b = pci_bus_b(ln);
+
+ b->resource[0]->start = ranges->io_start = ranges->io_end;
+ b->resource[1]->start = ranges->mem_start = ranges->mem_end;
+
+ pbus_assign_resources(b, ranges);
- if (outer) {
- outer->found_vga |= inner.found_vga;
- if (inner.io_start < outer->io_start)
- outer->io_start = inner.io_start;
- if (inner.io_end > outer->io_end)
- outer->io_end = inner.io_end;
- if (inner.mem_start < outer->mem_start)
- outer->mem_start = inner.mem_start;
- if (inner.mem_end > outer->mem_end)
- outer->mem_end = inner.mem_end;
+ b->resource[0]->end = ranges->io_end - 1;
+ b->resource[1]->end = ranges->mem_end - 1;
+
+ pci_setup_bridge(b);
}
}
void __init
-pci_set_bus_ranges(void)
+pci_assign_unassigned_resources(void)
{
+ struct pbus_set_ranges_data ranges;
struct list_head *ln;
+ struct pci_dev *dev;
+
+ for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) {
+ struct pci_bus *b = pci_bus_b(ln);
+
+ ranges.io_start = b->resource[0]->start + PCIBIOS_MIN_IO;
+ ranges.mem_start = b->resource[1]->start + PCIBIOS_MIN_MEM;
+ ranges.io_end = ranges.io_start;
+ ranges.mem_end = ranges.mem_start;
+ ranges.found_vga = 0;
+ pbus_assign_resources(b, &ranges);
+ }
+ pci_for_each_dev(dev) {
+ pdev_enable_device(dev);
+ }
+}
- for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
- pbus_set_ranges(pci_bus_b(ln), NULL);
+/* Check whether the bridge supports I/O forwarding.
+ If not, its I/O base/limit register must be
+ read-only and read as 0. */
+unsigned long __init
+pci_bridge_check_io(struct pci_dev *bridge)
+{
+ u16 io;
+
+ pci_read_config_word(bridge, PCI_IO_BASE, &io);
+ if (!io) {
+ pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0);
+ pci_read_config_word(bridge, PCI_IO_BASE, &io);
+ pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
+ }
+ if (io)
+ return IORESOURCE_IO;
+ printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n",
+ bridge->name);
+ return 0;
}
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 1a95544d8..1ca568254 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -11,15 +11,21 @@
/* fixed for multiple pci buses, 1999 Andrea Arcangeli <andrea@suse.de> */
+/*
+ * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+ * Resource sorting
+ */
+
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/cache.h>
+#include <linux/slab.h>
-#define DEBUG_CONFIG 0
+#define DEBUG_CONFIG 1
#if DEBUG_CONFIG
# define DBGC(args) printk args
#else
@@ -114,19 +120,67 @@ pci_assign_resource(struct pci_dev *dev, int i)
}
}
- DBGC((" got res[%lx:%lx] for resource %d\n", res->start, res->end, i));
+ DBGC((" got res[%lx:%lx] for resource %d of %s\n", res->start,
+ res->end, i, dev->name));
return 0;
}
-void
-pdev_assign_unassigned_resources(struct pci_dev *dev)
+/* Sort resources of a given type by alignment */
+void __init
+pdev_sort_resources(struct pci_dev *dev,
+ struct resource_list *head, u32 type_mask)
+{
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *r;
+ struct resource_list *list, *tmp;
+ unsigned long r_size;
+
+ /* PCI-PCI bridges may have I/O ports or
+ memory on the primary bus */
+ if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI &&
+ i >= PCI_BRIDGE_RESOURCES)
+ continue;
+
+ r = &dev->resource[i];
+ r_size = r->end - r->start;
+
+ if (!(r->flags & type_mask) || r->parent)
+ continue;
+ if (!r_size) {
+ printk(KERN_WARNING "PCI: Ignore bogus resource %d "
+ "[%lx:%lx] of %s\n",
+ i, r->start, r->end, dev->name);
+ continue;
+ }
+ for (list = head; ; list = list->next) {
+ unsigned long size = 0;
+ struct resource_list *ln = list->next;
+
+ if (ln)
+ size = ln->res->end - ln->res->start;
+ if (r_size > size) {
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ tmp->next = ln;
+ tmp->res = r;
+ tmp->dev = dev;
+ list->next = tmp;
+ break;
+ }
+ }
+ }
+}
+
+void __init
+pdev_enable_device(struct pci_dev *dev)
{
u32 reg;
u16 cmd;
int i;
- DBGC(("PCI assign unassigned: (%s)\n", dev->name));
+ DBGC(("PCI enable device: (%s)\n", dev->name));
pci_read_config_word(dev, PCI_COMMAND, &cmd);
@@ -137,13 +191,6 @@ pdev_assign_unassigned_resources(struct pci_dev *dev)
cmd |= PCI_COMMAND_IO;
else if (res->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
-
- /* If it is already assigned or the resource does
- not exist, there is nothing to do. */
- if (res->parent != NULL || res->flags == 0)
- continue;
-
- pci_assign_resource(dev, i);
}
/* Special case, disable the ROM. Several devices act funny
@@ -171,24 +218,12 @@ pdev_assign_unassigned_resources(struct pci_dev *dev)
it, the bit will go into the bucket. */
cmd |= PCI_COMMAND_MASTER;
+ /* Set the cache line and default latency (32). */
+ pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
+ (32 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
+
/* Enable the appropriate bits in the PCI command register. */
pci_write_config_word(dev, PCI_COMMAND, cmd);
DBGC((" cmd reg 0x%x\n", cmd));
-
- /* If this is a PCI bridge, set the cache line correctly. */
- if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
- (L1_CACHE_BYTES / sizeof(u32)));
- }
-}
-
-void __init
-pci_assign_unassigned_resources(void)
-{
- struct pci_dev *dev;
-
- pci_for_each_dev(dev) {
- pdev_assign_unassigned_resources(dev);
- }
}
diff --git a/drivers/pnp/isapnp.c b/drivers/pnp/isapnp.c
index 7d7b705c7..7256544ff 100644
--- a/drivers/pnp/isapnp.c
+++ b/drivers/pnp/isapnp.c
@@ -270,17 +270,16 @@ static int isapnp_next_rdp(void)
{
int rdp = isapnp_rdp;
while (rdp <= 0x3ff) {
- if (!check_region(rdp, 1)) {
- isapnp_rdp = rdp;
- return 0;
- }
- rdp += RDP_STEP;
/*
* We cannot use NE2000 probe spaces for ISAPnP or we
* will lock up machines.
*/
- if(rdp >= 0x280 && rdp <= 0x380)
- continue;
+ if ((rdp < 0x280 || rdp > 0x380) && !check_region(rdp, 1))
+ {
+ isapnp_rdp = rdp;
+ return 0;
+ }
+ rdp += RDP_STEP;
}
return -1;
}
@@ -748,6 +747,25 @@ static void __init isapnp_add_fixed_mem32_resource(struct pci_dev *dev,
}
/*
+ * Parse card name for ISA PnP device.
+ */
+
+static void __init
+isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
+{
+ if (name[0] == '\0') {
+ unsigned short size1 = *size >= name_max ? (name_max - 1) : *size;
+ isapnp_peek(name, size1);
+ name[size1] = '\0';
+ *size -= size1;
+
+ /* clean whitespace from end of string */
+ while (size1 > 0 && name[--size1] == ' ')
+ name[size1] = '\0';
+ }
+}
+
+/*
* Parse resource map for logical device.
*/
@@ -844,12 +862,7 @@ static int __init isapnp_create_device(struct pci_bus *card,
size = 0;
break;
case _LTAG_ANSISTR:
- if (dev->name[0] == '\0') {
- unsigned short size1 = size > 47 ? 47 : size;
- isapnp_peek(dev->name, size1);
- dev->name[size1] = '\0';
- size -= size1;
- }
+ isapnp_parse_name(dev->name, sizeof(dev->name), &size);
break;
case _LTAG_UNICODESTR:
/* silently ignore */
@@ -915,12 +928,7 @@ static void __init isapnp_parse_resource_map(struct pci_bus *card)
case _STAG_VENDOR:
break;
case _LTAG_ANSISTR:
- if (card->name[0] == '\0') {
- unsigned short size1 = size > 47 ? 47 : size;
- isapnp_peek(card->name, size1);
- card->name[size1] = '\0';
- size -= size1;
- }
+ isapnp_parse_name(card->name, sizeof(card->name), &size);
break;
case _LTAG_UNICODESTR:
/* silently ignore */
diff --git a/drivers/s390/net/ctc.c b/drivers/s390/net/ctc.c
index 4acc6e543..699eaba37 100644
--- a/drivers/s390/net/ctc.c
+++ b/drivers/s390/net/ctc.c
@@ -1313,7 +1313,7 @@ static int ctc_open(net_device *dev)
return -ENOMEM;
}
init_waitqueue_head(&privptr->channel[i].wait);
- privptr->channel[i].tq.next = NULL;
+ INIT_LIST_HEAD(&privptr->channel[i].tq.list);
privptr->channel[i].tq.sync = 0;
privptr->channel[i].tq.routine = (void *)(void *)ctc_irq_bh;
privptr->channel[i].tq.data = &privptr->channel[i];
diff --git a/drivers/sbus/audio/dmy.c b/drivers/sbus/audio/dmy.c
index 560134ba2..91cc447fb 100644
--- a/drivers/sbus/audio/dmy.c
+++ b/drivers/sbus/audio/dmy.c
@@ -547,7 +547,7 @@ static void dummy_start_output(struct sparcaudio_driver *drv, __u8 * buffer,
dummy_chip->perchip_info.play.active = 1;
/* fake an "interrupt" to deal with this block */
- dummy_chip->tqueue.next = NULL;
+ INIT_LIST_HEAD(&dummy_chip->tqueue.list);
dummy_chip->tqueue.sync = 0;
dummy_chip->tqueue.routine = dummy_output_done_task;
dummy_chip->tqueue.data = drv;
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index f2ee5ccc3..c640c9fe8 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -1,4 +1,4 @@
-/* $Id: aurora.c,v 1.9 2000/11/08 05:33:03 davem Exp $
+/* $Id: aurora.c,v 1.10 2000/12/07 04:35:38 anton Exp $
* linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
*
* Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro)
@@ -666,9 +666,11 @@ static void aurora_check_modem(struct Aurora_board const * bp, int chip)
if (sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD)
wake_up_interruptible(&port->open_wait);
else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
- (port->flags & ASYNC_CALLOUT_NOHUP)))
- queue_task(&port->tqueue_hangup,
- &tq_scheduler);
+ (port->flags & ASYNC_CALLOUT_NOHUP))) {
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&port->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
+ }
}
/* We don't have such things yet. My aurora board has DTR and RTS swapped, but that doesn't count in this driver. Let's hope
@@ -2211,13 +2213,13 @@ static void do_aurora_hangup(void *private_)
printk("do_aurora_hangup: start\n");
#endif
tty = port->tty;
- if (tty == NULL)
- return;
-
- tty_hangup(tty);
+ if (tty != NULL) {
+ tty_hangup(tty); /* FIXME: module removal race - AKPM */
#ifdef AURORA_DEBUG
- printk("do_aurora_hangup: end\n");
+ printk("do_aurora_hangup: end\n");
#endif
+ }
+ MOD_DEC_USE_COUNT;
}
static void aurora_hangup(struct tty_struct * tty)
diff --git a/drivers/sbus/char/sab82532.c b/drivers/sbus/char/sab82532.c
index fa5f383c3..5de83158b 100644
--- a/drivers/sbus/char/sab82532.c
+++ b/drivers/sbus/char/sab82532.c
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.53 2000/11/15 07:28:09 davem Exp $
+/* $Id: sab82532.c,v 1.54 2000/12/07 04:35:39 anton Exp $
* sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -527,8 +527,9 @@ check_modem:
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
-
- queue_task(&info->tqueue_hangup, &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&info->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
}
}
@@ -676,10 +677,9 @@ static void do_serial_hangup(void *private_)
struct tty_struct *tty;
tty = info->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty);
+ MOD_DEC_USE_COUNT;
}
static void
@@ -2134,7 +2134,7 @@ static void __init sab82532_kgdb_hook(int line)
static inline void __init show_serial_version(void)
{
- char *revision = "$Revision: 1.53 $";
+ char *revision = "$Revision: 1.54 $";
char *version, *p;
version = strchr(revision, ' ');
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 50d26c7e4..f8a982527 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -30,7 +30,7 @@ CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF
CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS
CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
-obj-$(CONFIG_SCSI) += scsi_mod.o scsi_syms.o
+obj-$(CONFIG_SCSI) += scsi_mod.o
obj-$(CONFIG_A4000T_SCSI) += amiga7xx.o 53c7xx.o
obj-$(CONFIG_A4091_SCSI) += amiga7xx.o 53c7xx.o
@@ -39,6 +39,7 @@ obj-$(CONFIG_WARPENGINE_SCSI) += amiga7xx.o 53c7xx.o
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o
+obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o
obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o
@@ -123,6 +124,7 @@ scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o \
scsicam.o scsi_proc.o scsi_error.o \
scsi_obsolete.o scsi_queue.o scsi_lib.o \
scsi_merge.o scsi_dma.o scsi_scan.o \
+ scsi_syms.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
initio-objs := ini9100u.o i91uscsi.o
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 5c657b2e5..64da3a507 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -231,8 +231,6 @@ int __init a2091_detect(Scsi_Host_Template *tpnt)
#define HOSTS_C
-#include "a2091.h"
-
static Scsi_Host_Template driver_template = A2091_SCSI;
#include "scsi_module.c"
diff --git a/drivers/scsi/a2091.h b/drivers/scsi/a2091.h
index 97beba146..b0bcaa4b1 100644
--- a/drivers/scsi/a2091.h
+++ b/drivers/scsi/a2091.h
@@ -1,4 +1,5 @@
#ifndef A2091_H
+#define A2091_H
/* $Id: a2091.h,v 1.4 1997/01/19 23:07:09 davem Exp $
*
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index c9a4253f0..ddb65b250 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -3,6 +3,7 @@
#include <linux/blk.h>
#include <linux/sched.h>
#include <linux/version.h>
+#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/spinlock.h>
@@ -100,7 +101,9 @@ static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
cache_push (addr, cmd->SCp.this_residual);
/* start DMA */
+ mb(); /* make sure setup is completed */
DMA(a3000_host)->ST_DMA = 1;
+ mb(); /* make sure DMA has started before next IO */
/* return success */
return 0;
@@ -116,12 +119,15 @@ static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
cntr |= CNTR_DDIR;
DMA(instance)->CNTR = cntr;
+ mb(); /* make sure CNTR is updated before next IO */
/* flush if we were reading */
if (HDATA(instance)->dma_dir) {
DMA(instance)->FLUSH = 1;
+ mb(); /* don't allow prefetch */
while (!(DMA(instance)->ISTR & ISTR_FE_FLG))
- ;
+ barrier();
+ mb(); /* no IO until FLUSH is done */
}
/* clear a possible interrupt */
@@ -132,9 +138,11 @@ static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
/* stop DMA */
DMA(instance)->SP_DMA = 1;
+ mb(); /* make sure DMA is stopped before next IO */
/* restore the CONTROL bits (minus the direction flag) */
DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
+ mb(); /* make sure CNTR is updated before next IO */
/* copy from a bounce buffer, if necessary */
if (status && HDATA(instance)->dma_bounce_buffer) {
@@ -170,13 +178,17 @@ int __init a3000_detect(Scsi_Host_Template *tpnt)
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI))
return 0;
+ if (!request_mem_region(0xDD0000, 256, "wd33c93"))
+ return -EBUSY;
tpnt->proc_name = "A3000";
tpnt->proc_info = &wd33c93_proc_info;
a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata));
- if(a3000_host == NULL)
+ if (a3000_host == NULL) {
+ release_mem_region(0xDD0000, 256);
return 0;
+ }
a3000_host->base = ZTWO_VADDR(0xDD0000);
a3000_host->irq = IRQ_AMIGA_PORTS;
DMA(a3000_host)->DAWR = DAWR_A3000;
@@ -192,9 +204,7 @@ int __init a3000_detect(Scsi_Host_Template *tpnt)
#define HOSTS_C
-#include "a3000.h"
-
-static Scsi_Host_Template driver_template = A3000_SCSI;
+static Scsi_Host_Template driver_template = _A3000_SCSI;
#include "scsi_module.c"
@@ -203,6 +213,7 @@ int a3000_release(struct Scsi_Host *instance)
#ifdef MODULE
wd33c93_release();
DMA(instance)->CNTR = 0;
+ release_mem_region(0xDD0000, 256);
free_irq(IRQ_AMIGA_PORTS, a3000_intr);
#endif
return 1;
diff --git a/drivers/scsi/a3000.h b/drivers/scsi/a3000.h
index 478c3d39a..78f51c8e0 100644
--- a/drivers/scsi/a3000.h
+++ b/drivers/scsi/a3000.h
@@ -1,4 +1,5 @@
#ifndef A3000_H
+#define A3000_H
/* $Id: a3000.h,v 1.4 1997/01/19 23:07:10 davem Exp $
*
@@ -29,7 +30,7 @@ int wd33c93_reset(Scsi_Cmnd *, unsigned int);
#define CAN_QUEUE 16
#endif
-#define A3000_SCSI { proc_name: "A3000", \
+#define _A3000_SCSI { proc_name: "A3000", \
proc_info: NULL, \
name: "Amiga 3000 built-in SCSI", \
detect: a3000_detect, \
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 9d3584a25..dd5f627d3 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -1416,6 +1416,7 @@ int aha1542_dev_reset(Scsi_Cmnd * SCpnt)
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
if (SCtmp->host_scribble) {
scsi_free(SCtmp->host_scribble, 512);
+ SCtmp->host_scribble = NULL;
}
HOSTDATA(SCpnt->host)->SCint[i] = NULL;
HOSTDATA(SCpnt->host)->mb[i].status = 0;
@@ -1478,6 +1479,7 @@ int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
}
if (SCtmp->host_scribble) {
scsi_free(SCtmp->host_scribble, 512);
+ SCtmp->host_scribble = NULL;
}
HOSTDATA(SCpnt->host)->SCint[i] = NULL;
HOSTDATA(SCpnt->host)->mb[i].status = 0;
@@ -1546,6 +1548,7 @@ int aha1542_host_reset(Scsi_Cmnd * SCpnt)
}
if (SCtmp->host_scribble) {
scsi_free(SCtmp->host_scribble, 512);
+ SCtmp->host_scribble = NULL;
}
HOSTDATA(SCpnt->host)->SCint[i] = NULL;
HOSTDATA(SCpnt->host)->mb[i].status = 0;
@@ -1681,8 +1684,10 @@ int aha1542_old_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
Scsi_Cmnd *SCtmp;
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
SCtmp->result = DID_RESET << 16;
- if (SCtmp->host_scribble)
+ if (SCtmp->host_scribble) {
scsi_free(SCtmp->host_scribble, 512);
+ SCtmp->host_scribble = NULL;
+ }
printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target);
SCtmp->scsi_done(SCpnt);
@@ -1725,8 +1730,10 @@ fail:
Scsi_Cmnd *SCtmp;
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
SCtmp->result = DID_RESET << 16;
- if (SCtmp->host_scribble)
+ if (SCtmp->host_scribble) {
scsi_free(SCtmp->host_scribble, 512);
+ SCtmp->host_scribble = NULL;
+ }
printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target);
SCtmp->scsi_done(SCpnt);
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 77feb1cbc..449b74013 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -656,7 +656,7 @@ int atari_scsi_detect (Scsi_Host_Template *host)
*/
if (MACH_IS_ATARI && ATARIHW_PRESENT(ST_SCSI) &&
!ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) {
- atari_dma_buffer = atari_stram_alloc( STRAM_BUFFER_SIZE, NULL, "SCSI" );
+ atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
if (!atari_dma_buffer) {
printk( KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
"double buffer\n" );
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index a1f277e8d..9436e6a65 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1,12 +1,26 @@
/*
* eata.c - Low-level driver for EATA/DMA SCSI host adapters.
*
+ * 22 Nov 2000 Rev. 6.02 for linux 2.4.0-test11
+ * + Return code checked when calling pci_enable_device.
+ * + Removed old scsi error handling support.
+ * + The obsolete boot option flag eh:n is silently ignored.
+ * + Removed error messages while a disk drive is powered up at
+ * boot time.
+ * + Improved boot messages: all tagged capable device are
+ * indicated as "tagged" or "soft-tagged" :
+ * - "soft-tagged" means that the driver is trying to do its
+ * own tagging (i.e. the tc:y option is in effect);
+ * - "tagged" means that the device supports tagged commands,
+ * but the driver lets the HBA be responsible for tagging
+ * support.
+ *
* 16 Sep 1999 Rev. 5.11 for linux 2.2.12 and 2.3.18
* + Updated to the new __setup interface for boot command line options.
* + When loaded as a module, accepts the new parameter boot_options
* which value is a string with the same format of the kernel boot
* command line options. A valid example is:
- * modprobe eata 'boot_options=\"0x7410,0x230,lc:y,tc:n,mq:4\"'
+ * modprobe eata boot_options=\"0x7410,0x230,lc:y,tc:n,mq:4\"
*
* 9 Sep 1999 Rev. 5.10 for linux 2.2.12 and 2.3.17
* + 64bit cleanup for Linux/Alpha platform support
@@ -196,7 +210,9 @@
* 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-1999 Dario Ballabio (dario@milano.europe.dg.com)
+ * Copyright (C) 1994-2000 Dario Ballabio (ballabio_dario@emc.com)
+ *
+ * Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that redistributions of source
@@ -288,8 +304,6 @@
* After the optional list of detection probes, other possible command line
* options are:
*
- * eh:y use new scsi code;
- * eh:n use old scsi code;
* et:y force use of extended translation (255 heads, 63 sectors);
* et:n use disk geometry detected by scsicam_bios_param;
* rs:y reverse scan order while detecting PCI boards;
@@ -306,13 +320,13 @@
*
* The default value is: "eata=lc:n,tc:n,mq:16,tm:0,et:n,rs:n".
* An example using the list of detection probes could be:
- * "eata=0x7410,0x230,lc:y,tc:n,mq:4,eh:n,et:n".
+ * "eata=0x7410,0x230,lc:y,tc:n,mq:4,et:n".
*
* When loading as a module, parameters can be specified as well.
* The above example would be (use 1 in place of y and 0 in place of n):
*
* modprobe eata io_port=0x7410,0x230 linked_comm=1 tagged_comm=0 \
- * max_queue_depth=4 tag_mode=0 use_new_eh_code=0 \
+ * max_queue_depth=4 tag_mode=0 \
* ext_tran=0 rev_scan=1
*
* ----------------------------------------------------------------------------
@@ -369,7 +383,10 @@
#include <linux/version.h>
+#ifndef LinuxVersionCode
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#endif
+
#define MAX_INT_PARAM 10
#if defined(MODULE)
@@ -382,7 +399,6 @@ MODULE_PARM(tagged_comm, "i");
MODULE_PARM(link_statistics, "i");
MODULE_PARM(max_queue_depth, "i");
MODULE_PARM(tag_mode, "i");
-MODULE_PARM(use_new_eh_code, "i");
MODULE_PARM(ext_tran, "i");
MODULE_PARM(rev_scan, "i");
MODULE_AUTHOR("Dario Ballabio");
@@ -410,12 +426,7 @@ MODULE_AUTHOR("Dario Ballabio");
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ctype.h>
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
-#include <asm/spinlock.h>
-#else
#include <linux/spinlock.h>
-#endif
#define SPIN_FLAGS unsigned long spin_flags;
#define SPIN_LOCK spin_lock_irq(&io_request_lock);
@@ -501,10 +512,6 @@ MODULE_AUTHOR("Dario Ballabio");
#define ASOK 0x00
#define ASST 0x01
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
-#define ARRAY_SIZE(x) (sizeof (x) / sizeof((x)[0]))
-#endif
-
#define YESNO(a) ((a) ? 'y' : 'n')
#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM)
@@ -693,7 +700,6 @@ static int link_statistics;
static int tag_mode = TAG_MIXED;
static int ext_tran = FALSE;
static int rev_scan = TRUE;
-static int use_new_eh_code = TRUE;
static char *boot_options;
#if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE)
@@ -761,9 +767,9 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
}
if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue)
- tag_suffix = ", tagged";
+ tag_suffix = ", soft-tagged";
else if (dev->tagged_supported && TLDEV(dev->type))
- tag_suffix = ", untagged";
+ tag_suffix = ", tagged";
printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n",
BN(j), host->host_no, dev->channel, dev->id, dev->lun,
@@ -831,7 +837,7 @@ static inline void tune_pci_port(unsigned long port_base) {
addr = pci_resource_start (dev, 0);
- pci_enable_device (dev); /* XXX handle error */
+ if (pci_enable_device (dev)) continue;
#if defined(DEBUG_PCI_DETECT)
printk("%s: tune_pci_port, bus %d, devfn 0x%x, addr 0x%x.\n",
@@ -1122,13 +1128,11 @@ static inline int port_detect \
}
else tag_type = 'n';
- sh[j]->hostt->use_new_eh_code = use_new_eh_code;
-
if (j == 0) {
- printk("EATA/DMA 2.0x: Copyright (C) 1994-1999 Dario Ballabio.\n");
- printk("%s config options -> tc:%c, lc:%c, mq:%d, eh:%c, rs:%c, et:%c.\n",
+ printk("EATA/DMA 2.0x: Copyright (C) 1994-2000 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(use_new_eh_code), YESNO(rev_scan), YESNO(ext_tran));
+ YESNO(rev_scan), YESNO(ext_tran));
}
printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d.\n",
@@ -1191,7 +1195,6 @@ static void internal_setup(char *str, int *ints) {
else if (!strncmp(cur, "tm:", 3)) tag_mode = val;
else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val;
else if (!strncmp(cur, "ls:", 3)) link_statistics = val;
- else if (!strncmp(cur, "eh:", 3)) use_new_eh_code = val;
else if (!strncmp(cur, "et:", 3)) ext_tran = val;
else if (!strncmp(cur, "rs:", 3)) rev_scan = val;
@@ -1439,79 +1442,6 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
return rtn;
}
-static inline int do_old_abort(Scsi_Cmnd *SCarg) {
- unsigned int i, j;
-
- j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-
- if (SCarg->host_scribble == NULL ||
- (SCarg->serial_number_at_timeout &&
- (SCarg->serial_number != SCarg->serial_number_at_timeout))) {
- printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
- BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- i = *(unsigned int *)SCarg->host_scribble;
- printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
- BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
-
- if (i >= sh[j]->can_queue)
- panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
-
- if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
- printk("%s: abort, timeout error.\n", BN(j));
- return SCSI_ABORT_ERROR;
- }
-
- if (HD(j)->cp_stat[i] == FREE) {
- printk("%s: abort, mbox %d is free.\n", BN(j), i);
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- if (HD(j)->cp_stat[i] == IN_USE) {
- printk("%s: abort, mbox %d is in use.\n", BN(j), i);
-
- if (SCarg != HD(j)->cp[i].SCpnt)
- panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
- BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
-
- if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)
- printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
-
- return SCSI_ABORT_SNOOZE;
- }
-
- if (HD(j)->cp_stat[i] == IN_RESET) {
- printk("%s: abort, mbox %d is in reset.\n", BN(j), i);
- return SCSI_ABORT_ERROR;
- }
-
- if (HD(j)->cp_stat[i] == LOCKED) {
- printk("%s: abort, mbox %d is locked.\n", BN(j), i);
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
- SCarg->result = DID_ABORT << 16;
- SCarg->host_scribble = NULL;
- HD(j)->cp_stat[i] = FREE;
- printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
- BN(j), i, SCarg->pid);
- SCarg->scsi_done(SCarg);
- return SCSI_ABORT_SUCCESS;
- }
-
- panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
-}
-
-int eata2x_old_abort(Scsi_Cmnd *SCarg) {
- int rtn;
-
- rtn = do_old_abort(SCarg);
- return rtn;
-}
-
static inline int do_abort(Scsi_Cmnd *SCarg) {
unsigned int i, j;
@@ -1589,151 +1519,6 @@ int eata2x_abort(Scsi_Cmnd *SCarg) {
return do_abort(SCarg);
}
-static inline int do_old_reset(Scsi_Cmnd *SCarg) {
- unsigned int i, j, time, k, c, limit = 0;
- int arg_done = FALSE;
- Scsi_Cmnd *SCpnt;
-
- j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
- printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n",
- BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
-
- if (SCarg->host_scribble == NULL)
- printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
-
- if (SCarg->serial_number_at_timeout &&
- (SCarg->serial_number != SCarg->serial_number_at_timeout)) {
- printk("%s: reset, pid %ld, reset not running.\n", BN(j), SCarg->pid);
- return SCSI_RESET_NOT_RUNNING;
- }
-
- if (HD(j)->in_reset) {
- printk("%s: reset, exit, already in reset.\n", BN(j));
- return SCSI_RESET_ERROR;
- }
-
- if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
- printk("%s: reset, exit, timeout error.\n", BN(j));
- return SCSI_RESET_ERROR;
- }
-
- HD(j)->retries = 0;
-
- for (c = 0; c <= sh[j]->max_channel; c++)
- for (k = 0; k < sh[j]->max_id; k++) {
- HD(j)->target_redo[k][c] = TRUE;
- HD(j)->target_to[k][c] = 0;
- }
-
- for (i = 0; i < sh[j]->can_queue; i++) {
-
- if (HD(j)->cp_stat[i] == FREE) continue;
-
- if (HD(j)->cp_stat[i] == LOCKED) {
- HD(j)->cp_stat[i] = FREE;
- printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
- continue;
- }
-
- if (!(SCpnt = HD(j)->cp[i].SCpnt))
- panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
-
- if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
- HD(j)->cp_stat[i] = ABORTING;
- printk("%s: reset, mbox %d aborting, pid %ld.\n",
- BN(j), i, SCpnt->pid);
- }
-
- else {
- HD(j)->cp_stat[i] = IN_RESET;
- printk("%s: reset, mbox %d in reset, pid %ld.\n",
- BN(j), i, SCpnt->pid);
- }
-
- if (SCpnt->host_scribble == NULL)
- panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
-
- if (*(unsigned int *)SCpnt->host_scribble != i)
- panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
-
- if (SCpnt->scsi_done == NULL)
- panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
-
- if (SCpnt == SCarg) arg_done = TRUE;
- }
-
- if (do_dma(sh[j]->io_port, 0, RESET_PIO)) {
- printk("%s: reset, cannot reset, timeout error.\n", BN(j));
- return SCSI_RESET_ERROR;
- }
-
- printk("%s: reset, board reset done, enabling interrupts.\n", BN(j));
-
-#if defined(DEBUG_RESET)
- do_trace = TRUE;
-#endif
-
- HD(j)->in_reset = TRUE;
- SPIN_UNLOCK
- time = jiffies;
- while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
- SPIN_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;
- SCpnt->result = DID_RESET << 16;
- SCpnt->host_scribble = NULL;
-
- /* This mailbox is still waiting for its interrupt */
- HD(j)->cp_stat[i] = LOCKED;
-
- printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
- BN(j), i, SCpnt->pid);
- }
-
- else if (HD(j)->cp_stat[i] == ABORTING) {
- SCpnt = HD(j)->cp[i].SCpnt;
- SCpnt->result = DID_RESET << 16;
- SCpnt->host_scribble = NULL;
-
- /* This mailbox was never queued to the adapter */
- HD(j)->cp_stat[i] = FREE;
-
- printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
- BN(j), i, SCpnt->pid);
- }
-
- else
-
- /* Any other mailbox has already been set free by interrupt */
- continue;
-
- SCpnt->scsi_done(SCpnt);
- }
-
- HD(j)->in_reset = FALSE;
- do_trace = FALSE;
-
- if (arg_done) {
- printk("%s: reset, exit, success.\n", BN(j));
- return SCSI_RESET_SUCCESS;
- }
- else {
- printk("%s: reset, exit, wakeup.\n", BN(j));
- return SCSI_RESET_PUNT;
- }
-}
-
-int eata2x_old_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
- int rtn;
-
- rtn = do_old_reset(SCarg);
- return rtn;
-}
-
static inline int do_reset(Scsi_Cmnd *SCarg) {
unsigned int i, j, time, k, c, limit = 0;
int arg_done = FALSE;
@@ -1983,7 +1768,7 @@ static inline int reorder(unsigned int j, unsigned long cursec,
if (link_statistics) {
if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec;
- batchcount++; readycount += n_ready, seeknosort += seek / 1024;
+ batchcount++; readycount += n_ready; seeknosort += seek / 1024;
if (input_only) inputcount++;
if (overlap) { ovlcount++; seeksorted += iseek / 1024; }
else seeksorted += (iseek + maxsec - minsec) / 1024;
@@ -2169,7 +1954,9 @@ static inline void ihdlr(int irq, unsigned int j) {
if (tstatus == GOOD)
HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
- if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+ if (spp->target_status && SCpnt->device->type == TYPE_DISK &&
+ (!(tstatus == CHECK_CONDITION && HD(j)->iocount <= 1000 &&
+ (SCpnt->sense_buffer[2] & 0xf) == NOT_READY)))
printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
"target_status 0x%x, sense key 0x%x.\n", BN(j),
SCpnt->channel, SCpnt->target, SCpnt->lun,
@@ -2297,13 +2084,5 @@ static Scsi_Host_Template driver_template = EATA;
#include "scsi_module.c"
#ifndef MODULE
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
-void eata2x_setup(char *str, int *ints) {
- internal_setup(str, ints);
-}
-#else
__setup("eata=", option_setup);
-#endif
-
#endif /* end MODULE */
diff --git a/drivers/scsi/eata.h b/drivers/scsi/eata.h
index 6c00ca0a2..5b3216e60 100644
--- a/drivers/scsi/eata.h
+++ b/drivers/scsi/eata.h
@@ -5,28 +5,23 @@
#define _EATA_H
#include <scsi/scsicam.h>
-#include <linux/version.h>
int eata2x_detect(Scsi_Host_Template *);
int eata2x_release(struct Scsi_Host *);
int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int eata2x_abort(Scsi_Cmnd *);
-int eata2x_old_abort(Scsi_Cmnd *);
int eata2x_reset(Scsi_Cmnd *);
-int eata2x_old_reset(Scsi_Cmnd *, unsigned int);
int eata2x_biosparam(Disk *, kdev_t, int *);
-#define EATA_VERSION "5.11.00"
-
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#define EATA_VERSION "6.02.00"
#define EATA { \
name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \
detect: eata2x_detect, \
release: eata2x_release, \
queuecommand: eata2x_queuecommand, \
- abort: eata2x_old_abort, \
- reset: eata2x_old_reset, \
+ abort: NULL, \
+ reset: NULL, \
eh_abort_handler: eata2x_abort, \
eh_device_reset_handler: NULL, \
eh_bus_reset_handler: NULL, \
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index e6d5b2942..116ddbb58 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -346,7 +346,7 @@ int __init gvp11_detect(Scsi_Host_Template *tpnt)
continue;
release:
- release_mem_region(ZTWO_PADDR(instance->base), 256);
+ release_mem_region(address, 256);
}
return num_gvp11;
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 2b51924cf..5d4031055 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -840,7 +840,7 @@ static void __exit exit_idescsi_module(void)
failed = 0;
while ((drive = ide_scan_devices (media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL)
if (idescsi_cleanup (drive)) {
- printk ("%s: cleanup_module() called while still busy\n", drive->name);
+ printk ("%s: exit_idescsi_module() called while still busy\n", drive->name);
failed++;
}
}
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 61298e9c0..cdc3f8989 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -51,7 +51,7 @@ typedef struct {
mode: IMM_AUTODETECT, \
host: -1, \
cur_cmd: NULL, \
- imm_tq: {0, 0, imm_interrupt, NULL}, \
+ imm_tq: { routine: imm_interrupt }, \
jstart: 0, \
failed: 0, \
dp: 0, \
@@ -122,7 +122,14 @@ int imm_detect(Scsi_Host_Template * host)
struct Scsi_Host *hreg;
int ports;
int i, nhosts, try_again;
- struct parport *pb = parport_enumerate();
+ struct parport *pb;
+
+ /*
+ * unlock to allow the lowlevel parport driver to probe
+ * the irqs
+ */
+ spin_unlock_irq(&io_request_lock);
+ pb = parport_enumerate();
printk("imm: Version %s\n", IMM_VERSION);
nhosts = 0;
@@ -130,6 +137,7 @@ int imm_detect(Scsi_Host_Template * host)
if (!pb) {
printk("imm: parport reports no devices.\n");
+ spin_lock_irq(&io_request_lock);
return 0;
}
retry_entry:
@@ -154,6 +162,7 @@ int imm_detect(Scsi_Host_Template * host)
printk(KERN_ERR "imm%d: failed to claim parport because a "
"pardevice is owning the port for too longtime!\n",
i);
+ spin_lock_irq(&io_request_lock);
return 0;
}
}
@@ -208,12 +217,16 @@ int imm_detect(Scsi_Host_Template * host)
nhosts++;
}
if (nhosts == 0) {
- if (try_again == 1)
+ if (try_again == 1) {
+ spin_lock_irq(&io_request_lock);
return 0;
+ }
try_again = 1;
goto retry_entry;
- } else
+ } else {
+ spin_lock_irq (&io_request_lock);
return 1; /* return number of hosts detected */
+ }
}
/* This is to give the imm driver a way to modify the timings (and other
diff --git a/drivers/scsi/imm.h b/drivers/scsi/imm.h
index 7b8c9df55..8c3d65bb8 100644
--- a/drivers/scsi/imm.h
+++ b/drivers/scsi/imm.h
@@ -10,7 +10,7 @@
#ifndef _IMM_H
#define _IMM_H
-#define IMM_VERSION "2.04 (for Linux 2.4.0)"
+#define IMM_VERSION "2.05 (for Linux 2.4.0)"
/*
* 10 Apr 1998 (Good Friday) - Received EN144302 by email from Iomega.
@@ -60,6 +60,9 @@
* added CONFIG_SCSI_IZIP_SLOW_CTR option
* [2.03]
* Fix kernel panic on scsi timeout. 20Aug00 [2.04]
+ *
+ * Avoid io_request_lock problems.
+ * John Cavan <johncavan@home.com> 16Nov00 [2.05]
*/
/* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index e55b26a0e..4d84fabc9 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -929,7 +929,7 @@ typedef struct ips_ha {
char *ioctl_data; /* IOCTL data area */
u32 ioctl_datasize; /* IOCTL data size */
u32 cmd_in_progress; /* Current command in progress*/
- u32 flags; /* HA flags */
+ long flags; /* HA flags */
u8 waitflag; /* are we waiting for cmd */
u8 active;
u16 reset_count; /* number of resets */
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 0e1dec169..264ae2fe0 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -194,9 +194,6 @@ MODULE_DESCRIPTION ("AMI MegaRAID driver");
*================================================================
*/
-#define queue_task_irq(a,b) queue_task(a,b)
-#define queue_task_irq_off(a,b) queue_task(a,b)
-
#define MAX_SERBUF 160
#define COM_BASE 0x2f8
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
new file mode 100644
index 000000000..26e3a277d
--- /dev/null
+++ b/drivers/scsi/mvme147.c
@@ -0,0 +1,116 @@
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/blk.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mvme147hw.h>
+#include <asm/irq.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "wd33c93.h"
+#include "mvme147.h"
+
+#include<linux/stat.h>
+
+#define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
+
+static struct Scsi_Host *mvme147_host = NULL;
+
+static void mvme147_intr (int irq, void *dummy, struct pt_regs *fp)
+{
+ if (irq == MVME147_IRQ_SCSI_PORT)
+ wd33c93_intr (mvme147_host);
+ else
+ m147_pcc->dma_intr = 0x89; /* Ack and enable ints */
+}
+
+static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
+{
+ unsigned char flags = 0x01;
+ unsigned long addr = virt_to_bus(cmd->SCp.ptr);
+
+ /* setup dma direction */
+ if (!dir_in)
+ flags |= 0x04;
+
+ /* remember direction */
+ HDATA(mvme147_host)->dma_dir = dir_in;
+
+ if (dir_in)
+ /* invalidate any cache */
+ cache_clear (addr, cmd->SCp.this_residual);
+ else
+ /* push any dirty cache */
+ cache_push (addr, cmd->SCp.this_residual);
+
+ /* start DMA */
+ m147_pcc->dma_bcr = cmd->SCp.this_residual | (1<<24);
+ m147_pcc->dma_dadr = addr;
+ m147_pcc->dma_cntrl = flags;
+
+ /* return success */
+ return 0;
+}
+
+static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
+ int status)
+{
+ m147_pcc->dma_cntrl = 0;
+}
+
+int mvme147_detect(Scsi_Host_Template *tpnt)
+{
+ static unsigned char called = 0;
+
+ if (!MACH_IS_MVME147 || called)
+ return 0;
+ called++;
+
+ tpnt->proc_name = "MVME147";
+ tpnt->proc_info = &wd33c93_proc_info;
+
+ mvme147_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata));
+ mvme147_host->base = 0xfffe4000;
+ mvme147_host->irq = MVME147_IRQ_SCSI_PORT;
+ wd33c93_init(mvme147_host, (wd33c93_regs *)0xfffe4000,
+ dma_setup, dma_stop, WD33C93_FS_8_10);
+
+ request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, "MVME147 SCSI PORT", mvme147_intr);
+ request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, "MVME147 SCSI DMA", mvme147_intr);
+#if 0 /* Disabled; causes problems booting */
+ m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */
+ udelay(100);
+ m147_pcc->scsi_interrupt = 0x00; /* Negate SCSI bus reset */
+ udelay(2000);
+ m147_pcc->scsi_interrupt = 0x40; /* Clear bus reset interrupt */
+#endif
+ m147_pcc->scsi_interrupt = 0x09; /* Enable interrupt */
+
+ m147_pcc->dma_cntrl = 0x00; /* ensure DMA is stopped */
+ m147_pcc->dma_intr = 0x89; /* Ack and enable ints */
+
+ return 1;
+}
+
+#define HOSTS_C
+
+#include "mvme147.h"
+
+static Scsi_Host_Template driver_template = MVME147_SCSI;
+
+#include "scsi_module.c"
+
+int mvme147_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+ /* XXX Make sure DMA is stopped! */
+ wd33c93_release();
+ free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr);
+ free_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr);
+#endif
+ return 1;
+}
diff --git a/drivers/scsi/mvme147.h b/drivers/scsi/mvme147.h
new file mode 100644
index 000000000..dabde1baf
--- /dev/null
+++ b/drivers/scsi/mvme147.h
@@ -0,0 +1,50 @@
+#ifndef MVME147_H
+
+/* $Id: mvme147.h,v 1.4 1997/01/19 23:07:10 davem Exp $
+ *
+ * Header file for the MVME147 built-in SCSI controller for Linux
+ *
+ * Written and (C) 1993, Hamish Macdonald, see mvme147.c for more info
+ *
+ */
+
+#include <linux/types.h>
+
+int mvme147_detect(Scsi_Host_Template *);
+int mvme147_release(struct Scsi_Host *);
+const char *wd33c93_info(void);
+int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int wd33c93_abort(Scsi_Cmnd *);
+int wd33c93_reset(Scsi_Cmnd *, unsigned int);
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 2
+#endif
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE 16
+#endif
+
+#ifdef HOSTS_C
+
+#define MVME147_SCSI {proc_name: "MVME147", \
+ proc_info: NULL, \
+ name: "MVME147 built-in SCSI", \
+ detect: mvme147_detect, \
+ release: mvme147_release, \
+ queuecommand: wd33c93_queuecommand, \
+ abort: wd33c93_abort, \
+ reset: wd33c93_reset, \
+ can_queue: CAN_QUEUE, \
+ this_id: 7, \
+ sg_tablesize: SG_ALL, \
+ cmd_per_lun: CMD_PER_LUN, \
+ use_clustering: ENABLE_CLUSTERING }
+
+#endif /* else def HOSTS_C */
+
+#endif /* MVME147_H */
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 661316cac..e85391bd1 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -41,7 +41,7 @@ typedef struct {
mode: PPA_AUTODETECT, \
host: -1, \
cur_cmd: NULL, \
- ppa_tq: {0, 0, ppa_interrupt, NULL}, \
+ ppa_tq: { routine: ppa_interrupt }, \
jstart: 0, \
failed: 0, \
p_busy: 0 \
@@ -111,7 +111,14 @@ int ppa_detect(Scsi_Host_Template * host)
struct Scsi_Host *hreg;
int ports;
int i, nhosts, try_again;
- struct parport *pb = parport_enumerate();
+ struct parport *pb;
+
+ /*
+ * unlock to allow the lowlevel parport driver to probe
+ * the irqs
+ */
+ spin_unlock_irq(&io_request_lock);
+ pb = parport_enumerate();
printk("ppa: Version %s\n", PPA_VERSION);
nhosts = 0;
@@ -119,6 +126,7 @@ int ppa_detect(Scsi_Host_Template * host)
if (!pb) {
printk("ppa: parport reports no devices.\n");
+ spin_lock_irq(&io_request_lock);
return 0;
}
retry_entry:
@@ -143,6 +151,7 @@ int ppa_detect(Scsi_Host_Template * host)
printk(KERN_ERR "ppa%d: failed to claim parport because a "
"pardevice is owning the port for too longtime!\n",
i);
+ spin_lock_irq(&io_request_lock);
return 0;
}
}
@@ -212,11 +221,14 @@ int ppa_detect(Scsi_Host_Template * host)
printk(" cable is marked with \"AutoDetect\", this is what has\n");
printk(" happened.\n");
return 0;
+ spin_lock_irq(&io_request_lock);
}
try_again = 1;
goto retry_entry;
- } else
+ } else {
+ spin_lock_irq(&io_request_lock);
return 1; /* return number of hosts detected */
+ }
}
/* This is to give the ppa driver a way to modify the timings (and other
diff --git a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h
index 74147c329..0c03366dc 100644
--- a/drivers/scsi/ppa.h
+++ b/drivers/scsi/ppa.h
@@ -10,7 +10,7 @@
#ifndef _PPA_H
#define _PPA_H
-#define PPA_VERSION "2.05 (for Linux 2.2.x)"
+#define PPA_VERSION "2.06 (for Linux 2.2.x)"
/*
* this driver has been hacked by Matteo Frigo (athena@theory.lcs.mit.edu)
@@ -58,6 +58,9 @@
* Tim Waugh <twaugh@redhat.com>
* [2.04]
* Fix kernel panic on scsi timeout, 2000-08-18 [2.05]
+ *
+ * Avoid io_request_lock problems.
+ * John Cavan <johncavan@home.com> [2.06]
*/
/* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 12c0c9256..50db38c97 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -312,7 +312,7 @@ STATIC void qla1280_abort_queue_single(scsi_qla_host_t *,uint32_t,uint32_t,uint3
STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd *cp);
STATIC void qla1280_removeq(scsi_lu_t *q, srb_t *sp);
STATIC void qla1280_mem_free(scsi_qla_host_t *ha);
-void qla1280_do_dpc(void *p);
+static void qla1280_do_dpc(void *p);
#ifdef QLA1280_UNUSED
static void qla1280_set_flags(char * s);
#endif
@@ -1082,7 +1082,8 @@ qla1280_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
{
CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16);
qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
- queue_task(&ha->run_qla_bh,&tq_scheduler);
+
+ schedule_task(&ha->run_qla_bh);
ha->flags.dpc_sched = TRUE;
DRIVER_UNLOCK
return(0);
@@ -1580,7 +1581,7 @@ void qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
ha->run_qla_bh.routine = qla1280_do_dpc;
COMTRACE('P')
- queue_task_irq(&ha->run_qla_bh,&tq_scheduler);
+ schedule_task(&ha->run_qla_bh);
ha->flags.dpc_sched = TRUE;
}
clear_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags);
@@ -1604,7 +1605,7 @@ void qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
* "host->can_queue". This can cause a panic if we were in our interrupt
* code .
**************************************************************************/
-void qla1280_do_dpc(void *p)
+static void qla1280_do_dpc(void *p)
{
scsi_qla_host_t *ha = (scsi_qla_host_t *) p;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index c99853935..0aa622002 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1,12 +1,20 @@
/*
* u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
*
+ * 01 Nov 2000 Rev. 6.02 for linux 2.4.0-test11
+ * + Removed old scsi error handling support.
+ * + The obsolete boot option flag eh:n is silently ignored.
+ * + Removed error messages while a disk drive is powered up at
+ * boot time.
+ * + Improved boot messages: all tagged capable device are
+ * indicated as "tagged".
+ *
* 16 Sep 1999 Rev. 5.11 for linux 2.2.12 and 2.3.18
* + Updated to the new __setup interface for boot command line options.
* + When loaded as a module, accepts the new parameter boot_options
* which value is a string with the same format of the kernel boot
* command line options. A valid example is:
- * modprobe u14-34f 'boot_options=\"0x230,0x340,lc:y,mq:4\"'
+ * modprobe u14-34f boot_options=\"0x230,0x340,lc:y,mq:4\"
*
* 22 Jul 1999 Rev. 5.00 for linux 2.2.10 and 2.3.11
* + Removed pre-2.2 source code compatibility.
@@ -169,7 +177,9 @@
*
* Multiple U14F and/or U34F host adapters are supported.
*
- * Copyright (C) 1994-1999 Dario Ballabio (dario@milano.europe.dg.com)
+ * Copyright (C) 1994-2000 Dario Ballabio (ballabio_dario@emc.com)
+ *
+ * Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that redistributions of source
@@ -261,8 +271,6 @@
* After the optional list of detection probes, other possible command line
* options are:
*
- * eh:y use new scsi code;
- * eh:n use old scsi code;
* et:y use disk geometry returned by scsicam_bios_param;
* et:n use disk geometry jumpered on the board;
* lc:y enables linked commands;
@@ -273,13 +281,13 @@
*
* The default value is: "u14-34f=lc:n,of:n,mq:8,et:n".
* An example using the list of detection probes could be:
- * "u14-34f=0x230,0x340,lc:y,of:n,mq:4,eh:n,et:n".
+ * "u14-34f=0x230,0x340,lc:y,of:n,mq:4,et:n".
*
* When loading as a module, parameters can be specified as well.
* The above example would be (use 1 in place of y and 0 in place of n):
*
* modprobe u14-34f io_port=0x230,0x340 linked_comm=1 have_old_firmware=0 \
- * max_queue_depth=4 use_new_eh_code=0 ext_tran=0
+ * max_queue_depth=4 ext_tran=0
*
* ----------------------------------------------------------------------------
* In this implementation, linked commands are designed to work with any DISK
@@ -322,7 +330,10 @@
#include <linux/version.h>
+#ifndef LinuxVersionCode
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#endif
+
#define MAX_INT_PARAM 10
#if defined(MODULE)
@@ -334,7 +345,6 @@ MODULE_PARM(linked_comm, "i");
MODULE_PARM(have_old_firmware, "i");
MODULE_PARM(link_statistics, "i");
MODULE_PARM(max_queue_depth, "i");
-MODULE_PARM(use_new_eh_code, "i");
MODULE_PARM(ext_tran, "i");
MODULE_AUTHOR("Dario Ballabio");
@@ -360,12 +370,7 @@ MODULE_AUTHOR("Dario Ballabio");
#include <linux/config.h>
#include <linux/init.h>
#include <linux/ctype.h>
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
-#include <asm/spinlock.h>
-#else
#include <linux/spinlock.h>
-#endif
#define SPIN_FLAGS unsigned long spin_flags;
#define SPIN_LOCK spin_lock_irq(&io_request_lock);
@@ -450,10 +455,6 @@ MODULE_AUTHOR("Dario Ballabio");
#define ASOK 0x00
#define ASST 0x91
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
-#define ARRAY_SIZE(x) (sizeof (x) / sizeof((x)[0]))
-#endif
-
#define YESNO(a) ((a) ? 'y' : 'n')
#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM)
@@ -554,10 +555,9 @@ static void do_interrupt_handler(int, void *, struct pt_regs *);
static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
static int do_trace = FALSE;
static int setup_done = FALSE;
-static int link_statistics = 0;
+static int link_statistics;
static int ext_tran = FALSE;
-static int use_new_eh_code = TRUE;
-static char *boot_options = NULL;
+static char *boot_options;
#if defined(HAVE_OLD_UX4F_FIRMWARE)
static int have_old_firmware = TRUE;
@@ -619,9 +619,9 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
}
if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue)
- tag_suffix = ", tagged";
+ tag_suffix = ", soft-tagged";
else if (dev->tagged_supported && TLDEV(dev->type))
- tag_suffix = ", untagged";
+ tag_suffix = ", tagged";
printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n",
BN(j), host->host_no, dev->channel, dev->id, dev->lun,
@@ -766,8 +766,6 @@ static inline int port_detect \
if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING;
- tpnt->use_new_eh_code = use_new_eh_code;
-
sh[j] = scsi_register(tpnt, sizeof(struct hostdata));
if (sh[j] == NULL) {
@@ -875,10 +873,10 @@ 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-1999 Dario Ballabio.\n");
- printk("%s config options -> of:%c, lc:%c, mq:%d, eh:%c, et:%c.\n",
+ printk("UltraStor 14F/34F: Copyright (C) 1994-2000 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(use_new_eh_code), YESNO(ext_tran));
+ max_queue_depth, YESNO(ext_tran));
}
printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d.\n",
@@ -921,7 +919,6 @@ static void internal_setup(char *str, int *ints) {
else if (!strncmp(cur, "of:", 3)) have_old_firmware = val;
else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val;
else if (!strncmp(cur, "ls:", 3)) link_statistics = val;
- else if (!strncmp(cur, "eh:", 3)) use_new_eh_code = val;
else if (!strncmp(cur, "et:", 3)) ext_tran = val;
if ((cur = strchr(cur, ','))) ++cur;
@@ -1112,79 +1109,6 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
return rtn;
}
-static inline int do_old_abort(Scsi_Cmnd *SCarg) {
- unsigned int i, j;
-
- j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-
- if (SCarg->host_scribble == NULL ||
- (SCarg->serial_number_at_timeout &&
- (SCarg->serial_number != SCarg->serial_number_at_timeout))) {
- printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
- BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- i = *(unsigned int *)SCarg->host_scribble;
- printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
- BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
-
- if (i >= sh[j]->can_queue)
- panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
-
- if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
- printk("%s: abort, timeout error.\n", BN(j));
- return SCSI_ABORT_ERROR;
- }
-
- if (HD(j)->cp_stat[i] == FREE) {
- printk("%s: abort, mbox %d is free.\n", BN(j), i);
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- if (HD(j)->cp_stat[i] == IN_USE) {
- printk("%s: abort, mbox %d is in use.\n", BN(j), i);
-
- if (SCarg != HD(j)->cp[i].SCpnt)
- panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
- BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
-
- if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED)
- printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
-
- return SCSI_ABORT_SNOOZE;
- }
-
- if (HD(j)->cp_stat[i] == IN_RESET) {
- printk("%s: abort, mbox %d is in reset.\n", BN(j), i);
- return SCSI_ABORT_ERROR;
- }
-
- if (HD(j)->cp_stat[i] == LOCKED) {
- printk("%s: abort, mbox %d is locked.\n", BN(j), i);
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
- SCarg->result = DID_ABORT << 16;
- SCarg->host_scribble = NULL;
- HD(j)->cp_stat[i] = FREE;
- printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
- BN(j), i, SCarg->pid);
- SCarg->scsi_done(SCarg);
- return SCSI_ABORT_SUCCESS;
- }
-
- panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
-}
-
-int u14_34f_old_abort(Scsi_Cmnd *SCarg) {
- int rtn;
-
- rtn = do_old_abort(SCarg);
- return rtn;
-}
-
static inline int do_abort(Scsi_Cmnd *SCarg) {
unsigned int i, j;
@@ -1262,152 +1186,6 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) {
return do_abort(SCarg);
}
-static inline int do_old_reset(Scsi_Cmnd *SCarg) {
- unsigned int i, j, time, k, c, limit = 0;
- int arg_done = FALSE;
- Scsi_Cmnd *SCpnt;
-
- j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
- printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n",
- BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
-
- if (SCarg->host_scribble == NULL)
- printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
-
- if (SCarg->serial_number_at_timeout &&
- (SCarg->serial_number != SCarg->serial_number_at_timeout)) {
- printk("%s: reset, pid %ld, reset not running.\n", BN(j), SCarg->pid);
- return SCSI_RESET_NOT_RUNNING;
- }
-
- if (HD(j)->in_reset) {
- printk("%s: reset, exit, already in reset.\n", BN(j));
- return SCSI_RESET_ERROR;
- }
-
- if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
- printk("%s: reset, exit, timeout error.\n", BN(j));
- return SCSI_RESET_ERROR;
- }
-
- HD(j)->retries = 0;
-
- for (c = 0; c <= sh[j]->max_channel; c++)
- for (k = 0; k < sh[j]->max_id; k++) {
- HD(j)->target_redo[k][c] = TRUE;
- HD(j)->target_to[k][c] = 0;
- }
-
- for (i = 0; i < sh[j]->can_queue; i++) {
-
- if (HD(j)->cp_stat[i] == FREE) continue;
-
- if (HD(j)->cp_stat[i] == LOCKED) {
- HD(j)->cp_stat[i] = FREE;
- printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
- continue;
- }
-
- if (!(SCpnt = HD(j)->cp[i].SCpnt))
- panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
-
- if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
- HD(j)->cp_stat[i] = ABORTING;
- printk("%s: reset, mbox %d aborting, pid %ld.\n",
- BN(j), i, SCpnt->pid);
- }
-
- else {
- HD(j)->cp_stat[i] = IN_RESET;
- printk("%s: reset, mbox %d in reset, pid %ld.\n",
- BN(j), i, SCpnt->pid);
- }
-
- if (SCpnt->host_scribble == NULL)
- panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
-
- if (*(unsigned int *)SCpnt->host_scribble != i)
- panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
-
- if (SCpnt->scsi_done == NULL)
- panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
-
- if (SCpnt == SCarg) arg_done = TRUE;
- }
-
- if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
- printk("%s: reset, cannot reset, timeout error.\n", BN(j));
- return SCSI_RESET_ERROR;
- }
-
- outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR);
- printk("%s: reset, board reset done, enabling interrupts.\n", BN(j));
-
-#if defined(DEBUG_RESET)
- do_trace = TRUE;
-#endif
-
- HD(j)->in_reset = TRUE;
- SPIN_UNLOCK
- time = jiffies;
- while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
- SPIN_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;
- SCpnt->result = DID_RESET << 16;
- SCpnt->host_scribble = NULL;
-
- /* This mailbox is still waiting for its interrupt */
- HD(j)->cp_stat[i] = LOCKED;
-
- printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
- BN(j), i, SCpnt->pid);
- }
-
- else if (HD(j)->cp_stat[i] == ABORTING) {
- SCpnt = HD(j)->cp[i].SCpnt;
- SCpnt->result = DID_RESET << 16;
- SCpnt->host_scribble = NULL;
-
- /* This mailbox was never queued to the adapter */
- HD(j)->cp_stat[i] = FREE;
-
- printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
- BN(j), i, SCpnt->pid);
- }
-
- else
-
- /* Any other mailbox has already been set free by interrupt */
- continue;
-
- SCpnt->scsi_done(SCpnt);
- }
-
- HD(j)->in_reset = FALSE;
- do_trace = FALSE;
-
- if (arg_done) {
- printk("%s: reset, exit, success.\n", BN(j));
- return SCSI_RESET_SUCCESS;
- }
- else {
- printk("%s: reset, exit, wakeup.\n", BN(j));
- return SCSI_RESET_PUNT;
- }
-}
-
-int u14_34f_old_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
- int rtn;
-
- rtn = do_old_reset(SCarg);
- return rtn;
-}
-
static inline int do_reset(Scsi_Cmnd *SCarg) {
unsigned int i, j, time, k, c, limit = 0;
int arg_done = FALSE;
@@ -1663,7 +1441,7 @@ static inline int reorder(unsigned int j, unsigned long cursec,
if (link_statistics) {
if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec;
- batchcount++; readycount += n_ready, seeknosort += seek / 1024;
+ batchcount++; readycount += n_ready; seeknosort += seek / 1024;
if (input_only) inputcount++;
if (overlap) { ovlcount++; seeksorted += iseek / 1024; }
else seeksorted += (iseek + maxsec - minsec) / 1024;
@@ -1837,7 +1615,9 @@ static inline void ihdlr(int irq, unsigned int j) {
if (tstatus == GOOD)
HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
- if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+ if (spp->target_status && SCpnt->device->type == TYPE_DISK &&
+ (!(tstatus == CHECK_CONDITION && HD(j)->iocount <= 1000 &&
+ (SCpnt->sense_buffer[2] & 0xf) == NOT_READY)))
printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
"target_status 0x%x, sense key 0x%x.\n", BN(j),
SCpnt->channel, SCpnt->target, SCpnt->lun,
@@ -1969,13 +1749,5 @@ static Scsi_Host_Template driver_template = ULTRASTOR_14_34F;
#include "scsi_module.c"
#ifndef MODULE
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
-void u14_34f_setup(char *str, int *ints) {
- internal_setup(str, ints);
-}
-#else
__setup("u14-34f=", option_setup);
-#endif
-
#endif /* end MODULE */
diff --git a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h
index ff49b56ea..5e481ea40 100644
--- a/drivers/scsi/u14-34f.h
+++ b/drivers/scsi/u14-34f.h
@@ -5,30 +5,23 @@
#define _U14_34F_H
#include <scsi/scsicam.h>
-#include <linux/version.h>
int u14_34f_detect(Scsi_Host_Template *);
int u14_34f_release(struct Scsi_Host *);
int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int u14_34f_abort(Scsi_Cmnd *);
-int u14_34f_old_abort(Scsi_Cmnd *);
int u14_34f_reset(Scsi_Cmnd *);
-int u14_34f_old_reset(Scsi_Cmnd *, unsigned int);
int u14_34f_biosparam(Disk *, kdev_t, int *);
-#define U14_34F_VERSION "5.11.00"
-
-#ifndef LinuxVersionCode
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-#endif
+#define U14_34F_VERSION "6.02.00"
#define ULTRASTOR_14_34F { \
name: "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
detect: u14_34f_detect, \
release: u14_34f_release, \
queuecommand: u14_34f_queuecommand, \
- abort: u14_34f_old_abort, \
- reset: u14_34f_old_reset, \
+ abort: NULL, \
+ reset: NULL, \
eh_abort_handler: u14_34f_abort, \
eh_device_reset_handler: NULL, \
eh_bus_reset_handler: NULL, \
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index 9d6d45e03..bed2b06a2 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -66,8 +66,14 @@
* this thing into as good a shape as possible, and I'm positive
* there are lots of lurking bugs and "Stupid Places".
*
+ * Updates:
+ *
+ * Added support for pre -A chips, which don't have advanced features
+ * and will generate CSR_RESEL rather than CSR_RESEL_AM.
+ * Richard Hirst <richard@sleepie.demon.co.uk> August 2000
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <asm/system.h>
@@ -1249,11 +1255,16 @@ DB(DB_INTR,printk(":%d",cmd->SCp.Status))
case CSR_RESEL_AM:
-DB(DB_INTR,printk("RESEL"))
-
- /* First we have to make sure this reselection didn't */
- /* happen during Arbitration/Selection of some other device. */
- /* If yes, put losing command back on top of input_Q. */
+ case CSR_RESEL:
+DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
+
+ /* Old chips (pre -A ???) don't have advanced features and will
+ * generate CSR_RESEL. In that case we have to extract the LUN the
+ * hard way (see below).
+ * First we have to make sure this reselection didn't
+ * happen during Arbitration/Selection of some other device.
+ * If yes, put losing command back on top of input_Q.
+ */
if (hostdata->level2 <= L2_NONE) {
@@ -1293,10 +1304,53 @@ DB(DB_INTR,printk("RESEL"))
* not the right way to go, but...)
*/
- lun = read_wd33c93(regp, WD_DATA);
- if (hostdata->level2 < L2_RESELECT)
- write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
- lun &= 7;
+ if (sr == CSR_RESEL_AM) {
+ lun = read_wd33c93(regp, WD_DATA);
+ if (hostdata->level2 < L2_RESELECT)
+ write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
+ lun &= 7;
+ }
+ else {
+ /* Old chip; wait for msgin phase to pick up the LUN. */
+ for (lun = 255; lun; lun--) {
+ if ((asr = READ_AUX_STAT()) & ASR_INT)
+ break;
+ udelay(10);
+ }
+ if (!(asr & ASR_INT)) {
+ printk("wd33c93: Reselected without IDENTIFY\n");
+ lun = 0;
+ }
+ else {
+ /* Verify this is a change to MSG_IN and read the message */
+ sr = read_wd33c93(regp, WD_SCSI_STATUS);
+ if (sr == (CSR_ABORT | PHS_MESS_IN) ||
+ sr == (CSR_UNEXP | PHS_MESS_IN) ||
+ sr == (CSR_SRV_REQ | PHS_MESS_IN)) {
+ /* Got MSG_IN, grab target LUN */
+ lun = read_1_byte(regp);
+ /* Now we expect a 'paused with ACK asserted' int.. */
+ asr = READ_AUX_STAT();
+ if (!(asr & ASR_INT)) {
+ udelay(10);
+ asr = READ_AUX_STAT();
+ if (!(asr & ASR_INT))
+ printk("wd33c93: No int after LUN on RESEL (%02x)\n",
+ asr);
+ }
+ sr = read_wd33c93(regp, WD_SCSI_STATUS);
+ if (sr != CSR_MSGIN)
+ printk("wd33c93: Not paused with ACK on RESEL (%02x)\n",
+ sr);
+ lun &= 7;
+ write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
+ }
+ else {
+ printk("wd33c93: Not MSG_IN on reselect (%02x)\n", sr);
+ lun = 0;
+ }
+ }
+ }
/* Now we look for the command that's reconnecting. */
@@ -1391,6 +1445,9 @@ extern void sgiwd93_reset(unsigned long);
write_wd33c93(regp, WD_SYNCHRONOUS_TRANSFER,
calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));
write_wd33c93(regp, WD_COMMAND, WD_CMD_RESET);
+#ifdef CONFIG_MVME147_SCSI
+ udelay(25); /* The old wd33c93 on MVME147 needs this, at least */
+#endif
while (!(READ_AUX_STAT() & ASR_INT))
;
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index 203c7d980..83e131918 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -190,7 +190,9 @@
/* This is what the 3393 chip looks like to us */
typedef struct {
volatile unsigned char SASR;
+#if !defined(CONFIG_MVME147_SCSI)
char pad;
+#endif
#ifdef CONFIG_SGI_IP22
char pad2,pad3;
#endif
@@ -341,5 +343,6 @@ int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
void wd33c93_intr (struct Scsi_Host *instance);
int wd33c93_proc_info(char *, char **, off_t, int, int, int);
int wd33c93_reset (Scsi_Cmnd *, unsigned int);
+void wd33c93_release(void);
#endif /* WD33C93_H */
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index 929c9cf0f..9fd35efcb 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -142,7 +142,10 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
dep_tristate ' Yamaha FM synthesizer (YM3812/OPL-3) support' CONFIG_SOUND_YM3812 $CONFIG_SOUND_OSS
dep_tristate ' Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS
dep_tristate ' Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
- dep_tristate ' Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI
+ dep_tristate ' Yamaha YMF7xx PCI audio (legacy mode)' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI
+ if [ "$CONFIG_SOUND_YMPCI" = "n" ]; then
+ dep_tristate ' Yamaha YMF7xx PCI audio (native mode) (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS $CONFIG_PCI $CONFIG_EXPERIMENTAL
+ fi
dep_tristate ' 6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS
dep_tristate ' Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_SOUND_AEDSP16 $CONFIG_SOUND_OSS
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index ad715e752..0a29d73d0 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o
obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o
obj-$(CONFIG_SOUND_YMPCI) += ymf_sb.o sb_lib.o uart401.o
+obj-$(CONFIG_SOUND_YMFPCI) += ymfpci.o ac97_codec.o
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
diff --git a/drivers/sound/ac97_codec.c b/drivers/sound/ac97_codec.c
index 20f307d13..e489fbd01 100644
--- a/drivers/sound/ac97_codec.c
+++ b/drivers/sound/ac97_codec.c
@@ -134,7 +134,7 @@ static struct mixer_defaults {
{SOUND_MIXER_PCM, 0x4343},
{SOUND_MIXER_SPEAKER, 0x4343},
{SOUND_MIXER_LINE, 0x4343},
- {SOUND_MIXER_MIC, 0x4343},
+ {SOUND_MIXER_MIC, 0x0000},
{SOUND_MIXER_CD, 0x4343},
{SOUND_MIXER_ALTPCM, 0x4343},
{SOUND_MIXER_IGAIN, 0x4343},
@@ -284,6 +284,10 @@ static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
if (oss_channel == SOUND_MIXER_IGAIN) {
right = (right * mh->scale) / 100;
left = (left * mh->scale) / 100;
+ if (right >= mh->scale)
+ right = mh->scale-1;
+ if (left >= mh->scale)
+ left = mh->scale-1;
} else {
/* these may have 5 or 6 bit resolution */
if (oss_channel == SOUND_MIXER_VOLUME ||
@@ -294,27 +298,49 @@ static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
right = ((100 - right) * scale) / 100;
left = ((100 - left) * scale) / 100;
- }
+ if (right >= scale)
+ right = scale-1;
+ if (left >= scale)
+ left = scale-1;
+ }
val = (left << 8) | right;
}
} else if (oss_channel == SOUND_MIXER_BASS) {
val = codec->codec_read(codec , mh->offset) & ~0x0f00;
- val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;
+ left = ((100 - left) * mh->scale) / 100;
+ if (left >= mh->scale)
+ left = mh->scale-1;
+ val |= (left << 8) & 0x0e00;
} else if (oss_channel == SOUND_MIXER_TREBLE) {
val = codec->codec_read(codec , mh->offset) & ~0x000f;
- val |= (((100 - left) * mh->scale) / 100) & 0x000e;
+ left = ((100 - left) * mh->scale) / 100;
+ if (left >= mh->scale)
+ left = mh->scale-1;
+ val |= left & 0x000e;
} else if(left == 0) {
val = AC97_MUTE;
} else if (oss_channel == SOUND_MIXER_SPEAKER) {
- val = (((100 - left) * mh->scale) / 100) << 1;
+ left = ((100 - left) * mh->scale) / 100;
+ if (left >= mh->scale)
+ left = mh->scale-1;
+ val = left << 1;
} else if (oss_channel == SOUND_MIXER_PHONEIN) {
- val = (((100 - left) * mh->scale) / 100);
+ left = ((100 - left) * mh->scale) / 100;
+ if (left >= mh->scale)
+ left = mh->scale-1;
+ val = left;
} else if (oss_channel == SOUND_MIXER_PHONEOUT) {
scale = (1 << codec->bit_resolution);
- val = (((100 - left) * scale) / 100);
+ left = ((100 - left) * scale) / 100;
+ if (left >= mh->scale)
+ left = mh->scale-1;
+ val = left;
} else if (oss_channel == SOUND_MIXER_MIC) {
val = codec->codec_read(codec , mh->offset) & ~0x801f;
- val |= (((100 - left) * mh->scale) / 100);
+ left = ((100 - left) * mh->scale) / 100;
+ if (left >= mh->scale)
+ left = mh->scale-1;
+ val |= left;
/* the low bit is optional in the tone sliders and masking
it lets us avoid the 0xf 'bypass'.. */
}
diff --git a/drivers/sound/cs4281.c b/drivers/sound/cs4281.c
index 3fcb068d1..661caa214 100644
--- a/drivers/sound/cs4281.c
+++ b/drivers/sound/cs4281.c
@@ -258,7 +258,7 @@ struct cs4281_state {
#define SNDCTL_DSP_CS_GETDBGMASK _SIOWR('P', 52, int)
#define SNDCTL_DSP_CS_SETDBGMASK _SIOWR('P', 53, int)
-void printioctl(unsigned int x)
+static void printioctl(unsigned int x)
{
unsigned int i;
unsigned char vidx;
diff --git a/drivers/sound/cs461x_image.h b/drivers/sound/cs461x_image.h
index 36d3ed18f..cef60057e 100644
--- a/drivers/sound/cs461x_image.h
+++ b/drivers/sound/cs461x_image.h
@@ -1,3459 +1,316 @@
-struct BA1struct BA1Struct __initdata = {
-{{ 0x00000000, 0x00003000 },{ 0x00010000, 0x00003800 },{ 0x00020000, 0x00007000 }},
-{0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00200040,0x00008010,0x00000000,
-0x00000000,0x80000001,0x00000001,0x00060000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00900080,0x00000173,0x00000000,
-0x00000000,0x00000010,0x00800000,0x00900000,
-0xf2c0000f,0x00000200,0x00000000,0x00010600,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x330300c2,
-0x06000000,0x00000000,0x80008000,0x80008000,
-0x3fc0000f,0x00000301,0x00010400,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00b00000,0x00d0806d,0x330480c3,
-0x04800000,0x00000001,0x00800001,0x0000ffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x066a0600,0x06350070,0x0000929d,0x929d929d,
-0x00000000,0x0000735a,0x00000600,0x00000000,
-0x929d735a,0x8734abfe,0x00010000,0x735a735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000804f,0x000000c3,
-0x05000000,0x00a00010,0x00000000,0x80008000,
-0x00000000,0x00000000,0x00000700,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000080,0x00a00000,0x0000809a,0x000000c2,
-0x07400000,0x00000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x000107a0,
-0x00c80028,0x000000c2,0x06800000,0x00000000,
-0x06e00080,0x00300000,0x000080bb,0x000000c9,
-0x07a00000,0x04000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x00000780,
-0x00c80028,0x000000c5,0xff800000,0x00000000,
-0x00640080,0x00c00000,0x00008197,0x000000c9,
-0x07800000,0x04000000,0x80008000,0xffffffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000805e,0x000000c1,
-0x00000000,0x00800000,0x80008000,0x80008000,
-0x00020000,0x0000ffff,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x929d0600,0x929d929d,0x929d929d,0x929d0000,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x00100635,0x060b013f,0x00000004,
-0x00000001,0x007a0002,0x00000000,0x066e0610,
-0x0105929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0xa431ac75,0x0001735a,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051,
-0x00000000,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x00000000,0x06400136,
-0x0000270f,0x00010000,0x007a0000,0x00000000,
-0x068e0645,0x0105929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0xa431ac75,0x0001735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x735a0100,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00010004,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00001705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00009705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00011705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00019705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00021705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00029705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00031705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00039705,0x00001400,0x000a411e,0x00001003,
-0x000fe19e,0x00001003,0x0009c730,0x00001003,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00009705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00011705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00019705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00021705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00029705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00031705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00039705,0x00001400,0x000a211e,0x00001003,
-0x0000a730,0x00001008,0x000e2730,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x00000000,0x00000000,0x000f619c,0x00001003,
-0x0007f801,0x000c0000,0x00000037,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0000373c,0x00001000,0x00000000,0x00000000,
-0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000273c,0x00001000,
-0x00000033,0x00001000,0x000e679e,0x00001003,
-0x00007705,0x00001400,0x000ac71e,0x00001003,
-0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000a730,0x00001003,
-0x00000033,0x00001000,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x000c0000,
-0x00000032,0x00001000,0x0000273d,0x00001000,
-0x0004a730,0x00001003,0x00000f41,0x00097140,
-0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-0x00002725,0x000aa400,0x00013705,0x00093a00,
-0x0000002e,0x0009d6c0,0x00038630,0x00001004,
-0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000,
-0x00000000,0x000c70e0,0x0007d182,0x0002c640,
-0x00000630,0x00001004,0x000799b8,0x0002c6c0,
-0x00031705,0x00092240,0x00039f05,0x000932c0,
-0x0003520a,0x00000000,0x00040731,0x0000100b,
-0x00010705,0x000b20c0,0x00000000,0x000eba44,
-0x00032108,0x000c60c4,0x00065208,0x000c2917,
-0x000406b0,0x00001007,0x00012f05,0x00036880,
-0x0002818e,0x000c0000,0x0004410a,0x00000000,
-0x00040630,0x00001007,0x00029705,0x000c0000,
-0x00000000,0x00000000,0x00003fc1,0x0003fc40,
-0x000037c1,0x00091b40,0x00003fc1,0x000911c0,
-0x000037c1,0x000957c0,0x00003fc1,0x000951c0,
-0x000037c1,0x00000000,0x00003fc1,0x000991c0,
-0x000037c1,0x00000000,0x00003fc1,0x0009d1c0,
-0x000037c1,0x00000000,0x0001ccc1,0x000915c0,
-0x0001c441,0x0009d800,0x0009cdc1,0x00091240,
-0x0001c541,0x00091d00,0x0009cfc1,0x00095240,
-0x0001c741,0x00095c80,0x000e8ca9,0x00099240,
-0x000e85ad,0x00095640,0x00069ca9,0x00099d80,
-0x000e952d,0x00099640,0x000eaca9,0x0009d6c0,
-0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80,
-0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0,
-0x000ec5ad,0x0009da40,0x000edca9,0x0009d300,
-0x000a6e0a,0x00001000,0x000ed52d,0x00091e40,
-0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40,
-0x0006fca9,0x00002500,0x000fb208,0x000c59a0,
-0x000ef52d,0x0009de40,0x00068ca9,0x000912c1,
-0x000683ad,0x00095241,0x00020f05,0x000991c1,
-0x00000000,0x00000000,0x00086f88,0x00001000,
-0x0009cf81,0x000b5340,0x0009c701,0x000b92c0,
-0x0009de81,0x000bd300,0x0009d601,0x000b1700,
-0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0,
-0x000a0f81,0x000bd740,0x00020701,0x000b5c80,
-0x000a1681,0x000b97c0,0x00021601,0x00002500,
-0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0,
-0x00021681,0x00002d00,0x00020f81,0x000bd800,
-0x000a0701,0x000b5bc0,0x00021601,0x00003500,
-0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0,
-0x00021681,0x00003d00,0x00020f81,0x000b1d00,
-0x000a0701,0x000b1fc0,0x00021601,0x00020500,
-0x00020f81,0x000b1341,0x000a0701,0x000b9fc0,
-0x00021681,0x00020d00,0x00020f81,0x000bde80,
-0x000a0701,0x000bdfc0,0x00021601,0x00021500,
-0x00020f81,0x000b9341,0x00020701,0x000b53c1,
-0x00021681,0x00021d00,0x000a0f81,0x000d0380,
-0x0000b601,0x000b15c0,0x00007b01,0x00000000,
-0x00007b81,0x000bd1c0,0x00007b01,0x00000000,
-0x00007b81,0x000b91c0,0x00007b01,0x000b57c0,
-0x00007b81,0x000b51c0,0x00007b01,0x000b1b40,
-0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0,
-0x0007e488,0x000d7e45,0x00000000,0x000d7a44,
-0x0007e48a,0x00000000,0x00011f05,0x00084080,
-0x00000000,0x00000000,0x00001705,0x000b3540,
-0x00008a01,0x000bf040,0x00007081,0x000bb5c0,
-0x00055488,0x00000000,0x0000d482,0x0003fc40,
-0x0003fc88,0x00000000,0x0001e401,0x000b3a00,
-0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784,
-0x000c86b0,0x00001007,0x00008281,0x000bb240,
-0x0000b801,0x000b7140,0x00007888,0x00000000,
-0x0000073c,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x00055288,0x000c555c,
-0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-0x0000fa88,0x00000000,0x00000032,0x00001000,
-0x0000073d,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x0008c01c,0x00001003,
-0x00002705,0x00001008,0x0008b201,0x000c1392,
-0x0000ba01,0x00000000,0x00008731,0x00001400,
-0x0004c108,0x000fe0c4,0x00057488,0x00000000,
-0x000a6388,0x00001001,0x0008b334,0x000bc141,
-0x0003020e,0x00000000,0x000886b0,0x00001008,
-0x00003625,0x000c5dfa,0x000a638a,0x00001001,
-0x0008020e,0x00001002,0x0008a6b0,0x00001008,
-0x0007f301,0x00000000,0x00000000,0x00000000,
-0x00002725,0x000a8c40,0x000000ae,0x00000000,
-0x000d8630,0x00001008,0x00000000,0x000c74e0,
-0x0007d182,0x0002d640,0x000a8630,0x00001008,
-0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5,
-0x0007420a,0x000c0000,0x00062208,0x000c4117,
-0x00070630,0x00001009,0x00000000,0x000c0000,
-0x0001022e,0x00000000,0x0003a630,0x00001009,
-0x00000000,0x000c0000,0x00000036,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x0002a730,0x00001008,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0002a730,0x00001008,
-0x00000033,0x00001000,0x0002a705,0x00001008,
-0x00007a01,0x000c0000,0x000e6288,0x000d550a,
-0x0006428a,0x00000000,0x00060730,0x0000100a,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0007aab0,0x00034880,0x00078fb0,0x0000100b,
-0x00057488,0x00000000,0x00033b94,0x00081140,
-0x000183ae,0x00000000,0x000786b0,0x0000100b,
-0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-0x00042731,0x00001003,0x0007aab0,0x00034880,
-0x00048fb0,0x0000100a,0x00057488,0x00000000,
-0x00033b94,0x00081140,0x000183ae,0x00000000,
-0x000806b0,0x0000100b,0x00022f05,0x00000000,
-0x00007401,0x00091140,0x00048f05,0x000951c0,
-0x00042731,0x00001003,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x000fe19e,0x00001003,0x00000000,0x00000000,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00000f41,0x00097140,0x0000a841,0x0009b240,
-0x0000a0c1,0x0009f040,0x0001c641,0x00093540,
-0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44,
-0x00055208,0x00000000,0x00010705,0x000a2880,
-0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5,
-0x0004ef0a,0x000c0000,0x00012f05,0x00036880,
-0x00065308,0x000c2997,0x000d86b0,0x0000100a,
-0x0004410a,0x000d40c7,0x00000000,0x00000000,
-0x00080730,0x00001004,0x00056f0a,0x000ea105,
-0x00000000,0x00000000,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x0000273d,0x00001000,0x00000000,0x000eba44,
-0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x00000000,0x000e5084,
-0x00000000,0x000eba44,0x00087401,0x000e4782,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x0007c108,0x000c0000,
-0x0007e721,0x000bed40,0x00005f25,0x000badc0,
-0x0003ba97,0x000beb80,0x00065590,0x000b2e00,
-0x00033217,0x00003ec0,0x00065590,0x000b8e40,
-0x0003ed80,0x000491c0,0x00073fb0,0x00074c80,
-0x000283a0,0x0000100c,0x000ee388,0x00042970,
-0x00008301,0x00021ef2,0x000b8f14,0x0000000f,
-0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6,
-0x000032ac,0x000c3916,0x0004edc2,0x00074c80,
-0x00078898,0x00001000,0x00038894,0x00000032,
-0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6,
-0x0004edc2,0x000c1956,0x0000722c,0x00034a00,
-0x00041705,0x0009ed40,0x00058730,0x00001400,
-0x000d7488,0x000c3a00,0x00048f05,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000}
- };
+/****************************************************************************
+ * "CWCIMAGE.H"-- For CS46XX. Ver 1.04
+ * Copyright 1998-2000 (c) Cirrus Logic Corp.
+ * Version 1.04
+ ****************************************************************************
+ */
+#define CLEAR__COUNT 3
+#define FILL__COUNT 4
+#define BA1__DWORD_SIZE 13*1024+512
+
+static struct
+{
+ unsigned BA1__DestByteOffset;
+ unsigned BA1__SourceSize;
+} ClrStat[CLEAR__COUNT] ={ {0x00000000, 0x00003000 },
+ {0x00010000, 0x00003800 },
+ {0x00020000, 0x00007000 } };
+
+static u32 FillArray1[]={
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000163,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00200040,0x00008010,0x00000000,
+0x00000000,0x80000001,0x00000001,0x00060000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00900080,0x00000173,0x00000000,
+0x00000000,0x00000010,0x00800000,0x00900000,
+0xf2c0000f,0x00000200,0x00000000,0x00010600,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000163,0x330300c2,
+0x06000000,0x00000000,0x80008000,0x80008000,
+0x3fc0000f,0x00000301,0x00010400,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00b00000,0x00d0806d,0x330480c3,
+0x04800000,0x00000001,0x00800001,0x0000ffff,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x066a0600,0x06350070,0x0000929d,0x929d929d,
+0x00000000,0x0000735a,0x00000600,0x00000000,
+0x929d735a,0x00000000,0x00010000,0x735a735a,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x0000804f,0x000000c3,
+0x05000000,0x00a00010,0x00000000,0x80008000,
+0x00000000,0x00000000,0x00000700,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000080,0x00a00000,0x0000809a,0x000000c2,
+0x07400000,0x00000000,0x80008000,0xffffffff,
+0x00c80028,0x00005555,0x00000000,0x000107a0,
+0x00c80028,0x000000c2,0x06800000,0x00000000,
+0x06e00080,0x00300000,0x000080bb,0x000000c9,
+0x07a00000,0x04000000,0x80008000,0xffffffff,
+0x00c80028,0x00005555,0x00000000,0x00000780,
+0x00c80028,0x000000c5,0xff800000,0x00000000,
+0x00640080,0x00c00000,0x00008197,0x000000c9,
+0x07800000,0x04000000,0x80008000,0xffffffff,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x0000805e,0x000000c1,
+0x00000000,0x00800000,0x80008000,0x80008000,
+0x00020000,0x0000ffff,0x00000000,0x00000000};
+
+static u32 FillArray2[]={
+0x929d0600,0x929d929d,0x929d929d,0x929d0000,
+0x929d929d,0x929d929d,0x929d929d,0x929d929d,
+0x929d929d,0x00100635,0x060b013f,0x00000004,
+0x00000001,0x007a0002,0x00000000,0x066e0610,
+0x0105929d,0x929d929d,0x929d929d,0x929d929d,
+0x929d929d,0xa431ac75,0x0001735a,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051,
+0x00000000,0x929d929d,0x929d929d,0x929d929d,
+0x929d929d,0x929d929d,0x929d929d,0x929d929d,
+0x929d929d,0x929d929d,0x00000000,0x06400136,
+0x0000270f,0x00010000,0x007a0000,0x00000000,
+0x068e0645,0x0105929d,0x929d929d,0x929d929d,
+0x929d929d,0x929d929d,0xa431ac75,0x0001735a,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
+0x735a0100,0x00000000,0x00000000,0x00000000};
+
+static u32 FillArray3[]={
+0x00000000,0x00000000,0x00000000,0x00010004};
+
+static u32 FillArray4[]={
+0x00040730,0x00001002,0x000f619e,0x00001003,
+0x00001705,0x00001400,0x000a411e,0x00001003,
+0x00040730,0x00001002,0x000f619e,0x00001003,
+0x00009705,0x00001400,0x000a411e,0x00001003,
+0x00040730,0x00001002,0x000f619e,0x00001003,
+0x00011705,0x00001400,0x000a411e,0x00001003,
+0x00040730,0x00001002,0x000f619e,0x00001003,
+0x00019705,0x00001400,0x000a411e,0x00001003,
+0x00040730,0x00001002,0x000f619e,0x00001003,
+0x00021705,0x00001400,0x000a411e,0x00001003,
+0x00040730,0x00001002,0x000f619e,0x00001003,
+0x00029705,0x00001400,0x000a411e,0x00001003,
+0x00040730,0x00001002,0x000f619e,0x00001003,
+0x00031705,0x00001400,0x000a411e,0x00001003,
+0x00040730,0x00001002,0x000f619e,0x00001003,
+0x00039705,0x00001400,0x000a411e,0x00001003,
+0x000fe19e,0x00001003,0x0009c730,0x00001003,
+0x0008e19c,0x00001003,0x000083c1,0x00093040,
+0x00098730,0x00001002,0x000ee19e,0x00001003,
+0x00009705,0x00001400,0x000a211e,0x00001003,
+0x00098730,0x00001002,0x000ee19e,0x00001003,
+0x00011705,0x00001400,0x000a211e,0x00001003,
+0x00098730,0x00001002,0x000ee19e,0x00001003,
+0x00019705,0x00001400,0x000a211e,0x00001003,
+0x00098730,0x00001002,0x000ee19e,0x00001003,
+0x00021705,0x00001400,0x000a211e,0x00001003,
+0x00098730,0x00001002,0x000ee19e,0x00001003,
+0x00029705,0x00001400,0x000a211e,0x00001003,
+0x00098730,0x00001002,0x000ee19e,0x00001003,
+0x00031705,0x00001400,0x000a211e,0x00001003,
+0x00098730,0x00001002,0x000ee19e,0x00001003,
+0x00039705,0x00001400,0x000a211e,0x00001003,
+0x0000a730,0x00001008,0x000e2730,0x00001002,
+0x0000a731,0x00001002,0x0000a731,0x00001002,
+0x0000a731,0x00001002,0x0000a731,0x00001002,
+0x0000a731,0x00001002,0x0000a731,0x00001002,
+0x00000000,0x00000000,0x000f619c,0x00001003,
+0x0007f801,0x000c0000,0x00000037,0x00001000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x000c0000,0x00000000,0x00000000,
+0x0000373c,0x00001000,0x00000000,0x00000000,
+0x000ee19c,0x00001003,0x0007f801,0x000c0000,
+0x00000037,0x00001000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x0000273c,0x00001000,
+0x00000033,0x00001000,0x000e679e,0x00001003,
+0x00007705,0x00001400,0x000ac71e,0x00001003,
+0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
+0x00000037,0x00001000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x0000a730,0x00001003,
+0x00000033,0x00001000,0x0007f801,0x000c0000,
+0x00000037,0x00001000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x000c0000,
+0x00000032,0x00001000,0x0000273d,0x00001000,
+0x0004a730,0x00001003,0x00000f41,0x00097140,
+0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
+0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
+0x00000000,0x00000000,0x0001bf05,0x0003fc40,
+0x00002725,0x000aa400,0x00013705,0x00093a00,
+0x0000002e,0x0009d6c0,0x00038630,0x00001004,
+0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000,
+0x00000000,0x000c70e0,0x0007d182,0x0002c640,
+0x00000630,0x00001004,0x000799b8,0x0002c6c0,
+0x00031705,0x00092240,0x00039f05,0x000932c0,
+0x0003520a,0x00000000,0x00040731,0x0000100b,
+0x00010705,0x000b20c0,0x00000000,0x000eba44,
+0x00032108,0x000c60c4,0x00065208,0x000c2917,
+0x000406b0,0x00001007,0x00012f05,0x00036880,
+0x0002818e,0x000c0000,0x0004410a,0x00000000,
+0x00040630,0x00001007,0x00029705,0x000c0000,
+0x00000000,0x00000000,0x00003fc1,0x0003fc40,
+0x000037c1,0x00091b40,0x00003fc1,0x000911c0,
+0x000037c1,0x000957c0,0x00003fc1,0x000951c0,
+0x000037c1,0x00000000,0x00003fc1,0x000991c0,
+0x000037c1,0x00000000,0x00003fc1,0x0009d1c0,
+0x000037c1,0x00000000,0x0001ccc1,0x000915c0,
+0x0001c441,0x0009d800,0x0009cdc1,0x00091240,
+0x0001c541,0x00091d00,0x0009cfc1,0x00095240,
+0x0001c741,0x00095c80,0x000e8ca9,0x00099240,
+0x000e85ad,0x00095640,0x00069ca9,0x00099d80,
+0x000e952d,0x00099640,0x000eaca9,0x0009d6c0,
+0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80,
+0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0,
+0x000ec5ad,0x0009da40,0x000edca9,0x0009d300,
+0x000a6e0a,0x00001000,0x000ed52d,0x00091e40,
+0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40,
+0x0006fca9,0x00002500,0x000fb208,0x000c59a0,
+0x000ef52d,0x0009de40,0x00068ca9,0x000912c1,
+0x000683ad,0x00095241,0x00020f05,0x000991c1,
+0x00000000,0x00000000,0x00086f88,0x00001000,
+0x0009cf81,0x000b5340,0x0009c701,0x000b92c0,
+0x0009de81,0x000bd300,0x0009d601,0x000b1700,
+0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0,
+0x000a0f81,0x000bd740,0x00020701,0x000b5c80,
+0x000a1681,0x000b97c0,0x00021601,0x00002500,
+0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0,
+0x00021681,0x00002d00,0x00020f81,0x000bd800,
+0x000a0701,0x000b5bc0,0x00021601,0x00003500,
+0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0,
+0x00021681,0x00003d00,0x00020f81,0x000b1d00,
+0x000a0701,0x000b1fc0,0x00021601,0x00020500,
+0x00020f81,0x000b1341,0x000a0701,0x000b9fc0,
+0x00021681,0x00020d00,0x00020f81,0x000bde80,
+0x000a0701,0x000bdfc0,0x00021601,0x00021500,
+0x00020f81,0x000b9341,0x00020701,0x000b53c1,
+0x00021681,0x00021d00,0x000a0f81,0x000d0380,
+0x0000b601,0x000b15c0,0x00007b01,0x00000000,
+0x00007b81,0x000bd1c0,0x00007b01,0x00000000,
+0x00007b81,0x000b91c0,0x00007b01,0x000b57c0,
+0x00007b81,0x000b51c0,0x00007b01,0x000b1b40,
+0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0,
+0x0007e488,0x000d7e45,0x00000000,0x000d7a44,
+0x0007e48a,0x00000000,0x00011f05,0x00084080,
+0x00000000,0x00000000,0x00001705,0x000b3540,
+0x00008a01,0x000bf040,0x00007081,0x000bb5c0,
+0x00055488,0x00000000,0x0000d482,0x0003fc40,
+0x0003fc88,0x00000000,0x0001e401,0x000b3a00,
+0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784,
+0x000c86b0,0x00001007,0x00008281,0x000bb240,
+0x0000b801,0x000b7140,0x00007888,0x00000000,
+0x0000073c,0x00001000,0x0007f188,0x000c0000,
+0x00000000,0x00000000,0x00055288,0x000c555c,
+0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
+0x0000fa88,0x00000000,0x00000032,0x00001000,
+0x0000073d,0x00001000,0x0007f188,0x000c0000,
+0x00000000,0x00000000,0x0008c01c,0x00001003,
+0x00002705,0x00001008,0x0008b201,0x000c1392,
+0x0000ba01,0x00000000,0x00008731,0x00001400,
+0x0004c108,0x000fe0c4,0x00057488,0x00000000,
+0x000a6388,0x00001001,0x0008b334,0x000bc141,
+0x0003020e,0x00000000,0x000886b0,0x00001008,
+0x00003625,0x000c5dfa,0x000a638a,0x00001001,
+0x0008020e,0x00001002,0x0008a6b0,0x00001008,
+0x0007f301,0x00000000,0x00000000,0x00000000,
+0x00002725,0x000a8c40,0x000000ae,0x00000000,
+0x000d8630,0x00001008,0x00000000,0x000c74e0,
+0x0007d182,0x0002d640,0x000a8630,0x00001008,
+0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5,
+0x0007420a,0x000c0000,0x00062208,0x000c4117,
+0x00070630,0x00001009,0x00000000,0x000c0000,
+0x0001022e,0x00000000,0x0003a630,0x00001009,
+0x00000000,0x000c0000,0x00000036,0x00001000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x0002a730,0x00001008,0x0007f801,0x000c0000,
+0x00000037,0x00001000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x00000000,0x00000000,
+0x00000000,0x00000000,0x0002a730,0x00001008,
+0x00000033,0x00001000,0x0002a705,0x00001008,
+0x00007a01,0x000c0000,0x000e6288,0x000d550a,
+0x0006428a,0x00000000,0x00060730,0x0000100a,
+0x00000000,0x000c0000,0x00000000,0x00000000,
+0x0007aab0,0x00034880,0x00078fb0,0x0000100b,
+0x00057488,0x00000000,0x00033b94,0x00081140,
+0x000183ae,0x00000000,0x000786b0,0x0000100b,
+0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
+0x00042731,0x00001003,0x0007aab0,0x00034880,
+0x00048fb0,0x0000100a,0x00057488,0x00000000,
+0x00033b94,0x00081140,0x000183ae,0x00000000,
+0x000806b0,0x0000100b,0x00022f05,0x00000000,
+0x00007401,0x00091140,0x00048f05,0x000951c0,
+0x00042731,0x00001003,0x0000473d,0x00001000,
+0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
+0x000fe19e,0x00001003,0x00000000,0x00000000,
+0x0008e19c,0x00001003,0x000083c1,0x00093040,
+0x00000f41,0x00097140,0x0000a841,0x0009b240,
+0x0000a0c1,0x0009f040,0x0001c641,0x00093540,
+0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44,
+0x00055208,0x00000000,0x00010705,0x000a2880,
+0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5,
+0x0004ef0a,0x000c0000,0x00012f05,0x00036880,
+0x00065308,0x000c2997,0x000d86b0,0x0000100a,
+0x0004410a,0x000d40c7,0x00000000,0x00000000,
+0x00080730,0x00001004,0x00056f0a,0x000ea105,
+0x00000000,0x00000000,0x0000473d,0x00001000,
+0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
+0x0000273d,0x00001000,0x00000000,0x000eba44,
+0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
+0x00000734,0x00001000,0x00010705,0x000a6880,
+0x00006a88,0x000c75c4,0x00000000,0x000e5084,
+0x00000000,0x000eba44,0x00087401,0x000e4782,
+0x00000734,0x00001000,0x00010705,0x000a6880,
+0x00006a88,0x000c75c4,0x0007c108,0x000c0000,
+0x0007e721,0x000bed40,0x00005f25,0x000badc0,
+0x0003ba97,0x000beb80,0x00065590,0x000b2e00,
+0x00033217,0x00003ec0,0x00065590,0x000b8e40,
+0x0003ed80,0x000491c0,0x00073fb0,0x00074c80,
+0x000283a0,0x0000100c,0x000ee388,0x00042970,
+0x00008301,0x00021ef2,0x000b8f14,0x0000000f,
+0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6,
+0x000032ac,0x000c3916,0x0004edc2,0x00074c80,
+0x00078898,0x00001000,0x00038894,0x00000032,
+0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6,
+0x0004edc2,0x000c1956,0x0000722c,0x00034a00,
+0x00041705,0x0009ed40,0x00058730,0x00001400,
+0x000d7488,0x000c3a00,0x00048f05,0x00000000};
+
+static struct
+{ u32 Offset;
+ u32 Size;
+ u32 *pFill;
+} FillStat[FILL__COUNT] = {
+ {0x00000000, sizeof(FillArray1), FillArray1},
+ {0x00001800, sizeof(FillArray2), FillArray2},
+ {0x000137f0, sizeof(FillArray3), FillArray3},
+ {0x00020000, sizeof(FillArray4), FillArray4}
+ };
diff --git a/drivers/sound/cs46xx.c b/drivers/sound/cs46xx.c
index a10f9d2c2..d3ff7d71f 100644
--- a/drivers/sound/cs46xx.c
+++ b/drivers/sound/cs46xx.c
@@ -1,6 +1,7 @@
/*
* Crystal SoundFusion CS46xx driver
*
+ * Copyright 1998-2000 Cirrus Logic Corporation <audio@crystal.cirrus.com>
* Copyright 1999-2000 Jaroslav Kysela <perex@suse.cz>
* Copyright 2000 Alan Cox <alan@redhat.com>
*
@@ -22,12 +23,31 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Changes:
- * 20000815 Updated driver to kernel 2.4, some cleanups/fixes
- * Nils Faerber <nils@kernelconcepts.de>
- * 20001110 Added __initdata to BA1Struct in cs461x_image.h
- * and three more __init here
- * Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
+ * Current maintainers:
+ * Cirrus Logic Corporation, Thomas Woller (tw)
+ * <twoller@crystal.cirrus.com>
+ * Nils Faerber (nf)
+ * <nils@kernelconcepts.de>
+ * Thanks to David Pollard for testing.
+ *
+ * Changes:
+ * 20000909-nf Changed cs_read, cs_write and drain_dac
+ * 20001025-tw Separate Playback/Capture structs and buffers.
+ * Added Scatter/Gather support for Playback.
+ * Added Capture.
+ * 20001027-nf Port to kernel 2.4.0-test9, some clean-ups
+ * Start of powermanagement support (CS46XX_PM).
+ * 20001128-tw Add module parm for default buffer order.
+ * added DMA_GFP flag to kmalloc dma buffer allocs.
+ * backfill silence to eliminate stuttering on
+ * underruns.
+ * 20001201-tw add resyncing of swptr on underruns.
+ * 20001205-tw-nf fixed GETOSPACE ioctl() after open()
+ *
+ *
+ * Status:
+ * Playback/Capture supported from 8k-48k.
+ * 16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported.
*/
#include <linux/module.h>
@@ -41,6 +61,9 @@
#include <linux/malloc.h>
#include <linux/soundcard.h>
#include <linux/pci.h>
+#ifdef CS46XX_PM
+#include <linux/pm.h>
+#endif
#include <asm/io.h>
#include <asm/dma.h>
#include <linux/init.h>
@@ -53,6 +76,11 @@
#include "cs461x.h"
+
+/* MIDI buffer sizes */
+#define CS_MIDIINBUF 500
+#define CS_MIDIOUTBUF 500
+
#define ADC_RUNNING 1
#define DAC_RUNNING 2
@@ -60,6 +88,8 @@
#define CS_FMT_STEREO 2
#define CS_FMT_MASK 3
+#define CS_TYPE_ADC 1
+#define CS_TYPE_DAC 2
/*
* CS461x definitions
*/
@@ -72,18 +102,58 @@
#define GOF_PER_SEC 200
+#define CSDEBUG_INTERFACE 1
+#define CSDEBUG 1
/*
- * Define this to enable recording,
- * this is curently broken and using it will cause data corruption
- * in kernel- and user-space!
+ * Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG
+ *
+ *
+ * CSDEBUG is usual mode is set to 1, then use the
+ * cs_debuglevel and cs_debugmask to turn on or off debugging.
+ * Debug level of 1 has been defined to be kernel errors and info
+ * that should be printed on any released driver.
+ */
+#if CSDEBUG
+#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;}
+#else
+#define CS_DBGOUT(mask,level,x)
+#endif
+/*
+ * cs_debugmask areas
*/
-/* #define CS46XX_ENABLE_RECORD */
+#define CS_INIT 0x00000001 /* initialization and probe functions */
+#define CS_ERROR 0x00000002 /* tmp debugging bit placeholder */
+#define CS_INTERRUPT 0x00000004 /* interrupt handler (separate from all other) */
+#define CS_FUNCTION 0x00000008 /* enter/leave functions */
+#define CS_WAVE_WRITE 0x00000010 /* write information for wave */
+#define CS_WAVE_READ 0x00000020 /* read information for wave */
+#define CS_MIDI_WRITE 0x00000040 /* write information for midi */
+#define CS_MIDI_READ 0x00000080 /* read information for midi */
+#define CS_MPU401_WRITE 0x00000100 /* write information for mpu401 */
+#define CS_MPU401_READ 0x00000200 /* read information for mpu401 */
+#define CS_OPEN 0x00000400 /* all open functions in the driver */
+#define CS_RELEASE 0x00000800 /* all release functions in the driver */
+#define CS_PARMS 0x00001000 /* functional and operational parameters */
+#define CS_IOCTL 0x00002000 /* ioctl (non-mixer) */
+#define CS_TMP 0x10000000 /* tmp debug mask bit */
+
+#if CSDEBUG
+static unsigned long cs_debuglevel=1; /* levels range from 1-9 */
+static unsigned long cs_debugmask=CS_INIT | CS_ERROR; /* use CS_DBGOUT with various mask values */
+#endif
+#define DMABUF_DEFAULTORDER 3
+static unsigned long defaultorder=DMABUF_DEFAULTORDER;
+#if MODULE
+MODULE_PARM(defaultorder, "i");
+MODULE_PARM(cs_debuglevel, "i");
+MODULE_PARM(cs_debugmask, "i");
+#endif
static int external_amp = 0;
static int thinkpad = 0;
-/* an instance of the 4610 channel */
+/* An instance of the 4610 channel */
struct cs_channel
{
@@ -92,11 +162,11 @@ struct cs_channel
void *state;
};
-#define DRIVER_VERSION "0.09"
+#define DRIVER_VERSION "1.10"
/* magic numbers to protect our data structures */
-#define CS_CARD_MAGIC 0x46524F4D /* "FROM" */
-#define CS_STATE_MAGIC 0x414c5341 /* "ALSA" */
+#define CS_CARD_MAGIC 0x43525553 /* "CRUS" */
+#define CS_STATE_MAGIC 0x4c4f4749 /* "LOGI" */
#define NR_HW_CH 3
/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
@@ -128,7 +198,6 @@ struct cs_state {
/* hardware channel */
struct cs_channel *channel;
int pringbuf; /* Software ring slot */
- int ppingbuf; /* Hardware ring slot */
void *pbuf; /* 4K hardware DMA buffer */
/* OSS buffer management stuff */
@@ -137,14 +206,21 @@ struct cs_state {
unsigned buforder;
unsigned numfrag;
unsigned fragshift;
+ unsigned divisor;
+ unsigned type;
+ void *tmpbuff; /* tmp buffer for sample conversions */
+ dma_addr_t dma_handle_tmpbuff;
+ unsigned buforder_tmpbuff; /* Log base 2 of size in bytes.. */
/* our buffer acts like a circular ring */
unsigned hwptr; /* where dma last started, updated by update_ptr */
unsigned swptr; /* where driver last clear/filled, updated by read/write */
int count; /* bytes to be comsumed or been generated by dma machine */
unsigned total_bytes; /* total bytes dmaed by hardware */
+ unsigned blocks; /* total blocks */
unsigned error; /* number of over/underruns */
+ unsigned underrun; /* underrun pending before next write has occurred */
wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */
/* redundant, but makes calculations easier */
@@ -156,6 +232,7 @@ struct cs_state {
unsigned mapped:1;
unsigned ready:1;
unsigned endcleared:1;
+ unsigned SGok:1;
unsigned update_flag;
unsigned ossfragshift;
int ossmaxfrags;
@@ -182,16 +259,17 @@ struct cs_card {
/* soundcore stuff */
int dev_audio;
+ int dev_midi;
/* structures for abstraction of hardware facilities, codecs, banks and channels*/
struct ac97_codec *ac97_codec[NR_AC97];
- struct cs_state *states[NR_HW_CH];
+ struct cs_state *states[2];
u16 ac97_features;
-
+
int amplifier; /* Amplifier control */
void (*amplifier_ctrl)(struct cs_card *, int);
-
+
int active; /* Active clocking */
void (*active_ctrl)(struct cs_card *, int);
@@ -218,6 +296,20 @@ struct cs_card {
struct cs_channel *(*alloc_pcm_channel)(struct cs_card *);
struct cs_channel *(*alloc_rec_pcm_channel)(struct cs_card *);
void (*free_pcm_channel)(struct cs_card *, int chan);
+
+ /* /dev/midi stuff */
+ struct {
+ unsigned ird, iwr, icnt;
+ unsigned ord, owr, ocnt;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t iwait;
+ wait_queue_head_t owait;
+ spinlock_t lock;
+ unsigned char ibuf[CS_MIDIINBUF];
+ unsigned char obuf[CS_MIDIOUTBUF];
+ mode_t open_mode;
+ struct semaphore open_sem;
+ } midi;
};
static struct cs_card *devs = NULL;
@@ -253,6 +345,224 @@ extern __inline__ unsigned ld2(unsigned int x)
return r;
}
+#if CSDEBUG
+
+/* DEBUG ROUTINES */
+
+#define SOUND_MIXER_CS_GETDBGLEVEL _SIOWR('M',120, int)
+#define SOUND_MIXER_CS_SETDBGLEVEL _SIOWR('M',121, int)
+#define SOUND_MIXER_CS_GETDBGMASK _SIOWR('M',122, int)
+#define SOUND_MIXER_CS_SETDBGMASK _SIOWR('M',123, int)
+
+#define SNDCTL_DSP_CS_GETDBGLEVEL _SIOWR('P', 50, int)
+#define SNDCTL_DSP_CS_SETDBGLEVEL _SIOWR('P', 51, int)
+#define SNDCTL_DSP_CS_GETDBGMASK _SIOWR('P', 52, int)
+#define SNDCTL_DSP_CS_SETDBGMASK _SIOWR('P', 53, int)
+
+static void printioctl(unsigned int x)
+{
+ unsigned int i;
+ unsigned char vidx;
+ /* these values are incorrect for the ac97 driver, fix.
+ * Index of mixtable1[] member is Device ID
+ * and must be <= SOUND_MIXER_NRDEVICES.
+ * Value of array member is index into s->mix.vol[]
+ */
+ static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
+ [SOUND_MIXER_PCM] = 1, /* voice */
+ [SOUND_MIXER_LINE1] = 2, /* AUX */
+ [SOUND_MIXER_CD] = 3, /* CD */
+ [SOUND_MIXER_LINE] = 4, /* Line */
+ [SOUND_MIXER_SYNTH] = 5, /* FM */
+ [SOUND_MIXER_MIC] = 6, /* Mic */
+ [SOUND_MIXER_SPEAKER] = 7, /* Speaker */
+ [SOUND_MIXER_RECLEV] = 8, /* Recording level */
+ [SOUND_MIXER_VOLUME] = 9 /* Master Volume */
+ };
+
+ switch(x)
+ {
+ case SOUND_MIXER_CS_GETDBGMASK:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGMASK: ") );
+ break;
+ case SOUND_MIXER_CS_GETDBGLEVEL:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGLEVEL: ") );
+ break;
+ case SOUND_MIXER_CS_SETDBGMASK:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGMASK: ") );
+ break;
+ case SOUND_MIXER_CS_SETDBGLEVEL:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGLEVEL: ") );
+ break;
+ case OSS_GETVERSION:
+ CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION: ") );
+ break;
+ case SNDCTL_DSP_SYNC:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC: ") );
+ break;
+ case SNDCTL_DSP_SETDUPLEX:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX: ") );
+ break;
+ case SNDCTL_DSP_GETCAPS:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS: ") );
+ break;
+ case SNDCTL_DSP_RESET:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET: ") );
+ break;
+ case SNDCTL_DSP_SPEED:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED: ") );
+ break;
+ case SNDCTL_DSP_STEREO:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO: ") );
+ break;
+ case SNDCTL_DSP_CHANNELS:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS: ") );
+ break;
+ case SNDCTL_DSP_GETFMTS:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS: ") );
+ break;
+ case SNDCTL_DSP_SETFMT:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT: ") );
+ break;
+ case SNDCTL_DSP_POST:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST: ") );
+ break;
+ case SNDCTL_DSP_GETTRIGGER:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER: ") );
+ break;
+ case SNDCTL_DSP_SETTRIGGER:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER: ") );
+ break;
+ case SNDCTL_DSP_GETOSPACE:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE: ") );
+ break;
+ case SNDCTL_DSP_GETISPACE:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE: ") );
+ break;
+ case SNDCTL_DSP_NONBLOCK:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK: ") );
+ break;
+ case SNDCTL_DSP_GETODELAY:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY: ") );
+ break;
+ case SNDCTL_DSP_GETIPTR:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR: ") );
+ break;
+ case SNDCTL_DSP_GETOPTR:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR: ") );
+ break;
+ case SNDCTL_DSP_GETBLKSIZE:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE: ") );
+ break;
+ case SNDCTL_DSP_SETFRAGMENT:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFRAGMENT: ") );
+ break;
+ case SNDCTL_DSP_SUBDIVIDE:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE: ") );
+ break;
+ case SOUND_PCM_READ_RATE:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE: ") );
+ break;
+ case SOUND_PCM_READ_CHANNELS:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_CHANNELS: ") );
+ break;
+ case SOUND_PCM_READ_BITS:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS: ") );
+ break;
+ case SOUND_PCM_WRITE_FILTER:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_WRITE_FILTER: ") );
+ break;
+ case SNDCTL_DSP_SETSYNCRO:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO: ") );
+ break;
+ case SOUND_PCM_READ_FILTER:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER: ") );
+ break;
+ case SNDCTL_DSP_CS_GETDBGMASK:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CS_GETDBGMASK: ") );
+ break;
+ case SNDCTL_DSP_CS_GETDBGLEVEL:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CS_GETDBGLEVEL: ") );
+ break;
+ case SNDCTL_DSP_CS_SETDBGMASK:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CS_SETDBGMASK: ") );
+ break;
+ case SNDCTL_DSP_CS_SETDBGLEVEL:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CS_SETDBGLEVEL: ") );
+ break;
+
+ case SOUND_MIXER_PRIVATE1:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1: ") );
+ break;
+ case SOUND_MIXER_PRIVATE2:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2: ") );
+ break;
+ case SOUND_MIXER_PRIVATE3:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3: ") );
+ break;
+ case SOUND_MIXER_PRIVATE4:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4: ") );
+ break;
+ case SOUND_MIXER_PRIVATE5:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5: ") );
+ break;
+ case SOUND_MIXER_INFO:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO: ") );
+ break;
+ case SOUND_OLD_MIXER_INFO:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO: ") );
+ break;
+
+ default:
+ switch (_IOC_NR(x))
+ {
+ case SOUND_MIXER_VOLUME:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME: ") );
+ break;
+ case SOUND_MIXER_SPEAKER:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SPEAKER: ") );
+ break;
+ case SOUND_MIXER_RECLEV:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECLEV: ") );
+ break;
+ case SOUND_MIXER_MIC:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_MIC: ") );
+ break;
+ case SOUND_MIXER_SYNTH:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SYNTH: ") );
+ break;
+ case SOUND_MIXER_RECSRC:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECSRC: ") );
+ break;
+ case SOUND_MIXER_DEVMASK:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_DEVMASK: ") );
+ break;
+ case SOUND_MIXER_RECMASK:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECMASK: ") );
+ break;
+ case SOUND_MIXER_STEREODEVS:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_STEREODEVS: ") );
+ break;
+ case SOUND_MIXER_CAPS:
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:") );
+ break;
+ default:
+ i = _IOC_NR(x);
+ if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
+ {
+ CS_DBGOUT(CS_IOCTL, 4, printk("UNKNOWN IOCTL: 0x%.8x NR=%d ",x,i) );
+ }
+ else
+ {
+ CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d ",
+ x,i) );
+ }
+ break;
+ }
+ }
+ CS_DBGOUT(CS_IOCTL, 4, printk("command = 0x%x IOC_NR=%d\n",x, _IOC_NR(x)) );
+}
+#endif
/*
* common I/O routines
@@ -306,6 +616,34 @@ static void cs_free_pcm_channel(struct cs_card *card, int channel)
card->channel[channel].used=0;
}
+/*
+ * setup a divisor value to help with conversion from
+ * 16bit Stereo, down to 8bit stereo/mono or 16bit mono.
+ * assign a divisor of 1 if using 16bit Stereo as that is
+ * the only format that the static image will capture.
+ */
+static void cs_set_divisor(struct dmabuf *dmabuf)
+{
+ if(dmabuf->type == CS_TYPE_DAC)
+ dmabuf->divisor = 1;
+ else if( !(dmabuf->fmt & CS_FMT_STEREO) &&
+ (dmabuf->fmt & CS_FMT_16BIT))
+ dmabuf->divisor = 2;
+ else if( (dmabuf->fmt & CS_FMT_STEREO) &&
+ !(dmabuf->fmt & CS_FMT_16BIT))
+ dmabuf->divisor = 2;
+ else if( !(dmabuf->fmt & CS_FMT_STEREO) &&
+ !(dmabuf->fmt & CS_FMT_16BIT))
+ dmabuf->divisor = 4;
+ else
+ dmabuf->divisor = 1;
+
+ CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, printk(
+ "cs46xx: cs_set_divisor()- %s %d\n",
+ (dmabuf->type == CS_TYPE_ADC) ? "ADC" : "DAC",
+ dmabuf->divisor) );
+}
+
/* set playback sample rate */
static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate)
{
@@ -313,6 +651,7 @@ static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate)
unsigned int tmp1, tmp2;
unsigned int phiIncr;
unsigned int correctionPerGOF, correctionPerSec;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()+ %d\n",rate) );
/*
* Compute the values used to drive the actual sample rate conversion.
@@ -354,6 +693,7 @@ static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate)
spin_unlock_irq(&state->card->lock);
dmabuf->rate = rate;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()- %d\n",rate) );
return rate;
}
@@ -365,6 +705,7 @@ static unsigned int cs_set_adc_rate(struct cs_state * state, unsigned int rate)
unsigned int phiIncr, coeffIncr, tmp1, tmp2;
unsigned int correctionPerGOF, correctionPerSec, initialDelay;
unsigned int frameGroupLength, cnt;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()+ %d\n",rate) );
/*
* We can only decimate by up to a factor of 1/9th the hardware rate.
@@ -464,6 +805,7 @@ static unsigned int cs_set_adc_rate(struct cs_state * state, unsigned int rate)
cs461x_poke(card, (BA1_CSPB + 4), 0x0000FFFF);
spin_unlock_irq(&card->lock);
dmabuf->rate = rate;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()- %d\n",rate) );
return rate;
}
@@ -472,27 +814,69 @@ static void cs_play_setup(struct cs_state *state)
{
struct dmabuf *dmabuf = &state->dmabuf;
struct cs_card *card = state->card;
- unsigned int tmp, tmp1;
+ unsigned int tmp, Count, playFormat;
+
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") );
+ cs461x_poke(card, BA1_PVOL, 0x80008000);
+ if(!dmabuf->SGok)
+ cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf));
+
+ Count = 4;
+ playFormat=cs461x_peek(card, BA1_PFIE);
+ if ((dmabuf->fmt & CS_FMT_STEREO)) {
+ playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO;
+ Count *= 2;
+ }
+ else
+ playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO;
+
+ if ((dmabuf->fmt & CS_FMT_16BIT)) {
+ playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT
+ | DMA_RQ_C2_AC_SIGNED_CONVERT);
+ Count *= 2;
+ }
+ else
+ playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT
+ | DMA_RQ_C2_AC_SIGNED_CONVERT);
+
+ cs461x_poke(card, BA1_PFIE, playFormat);
+
+ tmp = cs461x_peek(card, BA1_PDTC);
+ tmp &= 0xfffffe00;
+ cs461x_poke(card, BA1_PDTC, tmp | --Count);
+
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") );
- tmp1=16;
- if (!(dmabuf->fmt & CS_FMT_STEREO))
- tmp1>>=1;
- cs461x_poke(card, BA1_PVOL, 0x80008000);
- cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf));
-
- tmp=cs461x_peek(card, BA1_PDTC);
- tmp&=~0x000003FF;
- tmp|=tmp1-1;
- cs461x_poke(card, BA1_PDTC, tmp);
-
- tmp=cs461x_peek(card, BA1_PFIE);
- tmp&=~0x0000F03F;
- if(!(dmabuf->fmt & CS_FMT_STEREO))
+}
+
+struct InitStruct
+{
+ u32 long off;
+ u32 long val;
+} InitArray[] = { {0x00000040, 0x3fc0000f},
+ {0x0000004c, 0x04800000},
+
+ {0x000000b3, 0x00000780},
+ {0x000000b7, 0x00000000},
+ {0x000000bc, 0x07800000},
+
+ {0x000000cd, 0x00800000},
+ };
+
+/*
+ * "SetCaptureSPValues()" -- Initialize record task values before each
+ * capture startup.
+ */
+void SetCaptureSPValues(struct cs_card *card)
+{
+ unsigned i, offset;
+ CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") );
+ for(i=0; i<sizeof(InitArray)/sizeof(struct InitStruct); i++)
{
- tmp|=0x00002000;
+ offset = InitArray[i].off*4; /* 8bit to 32bit offset value */
+ cs461x_poke(card, offset, InitArray[i].val );
}
- cs461x_poke(card, BA1_PFIE, tmp);
-
+ CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()-\n") );
}
/* prepare channel attributes for recording */
@@ -500,9 +884,21 @@ static void cs_rec_setup(struct cs_state *state)
{
struct cs_card *card = state->card;
struct dmabuf *dmabuf = &state->dmabuf;
- /* set the attenuation to 0dB */
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n") );
+
+ SetCaptureSPValues(card);
+
+ /*
+ * set the attenuation to 0dB
+ */
cs461x_poke(card, BA1_CVOL, 0x80008000);
- cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->pbuf));
+
+ /*
+ * set the physical address of the capture buffer into the SP
+ */
+ cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->rawbuf));
+
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()-\n") );
}
@@ -514,10 +910,30 @@ extern __inline__ unsigned cs_get_dma_addr(struct cs_state *state)
struct dmabuf *dmabuf = &state->dmabuf;
u32 offset;
- if (!dmabuf->enable)
+ if ( (!(dmabuf->enable & DAC_RUNNING)) &&
+ (!(dmabuf->enable & ADC_RUNNING) ) )
+ {
+ CS_DBGOUT(CS_ERROR, 2, printk(
+ "cs46xx: ERROR cs_get_dma_addr(): not enabled \n") );
return 0;
+ }
- offset = dmabuf->pringbuf * 2048;
+ /*
+ * ganularity is byte boundry, good part.
+ */
+ if(dmabuf->enable & DAC_RUNNING)
+ {
+ offset = cs461x_peek(state->card, BA1_PBA);
+ }
+ else /* ADC_RUNNING must be set */
+ {
+ offset = cs461x_peek(state->card, BA1_CBA);
+ }
+ CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9,
+ printk("cs46xx: cs_get_dma_addr() %d\n",offset) );
+ offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf;
+ CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8,
+ printk("cs46xx: cs_get_dma_addr()- %d\n",offset) );
return offset;
}
@@ -526,14 +942,11 @@ static void resync_dma_ptrs(struct cs_state *state)
struct dmabuf *dmabuf = &state->dmabuf;
int offset;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") );
offset = 0;
dmabuf->hwptr=dmabuf->swptr = 0;
- dmabuf->ppingbuf = dmabuf->pringbuf = 0;
- dmabuf->ppingbuf = 1;
- if(dmabuf->fmt&CS_FMT_16BIT)
- memset(dmabuf->pbuf, 0, PAGE_SIZE);
- else
- memset(dmabuf->pbuf, 0x80, PAGE_SIZE);
+ dmabuf->pringbuf = 0;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") );
}
/* Stop recording (lock held) */
@@ -545,20 +958,20 @@ extern __inline__ void __stop_adc(struct cs_state *state)
dmabuf->enable &= ~ADC_RUNNING;
- tmp=cs461x_peek(card, BA1_CCTL);
- tmp&=0xFFFF;
- cs461x_poke(card, BA1_CCTL, tmp);
-
+ tmp = cs461x_peek(card, BA1_CCTL);
+ tmp &= 0xFFFF0000;
+ cs461x_poke(card, BA1_CCTL, tmp );
}
static void stop_adc(struct cs_state *state)
{
- struct cs_card *card = state->card;
unsigned long flags;
- spin_lock_irqsave(&card->lock, flags);
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()+ \n") );
+ spin_lock_irqsave(&state->card->lock, flags);
__stop_adc(state);
- spin_unlock_irqrestore(&card->lock, flags);
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()- \n") );
}
static void start_adc(struct cs_state *state)
@@ -569,11 +982,17 @@ static void start_adc(struct cs_state *state)
unsigned int tmp;
spin_lock_irqsave(&card->lock, flags);
- if ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) && dmabuf->ready) {
+ if (!(dmabuf->enable & ADC_RUNNING) &&
+ ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize)
+ && dmabuf->ready))
+ {
dmabuf->enable |= ADC_RUNNING;
- tmp=cs461x_peek(card, BA1_CCTL);
- tmp&=0xFFFF;
- tmp|=card->cctl;
+ cs_set_divisor(dmabuf);
+ tmp = cs461x_peek(card, BA1_CCTL);
+ tmp &= 0xFFFF0000;
+ tmp |= card->cctl;
+ CS_DBGOUT(CS_FUNCTION, 2, printk(
+ "cs46xx: start_adc() poke 0x%x \n",tmp) );
cs461x_poke(card, BA1_CCTL, tmp);
}
spin_unlock_irqrestore(&card->lock, flags);
@@ -595,12 +1014,13 @@ extern __inline__ void __stop_dac(struct cs_state *state)
static void stop_dac(struct cs_state *state)
{
- struct cs_card *card = state->card;
unsigned long flags;
- spin_lock_irqsave(&card->lock, flags);
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()+ \n") );
+ spin_lock_irqsave(&state->card->lock, flags);
__stop_dac(state);
- spin_unlock_irqrestore(&card->lock, flags);
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()- \n") );
}
static void start_dac(struct cs_state *state)
@@ -610,53 +1030,79 @@ static void start_dac(struct cs_state *state)
unsigned long flags;
int tmp;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()+ \n") );
spin_lock_irqsave(&card->lock, flags);
- if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) {
- if(!(dmabuf->enable&DAC_RUNNING))
- {
- dmabuf->enable |= DAC_RUNNING;
- tmp = cs461x_peek(card, BA1_PCTL);
- tmp &= 0xFFFF;
- tmp |= card->pctl;
- cs461x_poke(card, BA1_PCTL, tmp);
- }
+ if (!(dmabuf->enable & DAC_RUNNING) &&
+ ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready)) {
+ dmabuf->enable |= DAC_RUNNING;
+ tmp = cs461x_peek(card, BA1_PCTL);
+ tmp &= 0xFFFF;
+ tmp |= card->pctl;
+ CS_DBGOUT(CS_PARMS, 6, printk(
+ "cs46xx: start_dac() poke card=0x%.08x tmp=0x%.08x addr=0x%.08x \n",
+ (unsigned)card, (unsigned)tmp,
+ (unsigned)card->ba1.idx[(BA1_PCTL >> 16) & 3]+(BA1_PCTL&0xffff) ) );
+ cs461x_poke(card, BA1_PCTL, tmp);
}
spin_unlock_irqrestore(&card->lock, flags);
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()- \n") );
}
-#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
#define DMABUF_MINORDER 1
-/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
+/*
+ * allocate DMA buffer, playback and recording buffers are separate.
+ */
static int alloc_dmabuf(struct cs_state *state)
{
struct dmabuf *dmabuf = &state->dmabuf;
void *rawbuf = NULL;
+ void *tmpbuff = NULL;
int order;
struct page *page, *pend;
/* alloc as big a chunk as we can */
- for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
- if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order)))
+ for (order = defaultorder; order >= DMABUF_MINORDER; order--)
+ if((rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)))
break;
if (!rawbuf)
return -ENOMEM;
-#ifdef DEBUG
- printk("cs461x: allocated %ld (order = %d) bytes at %p\n",
- PAGE_SIZE << order, order, rawbuf);
-#endif
-
- dmabuf->ready = dmabuf->mapped = 0;
- dmabuf->rawbuf = rawbuf;
dmabuf->buforder = order;
-
+ dmabuf->rawbuf = rawbuf;
+
/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
for (page = virt_to_page(rawbuf); page <= pend; page++)
mem_map_reserve(page);
+ CS_DBGOUT(CS_PARMS, 9, printk("cs461x: allocated %ld (order = %d) bytes at %p\n",
+ PAGE_SIZE << order, order, rawbuf) );
+/*
+ * now the temp buffer for 16/8 conversions
+ */
+ for (order = defaultorder; order >= DMABUF_MINORDER; order--)
+ if((tmpbuff = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)))
+ break;
+ if (!tmpbuff)
+ return -ENOMEM;
+ CS_DBGOUT(CS_PARMS, 9, printk("cs461x: allocated %ld (order = %d) bytes at %p\n",
+ PAGE_SIZE << order, order, tmpbuff) );
+
+ dmabuf->tmpbuff = tmpbuff;
+ dmabuf->buforder_tmpbuff = order;
+
+ /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
+ pend = virt_to_page(tmpbuff + (PAGE_SIZE << order) - 1);
+ for (page = virt_to_page(tmpbuff); page <= pend; page++)
+ mem_map_reserve(page);
+
+ CS_DBGOUT(CS_PARMS, 9, printk("cs461x: allocated %ld (order = %d) bytes at %p\n",
+ PAGE_SIZE << order, order, tmpbuff) );
+
+ dmabuf->ready = dmabuf->mapped = 0;
+ dmabuf->SGok = 0;
return 0;
}
@@ -667,85 +1113,208 @@ static void dealloc_dmabuf(struct cs_state *state)
struct page *page, *pend;
if (dmabuf->rawbuf) {
- /* undo marking the pages as reserved */
pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
mem_map_unreserve(page);
pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder,
- dmabuf->rawbuf, dmabuf->dma_handle);
+ dmabuf->rawbuf, dmabuf->dma_handle);
+ }
+ dmabuf->rawbuf = NULL;
+
+ if (dmabuf->tmpbuff) {
+ /* undo marking the pages as reserved */
+ pend = virt_to_page(dmabuf->tmpbuff + (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);
+ for (page = virt_to_page(dmabuf->tmpbuff); page <= pend; page++)
+ mem_map_unreserve(page);
+ pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder_tmpbuff,
+ dmabuf->tmpbuff, dmabuf->dma_handle_tmpbuff);
}
+
dmabuf->rawbuf = NULL;
+ dmabuf->tmpbuff = NULL;
dmabuf->mapped = dmabuf->ready = 0;
+ dmabuf->SGok = 0;
}
-static int prog_dmabuf(struct cs_state *state, unsigned rec)
+static int prog_dmabuf(struct cs_state *state)
{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned bytepersec;
- unsigned bufsize;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&state->card->lock, flags);
- resync_dma_ptrs(state);
- dmabuf->total_bytes = 0;
- dmabuf->count = dmabuf->error = 0;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- /* allocate DMA buffer if not allocated yet */
- if (!dmabuf->rawbuf)
- if ((ret = alloc_dmabuf(state)))
- return ret;
+ struct dmabuf *dmabuf = &state->dmabuf;
+ unsigned long flags;
+ unsigned long allocated_pages, allocated_bytes;
+ unsigned long tmp1, tmp2, fmt=0;
+ unsigned long *ptmp = (unsigned long *) dmabuf->pbuf;
+ unsigned long SGarray[9], nSGpages=0;
+ int ret;
+
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()+ \n"));
+/*
+ * check for CAPTURE and use only non-sg for initial release
+ */
+ if(dmabuf->type == CS_TYPE_ADC)
+ {
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n"));
+ /*
+ * add in non-sg support for capture.
+ */
+ spin_lock_irqsave(&state->card->lock, flags);
+ /* add code to reset the rawbuf memory. TRW */
+ resync_dma_ptrs(state);
+ dmabuf->total_bytes = dmabuf->blocks = 0;
+ dmabuf->count = dmabuf->error = dmabuf->underrun = 0;
- /* FIXME: figure out all this OSS fragment stuff */
- bytepersec = dmabuf->rate << sample_shift[dmabuf->fmt];
- bufsize = PAGE_SIZE << dmabuf->buforder;
- if (dmabuf->ossfragshift) {
- if ((1000 << dmabuf->ossfragshift) < bytepersec)
- dmabuf->fragshift = ld2(bytepersec/1000);
- else
- dmabuf->fragshift = dmabuf->ossfragshift;
- } else {
- /* lets hand out reasonable big ass buffers by default */
- dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT -2);
- }
- dmabuf->numfrag = bufsize >> dmabuf->fragshift;
- while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) {
- dmabuf->fragshift--;
- dmabuf->numfrag = bufsize >> dmabuf->fragshift;
- }
- dmabuf->fragsize = 1 << dmabuf->fragshift;
- if (dmabuf->ossmaxfrags >= 4 && dmabuf->ossmaxfrags < dmabuf->numfrag)
- dmabuf->numfrag = dmabuf->ossmaxfrags;
- dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt];
- dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
+ dmabuf->SGok = 0;
- memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
- dmabuf->dmasize);
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ /* allocate DMA buffer if not allocated yet */
+ if (!dmabuf->rawbuf || !dmabuf->tmpbuff)
+ if ((ret = alloc_dmabuf(state)))
+ return ret;
/*
- * Now set up the ring
+ * static image only supports 16Bit signed, stereo - hard code fmt
*/
+ fmt = CS_FMT_16BIT | CS_FMT_STEREO;
- spin_lock_irqsave(&state->card->lock, flags);
- if (rec) {
+ dmabuf->numfrag = 2;
+ dmabuf->fragsize = 2048;
+ dmabuf->fragsamples = 2048 >> sample_shift[fmt];
+ dmabuf->dmasize = 4096;
+ dmabuf->fragshift = 11;
+
+ memset(dmabuf->rawbuf, (fmt & CS_FMT_16BIT) ? 0 : 0x80,
+ dmabuf->dmasize);
+ memset(dmabuf->tmpbuff, (fmt & CS_FMT_16BIT) ? 0 : 0x80,
+ PAGE_SIZE<<dmabuf->buforder_tmpbuff);
+
+ /*
+ * Now set up the ring
+ */
+
+ spin_lock_irqsave(&state->card->lock, flags);
cs_rec_setup(state);
- } else {
- cs_play_setup(state);
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
+ /* set the ready flag for the dma buffer */
+ dmabuf->ready = 1;
+
+ CS_DBGOUT(CS_PARMS, 4, printk(
+ "cs461x: prog_dmabuf(): CAPTURE rate=%d fmt=0x%x numfrag=%d "
+ "fragsize=%d dmasize=%d\n",
+ dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
+ dmabuf->fragsize, dmabuf->dmasize) );
+
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n"));
+ return 0;
}
- spin_unlock_irqrestore(&state->card->lock, flags);
+ else if (dmabuf->type == CS_TYPE_DAC)
+ {
+ /*
+ * Must be DAC
+ */
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() DAC\n"));
+ spin_lock_irqsave(&state->card->lock, flags);
+ resync_dma_ptrs(state);
+ dmabuf->total_bytes = dmabuf->blocks = 0;
+ dmabuf->count = dmabuf->error = dmabuf->underrun = 0;
- /* set the ready flag for the dma buffer */
- dmabuf->ready = 1;
+ dmabuf->SGok = 0;
-#ifdef DEBUG
- printk("cs461x: prog_dmabuf, sample rate = %d, format = %d, numfrag = %d, "
- "fragsize = %d dmasize = %d\n",
- dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
- dmabuf->fragsize, dmabuf->dmasize);
-#endif
+ spin_unlock_irqrestore(&state->card->lock, flags);
- return 0;
+ /* allocate DMA buffer if not allocated yet */
+ if (!dmabuf->rawbuf)
+ if ((ret = alloc_dmabuf(state)))
+ return ret;
+
+ allocated_pages = 1 << dmabuf->buforder;
+ allocated_bytes = allocated_pages*PAGE_SIZE;
+
+ if(allocated_pages < 2)
+ {
+ CS_DBGOUT(CS_FUNCTION, 4, printk(
+ "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n",
+ (unsigned)allocated_pages));
+ return -ENOMEM;
+ }
+
+ /* Use all the pages allocated, fragsize 4k. */
+ /* Use 'pbuf' for S/G page map table. */
+ dmabuf->SGok = 1; /* Use S/G. */
+
+ nSGpages = allocated_bytes/4096; /* S/G pages always 4k. */
+
+ /* Set up S/G variables. */
+ *ptmp = virt_to_bus(dmabuf->rawbuf);
+ *(ptmp+1) = 0x00000008;
+ for(tmp1= 1; tmp1 < nSGpages; tmp1++) {
+ *(ptmp+2*tmp1) = virt_to_bus( (dmabuf->rawbuf)+4096*tmp1);
+ if( tmp1 == nSGpages-1)
+ tmp2 = 0xbfff0000;
+ else
+ tmp2 = 0x80000000+8*(tmp1+1);
+ *(ptmp+2*tmp1+1) = tmp2;
+ }
+ SGarray[0] = 0x82c0200d;
+ SGarray[1] = 0xffff0000;
+ SGarray[2] = *ptmp;
+ SGarray[3] = 0x00010600;
+ SGarray[4] = *(ptmp+2);
+ SGarray[5] = 0x80000010;
+ SGarray[6] = *ptmp;
+ SGarray[7] = *(ptmp+2);
+ SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10;
+
+ if (dmabuf->SGok) {
+ dmabuf->numfrag = nSGpages;
+ dmabuf->fragsize = 4096;
+ dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt];
+ dmabuf->fragshift = 12;
+ dmabuf->dmasize = dmabuf->numfrag*4096;
+ }
+ else {
+ SGarray[0] = 0xf2c0000f;
+ SGarray[1] = 0x00000200;
+ SGarray[2] = 0;
+ SGarray[3] = 0x00010600;
+ SGarray[4]=SGarray[5]=SGarray[6]=SGarray[7]=SGarray[8] = 0;
+ dmabuf->numfrag = 2;
+ dmabuf->fragsize = 2048;
+ dmabuf->fragsamples = 2048 >> sample_shift[dmabuf->fmt];
+ dmabuf->dmasize = 4096;
+ dmabuf->fragshift = 11;
+ }
+ for(tmp1 = 0; tmp1 < sizeof(SGarray)/4; tmp1++)
+ cs461x_poke( state->card, BA1_PDTC+tmp1*4, SGarray[tmp1]);
+
+ memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
+ dmabuf->dmasize);
+
+ /*
+ * Now set up the ring
+ */
+
+ spin_lock_irqsave(&state->card->lock, flags);
+ cs_play_setup(state);
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
+ /* set the ready flag for the dma buffer */
+ dmabuf->ready = 1;
+
+ CS_DBGOUT(CS_PARMS, 4, printk(
+ "cs461x: prog_dmabuf(): PLAYBACK rate=%d fmt=0x%x numfrag=%d "
+ "fragsize=%d dmasize=%d\n",
+ dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
+ dmabuf->fragsize, dmabuf->dmasize) );
+
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n"));
+ return 0;
+ }
+ else
+ {
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n",
+ dmabuf->type));
+ }
+ return 1;
}
static void cs_clear_tail(struct cs_state *state)
@@ -787,8 +1356,8 @@ static int drain_dac(struct cs_state *state, int nonblock)
tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
tmo >>= sample_shift[dmabuf->fmt];
- tmo += (4096*HZ)/dmabuf->rate;
-
+ tmo += (2048*HZ)/dmabuf->rate;
+
if (!schedule_timeout(tmo ? tmo : 1) && tmo){
printk(KERN_ERR "cs461x: drain_dac, dma timeout? %d\n", count);
break;
@@ -802,91 +1371,149 @@ static int drain_dac(struct cs_state *state, int nonblock)
return 0;
}
+
/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */
-static void cs_update_ptr(struct cs_state *state)
+static void cs_update_ptr(void)
{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned hwptr, swptr;
- int clear_cnt = 0;
+ struct cs_card *card=devs;
+ struct cs_state *state;
+ struct dmabuf *dmabuf;
+ unsigned hwptr;
int diff;
- unsigned char silence;
-
- /* update hardware pointer */
- hwptr = cs_get_dma_addr(state);
- diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
- dmabuf->hwptr = hwptr;
- dmabuf->total_bytes += diff;
-
- /* error handling and process wake up for DAC */
- if (dmabuf->enable == ADC_RUNNING) {
- if (dmabuf->mapped) {
- dmabuf->count -= diff;
- if (dmabuf->count >= (signed)dmabuf->fragsize)
- wake_up(&dmabuf->wait);
- } else {
+
+ /* error handling and process wake up for ADC */
+ state = card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if (dmabuf->enable & ADC_RUNNING) {
+ /* update hardware pointer */
+ hwptr = cs_get_dma_addr(state);
+
+ diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
+ CS_DBGOUT(CS_PARMS, 9, printk(
+ "cs46xx: cs_update_ptr()+ ADC hwptr=%d diff=%d\n",
+ hwptr,diff) );
+ dmabuf->hwptr = hwptr;
+ dmabuf->total_bytes += diff;
dmabuf->count += diff;
+ if (dmabuf->count > dmabuf->dmasize)
+ dmabuf->count = dmabuf->dmasize;
- if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
- /* buffer underrun or buffer overrun, we have no way to recover
- it here, just stop the machine and let the process force hwptr
- and swptr to sync */
- __stop_adc(state);
- dmabuf->error++;
+ if(dmabuf->mapped)
+ {
+ if (dmabuf->count >= (signed)dmabuf->fragsize)
+ wake_up(&dmabuf->wait);
+ } else
+ {
+ if (dmabuf->count > 0)
+ wake_up(&dmabuf->wait);
}
- else if (!dmabuf->endcleared) {
- swptr = dmabuf->swptr;
- silence = (dmabuf->fmt & CS_FMT_16BIT ? 0 : 0x80);
- if (dmabuf->count < (signed) dmabuf->fragsize)
- {
- clear_cnt = dmabuf->fragsize;
- if ((swptr + clear_cnt) > dmabuf->dmasize)
- clear_cnt = dmabuf->dmasize - swptr;
- memset (dmabuf->rawbuf + swptr, silence, clear_cnt);
- dmabuf->endcleared = 1;
- }
- }
- wake_up(&dmabuf->wait);
}
}
- /* error handling and process wake up for DAC */
- if (dmabuf->enable == DAC_RUNNING) {
- if (dmabuf->mapped) {
- dmabuf->count += diff;
- if (dmabuf->count >= (signed)dmabuf->fragsize)
- wake_up(&dmabuf->wait);
- } else {
- dmabuf->count -= diff;
-
- if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
- /* buffer underrun or buffer overrun, we have no way to recover
- it here, just stop the machine and let the process force hwptr
- and swptr to sync */
- __stop_dac(state);
- dmabuf->error++;
+
+/*
+ * Now the DAC
+ */
+ state = card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ /* error handling and process wake up for DAC */
+ if (dmabuf->enable & DAC_RUNNING) {
+ /* update hardware pointer */
+ hwptr = cs_get_dma_addr(state);
+
+ diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
+ CS_DBGOUT(CS_PARMS, 9, printk(
+ "cs46xx: cs_update_ptr()+ DAC hwptr=%d diff=%d\n",
+ hwptr,diff) );
+ dmabuf->hwptr = hwptr;
+ dmabuf->total_bytes += diff;
+ if (dmabuf->mapped) {
+ dmabuf->count += diff;
+ if (dmabuf->count >= (signed)dmabuf->fragsize)
+ wake_up(&dmabuf->wait);
+ /*
+ * other drivers use fragsize, but don't see any sense
+ * in that, since dmasize is the buffer asked for
+ * via mmap.
+ */
+ if( dmabuf->count > dmabuf->dmasize)
+ dmabuf->count &= dmabuf->dmasize-1;
+ } else {
+ dmabuf->count -= diff;
+ /*
+ * backfill with silence and clear out the last
+ * "diff" number of bytes.
+ */
+ if(hwptr >= diff)
+ {
+ memset(dmabuf->rawbuf + hwptr - diff,
+ (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff);
+ }
+ else
+ {
+ memset(dmabuf->rawbuf,
+ (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
+ (unsigned)hwptr);
+ memset((void *)((unsigned)dmabuf->rawbuf +
+ dmabuf->dmasize + hwptr - diff),
+ (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
+ diff - hwptr);
+ }
+
+ if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
+ CS_DBGOUT(CS_ERROR, 2, printk(
+ "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n",
+ dmabuf->count));
+ /*
+ * buffer underrun or buffer overrun, reset the
+ * count of bytes written back to 0.
+ */
+ if(dmabuf->count < 0)
+ dmabuf->underrun=1;
+ dmabuf->count = 0;
+ dmabuf->error++;
+ }
+ if (dmabuf->count < (signed)dmabuf->dmasize/2)
+ wake_up(&dmabuf->wait);
}
- wake_up(&dmabuf->wait);
}
}
}
-static void cs_record_interrupt(struct cs_state *state)
-{
- memcpy(state->dmabuf.rawbuf + (2048*state->dmabuf.pringbuf++),
- state->dmabuf.pbuf+2048*state->dmabuf.ppingbuf++, 2048);
- state->dmabuf.ppingbuf&=1;
- if(state->dmabuf.pringbuf > (PAGE_SIZE<<state->dmabuf.buforder)/2048)
- state->dmabuf.pringbuf=0;
- cs_update_ptr(state);
-}
-static void cs_play_interrupt(struct cs_state *state)
+/* hold spinlock for the following! */
+static void cs_handle_midi(struct cs_card *card)
{
- memcpy(state->dmabuf.pbuf+2048*state->dmabuf.ppingbuf++,
- state->dmabuf.rawbuf + (2048*state->dmabuf.pringbuf++), 2048);
- state->dmabuf.ppingbuf&=1;
- if(state->dmabuf.pringbuf >= (PAGE_SIZE<<state->dmabuf.buforder)/2048)
- state->dmabuf.pringbuf=0;
- cs_update_ptr(state);
+ unsigned char ch;
+ int wake;
+ unsigned temp1;
+
+ wake = 0;
+ while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_RBE)) {
+ ch = cs461x_peekBA0(card, BA0_MIDRP);
+ if (card->midi.icnt < CS_MIDIINBUF) {
+ card->midi.ibuf[card->midi.iwr] = ch;
+ card->midi.iwr = (card->midi.iwr + 1) % CS_MIDIINBUF;
+ card->midi.icnt++;
+ }
+ wake = 1;
+ }
+ if (wake)
+ wake_up(&card->midi.iwait);
+ wake = 0;
+ while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) {
+ temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff;
+ cs461x_pokeBA0(card, BA0_MIDWP,temp1);
+ card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF;
+ card->midi.ocnt--;
+ if (card->midi.ocnt < CS_MIDIOUTBUF-16)
+ wake = 1;
+ }
+ if (wake)
+ wake_up(&card->midi.owait);
}
static void cs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -897,126 +1524,489 @@ static void cs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct cs_state *playstate = card->channel[1].state;
u32 status;
+ CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()+ \n"));
+
spin_lock(&card->lock);
status = cs461x_peekBA0(card, BA0_HISR);
- if((status&0x7fffffff)==0)
+ if ((status & 0x7fffffff) == 0)
{
cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
spin_unlock(&card->lock);
return;
}
- if((status & HISR_VC0) && playstate && playstate->dmabuf.ready)
- cs_play_interrupt(playstate);
- if((status & HISR_VC1) && recstate && recstate->dmabuf.ready)
- cs_record_interrupt(recstate);
+ /*
+ * check for playback or capture interrupt only
+ */
+ if( ((status & HISR_VC0) && playstate && playstate->dmabuf.ready) ||
+ (((status & HISR_VC1) && recstate && recstate->dmabuf.ready)) )
+ {
+ CS_DBGOUT(CS_INTERRUPT, 8, printk(
+ "cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status));
+ cs_update_ptr();
+ }
+
+ if( status & HISR_MIDI )
+ cs_handle_midi(card);
/* clear 'em */
cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
spin_unlock(&card->lock);
+ CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()- \n"));
+}
+
+
+/**********************************************************************/
+
+static ssize_t cs_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+ struct cs_card *card = (struct cs_card *)file->private_data;
+ ssize_t ret;
+ unsigned long flags;
+ unsigned ptr;
+ int cnt;
+
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+ if (!access_ok(VERIFY_WRITE, buffer, count))
+ return -EFAULT;
+ ret = 0;
+ while (count > 0) {
+ spin_lock_irqsave(&card->lock, flags);
+ ptr = card->midi.ird;
+ cnt = CS_MIDIINBUF - ptr;
+ if (card->midi.icnt < cnt)
+ cnt = card->midi.icnt;
+ spin_unlock_irqrestore(&card->lock, flags);
+ if (cnt > count)
+ cnt = count;
+ if (cnt <= 0) {
+ if (file->f_flags & O_NONBLOCK)
+ return ret ? ret : -EAGAIN;
+ interruptible_sleep_on(&card->midi.iwait);
+ if (signal_pending(current))
+ return ret ? ret : -ERESTARTSYS;
+ continue;
+ }
+ if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt))
+ return ret ? ret : -EFAULT;
+ ptr = (ptr + cnt) % CS_MIDIINBUF;
+ spin_lock_irqsave(&card->lock, flags);
+ card->midi.ird = ptr;
+ card->midi.icnt -= cnt;
+ spin_unlock_irqrestore(&card->lock, flags);
+ count -= cnt;
+ buffer += cnt;
+ ret += cnt;
+ }
+ return ret;
+}
+
+
+static ssize_t cs_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+ struct cs_card *card = (struct cs_card *)file->private_data;
+ ssize_t ret;
+ unsigned long flags;
+ unsigned ptr;
+ int cnt;
+
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+ if (!access_ok(VERIFY_READ, buffer, count))
+ return -EFAULT;
+ ret = 0;
+ while (count > 0) {
+ spin_lock_irqsave(&card->lock, flags);
+ ptr = card->midi.owr;
+ cnt = CS_MIDIOUTBUF - ptr;
+ if (card->midi.ocnt + cnt > CS_MIDIOUTBUF)
+ cnt = CS_MIDIOUTBUF - card->midi.ocnt;
+ if (cnt <= 0)
+ cs_handle_midi(card);
+ spin_unlock_irqrestore(&card->lock, flags);
+ if (cnt > count)
+ cnt = count;
+ if (cnt <= 0) {
+ if (file->f_flags & O_NONBLOCK)
+ return ret ? ret : -EAGAIN;
+ interruptible_sleep_on(&card->midi.owait);
+ if (signal_pending(current))
+ return ret ? ret : -ERESTARTSYS;
+ continue;
+ }
+ if (copy_from_user(card->midi.obuf + ptr, buffer, cnt))
+ return ret ? ret : -EFAULT;
+ ptr = (ptr + cnt) % CS_MIDIOUTBUF;
+ spin_lock_irqsave(&card->lock, flags);
+ card->midi.owr = ptr;
+ card->midi.ocnt += cnt;
+ spin_unlock_irqrestore(&card->lock, flags);
+ count -= cnt;
+ buffer += cnt;
+ ret += cnt;
+ spin_lock_irqsave(&card->lock, flags);
+ cs_handle_midi(card);
+ spin_unlock_irqrestore(&card->lock, flags);
+ }
+ return ret;
+}
+
+
+static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct cs_card *card = (struct cs_card *)file->private_data;
+ unsigned long flags;
+ unsigned int mask = 0;
+
+ if (file->f_flags & FMODE_WRITE)
+ poll_wait(file, &card->midi.owait, wait);
+ if (file->f_flags & FMODE_READ)
+ poll_wait(file, &card->midi.iwait, wait);
+ spin_lock_irqsave(&card->lock, flags);
+ if (file->f_flags & FMODE_READ) {
+ if (card->midi.icnt > 0)
+ mask |= POLLIN | POLLRDNORM;
+ }
+ if (file->f_flags & FMODE_WRITE) {
+ if (card->midi.ocnt < CS_MIDIOUTBUF)
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+ return mask;
}
+
+static int cs_midi_open(struct inode *inode, struct file *file)
+{
+ int minor = MINOR(inode->i_rdev);
+ struct cs_card *card = devs;
+ unsigned long flags;
+ while (card && card->dev_midi != minor)
+ card = card->next;
+ if (!card)
+ return -ENODEV;
+ file->private_data = card;
+ /* wait for device to become free */
+ down(&card->midi.open_sem);
+ while (card->midi.open_mode & file->f_mode) {
+ if (file->f_flags & O_NONBLOCK) {
+ up(&card->midi.open_sem);
+ return -EBUSY;
+ }
+ up(&card->midi.open_sem);
+ interruptible_sleep_on(&card->midi.open_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ down(&card->midi.open_sem);
+ }
+ spin_lock_irqsave(&card->midi.lock, flags);
+ if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) {
+ card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
+ card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
+ card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
+ cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f); /* Enable xmit, rcv. */
+ cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM); /* Enable interrupts */
+ }
+ if (file->f_mode & FMODE_READ) {
+ card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
+ }
+ spin_unlock_irqrestore(&card->midi.lock, flags);
+ card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE));
+ up(&card->midi.open_sem);
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+
+static int cs_midi_release(struct inode *inode, struct file *file)
+{
+ struct cs_card *card = (struct cs_card *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long flags;
+ unsigned count, tmo;
+
+ if (file->f_mode & FMODE_WRITE) {
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&card->midi.owait, &wait);
+ for (;;) {
+ spin_lock_irqsave(&card->midi.lock, flags);
+ count = card->midi.ocnt;
+ spin_unlock_irqrestore(&card->midi.lock, flags);
+ if (count <= 0)
+ break;
+ if (signal_pending(current))
+ break;
+ if (file->f_flags & O_NONBLOCK) {
+ remove_wait_queue(&card->midi.owait, &wait);
+ current->state = TASK_RUNNING;
+ return -EBUSY;
+ }
+ tmo = (count * HZ) / 3100;
+ if (!schedule_timeout(tmo ? : 1) && tmo)
+ printk(KERN_DEBUG "cs46xx: midi timed out??\n");
+ }
+ remove_wait_queue(&card->midi.owait, &wait);
+ current->state = TASK_RUNNING;
+ }
+ down(&card->midi.open_sem);
+ card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE)));
+ up(&card->midi.open_sem);
+ wake_up(&card->midi.open_wait);
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+/*
+ * Midi file operations struct.
+ */
+static /*const*/ struct file_operations cs_midi_fops = {
+ llseek: cs_llseek,
+ read: cs_midi_read,
+ write: cs_midi_write,
+ poll: cs_midi_poll,
+ open: cs_midi_open,
+ release: cs_midi_release,
+};
+
static loff_t cs_llseek(struct file *file, loff_t offset, int origin)
{
return -ESPIPE;
}
+/*
+ *
+ * CopySamples copies 16-bit stereo signed samples from the source to the
+ * destination, possibly converting down to unsigned 8-bit and/or mono.
+ * count specifies the number of output bytes to write.
+ *
+ * Arguments:
+ *
+ * dst - Pointer to a destination buffer.
+ * src - Pointer to a source buffer
+ * count - The number of bytes to copy into the destination buffer.
+ * fmt - CS_FMT_16BIT and/or CS_FMT_STEREO bits
+ * dmabuf - pointer to the dma buffer structure
+ *
+ * NOTES: only call this routine if the output desired is not 16 Signed Stereo
+ *
+ *
+ */
+static void CopySamples(char *dst, char *src, int count, unsigned fmt,
+ struct dmabuf *dmabuf)
+{
+
+ s32 s32AudioSample;
+ s16 *psSrc=(s16 *)src;
+ s16 *psDst=(s16 *)dst;
+ u8 *pucDst=(u8 *)dst;
+
+ CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: CopySamples()+ ") );
+ CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
+ " dst=0x%x src=0x%x count=%d fmt=0x%x\n",
+ (unsigned)dst,(unsigned)src,(unsigned)count,(unsigned)fmt) );
+
+ /*
+ * See if the data should be output as 8-bit unsigned stereo.
+ */
+ if((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT))
+ {
+ /*
+ * Convert each 16-bit signed stereo sample to 8-bit unsigned
+ * stereo using rounding.
+ */
+ psSrc = (s16 *)src;
+ count = count/2;
+ while(count--)
+ {
+ *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8);
+ }
+ }
+ /*
+ * See if the data should be output at 8-bit unsigned mono.
+ */
+ else if(!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT))
+ {
+ /*
+ * Convert each 16-bit signed stereo sample to 8-bit unsigned
+ * mono using averaging and rounding.
+ */
+ psSrc = (s16 *)src;
+ count = count/2;
+ while(count--)
+ {
+ s32AudioSample = ((*psSrc)+(*(psSrc + 1)))/2 + (s32)0x80;
+ if(s32AudioSample > 0x7fff)
+ s32AudioSample = 0x7fff;
+ *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8);
+ psSrc += 2;
+ }
+ }
+ /*
+ * See if the data should be output at 16-bit signed mono.
+ */
+ else if(!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT))
+ {
+ /*
+ * Convert each 16-bit signed stereo sample to 16-bit signed
+ * mono using averaging.
+ */
+ psSrc = (s16 *)src;
+ count = count/2;
+ while(count--)
+ {
+ *(psDst++) = (s16)((*psSrc)+(*(psSrc + 1)))/2;
+ psSrc += 2;
+ }
+ }
+}
+
+/*
+ * cs_copy_to_user()
+ * replacement for the standard copy_to_user, to allow for a conversion from
+ * 16 bit to 8 bit and from stereo to mono, if the record conversion is active.
+ * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo,
+ * so we convert from any of the other format combinations.
+ */
+static unsigned cs_copy_to_user(
+ struct cs_state *s,
+ void *dest,
+ void *hwsrc,
+ unsigned cnt,
+ unsigned *copied)
+{
+ struct dmabuf *dmabuf = &s->dmabuf;
+ void *src = hwsrc; /* default to the standard destination buffer addr */
+
+ CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO
+ "cs_copy_to_user()+ fmt=0x%x cnt=%d dest=0x%.8x\n",
+ dmabuf->fmt,(unsigned)cnt,(unsigned)dest) );
+
+ if(cnt > dmabuf->dmasize)
+ {
+ cnt = dmabuf->dmasize;
+ }
+ if(!cnt)
+ {
+ *copied = 0;
+ return 0;
+ }
+ if(dmabuf->divisor != 1)
+ {
+ if(!dmabuf->tmpbuff)
+ {
+ *copied = cnt/dmabuf->divisor;
+ return 0;
+ }
+
+ CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt,
+ dmabuf->fmt, dmabuf);
+ src = dmabuf->tmpbuff;
+ cnt = cnt/dmabuf->divisor;
+ }
+ if (copy_to_user(dest, src, cnt))
+ {
+ CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR
+ "cs4281: cs_copy_to_user()- fault dest=0x%x src=0x%x cnt=%d\n",
+ (unsigned)dest,(unsigned)src,cnt) );
+ *copied = 0;
+ return -EFAULT;
+ }
+ *copied = cnt;
+ CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO
+ "cs4281: cs_copy_to_user()- copied bytes is %d \n",cnt) );
+ return 0;
+}
+
/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to
the user's buffer. it is filled by the dma machine and drained by this loop. */
static ssize_t cs_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
- struct cs_state *state = (struct cs_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
- ssize_t ret;
+ struct cs_card *card=devs;
+ struct cs_state *state;
+ DECLARE_WAITQUEUE(wait, current);
+ struct dmabuf *dmabuf;
+ ssize_t ret = 0;
unsigned long flags;
unsigned swptr;
int cnt;
+ unsigned copied=0;
-#ifdef DEBUG
- printk("cs461x: cs_read called, count = %d\n", count);
-#endif
+ CS_DBGOUT(CS_WAVE_READ, 4, printk("cs461x: cs_read()+ %d\n",count) );
+ state = (struct cs_state *)card->states[0];
+ if(!state)
+ return -ENODEV;
+ dmabuf = &state->dmabuf;
if (ppos != &file->f_pos)
return -ESPIPE;
if (dmabuf->mapped)
return -ENXIO;
- if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
+ if (!dmabuf->ready && (ret = prog_dmabuf(state)))
return ret;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
- ret = 0;
+ add_wait_queue(&state->dmabuf.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
- if (dmabuf->count > (signed) dmabuf->dmasize) {
- /* buffer overrun, we are recovering from sleep_on_timeout,
- resync hwptr and swptr, make process flush the buffer */
- dmabuf->count = dmabuf->dmasize;
- dmabuf->swptr = dmabuf->hwptr;
- }
swptr = dmabuf->swptr;
cnt = dmabuf->dmasize - swptr;
if (dmabuf->count < cnt)
cnt = dmabuf->count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&state->card->lock, flags);
- if (cnt > count)
- cnt = count;
+ if (cnt > (count * dmabuf->divisor))
+ cnt = count * dmabuf->divisor;
if (cnt <= 0) {
- unsigned long tmo;
/* buffer is empty, start the dma machine and wait for data to be
recorded */
start_adc(state);
if (file->f_flags & O_NONBLOCK) {
if (!ret) ret = -EAGAIN;
- return ret;
- }
- /* This isnt strictly right for the 810 but it'll do */
- tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
- tmo >>= sample_shift[dmabuf->fmt];
- /* There are two situations when sleep_on_timeout returns, one is when
- the interrupt is serviced correctly and the process is waked up by
- ISR ON TIME. Another is when timeout is expired, which means that
- either interrupt is NOT serviced correctly (pending interrupt) or it
- is TOO LATE for the process to be scheduled to run (scheduler latency)
- which results in a (potential) buffer overrun. And worse, there is
- NOTHING we can do to prevent it. */
- if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
-#ifdef DEBUG
- printk(KERN_ERR "cs461x: recording schedule timeout, "
- "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
- dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
- dmabuf->hwptr, dmabuf->swptr);
-#endif
- /* a buffer overrun, we delay the recovery untill next time the
- while loop begin and we REALLY have space to record */
- }
+ remove_wait_queue(&state->dmabuf.wait, &wait);
+ break;
+ }
+ schedule();
if (signal_pending(current)) {
ret = ret ? ret : -ERESTARTSYS;
- return ret;
+ break;
}
continue;
}
- if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
+ CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO
+ "_read() copy_to cnt=%d count=%d ", cnt,count) );
+ CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
+ " .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n",
+ dmabuf->dmasize,dmabuf->count,(unsigned)buffer,ret) );
+
+ if (cs_copy_to_user(state, buffer,
+ (void *)((unsigned)dmabuf->rawbuf + swptr), cnt, &copied))
+ {
if (!ret) ret = -EFAULT;
- return ret;
+ break;
}
-
- swptr = (swptr + cnt) % dmabuf->dmasize;
-
- spin_lock_irqsave(&state->card->lock, flags);
- dmabuf->swptr = swptr;
- dmabuf->count -= cnt;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- start_adc(state);
+ swptr = (swptr + cnt) % dmabuf->dmasize;
+ spin_lock_irqsave(&card->lock, flags);
+ dmabuf->swptr = swptr;
+ dmabuf->count -= cnt;
+ spin_unlock_irqrestore(&card->lock, flags);
+ count -= copied;
+ buffer += copied;
+ ret += copied;
+ start_adc(state);
}
+ remove_wait_queue(&state->dmabuf.wait, &wait);
+ set_current_state(TASK_RUNNING);
+ CS_DBGOUT(CS_WAVE_READ, 4, printk("cs461x: cs_read()- %d\n",ret) );
return ret;
}
@@ -1024,27 +2014,31 @@ static ssize_t cs_read(struct file *file, char *buffer, size_t count, loff_t *pp
the soundcard. it is drained by the dma machine and filled by this loop. */
static ssize_t cs_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
- struct cs_state *state = (struct cs_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
- ssize_t ret;
+ struct cs_card *card=devs;
+ struct cs_state *state;
+ DECLARE_WAITQUEUE(wait, current);
+ struct dmabuf *dmabuf;
+ ssize_t ret = 0;
unsigned long flags;
unsigned swptr;
int cnt;
-#ifdef DEBUG
- printk("cs461x: cs_write called, count = %d\n", count);
-#endif
+ CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,
+ printk("cs461x: cs_write called, count = %d\n", count) );
+ state = (struct cs_state *)card->states[1];
+ if(!state)
+ return -ENODEV;
+ dmabuf = &state->dmabuf;
if (ppos != &file->f_pos)
return -ESPIPE;
if (dmabuf->mapped)
return -ENXIO;
- if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
+ if (!dmabuf->ready && (ret = prog_dmabuf(state)))
return ret;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
- ret = 0;
-
+ add_wait_queue(&state->dmabuf.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
if (dmabuf->count < 0) {
@@ -1053,49 +2047,37 @@ static ssize_t cs_write(struct file *file, const char *buffer, size_t count, lof
dmabuf->count = 0;
dmabuf->swptr = dmabuf->hwptr;
}
+ if (dmabuf->underrun)
+ {
+ dmabuf->underrun = 0;
+ dmabuf->hwptr = cs_get_dma_addr(state);
+ dmabuf->swptr = dmabuf->hwptr;
+ }
swptr = dmabuf->swptr;
cnt = dmabuf->dmasize - swptr;
if (dmabuf->count + cnt > dmabuf->dmasize)
cnt = dmabuf->dmasize - dmabuf->count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&state->card->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- unsigned long tmo;
/* buffer is full, start the dma machine and wait for data to be
played */
start_dac(state);
if (file->f_flags & O_NONBLOCK) {
if (!ret) ret = -EAGAIN;
- return ret;
- }
- /* Not strictly correct but works */
- tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
- tmo >>= sample_shift[dmabuf->fmt];
- /* There are two situations when sleep_on_timeout returns, one is when
- the interrupt is serviced correctly and the process is waked up by
- ISR ON TIME. Another is when timeout is expired, which means that
- either interrupt is NOT serviced correctly (pending interrupt) or it
- is TOO LATE for the process to be scheduled to run (scheduler latency)
- which results in a (potential) buffer underrun. And worse, there is
- NOTHING we can do to prevent it. */
- if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
-#ifdef DEBUG
- printk(KERN_ERR "cs461x: playback schedule timeout, "
- "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
- dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
- dmabuf->hwptr, dmabuf->swptr);
-#endif
- /* a buffer underrun, we delay the recovery untill next time the
- while loop begin and we REALLY have data to play */
- }
- if (signal_pending(current)) {
- if (!ret) ret = -ERESTARTSYS;
- return ret;
- }
- continue;
- }
+ break;
+ }
+ schedule();
+ if (signal_pending(current)) {
+ ret = ret ? ret : -ERESTARTSYS;
+ break;
+ }
+ continue;
+ }
if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
if (!ret) ret = -EFAULT;
return ret;
@@ -1106,6 +2088,12 @@ static ssize_t cs_write(struct file *file, const char *buffer, size_t count, lof
spin_lock_irqsave(&state->card->lock, flags);
dmabuf->swptr = swptr;
dmabuf->count += cnt;
+ if(dmabuf->count > dmabuf->dmasize)
+ {
+ CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk(
+ "cs46xx: cs_write() d->count > dmasize - resetting\n"));
+ dmabuf->count = dmabuf->dmasize;
+ }
dmabuf->endcleared = 0;
spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1114,63 +2102,142 @@ static ssize_t cs_write(struct file *file, const char *buffer, size_t count, lof
ret += cnt;
start_dac(state);
}
+ remove_wait_queue(&state->dmabuf.wait, &wait);
+ set_current_state(TASK_RUNNING);
+
+ CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2,
+ printk("cs46xx: cs_write()- ret=0x%x\n", ret) );
return ret;
}
static unsigned int cs_poll(struct file *file, struct poll_table_struct *wait)
{
- struct cs_state *state = (struct cs_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
+ struct cs_card *card = (struct cs_card *)file->private_data;
+ struct dmabuf *dmabuf;
+ struct cs_state *state;
+
unsigned long flags;
unsigned int mask = 0;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()+ \n"));
+ if (!(file->f_mode & (FMODE_WRITE | FMODE_READ)))
+ {
+ return -EINVAL;
+ }
if (file->f_mode & FMODE_WRITE)
- poll_wait(file, &dmabuf->wait, wait);
+ {
+ state = card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ poll_wait(file, &dmabuf->wait, wait);
+ }
+ }
if (file->f_mode & FMODE_READ)
- poll_wait(file, &dmabuf->wait, wait);
+ {
+ state = card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ poll_wait(file, &dmabuf->wait, wait);
+ }
+ }
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(state);
+ spin_lock_irqsave(&card->lock, flags);
+ cs_update_ptr();
if (file->f_mode & FMODE_READ) {
- if (dmabuf->count >= (signed)dmabuf->fragsize)
- mask |= POLLIN | POLLRDNORM;
+ state = card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if (dmabuf->count >= (signed)dmabuf->fragsize)
+ mask |= POLLIN | POLLRDNORM;
+ }
}
if (file->f_mode & FMODE_WRITE) {
- if (dmabuf->mapped) {
- if (dmabuf->count >= (signed)dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- } else {
- if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
+ state = card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if (dmabuf->mapped) {
+ if (dmabuf->count >= (signed)dmabuf->fragsize)
+ mask |= POLLOUT | POLLWRNORM;
+ } else {
+ if ((signed)dmabuf->dmasize >= dmabuf->count
+ + (signed)dmabuf->fragsize)
+ mask |= POLLOUT | POLLWRNORM;
+ }
}
}
- spin_unlock_irqrestore(&state->card->lock, flags);
+ spin_unlock_irqrestore(&card->lock, flags);
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()- \n"));
return mask;
}
+/*
+ * We let users mmap the ring buffer. Its not the real DMA buffer but
+ * that side of the code is hidden in the IRQ handling. We do a software
+ * emulation of DMA from a 64K or so buffer into a 2K FIFO.
+ * (the hardware probably deserves a moan here but Crystal send me nice
+ * toys ;)).
+ */
+
static int cs_mmap(struct file *file, struct vm_area_struct *vma)
{
- return -EINVAL;
-#if 0
- struct cs_state *state = (struct cs_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
+ struct cs_card *card=devs;
+ struct cs_state *state;
+ struct dmabuf *dmabuf;
int ret;
unsigned long size;
+ CS_DBGOUT(CS_FUNCTION | CS_PARMS, 2, printk("cs46xx: cs_mmap()+ file=0x%x %s %s\n",
+ (unsigned)file, vma->vm_flags & VM_WRITE ? "VM_WRITE" : "",
+ vma->vm_flags & VM_READ ? "VM_READ" : "") );
if (vma->vm_flags & VM_WRITE) {
- if ((ret = prog_dmabuf(state, 0)) != 0)
- return ret;
+ state = card->states[1];
+ if(state)
+ {
+ CS_DBGOUT(CS_OPEN, 2, printk(
+ "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") );
+ if ((ret = prog_dmabuf(state)) != 0)
+ return ret;
+ }
} else if (vma->vm_flags & VM_READ) {
- if ((ret = prog_dmabuf(state, 1)) != 0)
- return ret;
- } else
+ state = card->states[0];
+ if(state)
+ {
+ CS_DBGOUT(CS_OPEN, 2, printk(
+ "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") );
+ if ((ret = prog_dmabuf(state)) != 0)
+ return ret;
+ }
+ } else {
+ CS_DBGOUT(CS_ERROR, 2, printk(
+ "cs46xx: cs_mmap() return -EINVAL\n") );
return -EINVAL;
+ }
- if (vma->vm_offset != 0)
+/*
+ * For now ONLY support playback, but seems like the only way to use
+ * mmap() is to open an FD with RDWR, just read or just write access
+ * does not function, get an error back from the kernel.
+ * Also, QuakeIII opens with RDWR! So, there must be something
+ * to needing read/write access mapping. So, allow read/write but
+ * use the DAC only.
+ */
+ state = card->states[1];
+ if(!(unsigned)state)
+ return -EINVAL;
+
+ dmabuf = &state->dmabuf;
+ if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
+
+ CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) );
+
if (size > (PAGE_SIZE << dmabuf->buforder))
return -EINVAL;
if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf),
@@ -1178,24 +2245,35 @@ static int cs_mmap(struct file *file, struct vm_area_struct *vma)
return -EAGAIN;
dmabuf->mapped = 1;
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") );
return 0;
-#endif
}
static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
- struct cs_state *state = (struct cs_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
+ struct cs_card *card = (struct cs_card *)file->private_data;
+ struct cs_state *state;
+ struct dmabuf *dmabuf=0;
unsigned long flags;
audio_buf_info abinfo;
count_info cinfo;
- int val, mapped, ret;
+ int val, valsave, mapped, ret;
- mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) ||
- ((file->f_mode & FMODE_READ) && dmabuf->mapped);
-#ifdef DEBUG
- printk("cs461x: cs_ioctl, command = %2d, arg = 0x%08x\n",
- _IOC_NR(cmd), arg ? *(int *)arg : 0);
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ mapped = (file->f_mode & FMODE_READ) && dmabuf->mapped;
+ }
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ mapped |= (file->f_mode & FMODE_WRITE) && dmabuf->mapped;
+ }
+
+#if CSDEBUG
+ printioctl(cmd);
#endif
switch (cmd)
@@ -1206,21 +2284,36 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
case SNDCTL_DSP_RESET:
/* FIXME: spin_lock ? */
if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- synchronize_irq();
- dmabuf->ready = 0;
- resync_dma_ptrs(state);
- dmabuf->swptr = dmabuf->hwptr = 0;
- dmabuf->count = dmabuf->total_bytes = 0;
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_dac(state);
+ synchronize_irq();
+ dmabuf->ready = 0;
+ resync_dma_ptrs(state);
+ dmabuf->swptr = dmabuf->hwptr = 0;
+ dmabuf->count = dmabuf->total_bytes = 0;
+ dmabuf->blocks = 0;
+ dmabuf->SGok = 0;
+ }
}
if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- synchronize_irq();
- resync_dma_ptrs(state);
- dmabuf->ready = 0;
- dmabuf->swptr = dmabuf->hwptr = 0;
- dmabuf->count = dmabuf->total_bytes = 0;
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_adc(state);
+ synchronize_irq();
+ resync_dma_ptrs(state);
+ dmabuf->ready = 0;
+ dmabuf->swptr = dmabuf->hwptr = 0;
+ dmabuf->count = dmabuf->total_bytes = 0;
+ dmabuf->blocks = 0;
+ dmabuf->SGok = 0;
+ }
}
+ CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_RESET()-\n") );
return 0;
case SNDCTL_DSP_SYNC:
@@ -1228,170 +2321,335 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
return drain_dac(state, file->f_flags & O_NONBLOCK);
return 0;
- case SNDCTL_DSP_SPEED: /* set smaple rate */
+ case SNDCTL_DSP_SPEED: /* set sample rate */
if (get_user(val, (int *)arg))
return -EFAULT;
if (val >= 0) {
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dmabuf->ready = 0;
- cs_set_dac_rate(state, val);
- }
if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dmabuf->ready = 0;
- cs_set_adc_rate(state, val);
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_adc(state);
+ dmabuf->ready = 0;
+ dmabuf->SGok = 0;
+ cs_set_adc_rate(state, val);
+ cs_set_divisor(dmabuf);
+ }
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_dac(state);
+ dmabuf->ready = 0;
+ dmabuf->SGok = 0;
+ cs_set_dac_rate(state, val);
+ cs_set_divisor(dmabuf);
+ }
}
+ CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
+ "cs46xx: cs_ioctl() DSP_SPEED %s %s %d\n",
+ file->f_mode & FMODE_WRITE ? "DAC" : "",
+ file->f_mode & FMODE_READ ? "ADC" : "",
+ dmabuf->rate ) );
+ return put_user(dmabuf->rate, (int *)arg);
}
- return put_user(dmabuf->rate, (int *)arg);
+ return put_user(0, (int *)arg);
case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
if (get_user(val, (int *)arg))
return -EFAULT;
if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dmabuf->ready = 0;
- if(val)
- dmabuf->fmt |= CS_FMT_STEREO;
- else
- dmabuf->fmt &= ~CS_FMT_STEREO;
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_dac(state);
+ dmabuf->ready = 0;
+ dmabuf->SGok = 0;
+ if(val)
+ dmabuf->fmt |= CS_FMT_STEREO;
+ else
+ dmabuf->fmt &= ~CS_FMT_STEREO;
+ cs_set_divisor(dmabuf);
+ CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
+ "cs46xx: DSP_STEREO() DAC %s\n",
+ (dmabuf->fmt & CS_FMT_STEREO) ?
+ "STEREO":"MONO") );
+ }
}
if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dmabuf->ready = 0;
- if(val)
+ state = (struct cs_state *)card->states[0];
+ if(state)
{
- dmabuf->fmt |= CS_FMT_STEREO;
- return put_user(1, (int *)arg);
+ dmabuf = &state->dmabuf;
+ stop_adc(state);
+ dmabuf->ready = 0;
+ dmabuf->SGok = 0;
+ if(val)
+ dmabuf->fmt |= CS_FMT_STEREO;
+ else
+ dmabuf->fmt &= ~CS_FMT_STEREO;
+ cs_set_divisor(dmabuf);
+ CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
+ "cs46xx: DSP_STEREO() ADC %s\n",
+ (dmabuf->fmt & CS_FMT_STEREO) ?
+ "STEREO":"MONO") );
}
-#if 0
- /* Needs extra work to support this */
-
- else
- dmabuf->fmt &= ~CS_FMT_STEREO;
-#endif
}
return 0;
case SNDCTL_DSP_GETBLKSIZE:
if (file->f_mode & FMODE_WRITE) {
- if ((val = prog_dmabuf(state, 0)))
- return val;
- return put_user(dmabuf->fragsize, (int *)arg);
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if ((val = prog_dmabuf(state)))
+ return val;
+ return put_user(dmabuf->fragsize, (int *)arg);
+ }
}
if (file->f_mode & FMODE_READ) {
- if ((val = prog_dmabuf(state, 1)))
- return val;
- return put_user(dmabuf->fragsize, (int *)arg);
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if ((val = prog_dmabuf(state)))
+ return val;
+ return put_user(dmabuf->fragsize/dmabuf->divisor,
+ (int *)arg);
+ }
}
+ return put_user(0, (int *)arg);
case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
- return put_user(AFMT_S16_LE, (int *)arg);
+ return put_user(AFMT_S16_LE | AFMT_U8, (int *)arg);
case SNDCTL_DSP_SETFMT: /* Select sample format */
if (get_user(val, (int *)arg))
return -EFAULT;
+ CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(
+ "cs46xx: cs_ioctl() DSP_SETFMT %s %s %s %s\n",
+ file->f_mode & FMODE_WRITE ? "DAC" : "",
+ file->f_mode & FMODE_READ ? "ADC" : "",
+ val == AFMT_S16_LE ? "16Bit Signed" : "",
+ val == AFMT_U8 ? "8Bit Unsigned" : "") );
+ valsave = val;
if (val != AFMT_QUERY) {
- if(val==AFMT_S16_LE/* || val==AFMT_U8*/)
+ if(val==AFMT_S16_LE || val==AFMT_U8)
{
if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dmabuf->ready = 0;
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_dac(state);
+ dmabuf->ready = 0;
+ dmabuf->SGok = 0;
+ if(val==AFMT_S16_LE)
+ dmabuf->fmt |= CS_FMT_16BIT;
+ else
+ dmabuf->fmt &= ~CS_FMT_16BIT;
+ cs_set_divisor(dmabuf);
+ if((ret = prog_dmabuf(state)))
+ return ret;
+ }
}
if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dmabuf->ready = 0;
+ val = valsave;
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_adc(state);
+ dmabuf->ready = 0;
+ dmabuf->SGok = 0;
+ if(val==AFMT_S16_LE)
+ dmabuf->fmt |= CS_FMT_16BIT;
+ else
+ dmabuf->fmt &= ~CS_FMT_16BIT;
+ cs_set_divisor(dmabuf);
+ if((ret = prog_dmabuf(state)))
+ return ret;
+ }
}
- if(val==AFMT_S16_LE)
- dmabuf->fmt |= CS_FMT_16BIT;
- else
- dmabuf->fmt &= ~CS_FMT_16BIT;
+ }
+ else
+ {
+ CS_DBGOUT(CS_IOCTL | CS_ERROR, 2, printk(
+ "cs46xx: DSP_SETFMT() Unsupported format (0x%x)\n",
+ valsave) );
}
}
- if(dmabuf->fmt&CS_FMT_16BIT)
- return put_user(AFMT_S16_LE, (int *)arg);
else
- return put_user(AFMT_U8, (int *)arg);
+ {
+ if(file->f_mode & FMODE_WRITE)
+ {
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ dmabuf = &state->dmabuf;
+ }
+ else if(file->f_mode & FMODE_READ)
+ {
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ dmabuf = &state->dmabuf;
+ }
+ }
+ if(dmabuf)
+ {
+ if(dmabuf->fmt & CS_FMT_16BIT)
+ return put_user(AFMT_S16_LE, (int *)arg);
+ else
+ return put_user(AFMT_U8, (int *)arg);
+ }
+ return put_user(0, (int *)arg);
case SNDCTL_DSP_CHANNELS:
if (get_user(val, (int *)arg))
return -EFAULT;
if (val != 0) {
if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dmabuf->ready = 0;
- if (val > 1)
- dmabuf->fmt |= CS_FMT_STEREO;
- else
- dmabuf->fmt &= ~CS_FMT_STEREO;
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_dac(state);
+ dmabuf->ready = 0;
+ dmabuf->SGok = 0;
+ if(val>1)
+ dmabuf->fmt |= CS_FMT_STEREO;
+ else
+ dmabuf->fmt &= ~CS_FMT_STEREO;
+ cs_set_divisor(dmabuf);
+ if (prog_dmabuf(state))
+ return 0;
+ }
}
if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dmabuf->ready = 0;
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ stop_adc(state);
+ dmabuf->ready = 0;
+ dmabuf->SGok = 0;
+ if(val>1)
+ dmabuf->fmt |= CS_FMT_STEREO;
+ else
+ dmabuf->fmt &= ~CS_FMT_STEREO;
+ cs_set_divisor(dmabuf);
+ if (prog_dmabuf(state))
+ return 0;
+ }
}
}
return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
(int *)arg);
case SNDCTL_DSP_POST:
- /* FIXME: the same as RESET ?? */
+ /*
+ * There will be a longer than normal pause in the data.
+ * so... do nothing, because there is nothing that we can do.
+ */
return 0;
case SNDCTL_DSP_SUBDIVIDE:
- if (dmabuf->subdivision)
- return -EINVAL;
- if (get_user(val, (int *)arg))
- return -EFAULT;
- if (val != 1 && val != 2)
- return -EINVAL;
- dmabuf->subdivision = val;
+ if (file->f_mode & FMODE_WRITE) {
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if (dmabuf->subdivision)
+ return -EINVAL;
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (val != 1 && val != 2)
+ return -EINVAL;
+ dmabuf->subdivision = val;
+ }
+ }
+ if (file->f_mode & FMODE_READ) {
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if (dmabuf->subdivision)
+ return -EINVAL;
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (val != 1 && val != 2)
+ return -EINVAL;
+ dmabuf->subdivision = val;
+ }
+ }
return 0;
case SNDCTL_DSP_SETFRAGMENT:
if (get_user(val, (int *)arg))
return -EFAULT;
- dmabuf->ossfragshift = val & 0xffff;
- dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
- switch(dmabuf->ossmaxfrags)
- {
- case 1:
- dmabuf->ossfragshift=12;
- return 0;
- default:
- /* Fragments must be 2K long */
- dmabuf->ossfragshift = 11;
- dmabuf->ossmaxfrags=2;
+ if (file->f_mode & FMODE_WRITE) {
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ dmabuf->ossfragshift = val & 0xffff;
+ dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
+ }
+ }
+ if (file->f_mode & FMODE_READ) {
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ dmabuf->ossfragshift = val & 0xffff;
+ dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
+ }
}
return 0;
case SNDCTL_DSP_GETOSPACE:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- if (!dmabuf->enable && (val = prog_dmabuf(state, 0)) != 0)
- return val;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(state);
- abinfo.fragsize = dmabuf->fragsize;
- abinfo.bytes = dmabuf->dmasize - dmabuf->count;
- abinfo.fragstotal = dmabuf->numfrag;
- abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
- spin_unlock_irqrestore(&state->card->lock, flags);
- return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ spin_lock_irqsave(&state->card->lock, flags);
+ cs_update_ptr();
+ abinfo.fragsize = dmabuf->fragsize;
+ abinfo.fragstotal = dmabuf->numfrag;
+ /*
+ * for mmap we always have total space available
+ */
+ if (dmabuf->mapped)
+ abinfo.bytes = dmabuf->dmasize;
+ else
+ abinfo.bytes = dmabuf->dmasize - dmabuf->count;
+
+ abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+ }
+ return -ENODEV;
case SNDCTL_DSP_GETISPACE:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- if (!dmabuf->enable && (val = prog_dmabuf(state, 1)) != 0)
- return val;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(state);
- abinfo.fragsize = dmabuf->fragsize;
- abinfo.bytes = dmabuf->count;
- abinfo.fragstotal = dmabuf->numfrag;
- abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
- spin_unlock_irqrestore(&state->card->lock, flags);
- return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ spin_lock_irqsave(&state->card->lock, flags);
+ cs_update_ptr();
+ abinfo.fragsize = dmabuf->fragsize/dmabuf->divisor;
+ abinfo.bytes = dmabuf->count/dmabuf->divisor;
+ abinfo.fragstotal = dmabuf->numfrag;
+ abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+ }
+ return -ENODEV;
case SNDCTL_DSP_NONBLOCK:
file->f_flags |= O_NONBLOCK;
@@ -1403,58 +2661,106 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
case SNDCTL_DSP_GETTRIGGER:
val = 0;
- if (file->f_mode & FMODE_READ && dmabuf->enable)
- val |= PCM_ENABLE_INPUT;
- if (file->f_mode & FMODE_WRITE && dmabuf->enable)
- val |= PCM_ENABLE_OUTPUT;
+ CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()+\n") );
+ if (file->f_mode & FMODE_WRITE)
+ {
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if(dmabuf->enable & DAC_RUNNING)
+ val |= PCM_ENABLE_INPUT;
+ }
+ }
+ if (file->f_mode & FMODE_READ)
+ {
+ if(state)
+ {
+ state = (struct cs_state *)card->states[0];
+ dmabuf = &state->dmabuf;
+ if(dmabuf->enable & ADC_RUNNING)
+ val |= PCM_ENABLE_OUTPUT;
+ }
+ }
+ CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()- val=0x%x\n",val) );
return put_user(val, (int *)arg);
case SNDCTL_DSP_SETTRIGGER:
if (get_user(val, (int *)arg))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
- if (val & PCM_ENABLE_INPUT) {
- if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
- return ret;
- start_adc(state);
- } else
- stop_adc(state);
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if (val & PCM_ENABLE_INPUT) {
+ if (!dmabuf->ready && (ret = prog_dmabuf(state)))
+ return ret;
+ start_adc(state);
+ } else
+ stop_adc(state);
+ }
}
if (file->f_mode & FMODE_WRITE) {
- if (val & PCM_ENABLE_OUTPUT) {
- if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
- return ret;
- start_dac(state);
- } else
- stop_dac(state);
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ if (val & PCM_ENABLE_OUTPUT) {
+ if (!dmabuf->ready && (ret = prog_dmabuf(state)))
+ return ret;
+ start_dac(state);
+ } else
+ stop_dac(state);
+ }
}
return 0;
case SNDCTL_DSP_GETIPTR:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(state);
- cinfo.bytes = dmabuf->total_bytes;
- cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
- cinfo.ptr = dmabuf->hwptr;
- if (dmabuf->mapped)
- dmabuf->count &= dmabuf->fragsize-1;
- spin_unlock_irqrestore(&state->card->lock, flags);
- return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ spin_lock_irqsave(&state->card->lock, flags);
+ cs_update_ptr();
+ cinfo.bytes = dmabuf->total_bytes/dmabuf->divisor;
+ cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift;
+ cinfo.ptr = dmabuf->hwptr/dmabuf->divisor;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+ }
+ return -ENODEV;
case SNDCTL_DSP_GETOPTR:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(state);
- cinfo.bytes = dmabuf->total_bytes;
- cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
- cinfo.ptr = dmabuf->hwptr;
- if (dmabuf->mapped)
- dmabuf->count &= dmabuf->fragsize-1;
- spin_unlock_irqrestore(&state->card->lock, flags);
- return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ spin_lock_irqsave(&state->card->lock, flags);
+ cs_update_ptr();
+ cinfo.bytes = dmabuf->total_bytes;
+ if (dmabuf->mapped)
+ {
+ cinfo.blocks = (cinfo.bytes >> dmabuf->fragshift)
+ - dmabuf->blocks;
+ CS_DBGOUT(CS_PARMS, 8,
+ printk("total_bytes=%d blocks=%d dmabuf->blocks=%d\n",
+ cinfo.bytes,cinfo.blocks,dmabuf->blocks) );
+ dmabuf->blocks = cinfo.bytes >> dmabuf->fragshift;
+ }
+ else
+ {
+ cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
+ }
+ cinfo.ptr = dmabuf->hwptr;
+
+ CS_DBGOUT(CS_PARMS, 4, printk(
+ "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n",
+ cinfo.bytes,cinfo.blocks,cinfo.ptr) );
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+ }
+ return -ENODEV;
case SNDCTL_DSP_SETDUPLEX:
return -EINVAL;
@@ -1462,21 +2768,47 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
case SNDCTL_DSP_GETODELAY:
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(state);
- val = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
+ state = (struct cs_state *)card->states[1];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ spin_lock_irqsave(&state->card->lock, flags);
+ cs_update_ptr();
+ val = dmabuf->count;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ }
+ else
+ val = 0;
return put_user(val, (int *)arg);
case SOUND_PCM_READ_RATE:
- return put_user(dmabuf->rate, (int *)arg);
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ return put_user(dmabuf->rate, (int *)arg);
+ }
+ return put_user(0, (int *)arg);
+
case SOUND_PCM_READ_CHANNELS:
- return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
(int *)arg);
+ }
+ return put_user(0, (int *)arg);
case SOUND_PCM_READ_BITS:
- return put_user(AFMT_S16_LE, (int *)arg);
+ state = (struct cs_state *)card->states[0];
+ if(state)
+ {
+ dmabuf = &state->dmabuf;
+ return put_user(AFMT_S16_LE | AFMT_U8, (int *)arg);
+ }
+ return put_user(0, (int *)arg);
case SNDCTL_DSP_MAPINBUF:
case SNDCTL_DSP_MAPOUTBUF:
@@ -1492,20 +2824,22 @@ static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
/*
* AMP control - null AMP
*/
-
+
static void amp_none(struct cs_card *card, int change)
-{
+{
}
/*
* Crystal EAPD mode
*/
-
+
static void amp_voyetra(struct cs_card *card, int change)
{
- /* Manage the EAPD bit on the Crystal 4297 */
+ /* Manage the EAPD bit on the Crystal 4297
+ and the Analog AD1885 */
+
int old=card->amplifier;
-
+
card->amplifier+=change;
if(card->amplifier && !old)
{
@@ -1528,12 +2862,11 @@ static void amp_voyetra(struct cs_card *card, int change)
/*
* Untested
*/
-#if 0
+
static void amp_voyetra_4294(struct cs_card *card, int change)
{
struct ac97_codec *c=card->ac97_codec[0];
- int old = card->amplifier;
-
+
card->amplifier+=change;
if(card->amplifier)
@@ -1549,7 +2882,6 @@ static void amp_voyetra_4294(struct cs_card *card, int change)
cs_ac97_set(c, 0x54, cs_ac97_get(c, 0x54) | 0x0180);
}
}
-#endif
/*
* Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
@@ -1559,7 +2891,7 @@ static void amp_voyetra_4294(struct cs_card *card, int change)
* Linuxcare. Perhaps one day Crystal will document their chips well
* enough to make them useful.
*/
-
+
static void clkrun_hack(struct cs_card *card, int change)
{
struct pci_dev *acpi_dev;
@@ -1567,20 +2899,19 @@ static void clkrun_hack(struct cs_card *card, int change)
u8 pp;
unsigned long port;
int old=card->amplifier;
-
- card->amplifier += change;
-
+
+ card->amplifier+=change;
+
acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
if(acpi_dev == NULL)
return; /* Not a thinkpad thats for sure */
-
- /* Find the control port */
+ /* Find the control port */
pci_read_config_byte(acpi_dev, 0x41, &pp);
- port = pp<<8;
+ port=pp<<8;
- /* Read ACPI port */
- control = inw(port+0x10);
+ /* Read ACPI port */
+ control=inw(port+0x10);
/* Flip CLKRUN off while running */
if(!card->amplifier && old)
@@ -1589,142 +2920,227 @@ static void clkrun_hack(struct cs_card *card, int change)
outw(control&~0x2000, port+0x10);
}
-
+
static int cs_open(struct inode *inode, struct file *file)
{
- int i = 0;
struct cs_card *card = devs;
struct cs_state *state = NULL;
struct dmabuf *dmabuf = NULL;
+ int ret=0;
-#ifndef CS46XX_ENABLE_RECORD
- if (file->f_mode & FMODE_READ)
- return -ENODEV;
-#endif
+ CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()+ file=0x%x %s %s\n",
+ (unsigned)file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
+ file->f_mode & FMODE_READ ? "FMODE_READ" : "") );
- /* find an avaiable virtual channel (instance of /dev/dsp) */
- while (card != NULL) {
- for (i = 0; i < NR_HW_CH; i++) {
- if (card->states[i] == NULL) {
- state = card->states[i] = (struct cs_state *)
- kmalloc(sizeof(struct cs_state), GFP_KERNEL);
- if (state == NULL)
- return -ENOMEM;
- memset(state, 0, sizeof(struct cs_state));
- dmabuf = &state->dmabuf;
- dmabuf->pbuf = (void *)get_free_page(GFP_KERNEL);
- if(dmabuf->pbuf==NULL)
- {
- kfree(state);
- card->states[i]=NULL;
- return -ENOMEM;
- }
- goto found_virt;
+ /*
+ * hardcode state[0] for capture, [1] for playback
+ */
+ if(file->f_mode & FMODE_READ)
+ {
+ CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") );
+ if (card->states[0] == NULL) {
+ state = card->states[0] = (struct cs_state *)
+ kmalloc(sizeof(struct cs_state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+ memset(state, 0, sizeof(struct cs_state));
+ dmabuf = &state->dmabuf;
+ dmabuf->pbuf = (void *)get_free_page(GFP_KERNEL | GFP_DMA);
+ if(dmabuf->pbuf==NULL)
+ {
+ kfree(state);
+ card->states[0]=NULL;
+ return -ENOMEM;
}
}
- card = card->next;
- }
- /* no more virtual channel avaiable */
- if (!state)
- return -ENODEV;
-
- found_virt:
- /* found a free virtual channel, allocate hardware channels */
- if(file->f_mode & FMODE_READ)
+ else
+ {
+ state = card->states[0];
+ if(state->open_mode & FMODE_READ)
+ return -EBUSY;
+ }
dmabuf->channel = card->alloc_rec_pcm_channel(card);
- else
- dmabuf->channel = card->alloc_pcm_channel(card);
-
- if (dmabuf->channel == NULL) {
- kfree (card->states[i]);
- card->states[i] = NULL;;
- return -ENODEV;
- }
+
+ if (dmabuf->channel == NULL) {
+ kfree (card->states[0]);
+ card->states[0] = NULL;;
+ return -ENODEV;
+ }
- /* Now turn on external AMP if needed */
- state->card = card;
- state->card->active_ctrl(state->card,1);
- state->card->amplifier_ctrl(state->card,1);
+ /* Now turn on external AMP if needed */
+ state->card = card;
+ state->card->active_ctrl(state->card,1);
+ state->card->amplifier_ctrl(state->card,1);
+
+ dmabuf->channel->state = state;
+ /* initialize the virtual channel */
+ state->virt = 0;
+ state->magic = CS_STATE_MAGIC;
+ init_waitqueue_head(&dmabuf->wait);
+ init_MUTEX(&state->open_sem);
+ file->private_data = card;
- dmabuf->channel->state = state;
- /* initialize the virtual channel */
- state->virt = i;
- state->magic = CS_STATE_MAGIC;
- init_waitqueue_head(&dmabuf->wait);
- init_MUTEX(&state->open_sem);
- file->private_data = state;
+ down(&state->open_sem);
- down(&state->open_sem);
+ /* set default sample format. According to OSS Programmer's Guide /dev/dsp
+ should be default to unsigned 8-bits, mono, with sample rate 8kHz and
+ /dev/dspW will accept 16-bits sample */
- /* set default sample format. According to OSS Programmer's Guide /dev/dsp
- should be default to unsigned 8-bits, mono, with sample rate 8kHz and
- /dev/dspW will accept 16-bits sample */
- if (file->f_mode & FMODE_WRITE) {
- /* Output is 16bit only mono or stereo */
+ /* Default input is 8bit mono */
dmabuf->fmt &= ~CS_FMT_MASK;
- dmabuf->fmt |= CS_FMT_16BIT;
+ dmabuf->type = CS_TYPE_ADC;
dmabuf->ossfragshift = 0;
dmabuf->ossmaxfrags = 0;
dmabuf->subdivision = 0;
- cs_set_dac_rate(state, 8000);
+ cs_set_adc_rate(state, 8000);
+ cs_set_divisor(dmabuf);
+
+ state->open_mode |= FMODE_READ;
+ up(&state->open_sem);
+ MOD_INC_USE_COUNT;
}
+ if(file->f_mode & FMODE_WRITE)
+ {
+ CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") );
+ if (card->states[1] == NULL) {
+ state = card->states[1] = (struct cs_state *)
+ kmalloc(sizeof(struct cs_state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+ memset(state, 0, sizeof(struct cs_state));
+ dmabuf = &state->dmabuf;
+ dmabuf->pbuf = (void *)get_free_page(GFP_KERNEL | GFP_DMA);
+ if(dmabuf->pbuf==NULL)
+ {
+ kfree(state);
+ card->states[1]=NULL;
+ return -ENOMEM;
+ }
+ }
+ else
+ {
+ state = card->states[1];
+ if(state->open_mode & FMODE_WRITE)
+ return -EBUSY;
+ }
+ dmabuf->channel = card->alloc_pcm_channel(card);
+
+ if (dmabuf->channel == NULL) {
+ kfree (card->states[1]);
+ card->states[1] = NULL;;
+ return -ENODEV;
+ }
- if (file->f_mode & FMODE_READ) {
- /* Input is 16bit stereo only */
+ /* Now turn on external AMP if needed */
+ state->card = card;
+ state->card->active_ctrl(state->card,1);
+ state->card->amplifier_ctrl(state->card,1);
+
+ dmabuf->channel->state = state;
+ /* initialize the virtual channel */
+ state->virt = 1;
+ state->magic = CS_STATE_MAGIC;
+ init_waitqueue_head(&dmabuf->wait);
+ init_MUTEX(&state->open_sem);
+ file->private_data = card;
+
+ down(&state->open_sem);
+
+ /* set default sample format. According to OSS Programmer's Guide /dev/dsp
+ should be default to unsigned 8-bits, mono, with sample rate 8kHz and
+ /dev/dspW will accept 16-bits sample */
+
+ /* Default output is 8bit mono. */
dmabuf->fmt &= ~CS_FMT_MASK;
- dmabuf->fmt |= CS_FMT_16BIT|CS_FMT_STEREO;
+ dmabuf->type = CS_TYPE_DAC;
dmabuf->ossfragshift = 0;
dmabuf->ossmaxfrags = 0;
dmabuf->subdivision = 0;
- cs_set_adc_rate(state, 8000);
- }
-
- state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
- up(&state->open_sem);
+ cs_set_dac_rate(state, 8000);
+ cs_set_divisor(dmabuf);
+ state->open_mode |= FMODE_WRITE;
+ up(&state->open_sem);
+ MOD_INC_USE_COUNT;
+ if((ret = prog_dmabuf(state)))
+ return ret;
+ }
- MOD_INC_USE_COUNT;
+ CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n") );
return 0;
}
static int cs_release(struct inode *inode, struct file *file)
{
- struct cs_state *state = (struct cs_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
-
- if (file->f_mode & FMODE_WRITE) {
- /* FIXME :.. */
- cs_clear_tail(state);
- drain_dac(state, file->f_flags & O_NONBLOCK);
+ struct cs_card *card = (struct cs_card *)file->private_data;
+ struct dmabuf *dmabuf;
+ struct cs_state *state;
+ CS_DBGOUT(CS_RELEASE | CS_FUNCTION, 2, printk("cs46xx: cs_release()+ file=0x%x %s %s\n",
+ (unsigned)file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
+ file->f_mode & FMODE_READ ? "FMODE_READ" : "") );
+
+ if (!(file->f_mode & (FMODE_WRITE | FMODE_READ)))
+ {
+ return -EINVAL;
}
+ state = card->states[1];
+ if(state)
+ {
+ if ( (state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE) )
+ {
+ CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n") );
+ dmabuf = &state->dmabuf;
+ cs_clear_tail(state);
+ drain_dac(state, file->f_flags & O_NONBLOCK);
+ /* stop DMA state machine and free DMA buffers/channels */
+ down(&state->open_sem);
+ stop_dac(state);
+ dealloc_dmabuf(state);
+ state->card->free_pcm_channel(state->card, dmabuf->channel->num);
+ free_page((unsigned long)state->dmabuf.pbuf);
- /* stop DMA state machine and free DMA buffers/channels */
- down(&state->open_sem);
+ /* we're covered by the open_sem */
+ up(&state->open_sem);
+ state->card->states[state->virt] = NULL;
+ state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dealloc_dmabuf(state);
- state->card->free_pcm_channel(state->card, dmabuf->channel->num);
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dealloc_dmabuf(state);
- state->card->free_pcm_channel(state->card, dmabuf->channel->num);
+ /* Now turn off external AMP if needed */
+ state->card->amplifier_ctrl(state->card, -1);
+ state->card->active_ctrl(state->card, -1);
+
+ kfree(state);
+ }
+ MOD_DEC_USE_COUNT;
}
- free_page((unsigned long)state->dmabuf.pbuf);
+ state = card->states[0];
+ if(state)
+ {
+ if ( (state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ) )
+ {
+ CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n") );
+ dmabuf = &state->dmabuf;
+ down(&state->open_sem);
+ stop_adc(state);
+ dealloc_dmabuf(state);
+ state->card->free_pcm_channel(state->card, dmabuf->channel->num);
+ free_page((unsigned long)state->dmabuf.pbuf);
- /* we're covered by the open_sem */
- up(&state->open_sem);
- state->card->states[state->virt] = NULL;
- state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
+ /* we're covered by the open_sem */
+ up(&state->open_sem);
+ state->card->states[state->virt] = NULL;
+ state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
- /* Now turn off external AMP if needed */
- state->card->amplifier_ctrl(state->card, -1);
- state->card->active_ctrl(state->card, -1);
+ /* Now turn off external AMP if needed */
+ state->card->amplifier_ctrl(state->card, -1);
+ state->card->active_ctrl(state->card, -1);
- kfree(state);
- MOD_DEC_USE_COUNT;
+ kfree(state);
+ }
+ MOD_DEC_USE_COUNT;
+ }
+
+ CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n") );
return 0;
}
@@ -1841,6 +3257,12 @@ static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val)
{
struct cs_card *card = dev->private_data;
int count;
+ int val2 = 0;
+
+ if(reg == AC97_CD_VOL)
+ {
+ val2 = cs_ac97_get(dev, AC97_CD_VOL);
+ }
/*
* 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
@@ -1883,6 +3305,47 @@ static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val)
*/
if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV)
printk(KERN_WARNING "cs461x: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val);
+
+ /*
+ * Adjust power if the mixer is selected/deselected according
+ * to the CD.
+ *
+ * IF the CD is a valid input source (mixer or direct) AND
+ * the CD is not muted THEN power is needed
+ *
+ * We do two things. When record select changes the input to
+ * add/remove the CD we adjust the power count if the CD is
+ * unmuted.
+ *
+ * When the CD mute changes we adjust the power level if the
+ * CD was a valid input.
+ *
+ * We also check for CD volume != 0, as the CD mute isn't
+ * normally tweaked from userspace.
+ */
+
+ /* CD mute change ? */
+
+ if(reg==AC97_CD_VOL)
+ {
+ /* Mute bit change ? */
+ if((val2^val)&0x8000 || ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val))
+ {
+ /* This is a hack but its cleaner than the alternatives.
+ Right now card->ac97_codec[0] might be NULL as we are
+ still doing codec setup. This does an early assignment
+ to avoid the problem if it occurs */
+
+ if(card->ac97_codec[0]==NULL)
+ card->ac97_codec[0]=dev;
+
+ /* Mute on */
+ if(val&0x8000 || val == 0x1f1f)
+ card->amplifier_ctrl(card, -1);
+ else /* Mute off power on */
+ card->amplifier_ctrl(card, 1);
+ }
+ }
}
@@ -1916,7 +3379,7 @@ static int cs_release_mixdev(struct inode *inode, struct file *file)
int minor = MINOR(inode->i_rdev);
struct cs_card *card = devs;
int i;
-
+
for (card = devs; card != NULL; card = card->next)
for (i = 0; i < NR_AC97; i++)
if (card->ac97_codec[i] != NULL &&
@@ -1927,7 +3390,6 @@ static int cs_release_mixdev(struct inode *inode, struct file *file)
return -ENODEV;
match:
card->active_ctrl(card, -1);
-
MOD_DEC_USE_COUNT;
return 0;
}
@@ -1937,6 +3399,41 @@ static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int
{
struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
+#if CSDEBUG_INTERFACE
+ int val;
+
+ if( (cmd == SOUND_MIXER_CS_GETDBGMASK) ||
+ (cmd == SOUND_MIXER_CS_SETDBGMASK) ||
+ (cmd == SOUND_MIXER_CS_GETDBGLEVEL) ||
+ (cmd == SOUND_MIXER_CS_SETDBGLEVEL) )
+ {
+ switch(cmd)
+ {
+
+ case SOUND_MIXER_CS_GETDBGMASK:
+ return put_user(cs_debugmask, (unsigned long *)arg);
+
+ case SOUND_MIXER_CS_GETDBGLEVEL:
+ return put_user(cs_debuglevel, (unsigned long *)arg);
+
+ case SOUND_MIXER_CS_SETDBGMASK:
+ if (get_user(val, (unsigned long *)arg))
+ return -EFAULT;
+ cs_debugmask = val;
+ return 0;
+
+ case SOUND_MIXER_CS_SETDBGLEVEL:
+ if (get_user(val, (unsigned long *)arg))
+ return -EFAULT;
+ cs_debuglevel = val;
+ return 0;
+ default:
+ CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
+ "cs4281: mixer_ioctl(): ERROR unknown debug cmd\n") );
+ return 0;
+ }
+ }
+#endif
return codec->mixer_ioctl(codec, cmd, arg);
}
@@ -1981,7 +3478,6 @@ static int __init cs_ac97_init(struct cs_card *card)
}
card->ac97_features = eid;
-
if ((codec->dev_mixer = register_sound_mixer(&cs_mixer_fops, -1)) < 0) {
printk(KERN_ERR "cs461x: couldn't register mixer!\n");
@@ -1998,47 +3494,35 @@ static int __init cs_ac97_init(struct cs_card *card)
return num_ac97;
}
-/* Boot the card
+/*
+ * load the static image into the DSP
*/
-
-static void __init cs461x_download(struct cs_card *card, u32 *src, unsigned long offset, unsigned long len)
-{
- unsigned long counter;
- void *dst;
-
- dst = card->ba1.idx[(offset>>16)&3];
- dst += (offset&0xFFFF)<<2;
- for(counter=0;counter<len;counter+=4)
- writel(*src++, dst+counter);
-}
-
-/* 3*1024 parameter, 3.5*1024 sample, 2*3.5*1024 code */
-#define BA1_DWORD_SIZE (13 * 1024 + 512)
-#define BA1_MEMORY_COUNT 3
-
-struct BA1struct {
- struct {
- unsigned long offset;
- unsigned long size;
- } memory[BA1_MEMORY_COUNT];
- unsigned int map[BA1_DWORD_SIZE];
-};
-
#include "cs461x_image.h"
-
-static void __init cs461x_download_image(struct cs_card *card)
+static void cs461x_download_image(struct cs_card *card)
{
- int idx;
- unsigned long offset = 0;
-
- for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
- cs461x_download(card,&BA1Struct.map[offset],
- BA1Struct.memory[idx].offset,
- BA1Struct.memory[idx].size);
- offset += BA1Struct.memory[idx].size >> 2;
- }
+ unsigned i, j, temp1, temp2, offset, count;
+ unsigned char *pBA1 = ioremap(card->ba1_addr, 0x40000);
+ for( i=0; i < CLEAR__COUNT; i++)
+ {
+ offset = ClrStat[i].BA1__DestByteOffset;
+ count = ClrStat[i].BA1__SourceSize;
+ for( temp1 = offset; temp1<(offset+count); temp1+=4 );
+ writel(0, pBA1+temp1);
+ }
+
+ for(i=0; i<FILL__COUNT; i++)
+ {
+ temp2 = FillStat[i].Offset;
+ for(j=0; j<(FillStat[i].Size)/4; j++)
+ {
+ temp1 = (FillStat[i]).pFill[j];
+ writel(temp1, pBA1+temp2+j*4);
+ }
+ }
+ iounmap(pBA1);
}
+
/*
* Chip reset
*/
@@ -2242,7 +3726,7 @@ static void cs461x_proc_stop(struct cs_card *card)
-static int __init cs_hardware_init(struct cs_card *card)
+static int cs_hardware_init(struct cs_card *card)
{
unsigned long end_time;
unsigned int tmp;
@@ -2269,7 +3753,7 @@ static int __init cs_hardware_init(struct cs_card *card)
* for a reset.
*/
cs461x_pokeBA0(card, BA0_ACCTL, 0);
- udelay(500);
+ udelay(50);
cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_RSTN);
/*
@@ -2284,7 +3768,7 @@ static int __init cs_hardware_init(struct cs_card *card)
* generating bit clock (so we don't try to start the PLL without an
* input clock).
*/
- mdelay(10); /* 1 should be enough ?? */
+ mdelay(5); /* 1 should be enough ?? (and pigs might fly) */
/*
* Set the serial port timing configuration, so that
@@ -2309,7 +3793,7 @@ static int __init cs_hardware_init(struct cs_card *card)
/*
* Wait until the PLL has stabilized.
*/
- mdelay(100); /* Again 1 should be enough ?? */
+ mdelay(5); /* Again 1 should be enough ?? */
/*
* Turn on clocking of the core so that we can setup the serial ports.
@@ -2465,13 +3949,13 @@ static int __init cs_hardware_init(struct cs_card *card)
}
/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered
- until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
-
-
+ untill "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
+
+
/*
* Card subid table
*/
-
+
struct cs_card_type
{
u16 vendor;
@@ -2484,22 +3968,48 @@ struct cs_card_type
static struct cs_card_type __initdata cards[]={
{0x1489, 0x7001, "Genius Soundmaker 128 value", amp_none, NULL},
{0x5053, 0x3357, "Voyetra", amp_voyetra, NULL},
- /* MI6020/21 use the same chipset as the Thinkpads, maybe needed */
- {0x1071, 0x6003, "Mitac MI6020/21", amp_none, clkrun_hack},
+ {0x1071, 0x6003, "Mitac MI6020/21", amp_voyetra, NULL},
/* Not sure if the 570 needs the clkrun hack */
{PCI_VENDOR_ID_IBM, 0x0132, "Thinkpad 570", amp_none, clkrun_hack},
{PCI_VENDOR_ID_IBM, 0x0153, "Thinkpad 600X/A20/T20", amp_none, clkrun_hack},
{PCI_VENDOR_ID_IBM, 0x1010, "Thinkpad 600E (unsupported)", NULL, NULL},
+ {0, 0, "Card without SSID set", NULL, NULL },
{0, 0, NULL, NULL, NULL}
};
+#ifdef CS46XX_PM
+static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+struct cs_state *state = (struct cs_state *) dev->data;
+
+ if (state) {
+ switch(rqst) {
+ case PM_RESUME:
+ printk( KERN_DEBUG "cs46xx: PM resume request\n");
+ cs_hardware_init(state->card);
+ break;
+ case PM_SUSPEND:
+ printk( KERN_DEBUG "cs46xx: PM suspend request\n");
+ stop_dac(state);
+ resync_dma_ptrs(state);
+ break;
+ }
+ }
+
+return 0;
+}
+#endif
+
static int __init cs_install(struct pci_dev *pci_dev)
{
struct cs_card *card;
struct cs_card_type *cp = &cards[0];
+#ifdef CS46XX_PM
+ struct pm_dev *pmdev;
+#endif
u16 ss_card, ss_vendor;
-
-
+
+
pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card);
@@ -2526,8 +4036,8 @@ static int __init cs_install(struct pci_dev *pci_dev)
card->free_pcm_channel = cs_free_pcm_channel;
card->amplifier_ctrl = amp_none;
card->active_ctrl = amp_none;
-
- while(cp->name)
+
+ while (cp->name)
{
if(cp->vendor == ss_vendor && cp->id == ss_card)
{
@@ -2538,38 +4048,37 @@ static int __init cs_install(struct pci_dev *pci_dev)
}
cp++;
}
- if(cp->name==NULL)
+ if (cp->name==NULL)
{
- printk(KERN_INFO "cs461x: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
- ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq);
+ printk(KERN_INFO "cs461x: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
+ ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq);
}
else
{
printk(KERN_INFO "cs461x: %s at 0x%08lx/0x%08lx, IRQ %d\n",
cp->name, card->ba0_addr, card->ba1_addr, card->irq);
}
-
- if(card->amplifier_ctrl==NULL)
+
+ if (card->amplifier_ctrl==NULL)
{
- printk(KERN_ERR "cs461x: Unsupported configuration due to lack of documentation.\n");
- kfree(card);
- return -EINVAL;
- }
-
- if(external_amp == 1)
+ card->amplifier_ctrl = amp_none;
+ card->active_ctrl = clkrun_hack;
+ }
+
+ if (external_amp == 1)
{
printk(KERN_INFO "cs461x: Crystal EAPD support forced on.\n");
card->amplifier_ctrl = amp_voyetra;
}
- if(thinkpad == 1)
+ if (thinkpad == 1)
{
card->active_ctrl = clkrun_hack;
printk(KERN_INFO "cs461x: Activating CLKRUN hack for Thinkpad.\n");
}
-
+
card->active_ctrl(card, 1);
-
+
/* claim our iospace and irq */
card->ba0 = ioremap(card->ba0_addr, CS461X_BA0_SIZE);
@@ -2578,6 +4087,13 @@ static int __init cs_install(struct pci_dev *pci_dev)
card->ba1.name.pmem = ioremap(card->ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE);
card->ba1.name.reg = ioremap(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
+ CS_DBGOUT(CS_INIT, 4, printk("card->ba0=0x%.08x\n",(unsigned)card->ba0) );
+ CS_DBGOUT(CS_INIT, 4, printk("card->ba1=0x%.08x 0x%.08x 0x%.08x 0x%.08x\n",
+ (unsigned)card->ba1.name.data0,
+ (unsigned)card->ba1.name.data1,
+ (unsigned)card->ba1.name.pmem,
+ (unsigned)card->ba1.name.reg) );
+
if(card->ba0 == 0 || card->ba1.name.data0 == 0 ||
card->ba1.name.data1 == 0 || card->ba1.name.pmem == 0 ||
card->ba1.name.reg == 0)
@@ -2593,17 +4109,34 @@ static int __init cs_install(struct pci_dev *pci_dev)
goto fail;
}
- if (cs_hardware_init(card)<0)
- {
- unregister_sound_dsp(card->dev_audio);
- goto fail;
- }
- card->next = devs;
- devs = card;
-
- card->active_ctrl(card, -1);
- return 0;
-
+ /* register /dev/midi */
+ if((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0)
+ printk(KERN_ERR "cs461x: unable to register midi\n");
+
+ if (cs_hardware_init(card)<0)
+ {
+ unregister_sound_dsp(card->dev_audio);
+ if(card->dev_midi)
+ unregister_sound_midi(card->dev_midi);
+ goto fail;
+ }
+ init_waitqueue_head(&card->midi.open_wait);
+ init_MUTEX(&card->midi.open_sem);
+ init_waitqueue_head(&card->midi.iwait);
+ init_waitqueue_head(&card->midi.owait);
+ card->next = devs;
+ devs = card;
+ cs461x_pokeBA0(card, BA0_MIDCR, MIDCR_MRST);
+ cs461x_pokeBA0(card, BA0_MIDCR, 0);
+
+ card->active_ctrl(card, -1);
+#ifdef CS46XX_PM
+ pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), cs46xx_pm_callback);
+ if (pmdev)
+ pmdev->data = card;
+#endif
+ return 0;
+
fail:
free_irq(card->irq, card);
fail2:
@@ -2628,7 +4161,7 @@ static void cs_remove(struct cs_card *card)
unsigned int tmp;
card->active_ctrl(card,1);
-
+
tmp = cs461x_peek(card, BA1_PFIE);
tmp &= ~0x0000f03f;
tmp |= 0x00000010;
@@ -2693,10 +4226,12 @@ static void cs_remove(struct cs_card *card)
kfree (card->ac97_codec[i]);
}
unregister_sound_dsp(card->dev_audio);
+ if(card->dev_midi)
+ unregister_sound_midi(card->dev_midi);
kfree(card);
}
-MODULE_AUTHOR("Alan Cox <alan@redhat.com>, Jaroslav Kysela");
+MODULE_AUTHOR("Alan Cox <alan@redhat.com>, Jaroslav Kysela, <audio@crystal.cirrus.com>");
MODULE_DESCRIPTION("Crystal SoundFusion Audio Support");
int __init cs_probe(void)
@@ -2728,18 +4263,19 @@ int __init cs_probe(void)
return foundone;
}
-#ifdef MODULE
-
-int init_module(void)
+int __init init_module(void)
{
if(cs_probe()==0)
printk(KERN_ERR "cs461x: No devices found.\n");
return 0;
}
-void cleanup_module (void)
+void __exit cleanup_module (void)
{
struct cs_card *next;
+#ifdef CS46XX_PM
+ pm_unregister_all(cs46xx_pm_callback);
+#endif
while(devs)
{
next=devs->next;
@@ -2750,5 +4286,3 @@ void cleanup_module (void)
MODULE_PARM(external_amp, "i");
MODULE_PARM(thinkpad, "i");
-
-#endif
diff --git a/drivers/sound/dmasound/dmasound_atari.c b/drivers/sound/dmasound/dmasound_atari.c
index faf00d798..0845ecd52 100644
--- a/drivers/sound/dmasound/dmasound_atari.c
+++ b/drivers/sound/dmasound/dmasound_atari.c
@@ -816,7 +816,7 @@ static void AtaRelease(void)
static void *AtaAlloc(unsigned int size, int flags)
{
- return atari_stram_alloc( size, NULL, "dmasound" );
+ return atari_stram_alloc(size, "dmasound");
}
static void AtaFree(void *obj, unsigned int size)
diff --git a/drivers/sound/dmasound/dmasound_paula.c b/drivers/sound/dmasound/dmasound_paula.c
index 18f6be2d0..d76c07937 100644
--- a/drivers/sound/dmasound/dmasound_paula.c
+++ b/drivers/sound/dmasound/dmasound_paula.c
@@ -27,8 +27,6 @@
/*
* The minimum period for audio depends on htotal (for OCS/ECS/AGA)
* (Imported from arch/m68k/amiga/amisound.c)
- *
- * FIXME: if amifb is not used, there should be a method to change htotal
*/
extern volatile u_short amiga_audio_min_period;
diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c
index 699e79677..9da701604 100644
--- a/drivers/sound/es1370.c
+++ b/drivers/sound/es1370.c
@@ -116,6 +116,7 @@
* 08.01.2000 0.32 Prevent some ioctl's from returning bad count values on underrun/overrun;
* Tim Janik's BSE (Bedevilled Sound Engine) found this
* 07.02.2000 0.33 Use pci_alloc_consistent and pci_register_driver
+ * 21.11.2000 0.34 Initialize dma buffers in poll, otherwise poll may return a bogus mask
*
* some important things missing in Ensoniq documentation:
*
@@ -1280,10 +1281,16 @@ static unsigned int es1370_poll(struct file *file, struct poll_table_struct *wai
unsigned int mask = 0;
VALIDATE_STATE(s);
- if (file->f_mode & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE) {
+ if (!s->dma_dac2.ready && prog_dmabuf_dac2(s))
+ return 0;
poll_wait(file, &s->dma_dac2.wait, wait);
- if (file->f_mode & FMODE_READ)
+ }
+ if (file->f_mode & FMODE_READ) {
+ if (!s->dma_adc.ready && prog_dmabuf_adc(s))
+ return 0;
poll_wait(file, &s->dma_adc.wait, wait);
+ }
spin_lock_irqsave(&s->lock, flags);
es1370_update_ptr(s);
if (file->f_mode & FMODE_READ) {
@@ -1855,6 +1862,8 @@ static unsigned int es1370_poll_dac(struct file *file, struct poll_table_struct
unsigned int mask = 0;
VALIDATE_STATE(s);
+ if (!s->dma_dac1.ready && prog_dmabuf_dac1(s))
+ return 0;
poll_wait(file, &s->dma_dac1.wait, wait);
spin_lock_irqsave(&s->lock, flags);
es1370_update_ptr(s);
@@ -2655,7 +2664,7 @@ static int __init init_es1370(void)
{
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1370: version v0.33 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.34 time " __TIME__ " " __DATE__ "\n");
return pci_module_init(&es1370_driver);
}
diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c
index ac420b390..6c5253550 100644
--- a/drivers/sound/es1371.c
+++ b/drivers/sound/es1371.c
@@ -101,6 +101,7 @@
* 07.02.2000 0.25 Use ac97_codec
* 01.03.2000 0.26 SPDIF patch by Mikael Bouillot <mikael.bouillot@bigfoot.com>
* Use pci_module_init
+ * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask
*/
/*****************************************************************************/
@@ -1463,10 +1464,16 @@ static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wai
unsigned int mask = 0;
VALIDATE_STATE(s);
- if (file->f_mode & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE) {
+ if (!s->dma_dac2.ready && prog_dmabuf_dac2(s))
+ return 0;
poll_wait(file, &s->dma_dac2.wait, wait);
- if (file->f_mode & FMODE_READ)
+ }
+ if (file->f_mode & FMODE_READ) {
+ if (!s->dma_adc.ready && prog_dmabuf_adc(s))
+ return 0;
poll_wait(file, &s->dma_adc.wait, wait);
+ }
spin_lock_irqsave(&s->lock, flags);
es1371_update_ptr(s);
if (file->f_mode & FMODE_READ) {
@@ -2035,6 +2042,8 @@ static unsigned int es1371_poll_dac(struct file *file, struct poll_table_struct
unsigned int mask = 0;
VALIDATE_STATE(s);
+ if (!s->dma_dac1.ready && prog_dmabuf_dac1(s))
+ return 0;
poll_wait(file, &s->dma_dac1.wait, wait);
spin_lock_irqsave(&s->lock, flags);
es1371_update_ptr(s);
@@ -2927,7 +2936,7 @@ static int __init init_es1371(void)
{
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO PFX "version v0.26 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO PFX "version v0.27 time " __TIME__ " " __DATE__ "\n");
return pci_module_init(&es1371_driver);
}
diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c
index 548ee0949..c06c57633 100644
--- a/drivers/sound/esssolo1.c
+++ b/drivers/sound/esssolo1.c
@@ -69,6 +69,7 @@
* 07.02.2000 0.13 Use pci_alloc_consistent and pci_register_driver
* 19.02.2000 0.14 Use pci_dma_supported to determine if recording should be disabled
* 13.03.2000 0.15 Reintroduce initialization of a couple of PCI config space registers
+ * 21.11.2000 0.16 Initialize dma buffers in poll, otherwise poll may return a bogus mask
*/
/*****************************************************************************/
@@ -1168,10 +1169,16 @@ static unsigned int solo1_poll(struct file *file, struct poll_table_struct *wait
unsigned int mask = 0;
VALIDATE_STATE(s);
- if (file->f_mode & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE) {
+ if (!s->dma_dac.ready && prog_dmabuf_dac(s))
+ return 0;
poll_wait(file, &s->dma_dac.wait, wait);
- if (file->f_mode & FMODE_READ)
+ }
+ if (file->f_mode & FMODE_READ) {
+ if (!s->dma_adc.ready && prog_dmabuf_adc(s))
+ return 0;
poll_wait(file, &s->dma_adc.wait, wait);
+ }
spin_lock_irqsave(&s->lock, flags);
solo1_update_ptr(s);
if (file->f_mode & FMODE_READ) {
@@ -2384,7 +2391,7 @@ static int __init init_solo1(void)
{
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "solo1: version v0.15 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "solo1: version v0.16 time " __TIME__ " " __DATE__ "\n");
if (!pci_register_driver(&solo1_driver)) {
pci_unregister_driver(&solo1_driver);
return -ENODEV;
diff --git a/drivers/sound/maestro.c b/drivers/sound/maestro.c
index ca96b7f99..7529c1db3 100644
--- a/drivers/sound/maestro.c
+++ b/drivers/sound/maestro.c
@@ -115,6 +115,8 @@
* themselves, but we'll see.
*
* History
+ * (still kind of v0.14) Nov 23 - Alan Cox <alan@redhat.com>
+ * Add clocking= for people with seriously warped hardware
* (still v0.14) Nov 10 2000 - Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
* add __init to maestro_ac97_init() and maestro_install()
* (still based on v0.14) Mar 29 2000 - Zach Brown <zab@redhat.com>
@@ -262,6 +264,10 @@ static int debug=0;
static int dsps_order=0;
/* wether or not we mess around with power management */
static int use_pm=2; /* set to 1 for force */
+/* clocking for broken hardware - a few laptops seem to use a 50Khz clock
+ ie insmod with clocking=50000 or so */
+
+static int clocking=48000;
/* --------------------------------------------------------------------- */
#define DRIVER_VERSION "0.14"
@@ -1200,7 +1206,10 @@ static u32 compute_rate(struct ess_state *s, u32 freq)
{
u32 clock = clock_freq[s->card->card_type];
- if (freq == 48000) return 0x10000;
+ freq = (freq * clocking)/48000;
+
+ if (freq == 48000)
+ return 0x10000;
return ((freq / clock) <<16 )+
(((freq % clock) << 16) / clock);
@@ -1958,6 +1967,7 @@ mixer_push_state(struct ess_card *card)
static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long arg)
{
int i, val=0;
+ unsigned long flags;
VALIDATE_CARD(card);
if (cmd == SOUND_MIXER_INFO) {
@@ -1990,9 +2000,9 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long ar
if(!card->mix.recmask_io) {
val = 0;
} else {
- spin_lock(&card->lock);
+ spin_lock_irqsave(&card->lock, flags);
val = card->mix.recmask_io(card,1,0);
- spin_unlock(&card->lock);
+ spin_unlock_irqrestore(&card->lock, flags);
}
break;
@@ -2019,9 +2029,9 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long ar
return -EINVAL;
/* do we ever want to touch the hardware? */
-/* spin_lock(&card->lock);
+/* spin_lock_irqsave(&card->lock, flags);
val = card->mix.read_mixer(card,i);
- spin_unlock(&card->lock);*/
+ spin_unlock_irqrestore(&card->lock, flags);*/
val = card->mix.mixer_state[i];
/* M_printk("returned 0x%x for mixer %d\n",val,i);*/
@@ -2046,9 +2056,9 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long ar
if(!val) return 0;
if(! (val &= card->mix.record_sources)) return -EINVAL;
- spin_lock(&card->lock);
+ spin_lock_irqsave(&card->lock, flags);
card->mix.recmask_io(card,0,val);
- spin_unlock(&card->lock);
+ spin_unlock_irqrestore(&card->lock, flags);
return 0;
default:
@@ -2057,9 +2067,9 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long ar
if ( ! supported_mixer(card,i))
return -EINVAL;
- spin_lock(&card->lock);
+ spin_lock_irqsave(&card->lock, flags);
set_mixer(card,i,val);
- spin_unlock(&card->lock);
+ spin_unlock_irqrestore(&card->lock, flags);
return 0;
}
@@ -3392,6 +3402,19 @@ maestro_install(struct pci_dev *pcidev, int card_type)
ess = &card->channels[0];
+ if (pci_enable_device(pcidev)) {
+ printk (KERN_ERR "maestro: pci_enable_device() failed\n");
+ for (i = 0; i < NR_DSPS; i++) {
+ struct ess_state *s = &card->channels[i];
+ if (s->dev_audio != -1)
+ unregister_sound_dsp(s->dev_audio);
+ }
+ release_region(card->iobase, 256);
+ unregister_reboot_notifier(&maestro_nb);
+ kfree(card);
+ return 0;
+ }
+
/*
* Ok card ready. Begin setup proper
*/
@@ -3564,6 +3587,7 @@ MODULE_PARM(debug,"i");
#endif
MODULE_PARM(dsps_order,"i");
MODULE_PARM(use_pm,"i");
+MODULE_PARM(clocking, "i");
void cleanup_module(void) {
M_printk("maestro: unloading\n");
diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c
index 8727e2a88..14f11dcaf 100644
--- a/drivers/sound/sonicvibes.c
+++ b/drivers/sound/sonicvibes.c
@@ -87,6 +87,7 @@
* Tim Janik's BSE (Bedevilled Sound Engine) found this
* use Martin Mares' pci_assign_resource
* 07.02.2000 0.26 Use pci_alloc_consistent and pci_register_driver
+ * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask
*
*/
@@ -1484,10 +1485,16 @@ static unsigned int sv_poll(struct file *file, struct poll_table_struct *wait)
unsigned int mask = 0;
VALIDATE_STATE(s);
- if (file->f_mode & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE) {
+ if (!s->dma_dac.ready && prog_dmabuf(s, 1))
+ return 0;
poll_wait(file, &s->dma_dac.wait, wait);
- if (file->f_mode & FMODE_READ)
+ }
+ if (file->f_mode & FMODE_READ) {
+ if (!s->dma_adc.ready && prog_dmabuf(s, 0))
+ return 0;
poll_wait(file, &s->dma_adc.wait, wait);
+ }
spin_lock_irqsave(&s->lock, flags);
sv_update_ptr(s);
if (file->f_mode & FMODE_READ) {
@@ -2666,7 +2673,7 @@ static int __init init_sonicvibes(void)
{
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "sv: version v0.26 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "sv: version v0.27 time " __TIME__ " " __DATE__ "\n");
#if 0
if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c
index 50a045c1c..d266b1353 100644
--- a/drivers/sound/sound_core.c
+++ b/drivers/sound/sound_core.c
@@ -454,11 +454,8 @@ static int soundcore_open(struct inode *, struct file *);
static struct file_operations soundcore_fops=
{
-/* owner: THIS_MODULE, * this is a bug: if we have an owner, the kernel
- generates a MOD_INC_USE_COUNT - thus
- the module cannot be unloaded since the device
- is never released here ! - solution: owner
- has to be NULL. Patch by Peter Wahl <Peter.Wahl@epost.de> */
+ /* We must have an owner or the module locking fails */
+ owner: THIS_MODULE,
open: soundcore_open,
};
diff --git a/drivers/sound/vwsnd.c b/drivers/sound/vwsnd.c
index b79ce2b32..4db994a45 100644
--- a/drivers/sound/vwsnd.c
+++ b/drivers/sound/vwsnd.c
@@ -144,6 +144,8 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
#include <linux/stddef.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
diff --git a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c
new file mode 100644
index 000000000..a8cdc58f2
--- /dev/null
+++ b/drivers/sound/ymfpci.c
@@ -0,0 +1,2385 @@
+/*
+ * Copyright 1999 Jaroslav Kysela <perex@suse.cz>
+ * Copyright 2000 Alan Cox <alan@redhat.com>
+ *
+ * Yamaha YMF7xx driver.
+ *
+ * This code is a result of high-speed collision
+ * between ymfpci.c of ALSA and cs46xx.c of Linux.
+ * -- Pete Zaitcev <zaitcev@metabyte.com>; 2000/09/18
+ *
+ * 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.
+ *
+ * TODO:
+ * - Use P44Slot for 44.1 playback.
+ * - Capture and duplex
+ * - 96KHz playback for DVD - use pitch of 2.0.
+ * - uLaw for Sun apps.
+ * - Retain DMA buffer on close, do not wait the end of frame.
+ * - Cleanup
+ * ? merge ymf_pcm and state
+ * ? pcm interrupt no pointer
+ * ? underused structure members
+ * - Remove remaining P3 tags (debug messages).
+ * - Resolve XXX tagged questions.
+ * - Cannot play 5133Hz.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+#include <linux/poll.h>
+#include <linux/ac97_codec.h>
+#include <linux/sound.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+#include "ymfpci.h"
+
+#define snd_magic_cast(t, p, err) ((t *)(p))
+
+/* Channels, such as play and record. I do only play a.t.m. XXX */
+#define NR_HW_CH 1
+
+static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd);
+static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type,
+ int pair, ymfpci_voice_t **rvoice);
+static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice);
+static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state);
+static int ymf_state_alloc(ymfpci_t *unit, int nvirt);
+
+static LIST_HEAD(ymf_devs);
+
+/*
+ * constants
+ */
+
+static struct pci_device_id ymf_id_tbl[] __devinitdata = {
+#define DEV(v, d, data) \
+ { PCI_VENDOR_ID_##v, PCI_DEVICE_ID_##v##_##d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)data }
+ DEV (YAMAHA, 724, "YMF724"),
+ DEV (YAMAHA, 724F, "YMF724F"),
+ DEV (YAMAHA, 740, "YMF740"),
+ DEV (YAMAHA, 740C, "YMF740C"),
+ DEV (YAMAHA, 744, "YMF744"),
+ DEV (YAMAHA, 754, "YMF754"),
+#undef DEV
+ { }
+};
+MODULE_DEVICE_TABLE(pci, ymf_id_tbl);
+
+/*
+ * Mindlessly copied from cs46xx XXX
+ */
+extern __inline__ unsigned ld2(unsigned int x)
+{
+ unsigned r = 0;
+
+ if (x >= 0x10000) {
+ x >>= 16;
+ r += 16;
+ }
+ if (x >= 0x100) {
+ x >>= 8;
+ r += 8;
+ }
+ if (x >= 0x10) {
+ x >>= 4;
+ r += 4;
+ }
+ if (x >= 4) {
+ x >>= 2;
+ r += 2;
+ }
+ if (x >= 2)
+ r++;
+ return r;
+}
+
+/*
+ * common I/O routines
+ */
+
+static inline u8 ymfpci_readb(ymfpci_t *codec, u32 offset)
+{
+ return readb(codec->reg_area_virt + offset);
+}
+
+static inline void ymfpci_writeb(ymfpci_t *codec, u32 offset, u8 val)
+{
+ writeb(val, codec->reg_area_virt + offset);
+}
+
+static inline u16 ymfpci_readw(ymfpci_t *codec, u32 offset)
+{
+ return readw(codec->reg_area_virt + offset);
+}
+
+static inline void ymfpci_writew(ymfpci_t *codec, u32 offset, u16 val)
+{
+ writew(val, codec->reg_area_virt + offset);
+}
+
+static inline u32 ymfpci_readl(ymfpci_t *codec, u32 offset)
+{
+ return readl(codec->reg_area_virt + offset);
+}
+
+static inline void ymfpci_writel(ymfpci_t *codec, u32 offset, u32 val)
+{
+ writel(val, codec->reg_area_virt + offset);
+}
+
+static int ymfpci_codec_ready(ymfpci_t *codec, int secondary, int sched)
+{
+ signed long end_time;
+ u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
+
+ end_time = jiffies + 3 * (HZ / 4);
+ do {
+ if ((ymfpci_readw(codec, reg) & 0x8000) == 0)
+ return 0;
+ if (sched) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+ } while (end_time - (signed long)jiffies >= 0);
+ printk("ymfpci_codec_ready: codec %i is not ready [0x%x]\n",
+ secondary, ymfpci_readw(codec, reg));
+ return -EBUSY;
+}
+
+static void ymfpci_codec_write(struct ac97_codec *dev, u8 reg, u16 val)
+{
+ ymfpci_t *codec = dev->private_data;
+ u32 cmd;
+
+ /* XXX Do make use of dev->id */
+ ymfpci_codec_ready(codec, 0, 0);
+ cmd = ((YDSXG_AC97WRITECMD | reg) << 16) | val;
+ ymfpci_writel(codec, YDSXGR_AC97CMDDATA, cmd);
+}
+
+static u16 ymfpci_codec_read(struct ac97_codec *dev, u8 reg)
+{
+ ymfpci_t *codec = dev->private_data;
+
+ if (ymfpci_codec_ready(codec, 0, 0))
+ return ~0;
+ ymfpci_writew(codec, YDSXGR_AC97CMDADR, YDSXG_AC97READCMD | reg);
+ if (ymfpci_codec_ready(codec, 0, 0))
+ return ~0;
+ if (codec->pci->device == PCI_DEVICE_ID_YAMAHA_744 && codec->rev < 2) {
+ int i;
+ for (i = 0; i < 600; i++)
+ ymfpci_readw(codec, YDSXGR_PRISTATUSDATA);
+ }
+ return ymfpci_readw(codec, YDSXGR_PRISTATUSDATA);
+}
+
+/*
+ * Misc routines
+ */
+
+/*
+ * Calculate the actual sampling rate relatetively to the base clock (48kHz).
+ */
+static u32 ymfpci_calc_delta(u32 rate)
+{
+ switch (rate) {
+ case 8000: return 0x02aaab00;
+ case 11025: return 0x03accd00;
+ case 16000: return 0x05555500;
+ case 22050: return 0x07599a00;
+ case 32000: return 0x0aaaab00;
+ case 44100: return 0x0eb33300;
+ default: return ((rate << 16) / 48000) << 12;
+ }
+}
+
+static u32 def_rate[8] = {
+ 100, 2000, 8000, 11025, 16000, 22050, 32000, 48000
+};
+
+static u32 ymfpci_calc_lpfK(u32 rate)
+{
+ u32 i;
+ static u32 val[8] = {
+ 0x00570000, 0x06AA0000, 0x18B20000, 0x20930000,
+ 0x2B9A0000, 0x35A10000, 0x3EAA0000, 0x40000000
+ };
+
+ if (rate == 44100)
+ return 0x40000000; /* FIXME: What's the right value? */
+ for (i = 0; i < 8; i++)
+ if (rate <= def_rate[i])
+ return val[i];
+ return val[0];
+}
+
+static u32 ymfpci_calc_lpfQ(u32 rate)
+{
+ u32 i;
+ static u32 val[8] = {
+ 0x35280000, 0x34A70000, 0x32020000, 0x31770000,
+ 0x31390000, 0x31C90000, 0x33D00000, 0x40000000
+ };
+
+ if (rate == 44100)
+ return 0x370A0000;
+ for (i = 0; i < 8; i++)
+ if (rate <= def_rate[i])
+ return val[i];
+ return val[0];
+}
+
+static u32 ymf_calc_lend(u32 rate)
+{
+ return (rate * YMF_SAMPF) / 48000;
+}
+
+/*
+ * XXX Find if this function exists in the OSS framework.
+ * XXX Make sure we do no panic when ADPCM is selected.
+ */
+static int ymf_pcm_format_width(int format)
+{
+ static int mask16 = AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE;
+
+ if ((format & (format-1)) != 0) {
+ printk(KERN_ERR "ymfpci: format 0x%x is not a power of 2\n", format);
+ return 8;
+ }
+
+ if (format == AFMT_IMA_ADPCM) return 4;
+ if ((format & mask16) != 0) return 16;
+ return 8;
+}
+
+static void ymf_pcm_update_shift(struct ymf_pcm_format *f)
+{
+ f->shift = 0;
+ if (f->voices == 2)
+ f->shift++;
+ if (ymf_pcm_format_width(f->format) == 16)
+ f->shift++;
+}
+
+/*
+ * Whole OSS-style DMA machinery is taken from cs46xx.
+ */
+
+/* Are you sure 32K is not too much? See if mpg123 skips on loaded systems. */
+#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
+#define DMABUF_MINORDER 1
+
+/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
+static int alloc_dmabuf(struct ymf_state *state)
+{
+ struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ void *rawbuf = NULL;
+ int order;
+ struct page * map, * mapend;
+
+ /* alloc as big a chunk as we can */
+ for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
+ if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order)))
+ break;
+
+ if (!rawbuf)
+ return -ENOMEM;
+
+#if 0
+ printk(KERN_DEBUG "ymfpci: allocated %ld (order = %d) bytes at %p\n",
+ PAGE_SIZE << order, order, rawbuf);
+#endif
+
+ dmabuf->ready = dmabuf->mapped = 0;
+ dmabuf->rawbuf = rawbuf;
+ dmabuf->buforder = order;
+
+ /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
+ mapend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
+ for (map = virt_to_page(rawbuf); map <= mapend; map++)
+ set_bit(PG_reserved, &map->flags);
+
+ return 0;
+}
+
+/* free DMA buffer */
+static void dealloc_dmabuf(struct ymf_state *state)
+{
+ struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ struct page *map, *mapend;
+
+ if (dmabuf->rawbuf) {
+ /* undo marking the pages as reserved */
+ mapend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
+ for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
+ clear_bit(PG_reserved, &map->flags);
+ free_pages((unsigned long)dmabuf->rawbuf,dmabuf->buforder);
+ }
+ dmabuf->rawbuf = NULL;
+ dmabuf->mapped = dmabuf->ready = 0;
+}
+
+static int prog_dmabuf(struct ymf_state *state, unsigned rec)
+{
+ struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ int w_16;
+ unsigned bytepersec;
+ unsigned bufsize;
+ unsigned long flags;
+ int redzone;
+ int ret;
+
+ w_16 = ymf_pcm_format_width(state->format.format) == 16;
+
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->hwptr = dmabuf->swptr = 0;
+ dmabuf->total_bytes = 0;
+ dmabuf->count = dmabuf->error = 0;
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+
+ /* allocate DMA buffer if not allocated yet */
+ if (!dmabuf->rawbuf)
+ if ((ret = alloc_dmabuf(state)))
+ return ret;
+
+ bytepersec = state->format.rate << state->format.shift;
+
+ /*
+ * Create fake fragment sizes and numbers for OSS ioctls.
+ */
+ bufsize = PAGE_SIZE << dmabuf->buforder;
+ if (dmabuf->ossfragshift) {
+ if ((1000 << dmabuf->ossfragshift) < bytepersec)
+ dmabuf->fragshift = ld2(bytepersec/1000);
+ else
+ dmabuf->fragshift = dmabuf->ossfragshift;
+ } else {
+ /* lets hand out reasonable big ass buffers by default */
+ dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT -2);
+ }
+ dmabuf->numfrag = bufsize >> dmabuf->fragshift;
+ while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) {
+ dmabuf->fragshift--;
+ dmabuf->numfrag = bufsize >> dmabuf->fragshift;
+ }
+ dmabuf->fragsize = 1 << dmabuf->fragshift;
+ dmabuf->fragsamples = dmabuf->fragsize >> state->format.shift;
+ dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
+
+ /*
+ * Import what Doom might have set with SNDCTL_DSD_SETFRAGMENT.
+ */
+ if (dmabuf->ossmaxfrags >= 2 && dmabuf->ossmaxfrags < dmabuf->numfrag) {
+ dmabuf->numfrag = dmabuf->ossmaxfrags;
+ dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
+
+ redzone = ymf_calc_lend(state->format.rate);
+ redzone <<= (state->format.shift + 1);
+ if (dmabuf->dmasize < redzone*3) {
+ /*
+ * The driver works correctly with minimum dmasize
+ * of redzone*2, but it produces stoppage and clicks.
+ * So, make it little larger for smoother sound.
+ * XXX Make dmasize a wholy divisible by fragsize.
+ */
+// printk(KERN_ERR "ymfpci: dmasize=%d < redzone=%d * 3\n",
+// dmabuf->dmasize, redzone);
+ dmabuf->dmasize = redzone*3;
+ }
+ }
+
+ memset(dmabuf->rawbuf, w_16 ? 0 : 0x80, dmabuf->dmasize);
+
+ /*
+ * Now set up the ring
+ */
+
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (rec) {
+ /* ymf_rec_setup(state); */
+ } else {
+ if ((ret = ymf_playback_prepare(state->unit, state)) != 0) {
+ return ret;
+ }
+ }
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+
+ /* set the ready flag for the dma buffer (this comment is not stupid) */
+ dmabuf->ready = 1;
+
+#if 0
+ printk("prog_dmabuf: rate %d format 0x%x,"
+ " numfrag %d fragsize %d dmasize %d\n",
+ state->format.rate, state->format.format, dmabuf->numfrag,
+ dmabuf->fragsize, dmabuf->dmasize);
+#endif
+
+ return 0;
+}
+
+static void ymf_start_dac(struct ymf_state *state)
+{
+ ymf_playback_trigger(state->unit, &state->ypcm, 1);
+}
+
+/*
+ * Wait until output is drained.
+ * This does not kill the hardware for the sake of ioctls.
+ */
+static void ymf_wait_dac(struct ymf_state *state)
+{
+ struct ymf_unit *unit = state->unit;
+ ymfpci_pcm_t *ypcm = &state->ypcm;
+ DECLARE_WAITQUEUE(waita, current);
+ unsigned long flags;
+
+ add_wait_queue(&state->dmabuf.wait, &waita);
+
+ spin_lock_irqsave(&unit->reg_lock, flags);
+ if (state->dmabuf.count != 0 && !state->ypcm.running) {
+ ymf_playback_trigger(unit, ypcm, 1);
+ }
+
+#if 0
+ if (file->f_flags & O_NONBLOCK) {
+ /*
+ * XXX Our mistake is to attach DMA buffer to state
+ * rather than to some per-device structure.
+ * Cannot skip waiting, can only make it shorter.
+ */
+ }
+#endif
+
+ while (ypcm->running) {
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule();
+ spin_lock_irqsave(&unit->reg_lock, flags);
+ }
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&state->dmabuf.wait, &waita);
+
+ /*
+ * This function may take up to 4 seconds to reach this point
+ * (32K circular buffer, 8000 Hz). User notices.
+ */
+}
+
+/*
+ * Hardware start management
+ */
+
+static void ymfpci_hw_start(ymfpci_t *codec)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&codec->reg_lock, flags);
+ if (codec->start_count++ == 0) {
+ ymfpci_writel(codec, YDSXGR_MODE, 3);
+ codec->active_bank = ymfpci_readl(codec, YDSXGR_CTRLSELECT) & 1;
+ }
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+}
+
+static void ymfpci_hw_stop(ymfpci_t *codec)
+{
+ unsigned long flags;
+ long timeout = 1000;
+
+ spin_lock_irqsave(&codec->reg_lock, flags);
+ if (--codec->start_count == 0) {
+ ymfpci_writel(codec, YDSXGR_MODE, 0);
+ while (timeout-- > 0) {
+ if ((ymfpci_readl(codec, YDSXGR_STATUS) & 2) == 0)
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+}
+
+/*
+ * Playback voice management
+ */
+
+static int voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice)
+{
+ ymfpci_voice_t *voice, *voice2;
+ int idx;
+
+ *rvoice = NULL;
+ for (idx = 0; idx < 64; idx += pair ? 2 : 1) {
+ voice = &codec->voices[idx];
+ voice2 = pair ? &codec->voices[idx+1] : NULL;
+ if (voice->use || (voice2 && voice2->use))
+ continue;
+ voice->use = 1;
+ if (voice2)
+ voice2->use = 1;
+ switch (type) {
+ case YMFPCI_PCM:
+ voice->pcm = 1;
+ if (voice2)
+ voice2->pcm = 1;
+ break;
+ case YMFPCI_SYNTH:
+ voice->synth = 1;
+ break;
+ case YMFPCI_MIDI:
+ voice->midi = 1;
+ break;
+ }
+ ymfpci_hw_start(codec);
+ if (voice2)
+ ymfpci_hw_start(codec);
+ *rvoice = voice;
+ return 0;
+ }
+ return -ENOMEM;
+}
+
+static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type,
+ int pair, ymfpci_voice_t **rvoice)
+{
+ unsigned long flags;
+ int result;
+
+ spin_lock_irqsave(&codec->voice_lock, flags);
+ for (;;) {
+ result = voice_alloc(codec, type, pair, rvoice);
+ if (result == 0 || type != YMFPCI_PCM)
+ break;
+ /* TODO: synth/midi voice deallocation */
+ break;
+ }
+ spin_unlock_irqrestore(&codec->voice_lock, flags);
+ return result;
+}
+
+static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice)
+{
+ unsigned long flags;
+
+ ymfpci_hw_stop(codec);
+ spin_lock_irqsave(&codec->voice_lock, flags);
+ pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
+ pvoice->ypcm = NULL;
+ pvoice->interrupt = NULL;
+ spin_unlock_irqrestore(&codec->voice_lock, flags);
+ return 0;
+}
+
+/*
+ * PCM part
+ */
+
+static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
+{
+ ymfpci_pcm_t *ypcm;
+ int redzone;
+ int pos, delta, swptr;
+ int played, distance;
+ struct ymf_state *state;
+ struct ymf_dmabuf *dmabuf;
+ char silence;
+
+ if ((ypcm = voice->ypcm) == NULL) {
+ return;
+ }
+ if ((state = ypcm->state) == NULL) {
+ ypcm->running = 0; // lock it
+ return;
+ }
+ dmabuf = &state->dmabuf;
+ spin_lock(&codec->reg_lock);
+ if (ypcm->running) {
+/* P3 */ /** printk("ymfpci: %d, intr bank %d count %d start 0x%x:%x\n",
+ voice->number, codec->active_bank, dmabuf->count,
+ voice->bank[0].start, voice->bank[1].start); **/
+ silence = (ymf_pcm_format_width(state->format.format) == 16) ?
+ 0 : 0x80;
+ /* We need actual left-hand-side redzone size here. */
+ redzone = ymf_calc_lend(state->format.rate);
+ redzone <<= (state->format.shift + 1);
+ swptr = dmabuf->swptr;
+
+ pos = voice->bank[codec->active_bank].start;
+ pos <<= state->format.shift;
+ if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */
+ printk(KERN_ERR
+ "ymfpci%d: %d: runaway: hwptr %d dmasize %d\n",
+ codec->dev_audio, voice->number,
+ dmabuf->hwptr, dmabuf->dmasize);
+ pos = 0;
+ }
+ if (pos < dmabuf->hwptr) {
+ delta = dmabuf->dmasize - dmabuf->hwptr;
+ memset(dmabuf->rawbuf + dmabuf->hwptr, silence, delta);
+ delta += pos;
+ memset(dmabuf->rawbuf, silence, pos);
+ } else {
+ delta = pos - dmabuf->hwptr;
+ memset(dmabuf->rawbuf + dmabuf->hwptr, silence, delta);
+ }
+ dmabuf->hwptr = pos;
+
+ if (dmabuf->count == 0) {
+ printk("ymfpci%d: %d: strain: hwptr %d\n",
+ codec->dev_audio, voice->number, dmabuf->hwptr);
+ ymf_playback_trigger(codec, ypcm, 0);
+ }
+
+ if (swptr <= pos) {
+ distance = pos - swptr;
+ } else {
+ distance = dmabuf->dmasize - (swptr - pos);
+ }
+ if (distance < redzone) {
+ /*
+ * hwptr inside redzone => DMA ran out of samples.
+ */
+ if (delta < dmabuf->count) {
+ /*
+ * Lost interrupt or other screwage.
+ */
+ printk("ymfpci%d: %d: lost: delta %d"
+ " hwptr %d swptr %d distance %d count %d\n",
+ codec->dev_audio, voice->number, delta,
+ dmabuf->hwptr, swptr, distance, dmabuf->count);
+ } else {
+ /*
+ * Normal end of DMA.
+ */
+// printk("ymfpci%d: %d: done: delta %d"
+// " hwptr %d swptr %d distance %d count %d\n",
+// codec->dev_audio, voice->number, delta,
+// dmabuf->hwptr, swptr, distance, dmabuf->count);
+ }
+ played = dmabuf->count;
+ if (ypcm->running) {
+ ymf_playback_trigger(codec, ypcm, 0);
+ }
+ } else {
+ /*
+ * hwptr is chipping away towards a remote swptr.
+ * Calculate other distance and apply it to count.
+ */
+ if (swptr >= pos) {
+ distance = swptr - pos;
+ } else {
+ distance = dmabuf->dmasize - (pos - swptr);
+ }
+ if (distance < dmabuf->count) {
+ played = dmabuf->count - distance;
+ } else {
+ played = 0;
+ }
+ }
+
+ dmabuf->total_bytes += played;
+ dmabuf->count -= played;
+ if (dmabuf->count < dmabuf->dmasize / 2) {
+ wake_up(&dmabuf->wait);
+ }
+ }
+ spin_unlock(&codec->reg_lock);
+}
+
+#if HAVE_RECORD
+static void ymfpci_pcm_capture_interrupt(snd_pcm_subchn_t *substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, );
+ ymfpci_t *codec = ypcm->codec;
+ u32 pos, delta;
+
+ spin_lock(&codec->reg_lock);
+ if (ypcm->running) {
+ pos = codec->bank_capture[ypcm->capture_bank_number][codec->active_bank]->start << ypcm->shift_offset;
+ if (pos < ypcm->last_pos) // <-- dmabuf->hwptr
+ delta = pos + (ypcm->buffer_size - ypcm->last_pos);
+ else
+ delta = pos - ypcm->last_pos;
+ ypcm->frag_pos += delta;
+ ypcm->last_pos = pos;
+ while (ypcm->frag_pos >= ypcm->frag_size) {
+ ypcm->frag_pos -= ypcm->frag_size;
+ // printk("done - active_bank = 0x%x, start = 0x%x\n", codec->active_bank, voice->bank[codec->active_bank].start);
+ spin_unlock(&codec->reg_lock);
+ snd_pcm_transfer_done(substream);
+ spin_lock(&codec->reg_lock);
+ }
+ }
+ spin_unlock(&codec->reg_lock);
+}
+#endif
+
+static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd)
+{
+
+ if (ypcm->voices[0] == NULL) {
+ return -EINVAL;
+ }
+ if (cmd != 0) {
+ codec->ctrl_playback[ypcm->voices[0]->number + 1] = virt_to_bus(ypcm->voices[0]->bank);
+ if (ypcm->voices[1] != NULL)
+ codec->ctrl_playback[ypcm->voices[1]->number + 1] = virt_to_bus(ypcm->voices[1]->bank);
+ ypcm->running = 1;
+ } else {
+ codec->ctrl_playback[ypcm->voices[0]->number + 1] = 0;
+ if (ypcm->voices[1] != NULL)
+ codec->ctrl_playback[ypcm->voices[1]->number + 1] = 0;
+ ypcm->running = 0;
+ }
+ return 0;
+}
+
+#if HAVE_RECORD
+static int ymfpci_capture_trigger(void *private_data,
+ snd_pcm_subchn_t * substream,
+ int cmd)
+{
+ unsigned long flags;
+ ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
+ ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, -ENXIO);
+ int result = 0;
+ u32 tmp;
+
+ spin_lock_irqsave(&codec->reg_lock, flags);
+ if (cmd == SND_PCM_TRIGGER_GO) {
+ tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) | (1 << ypcm->capture_bank_number);
+ ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp);
+ ypcm->running = 1;
+ } else if (cmd == SND_PCM_TRIGGER_STOP) {
+ tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) & ~(1 << ypcm->capture_bank_number);
+ ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp);
+ ypcm->running = 0;
+ } else {
+ result = -EINVAL;
+ }
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+ return result;
+}
+#endif
+
+static int ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices)
+{
+ int err;
+
+ if (ypcm->voices[1] != NULL && voices < 2) {
+ ymfpci_voice_free(ypcm->codec, ypcm->voices[1]);
+ ypcm->voices[1] = NULL;
+ }
+ if (voices == 1 && ypcm->voices[0] != NULL)
+ return 0; /* already allocated */
+ if (voices == 2 && ypcm->voices[0] != NULL && ypcm->voices[1] != NULL)
+ return 0; /* already allocated */
+ if (voices > 1) {
+ if (ypcm->voices[0] != NULL && ypcm->voices[1] == NULL) {
+ ymfpci_voice_free(ypcm->codec, ypcm->voices[0]);
+ ypcm->voices[0] = NULL;
+ }
+ }
+ err = ymfpci_voice_alloc(ypcm->codec, YMFPCI_PCM, voices > 1, &ypcm->voices[0]);
+ if (err < 0)
+ return err;
+ ypcm->voices[0]->ypcm = ypcm;
+ ypcm->voices[0]->interrupt = ymf_pcm_interrupt;
+ if (voices > 1) {
+ ypcm->voices[1] = &ypcm->codec->voices[ypcm->voices[0]->number + 1];
+ ypcm->voices[1]->ypcm = ypcm;
+ }
+ return 0;
+}
+
+static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
+ int rate, int w_16, unsigned long addr, unsigned int end, int spdif)
+{
+ u32 format;
+ u32 delta = ymfpci_calc_delta(rate);
+ u32 lpfQ = ymfpci_calc_lpfQ(rate);
+ u32 lpfK = ymfpci_calc_lpfK(rate);
+ ymfpci_playback_bank_t *bank;
+ int nbank;
+
+ format = (stereo ? 0x00010000 : 0) | (w_16 ? 0 : 0x80000000);
+ if (stereo)
+ end >>= 1;
+ if (w_16)
+ end >>= 1;
+/* P3 */ // printk("ymf_pcm_init_voice: %d: Rate %d Format 0x%08x Delta 0x%x End 0x%x\n",
+// voice->number, rate, format, delta, end);
+ for (nbank = 0; nbank < 2; nbank++) {
+ bank = &voice->bank[nbank];
+ bank->format = format;
+ bank->loop_default = 0; /* 0-loops forever, otherwise count */
+ bank->base = addr;
+ bank->loop_start = 0;
+ bank->loop_end = end;
+ bank->loop_frac = 0;
+ bank->eg_gain_end = 0x40000000;
+ bank->lpfQ = lpfQ;
+ bank->status = 0;
+ bank->num_of_frames = 0;
+ bank->loop_count = 0;
+ bank->start = 0;
+ bank->start_frac = 0;
+ bank->delta =
+ bank->delta_end = delta;
+ bank->lpfK =
+ bank->lpfK_end = lpfK;
+ bank->eg_gain = 0x40000000;
+ bank->lpfD1 =
+ bank->lpfD2 = 0;
+
+ bank->left_gain =
+ bank->right_gain =
+ bank->left_gain_end =
+ bank->right_gain_end =
+ bank->eff1_gain =
+ bank->eff2_gain =
+ bank->eff3_gain =
+ bank->eff1_gain_end =
+ bank->eff2_gain_end =
+ bank->eff3_gain_end = 0;
+
+ if (!stereo) {
+ if (!spdif) {
+ bank->left_gain =
+ bank->right_gain =
+ bank->left_gain_end =
+ bank->right_gain_end = 0x40000000;
+ } else {
+ bank->eff2_gain =
+ bank->eff2_gain_end =
+ bank->eff3_gain =
+ bank->eff3_gain_end = 0x40000000;
+ }
+ } else {
+ if (!spdif) {
+ if ((voice->number & 1) == 0) {
+ bank->format |= 1;
+ bank->left_gain =
+ bank->left_gain_end = 0x40000000;
+ } else {
+ bank->right_gain =
+ bank->right_gain_end = 0x40000000;
+ }
+ } else {
+ if ((voice->number & 1) == 0) {
+ bank->format |= 1;
+ bank->eff2_gain =
+ bank->eff2_gain_end = 0x40000000;
+ } else {
+ bank->eff3_gain =
+ bank->eff3_gain_end = 0x40000000;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * XXX Use new cache coherent PCI DMA routines instead of virt_to_bus.
+ */
+static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state)
+{
+ ymfpci_pcm_t *ypcm = &state->ypcm;
+ int err, nvoice;
+
+ if ((err = ymfpci_pcm_voice_alloc(ypcm, state->format.voices)) < 0) {
+ /* Cannot be unless we leak voices in ymf_release! */
+ printk(KERN_ERR "ymfpci%d: cannot allocate voice!\n",
+ codec->dev_audio);
+ return err;
+ }
+
+ for (nvoice = 0; nvoice < state->format.voices; nvoice++) {
+ ymf_pcm_init_voice(ypcm->voices[nvoice],
+ state->format.voices == 2, state->format.rate,
+ ymf_pcm_format_width(state->format.format) == 16,
+ virt_to_bus(state->dmabuf.rawbuf), state->dmabuf.dmasize,
+ ypcm->spdif);
+ }
+ return 0;
+}
+
+#if 0 /* old */
+static int ymfpci_capture_prepare(void *private_data,
+ snd_pcm_subchn_t * substream)
+{
+ ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
+ ymfpci_capture_bank_t * bank;
+ int nbank;
+ u32 rate, format;
+
+ ypcm->frag_size = snd_pcm_lib_transfer_fragment(substream);
+ ypcm->buffer_size = snd_pcm_lib_transfer_size(substream);
+ ypcm->frag_pos = 0;
+ ypcm->last_pos = 0;
+ ypcm->shift_offset = 0;
+ rate = ((48000 * 4096) / runtime->format.rate) - 1;
+ format = 0;
+ if (runtime->format.voices == 2)
+ format |= 2;
+ if (snd_pcm_format_width(runtime->format.format) == 8)
+ format |= 1;
+ switch (ypcm->capture_bank_number) {
+ case 0:
+ ymfpci_writel(codec, YDSXGR_RECFORMAT, format);
+ ymfpci_writel(codec, YDSXGR_RECSLOTSR, rate);
+ break;
+ case 1:
+ ymfpci_writel(codec, YDSXGR_ADCFORMAT, format);
+ ymfpci_writel(codec, YDSXGR_ADCSLOTSR, rate);
+ break;
+ }
+ for (nbank = 0; nbank < 2; nbank++) {
+ bank = codec->bank_capture[ypcm->capture_bank_number][nbank];
+ bank->base = virt_to_bus(runtime->dma_area->buf);
+ bank->loop_end = ypcm->buffer_size;
+ bank->start = 0;
+ bank->num_of_loops = 0;
+ }
+ if (runtime->digital.dig_valid)
+ /*runtime->digital.type == SND_PCM_DIG_AES_IEC958*/
+ ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS, runtime->digital.dig_status[0] |
+ (runtime->digital.dig_status[1] << 8));
+ return 0;
+}
+
+static unsigned int ymfpci_playback_pointer(void *private_data,
+ snd_pcm_subchn_t * substream)
+{
+ ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
+ ymfpci_voice_t *voice = ypcm->voices[0];
+ unsigned long flags;
+ unsigned int result;
+
+ spin_lock_irqsave(&codec->reg_lock, flags);
+ if (ypcm->running && voice)
+ result = voice->bank[codec->active_bank].start << ypcm->shift_offset;
+ else
+ result = 0;
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+ return result;
+}
+
+static unsigned int ymfpci_capture_pointer(void *private_data,
+ snd_pcm_subchn_t * substream)
+{
+ ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
+ unsigned long flags;
+ unsigned int result;
+
+ spin_lock_irqsave(&codec->reg_lock, flags);
+ if (ypcm->running)
+ result = codec->bank_capture[ypcm->capture_bank_number][codec->active_bank]->start << ypcm->shift_offset;
+ else
+ result = 0;
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+ return result;
+}
+#endif /* old */
+
+void ymf_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ ymfpci_t *codec = dev_id;
+ u32 status, nvoice, mode;
+ ymfpci_voice_t *voice;
+
+ status = ymfpci_readl(codec, YDSXGR_STATUS);
+ if (status & 0x80000000) {
+ spin_lock(&codec->reg_lock);
+ ymfpci_writel(codec, YDSXGR_STATUS, 0x80000000);
+ mode = ymfpci_readl(codec, YDSXGR_MODE) | 2;
+ ymfpci_writel(codec, YDSXGR_MODE, mode);
+ spin_unlock(&codec->reg_lock);
+ codec->active_bank = ymfpci_readl(codec, YDSXGR_CTRLSELECT) & 1;
+ spin_lock(&codec->voice_lock);
+ for (nvoice = 0; nvoice < 64; nvoice++) {
+ voice = &codec->voices[nvoice];
+ if (voice->interrupt)
+ voice->interrupt(codec, voice);
+ }
+ spin_unlock(&codec->voice_lock);
+ }
+
+ status = ymfpci_readl(codec, YDSXGR_INTFLAG);
+ if (status & 1) {
+ /* timer handler */
+ ymfpci_writel(codec, YDSXGR_INTFLAG, ~0);
+ }
+}
+
+static void ymf_pcm_free_substream(ymfpci_pcm_t *ypcm)
+{
+ ymfpci_t *codec;
+
+ if (ypcm) {
+ codec = ypcm->codec;
+ if (ypcm->voices[1])
+ ymfpci_voice_free(codec, ypcm->voices[1]);
+ if (ypcm->voices[0])
+ ymfpci_voice_free(codec, ypcm->voices[0]);
+ }
+}
+
+static int ymf_state_alloc(ymfpci_t *unit, int nvirt)
+{
+ ymfpci_pcm_t *ypcm;
+ struct ymf_state *state;
+
+ if ((state = kmalloc(sizeof(struct ymf_state), GFP_KERNEL)) == NULL) {
+ goto out0;
+ }
+ memset(state, 0, sizeof(struct ymf_state));
+
+ init_waitqueue_head(&state->dmabuf.wait);
+
+ ypcm = &state->ypcm;
+ ypcm->state = state;
+ ypcm->codec = unit;
+ ypcm->type = PLAYBACK_VOICE;
+
+ state->unit = unit;
+ state->virt = nvirt;
+
+ state->format.format = AFMT_U8;
+ state->format.rate = 8000;
+ state->format.voices = 1;
+ ymf_pcm_update_shift(&state->format);
+
+ unit->states[nvirt] = state;
+ return 0;
+
+out0:
+ return -ENOMEM;
+}
+
+#if HAVE_RECORD
+
+static int ymfpci_capture_open(void *private_data,
+ snd_pcm_subchn_t * substream,
+ u32 capture_bank_number)
+{
+ ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ ymfpci_pcm_t *ypcm;
+ int err;
+
+ if ((err = snd_pcm_dma_alloc(substream, !capture_bank_number ? codec->dma2ptr : codec->dma3ptr, "YMFPCI - ADC")) < 0)
+ return err;
+ ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);
+ if (ypcm == NULL) {
+ snd_pcm_dma_free(substream);
+ return -ENOMEM;
+ }
+ ypcm->codec = codec;
+ ypcm->type = capture_bank_number + CAPTURE_REC;
+ ypcm->substream = substream;
+ ypcm->capture_bank_number = capture_bank_number;
+ codec->capture_substream[capture_bank_number] = substream;
+ runtime->hw = &ymfpci_capture;
+ snd_pcm_set_mixer(substream, codec->mixer->device, codec->ac97->me_capture);
+ runtime->private_data = ypcm;
+ runtime->private_free = ymfpci_pcm_free_substream;
+ ymfpci_hw_start(codec);
+ return 0;
+}
+
+#endif /* old */
+
+/* AES/IEC958 channel status bits */
+#define SND_PCM_AES0_PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
+#define SND_PCM_AES0_NONAUDIO (1<<1) /* 0 = audio, 1 = non-audio */
+#define SND_PCM_AES0_PRO_EMPHASIS (7<<2) /* mask - emphasis */
+#define SND_PCM_AES0_PRO_EMPHASIS_NOTID (0<<2) /* emphasis not indicated */
+#define SND_PCM_AES0_PRO_EMPHASIS_NONE (1<<2) /* none emphasis */
+#define SND_PCM_AES0_PRO_EMPHASIS_5015 (3<<2) /* 50/15us emphasis */
+#define SND_PCM_AES0_PRO_EMPHASIS_CCITT (7<<2) /* CCITT J.17 emphasis */
+#define SND_PCM_AES0_PRO_FREQ_UNLOCKED (1<<5) /* source sample frequency: 0 = locked, 1 = unlocked */
+#define SND_PCM_AES0_PRO_FS (3<<6) /* mask - sample frequency */
+#define SND_PCM_AES0_PRO_FS_NOTID (0<<6) /* fs not indicated */
+#define SND_PCM_AES0_PRO_FS_44100 (1<<6) /* 44.1kHz */
+#define SND_PCM_AES0_PRO_FS_48000 (2<<6) /* 48kHz */
+#define SND_PCM_AES0_PRO_FS_32000 (3<<6) /* 32kHz */
+#define SND_PCM_AES0_CON_NOT_COPYRIGHT (1<<2) /* 0 = copyright, 1 = not copyright */
+#define SND_PCM_AES0_CON_EMPHASIS (7<<3) /* mask - emphasis */
+#define SND_PCM_AES0_CON_EMPHASIS_NONE (0<<3) /* none emphasis */
+#define SND_PCM_AES0_CON_EMPHASIS_5015 (1<<3) /* 50/15us emphasis */
+#define SND_PCM_AES0_CON_MODE (3<<6) /* mask - mode */
+#define SND_PCM_AES1_PRO_MODE (15<<0) /* mask - channel mode */
+#define SND_PCM_AES1_PRO_MODE_NOTID (0<<0) /* not indicated */
+#define SND_PCM_AES1_PRO_MODE_STEREOPHONIC (2<<0) /* stereophonic - ch A is left */
+#define SND_PCM_AES1_PRO_MODE_SINGLE (4<<0) /* single channel */
+#define SND_PCM_AES1_PRO_MODE_TWO (8<<0) /* two channels */
+#define SND_PCM_AES1_PRO_MODE_PRIMARY (12<<0) /* primary/secondary */
+#define SND_PCM_AES1_PRO_MODE_BYTE3 (15<<0) /* vector to byte 3 */
+#define SND_PCM_AES1_PRO_USERBITS (15<<4) /* mask - user bits */
+#define SND_PCM_AES1_PRO_USERBITS_NOTID (0<<4) /* not indicated */
+#define SND_PCM_AES1_PRO_USERBITS_192 (8<<4) /* 192-bit structure */
+#define SND_PCM_AES1_PRO_USERBITS_UDEF (12<<4) /* user defined application */
+#define SND_PCM_AES1_CON_CATEGORY 0x7f
+#define SND_PCM_AES1_CON_GENERAL 0x00
+#define SND_PCM_AES1_CON_EXPERIMENTAL 0x40
+#define SND_PCM_AES1_CON_SOLIDMEM_MASK 0x0f
+#define SND_PCM_AES1_CON_SOLIDMEM_ID 0x08
+#define SND_PCM_AES1_CON_BROADCAST1_MASK 0x07
+#define SND_PCM_AES1_CON_BROADCAST1_ID 0x04
+#define SND_PCM_AES1_CON_DIGDIGCONV_MASK 0x07
+#define SND_PCM_AES1_CON_DIGDIGCONV_ID 0x02
+#define SND_PCM_AES1_CON_ADC_COPYRIGHT_MASK 0x1f
+#define SND_PCM_AES1_CON_ADC_COPYRIGHT_ID 0x06
+#define SND_PCM_AES1_CON_ADC_MASK 0x1f
+#define SND_PCM_AES1_CON_ADC_ID 0x16
+#define SND_PCM_AES1_CON_BROADCAST2_MASK 0x0f
+#define SND_PCM_AES1_CON_BROADCAST2_ID 0x0e
+#define SND_PCM_AES1_CON_LASEROPT_MASK 0x07
+#define SND_PCM_AES1_CON_LASEROPT_ID 0x01
+#define SND_PCM_AES1_CON_MUSICAL_MASK 0x07
+#define SND_PCM_AES1_CON_MUSICAL_ID 0x05
+#define SND_PCM_AES1_CON_MAGNETIC_MASK 0x07
+#define SND_PCM_AES1_CON_MAGNETIC_ID 0x03
+#define SND_PCM_AES1_CON_IEC908_CD (SND_PCM_AES1_CON_LASEROPT_ID|0x00)
+#define SND_PCM_AES1_CON_NON_IEC908_CD (SND_PCM_AES1_CON_LASEROPT_ID|0x08)
+#define SND_PCM_AES1_CON_PCM_CODER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x00)
+#define SND_PCM_AES1_CON_SAMPLER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x20)
+#define SND_PCM_AES1_CON_MIXER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x10)
+#define SND_PCM_AES1_CON_RATE_CONVERTER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x18)
+#define SND_PCM_AES1_CON_SYNTHESIZER (SND_PCM_AES1_CON_MUSICAL_ID|0x00)
+#define SND_PCM_AES1_CON_MICROPHONE (SND_PCM_AES1_CON_MUSICAL_ID|0x08)
+#define SND_PCM_AES1_CON_DAT (SND_PCM_AES1_CON_MAGNETIC_ID|0x00)
+#define SND_PCM_AES1_CON_VCR (SND_PCM_AES1_CON_MAGNETIC_ID|0x08)
+#define SND_PCM_AES1_CON_ORIGINAL (1<<7) /* this bits depends on the category code */
+#define SND_PCM_AES2_PRO_SBITS (7<<0) /* mask - sample bits */
+#define SND_PCM_AES2_PRO_SBITS_20 (2<<0) /* 20-bit - coordination */
+#define SND_PCM_AES2_PRO_SBITS_24 (4<<0) /* 24-bit - main audio */
+#define SND_PCM_AES2_PRO_SBITS_UDEF (6<<0) /* user defined application */
+#define SND_PCM_AES2_PRO_WORDLEN (7<<3) /* mask - source word length */
+#define SND_PCM_AES2_PRO_WORDLEN_NOTID (0<<3) /* not indicated */
+#define SND_PCM_AES2_PRO_WORDLEN_22_18 (2<<3) /* 22-bit or 18-bit */
+#define SND_PCM_AES2_PRO_WORDLEN_23_19 (4<<3) /* 23-bit or 19-bit */
+#define SND_PCM_AES2_PRO_WORDLEN_24_20 (5<<3) /* 24-bit or 20-bit */
+#define SND_PCM_AES2_PRO_WORDLEN_20_16 (6<<3) /* 20-bit or 16-bit */
+#define SND_PCM_AES2_CON_SOURCE (15<<0) /* mask - source number */
+#define SND_PCM_AES2_CON_SOURCE_UNSPEC (0<<0) /* unspecified */
+#define SND_PCM_AES2_CON_CHANNEL (15<<4) /* mask - channel number */
+#define SND_PCM_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */
+#define SND_PCM_AES3_CON_FS (15<<0) /* mask - sample frequency */
+#define SND_PCM_AES3_CON_FS_44100 (0<<0) /* 44.1kHz */
+#define SND_PCM_AES3_CON_FS_48000 (2<<0) /* 48kHz */
+#define SND_PCM_AES3_CON_FS_32000 (3<<0) /* 32kHz */
+#define SND_PCM_AES3_CON_CLOCK (3<<4) /* mask - clock accuracy */
+#define SND_PCM_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */
+#define SND_PCM_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */
+#define SND_PCM_AES3_CON_CLOCK_VARIABLE (2<<4) /* variable pitch */
+
+#if HAVE_RECORD /* old */
+
+static int ymfpci_capture_close(void *private_data,
+ snd_pcm_subchn_t * substream)
+{
+ ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
+
+ if (ypcm != NULL) {
+ codec->capture_substream[ypcm->capture_bank_number] = NULL;
+ ymfpci_hw_stop(codec);
+ }
+ snd_pcm_dma_free(substream);
+ return 0;
+}
+#endif
+
+/*
+ * User interface
+ */
+
+static loff_t ymf_llseek(struct file *file, loff_t offset, int origin)
+{
+ return -ESPIPE;
+}
+
+/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to
+ the user's buffer. it is filled by the dma machine and drained by this loop. */
+static ssize_t ymf_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+#if HAVE_RECORD
+ struct cs_state *state = (struct cs_state *)file->private_data;
+ struct dmabuf *dmabuf = &state->dmabuf;
+ ssize_t ret;
+ unsigned long flags;
+ unsigned swptr;
+ int cnt;
+
+#ifdef DEBUG
+ printk("cs461x: cs_read called, count = %d\n", count);
+#endif
+
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+ if (dmabuf->mapped)
+ return -ENXIO;
+ if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
+ return ret;
+ if (!access_ok(VERIFY_WRITE, buffer, count))
+ return -EFAULT;
+ ret = 0;
+
+ while (count > 0) {
+ spin_lock_irqsave(&state->card->lock, flags);
+ if (dmabuf->count > (signed) dmabuf->dmasize) {
+ /* buffer overrun, we are recovering from sleep_on_timeout,
+ resync hwptr and swptr, make process flush the buffer */
+ dmabuf->count = dmabuf->dmasize;
+ dmabuf->swptr = dmabuf->hwptr;
+ }
+ swptr = dmabuf->swptr;
+ cnt = dmabuf->dmasize - swptr;
+ if (dmabuf->count < cnt)
+ cnt = dmabuf->count;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
+ if (cnt > count)
+ cnt = count;
+ if (cnt <= 0) {
+ unsigned long tmo;
+ /* buffer is empty, start the dma machine and wait for data to be
+ recorded */
+ start_adc(state);
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret) ret = -EAGAIN;
+ return ret;
+ }
+ /* This isnt strictly right for the 810 but it'll do */
+ tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
+ tmo >>= sample_shift[dmabuf->fmt];
+ /* There are two situations when sleep_on_timeout returns, one is when
+ the interrupt is serviced correctly and the process is waked up by
+ ISR ON TIME. Another is when timeout is expired, which means that
+ either interrupt is NOT serviced correctly (pending interrupt) or it
+ is TOO LATE for the process to be scheduled to run (scheduler latency)
+ which results in a (potential) buffer overrun. And worse, there is
+ NOTHING we can do to prevent it. */
+ if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
+#ifdef DEBUG
+ printk(KERN_ERR "cs461x: recording schedule timeout, "
+ "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+ dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
+ dmabuf->hwptr, dmabuf->swptr);
+#endif
+ /* a buffer overrun, we delay the recovery untill next time the
+ while loop begin and we REALLY have space to record */
+ }
+ if (signal_pending(current)) {
+ ret = ret ? ret : -ERESTARTSYS;
+ return ret;
+ }
+ continue;
+ }
+
+ if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
+ if (!ret) ret = -EFAULT;
+ return ret;
+ }
+
+ swptr = (swptr + cnt) % dmabuf->dmasize;
+
+ spin_lock_irqsave(&state->card->lock, flags);
+ dmabuf->swptr = swptr;
+ dmabuf->count -= cnt;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
+ count -= cnt;
+ buffer += cnt;
+ ret += cnt;
+ start_adc(state);
+ }
+ return ret;
+#else
+ return -EINVAL;
+#endif
+}
+
+static ssize_t ymf_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+ struct ymf_state *state = (struct ymf_state *)file->private_data;
+ struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ DECLARE_WAITQUEUE(waita, current);
+ ssize_t ret;
+ unsigned long flags;
+ unsigned int swptr;
+ int cnt; /* This many to go in this revolution */
+ int redzone;
+ int delay;
+
+/* P3 */ /* printk("ymf_write: count %d\n", count); */
+
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+ if (dmabuf->mapped)
+ return -ENXIO;
+ if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
+ return ret;
+ if (!access_ok(VERIFY_READ, buffer, count))
+ return -EFAULT;
+ ret = 0;
+
+ /*
+ * Alan's cs46xx works without a red zone - marvel of ingenuity.
+ * We are not so brilliant... Red zone does two things:
+ * 1. allows for safe start after a pause as we have no way
+ * to know what the actual, relentlessly advancing, hwptr is.
+ * 2. makes computations in ymf_pcm_interrupt simpler.
+ */
+ redzone = ymf_calc_lend(state->format.rate) << state->format.shift;
+ redzone *= 3; /* 2 redzone + 1 possible uncertainty reserve. */
+
+ add_wait_queue(&dmabuf->wait, &waita);
+ while (count > 0) {
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (dmabuf->count < 0) {
+ printk(KERN_ERR
+ "ymf_write: count %d, was legal in cs46xx\n",
+ dmabuf->count);
+ dmabuf->count = 0;
+ }
+ if (dmabuf->count == 0) {
+ swptr = dmabuf->hwptr;
+ if (state->ypcm.running) {
+ /*
+ * Add uncertainty reserve.
+ */
+ cnt = ymf_calc_lend(state->format.rate);
+ cnt <<= state->format.shift;
+ if ((swptr += cnt) >= dmabuf->dmasize) {
+ swptr -= dmabuf->dmasize;
+ }
+ }
+ dmabuf->swptr = swptr;
+ } else {
+ /*
+ * XXX This is not right if dmabuf->count is small -
+ * about 2*x frame size or less. We cannot count on
+ * on appending and not causing an artefact.
+ * Should use a variation of the count==0 case above.
+ */
+ swptr = dmabuf->swptr;
+ }
+ cnt = dmabuf->dmasize - swptr;
+ if (dmabuf->count + cnt > dmabuf->dmasize - redzone)
+ cnt = (dmabuf->dmasize - redzone) - dmabuf->count;
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+
+ if (cnt > count)
+ cnt = count;
+ if (cnt <= 0) {
+/* P3 */ /* printk("ymf_write: full, count %d swptr %d\n",
+ dmabuf->count, dmabuf->swptr); */
+ /*
+ * buffer is full, start the dma machine and
+ * wait for data to be played
+ */
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (!state->ypcm.running) {
+ ymf_playback_trigger(state->unit, &state->ypcm, 1);
+ }
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret) ret = -EAGAIN;
+ break;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret) ret = -ERESTARTSYS;
+ break;
+ }
+ continue;
+ }
+ if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
+ if (!ret) ret = -EFAULT;
+ break;
+ }
+
+ if ((swptr += cnt) >= dmabuf->dmasize) {
+ swptr -= dmabuf->dmasize;
+ }
+
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->swptr = swptr;
+ dmabuf->count += cnt;
+
+ /*
+ * Start here is a bad idea - may cause startup click
+ * in /bin/play when dmabuf is not full yet.
+ * However, some broken applications do not make
+ * any use of SNDCTL_DSP_SYNC (Doom is the worst).
+ * One frame is about 5.3ms, Doom write size is 46ms.
+ */
+ delay = state->format.rate / 20; /* 50ms */
+ delay <<= state->format.shift;
+ if (dmabuf->count >= delay && !state->ypcm.running) {
+ ymf_playback_trigger(state->unit, &state->ypcm, 1);
+ }
+
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+
+ count -= cnt;
+ buffer += cnt;
+ ret += cnt;
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&dmabuf->wait, &waita);
+
+/* P3 */ /* printk("ymf_write: dmabuf.count %d\n", dmabuf->count); */
+ return ret;
+}
+
+static unsigned int ymf_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct ymf_state *state = (struct ymf_state *)file->private_data;
+ struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ unsigned long flags;
+ unsigned int mask = 0;
+
+ if (file->f_mode & (FMODE_WRITE | FMODE_READ))
+ poll_wait(file, &dmabuf->wait, wait);
+
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (file->f_mode & FMODE_READ) {
+ if (dmabuf->count >= (signed)dmabuf->fragsize)
+ mask |= POLLIN | POLLRDNORM;
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ if (dmabuf->mapped) {
+ if (dmabuf->count >= (signed)dmabuf->fragsize)
+ mask |= POLLOUT | POLLWRNORM;
+ } else {
+ if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize)
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ }
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+
+ return mask;
+}
+
+static int ymf_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct ymf_state *state = (struct ymf_state *)file->private_data;
+ struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ int ret;
+ unsigned long size;
+
+
+ if (vma->vm_flags & VM_WRITE) {
+ if ((ret = prog_dmabuf(state, 0)) != 0)
+ return ret;
+ } else if (vma->vm_flags & VM_READ) {
+ if ((ret = prog_dmabuf(state, 1)) != 0)
+ return ret;
+ } else
+ return -EINVAL;
+
+ if (vma->vm_pgoff != 0)
+ return -EINVAL;
+ size = vma->vm_end - vma->vm_start;
+ if (size > (PAGE_SIZE << dmabuf->buforder))
+ return -EINVAL;
+ if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf),
+ size, vma->vm_page_prot))
+ return -EAGAIN;
+ dmabuf->mapped = 1;
+
+ return 0;
+}
+
+static int ymf_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ymf_state *state = (struct ymf_state *)file->private_data;
+ struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ unsigned long flags;
+ audio_buf_info abinfo;
+ count_info cinfo;
+ int val;
+
+ switch (cmd) {
+ case OSS_GETVERSION:
+ return put_user(SOUND_VERSION, (int *)arg);
+
+ case SNDCTL_DSP_RESET:
+ if (file->f_mode & FMODE_WRITE) {
+ ymf_wait_dac(state);
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ dmabuf->swptr = dmabuf->hwptr = 0;
+ dmabuf->count = dmabuf->total_bytes = 0;
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ }
+#if HAVE_RECORD
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(state);
+ synchronize_irq();
+ dmabuf->ready = 0;
+ dmabuf->swptr = dmabuf->hwptr = 0;
+ dmabuf->count = dmabuf->total_bytes = 0;
+ }
+#endif
+ return 0;
+
+ case SNDCTL_DSP_SYNC:
+ if (file->f_mode & FMODE_WRITE) {
+ if (file->f_flags & O_NONBLOCK) {
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (dmabuf->count != 0 && !state->ypcm.running) {
+ ymf_start_dac(state);
+ }
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ } else {
+ ymf_wait_dac(state);
+ }
+ }
+ return 0;
+
+ case SNDCTL_DSP_SPEED: /* set smaple rate */
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (val >= 8000 && val <= 48000) {
+ if (file->f_mode & FMODE_WRITE) {
+ ymf_wait_dac(state);
+ }
+#if HAVE_RECORD
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(state);
+ }
+#endif
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ state->format.rate = val;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ }
+ return put_user(state->format.rate, (int *)arg);
+
+ /*
+ * OSS manual does not mention SNDCTL_DSP_STEREO at all.
+ * All channels are mono and if you want stereo, you
+ * play into two channels with SNDCTL_DSP_CHANNELS.
+ * However, mpg123 uses it. I wonder, why Michael Hipp uses it.
+ */
+ case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (file->f_mode & FMODE_WRITE) {
+ ymf_wait_dac(state);
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ state->format.voices = val ? 2 : 1;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ }
+#if HAVE_RECORD
+ if (file->f_mode & FMODE_READ) {
+ /* stop_adc(state); */
+ dmabuf->ready = 0;
+ if(val)
+ dmabuf->fmt |= CS_FMT_STEREO;
+ else
+ dmabuf->fmt &= ~CS_FMT_STEREO;
+ }
+#endif
+ return 0;
+
+ case SNDCTL_DSP_GETBLKSIZE:
+ if (file->f_mode & FMODE_WRITE) {
+ if ((val = prog_dmabuf(state, 0)))
+ return val;
+ return put_user(dmabuf->fragsize, (int *)arg);
+ }
+ if (file->f_mode & FMODE_READ) {
+ if ((val = prog_dmabuf(state, 1)))
+ return val;
+ return put_user(dmabuf->fragsize, (int *)arg);
+ }
+ return -EINVAL;
+
+ case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
+ return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
+
+ case SNDCTL_DSP_SETFMT: /* Select sample format */
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (val == AFMT_S16_LE || val == AFMT_U8) {
+ if (file->f_mode & FMODE_WRITE) {
+ ymf_wait_dac(state);
+ }
+#if HAVE_RECORD
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(state);
+ }
+#endif
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ state->format.format = val;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ }
+ return put_user(state->format.format, (int *)arg);
+
+ case SNDCTL_DSP_CHANNELS:
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ /* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_CHANNELS 0x%x\n", val); */
+ if (val != 0) {
+ if (file->f_mode & FMODE_WRITE) {
+ ymf_wait_dac(state);
+ if (val == 1 || val == 2) {
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ state->format.voices = val;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ }
+ }
+#if HAVE_RECORD
+ if (file->f_mode & FMODE_READ) {
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ stop_adc(state);
+ dmabuf->ready = 0;
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ }
+#endif
+ }
+ return put_user(state->format.voices, (int *)arg);
+
+ case SNDCTL_DSP_POST:
+ /*
+ * Quoting OSS PG:
+ * The ioctl SNDCTL_DSP_POST is a lightweight version of
+ * SNDCTL_DSP_SYNC. It just tells to the driver that there
+ * is likely to be a pause in the output. This makes it
+ * possible for the device to handle the pause more
+ * intelligently. This ioctl doesn't block the application.
+ *
+ * The paragraph above is a clumsy way to say "flush ioctl".
+ * This ioctl is used by mpg123.
+ */
+ /* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_POST\n"); */
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (dmabuf->count != 0 && !state->ypcm.running) {
+ ymf_start_dac(state);
+ }
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ return 0;
+
+ case SNDCTL_DSP_SUBDIVIDE:
+ if (dmabuf->subdivision)
+ return -EINVAL;
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (val != 1 && val != 2)
+ return -EINVAL;
+ dmabuf->subdivision = val;
+ return 0;
+
+ case SNDCTL_DSP_SETFRAGMENT:
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ /* P3: these frags are for Doom. Amasingly, it sets [2,2**11]. */
+ /* P3 */ // printk("ymfpci: ioctl SNDCTL_DSP_SETFRAGMENT 0x%x\n", val);
+
+ dmabuf->ossfragshift = val & 0xffff;
+ dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
+ switch (dmabuf->ossmaxfrags) {
+ case 1:
+ dmabuf->ossfragshift = 12;
+ return 0;
+ default:
+ /* Fragments must be 2K long */
+ dmabuf->ossfragshift = 11;
+ dmabuf->ossmaxfrags = 2;
+ }
+ return 0;
+
+ case SNDCTL_DSP_GETOSPACE:
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
+ if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
+ return val;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ /* cs_update_ptr(state); */ /* XXX Always up to date? */
+ abinfo.fragsize = dmabuf->fragsize;
+ abinfo.bytes = dmabuf->dmasize - dmabuf->count;
+ abinfo.fragstotal = dmabuf->numfrag;
+ abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+#if HAVE_RECORD
+ case SNDCTL_DSP_GETISPACE:
+ if (!(file->f_mode & FMODE_READ))
+ return -EINVAL;
+ if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
+ return val;
+ spin_lock_irqsave(&state->card->lock, flags);
+ cs_update_ptr(state);
+ abinfo.fragsize = dmabuf->fragsize;
+ abinfo.bytes = dmabuf->count;
+ abinfo.fragstotal = dmabuf->numfrag;
+ abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+#endif
+
+ case SNDCTL_DSP_NONBLOCK:
+ file->f_flags |= O_NONBLOCK;
+ return 0;
+
+ case SNDCTL_DSP_GETCAPS:
+ /* return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP,
+ (int *)arg); */
+ return put_user(0, (int *)arg);
+
+#if 0 /* old */
+ case SNDCTL_DSP_GETTRIGGER:
+ val = 0;
+ if (file->f_mode & FMODE_READ && dmabuf->enable)
+ val |= PCM_ENABLE_INPUT;
+ if (file->f_mode & FMODE_WRITE && dmabuf->enable)
+ val |= PCM_ENABLE_OUTPUT;
+ return put_user(val, (int *)arg);
+
+ case SNDCTL_DSP_SETTRIGGER:
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (file->f_mode & FMODE_READ) {
+ if (val & PCM_ENABLE_INPUT) {
+ if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
+ return ret;
+ start_adc(state);
+ } else
+ stop_adc(state);
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ if (val & PCM_ENABLE_OUTPUT) {
+ if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
+ return ret;
+ start_dac(state); // sure?
+ } else
+ stop_dac(state);
+ }
+ return 0;
+
+#endif
+
+#if HAVE_RECORD
+ case SNDCTL_DSP_GETIPTR:
+ if (!(file->f_mode & FMODE_READ))
+ return -EINVAL;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ cs_update_ptr(state);
+ cinfo.bytes = dmabuf->total_bytes;
+ cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
+ cinfo.ptr = dmabuf->hwptr;
+ if (dmabuf->mapped)
+ dmabuf->count &= dmabuf->fragsize-1;
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+#endif
+
+ case SNDCTL_DSP_GETOPTR:
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ /* cs_update_ptr(state); */ /* Always up to date */
+ cinfo.bytes = dmabuf->total_bytes;
+ cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
+ cinfo.ptr = dmabuf->hwptr;
+ if (dmabuf->mapped)
+ dmabuf->count &= dmabuf->fragsize-1;
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+ case SNDCTL_DSP_SETDUPLEX: /* XXX TODO */
+ return -EINVAL;
+
+#if 0 /* old */
+ case SNDCTL_DSP_GETODELAY:
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ cs_update_ptr(state);
+ val = dmabuf->count;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return put_user(val, (int *)arg);
+#endif
+
+ case SOUND_PCM_READ_RATE:
+ return put_user(state->format.rate, (int *)arg);
+
+ case SOUND_PCM_READ_CHANNELS:
+ return put_user(state->format.voices, (int *)arg);
+
+ case SOUND_PCM_READ_BITS:
+ return put_user(AFMT_S16_LE, (int *)arg);
+
+ case SNDCTL_DSP_MAPINBUF:
+ case SNDCTL_DSP_MAPOUTBUF:
+ case SNDCTL_DSP_SETSYNCRO:
+ case SOUND_PCM_WRITE_FILTER:
+ case SOUND_PCM_READ_FILTER:
+ return -ENOTTY;
+
+ default:
+ /*
+ * Some programs mix up audio devices and ioctls
+ * or perhaps they expect "universal" ioctls,
+ * for instance we get SNDCTL_TMR_CONTINUE here.
+ * XXX Is there sound_generic_ioctl() around?
+ */
+ }
+ return -ENOTTY;
+}
+
+static int ymf_open(struct inode *inode, struct file *file)
+{
+ struct list_head *list;
+ ymfpci_t *unit;
+ int minor;
+ struct ymf_state *state;
+ int nvirt;
+ int err;
+
+ /*
+ * This is how we do it currently: only one channel is used
+ * in every board, so that we could use several boards in one machine.
+ * We waste 63 out of 64 playback slots, but so what.
+ * OSS model is constructed for devices with single playback channel.
+ */
+ minor = MINOR(inode->i_rdev);
+ if ((minor & 0x0F) == 3) { /* /dev/dspN */
+ ;
+ } else {
+ return -ENXIO;
+ }
+ nvirt = 0; /* Such is the partitioning of minor */
+
+ for (list = ymf_devs.next; list != &ymf_devs; list = list->next) {
+ unit = list_entry(list, ymfpci_t, ymf_devs);
+ if (((unit->dev_audio ^ minor) & ~0x0F) == 0)
+ break;
+ }
+ if (list == &ymf_devs)
+ return -ENODEV;
+
+ down(&unit->open_sem);
+ if (unit->states[nvirt] != NULL) {
+ up(&unit->open_sem);
+ return -EBUSY;
+ }
+
+ if ((err = ymf_state_alloc(unit, nvirt)) != 0) {
+ up(&unit->open_sem);
+ return err;
+ }
+ state = unit->states[nvirt];
+
+ file->private_data = state;
+
+ /*
+ * XXX This ymf_playback_prepare is totally unneeded here.
+ * The question is if we want to allow write to fail if
+ * prog_dmabuf fails... Say, no memory in DMA zone?
+ */
+ if ((err = ymf_playback_prepare(unit, state)) != 0) {
+ /* XXX This recovery is ugly as hell. */
+
+ ymf_pcm_free_substream(&state->ypcm);
+
+ unit->states[state->virt] = NULL;
+ kfree(state);
+
+ up(&unit->open_sem);
+ return err;
+ }
+
+#if 0 /* test if interrupts work */
+ ymfpci_writew(codec, YDSXGR_TIMERCOUNT, 0xfffe); /* ~ 680ms */
+ ymfpci_writeb(codec, YDSXGR_TIMERCTRL,
+ (YDSXGR_TIMERCTRL_TEN|YDSXGR_TIMERCTRL_TIEN));
+#endif
+ up(&unit->open_sem);
+ /* XXX Is it correct to have MOD_INC_USE_COUNT outside of sem.? */
+
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int ymf_release(struct inode *inode, struct file *file)
+{
+ struct ymf_state *state = (struct ymf_state *)file->private_data;
+ ymfpci_t *codec = state->unit;
+
+#if 0 /* test if interrupts work */
+ ymfpci_writeb(codec, YDSXGR_TIMERCTRL, 0);
+#endif
+
+ if (state != codec->states[state->virt]) {
+ printk(KERN_ERR "ymfpci%d.%d: state mismatch\n",
+ state->unit->dev_audio, state->virt);
+ return -EIO;
+ }
+
+ down(&codec->open_sem);
+
+ /*
+ * XXX Solve the case of O_NONBLOCK close - don't deallocate here.
+ * Deallocate when unloading the driver and we can wait.
+ */
+ ymf_wait_dac(state);
+ dealloc_dmabuf(state);
+ ymf_pcm_free_substream(&state->ypcm);
+
+ codec->states[state->virt] = NULL;
+ kfree(state);
+
+ up(&codec->open_sem);
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+/*
+ * Mixer operations are based on cs46xx.
+ */
+static int ymf_open_mixdev(struct inode *inode, struct file *file)
+{
+ int i;
+ int minor = MINOR(inode->i_rdev);
+ struct list_head *list;
+ ymfpci_t *unit;
+
+ for (list = ymf_devs.next; list != &ymf_devs; list = list->next) {
+ unit = list_entry(list, ymfpci_t, ymf_devs);
+ for (i = 0; i < NR_AC97; i++) {
+ if (unit->ac97_codec[i] != NULL &&
+ unit->ac97_codec[i]->dev_mixer == minor) {
+ goto match;
+ }
+ }
+ }
+ return -ENODEV;
+
+ match:
+ file->private_data = unit->ac97_codec[i];
+
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int ymf_ioctl_mixdev(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
+
+ return codec->mixer_ioctl(codec, cmd, arg);
+}
+
+static int ymf_release_mixdev(struct inode *inode, struct file *file)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static /*const*/ struct file_operations ymf_fops = {
+ llseek: ymf_llseek,
+ read: ymf_read,
+ write: ymf_write,
+ poll: ymf_poll,
+ ioctl: ymf_ioctl,
+ mmap: ymf_mmap,
+ open: ymf_open,
+ release: ymf_release,
+};
+
+static /*const*/ struct file_operations ymf_mixer_fops = {
+ llseek: ymf_llseek,
+ ioctl: ymf_ioctl_mixdev,
+ open: ymf_open_mixdev,
+ release: ymf_release_mixdev,
+};
+
+/*
+ * initialization routines
+ */
+
+static void ymfpci_aclink_reset(struct pci_dev * pci)
+{
+ u8 cmd;
+
+ pci_read_config_byte(pci, PCIR_DSXGCTRL, &cmd);
+ if (cmd & 0x03) {
+ pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc);
+ pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd | 0x03);
+ pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc);
+ }
+}
+
+static void ymfpci_enable_dsp(ymfpci_t *codec)
+{
+ ymfpci_writel(codec, YDSXGR_CONFIG, 0x00000001);
+}
+
+static void ymfpci_disable_dsp(ymfpci_t *codec)
+{
+ u32 val;
+ int timeout = 1000;
+
+ val = ymfpci_readl(codec, YDSXGR_CONFIG);
+ if (val)
+ ymfpci_writel(codec, YDSXGR_CONFIG, 0x00000000);
+ while (timeout-- > 0) {
+ val = ymfpci_readl(codec, YDSXGR_STATUS);
+ if ((val & 0x00000002) == 0)
+ break;
+ }
+}
+
+#include "ymfpci_image.h"
+
+static void ymfpci_download_image(ymfpci_t *codec)
+{
+ int i, ver_1e;
+ u16 ctrl;
+
+ ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0x00000000);
+ ymfpci_disable_dsp(codec);
+ ymfpci_writel(codec, YDSXGR_MODE, 0x00010000);
+ ymfpci_writel(codec, YDSXGR_MODE, 0x00000000);
+ ymfpci_writel(codec, YDSXGR_MAPOFREC, 0x00000000);
+ ymfpci_writel(codec, YDSXGR_MAPOFEFFECT, 0x00000000);
+ ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, 0x00000000);
+ ymfpci_writel(codec, YDSXGR_RECCTRLBASE, 0x00000000);
+ ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, 0x00000000);
+ ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL);
+ ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
+
+ /* setup DSP instruction code */
+ for (i = 0; i < YDSXG_DSPLENGTH; i++)
+ ymfpci_writel(codec, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2]);
+
+ switch (codec->pci->device) {
+ case PCI_DEVICE_ID_YAMAHA_724F:
+ case PCI_DEVICE_ID_YAMAHA_740C:
+ case PCI_DEVICE_ID_YAMAHA_744:
+ case PCI_DEVICE_ID_YAMAHA_754:
+ ver_1e = 1;
+ break;
+ default:
+ ver_1e = 0;
+ }
+
+ if (ver_1e) {
+ /* setup control instruction code */
+ for (i = 0; i < YDSXG_CTRLLENGTH; i++)
+ ymfpci_writel(codec, YDSXGR_CTRLINSTRAM + i, CntrlInst1E[i >> 2]);
+ } else {
+ for (i = 0; i < YDSXG_CTRLLENGTH; i++)
+ ymfpci_writel(codec, YDSXGR_CTRLINSTRAM + i, CntrlInst[i >> 2]);
+ }
+
+ ymfpci_enable_dsp(codec);
+}
+
+static int ymfpci_memalloc(ymfpci_t *codec)
+{
+ long size, playback_ctrl_size;
+ int voice, bank;
+ u8 *ptr;
+
+ playback_ctrl_size = 4 + 4 * YDSXG_PLAYBACK_VOICES;
+ codec->bank_size_playback = ymfpci_readl(codec, YDSXGR_PLAYCTRLSIZE) << 2;
+ codec->bank_size_capture = ymfpci_readl(codec, YDSXGR_RECCTRLSIZE) << 2;
+ codec->bank_size_effect = ymfpci_readl(codec, YDSXGR_EFFCTRLSIZE) << 2;
+ codec->work_size = YDSXG_DEFAULT_WORK_SIZE;
+
+ size = ((playback_ctrl_size + 0x00ff) & ~0x00ff) +
+ ((codec->bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES + 0xff) & ~0xff) +
+ ((codec->bank_size_capture * 2 * YDSXG_CAPTURE_VOICES + 0xff) & ~0xff) +
+ ((codec->bank_size_effect * 2 * YDSXG_EFFECT_VOICES + 0xff) & ~0xff) +
+ codec->work_size;
+
+ ptr = (u8 *)kmalloc(size + 0x00ff, GFP_KERNEL);
+ if (ptr == NULL)
+ return -ENOMEM;
+
+ codec->work_ptr = ptr;
+ ptr += 0x00ff;
+ (long)ptr &= ~0x00ff;
+
+ codec->bank_base_playback = ptr;
+ codec->ctrl_playback = (u32 *)ptr;
+ codec->ctrl_playback[0] = YDSXG_PLAYBACK_VOICES;
+ ptr += (playback_ctrl_size + 0x00ff) & ~0x00ff;
+ for (voice = 0; voice < YDSXG_PLAYBACK_VOICES; voice++) {
+ for (bank = 0; bank < 2; bank++) {
+ codec->bank_playback[voice][bank] = (ymfpci_playback_bank_t *)ptr;
+ ptr += codec->bank_size_playback;
+ }
+ codec->voices[voice].number = voice;
+ codec->voices[voice].bank = codec->bank_playback[voice][0];
+ }
+ ptr += (codec->bank_size_playback + 0x00ff) & ~0x00ff;
+ codec->bank_base_capture = ptr;
+ for (voice = 0; voice < YDSXG_CAPTURE_VOICES; voice++)
+ for (bank = 0; bank < 2; bank++) {
+ codec->bank_capture[voice][bank] = (ymfpci_capture_bank_t *)ptr;
+ ptr += codec->bank_size_capture;
+ }
+ ptr += (codec->bank_size_capture + 0x00ff) & ~0x00ff;
+ codec->bank_base_effect = ptr;
+ for (voice = 0; voice < YDSXG_EFFECT_VOICES; voice++)
+ for (bank = 0; bank < 2; bank++) {
+ codec->bank_effect[voice][bank] = (ymfpci_effect_bank_t *)ptr;
+ ptr += codec->bank_size_effect;
+ }
+ ptr += (codec->bank_size_effect + 0x00ff) & ~0x00ff;
+ codec->work_base = ptr;
+
+ ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, virt_to_bus(codec->bank_base_playback));
+ ymfpci_writel(codec, YDSXGR_RECCTRLBASE, virt_to_bus(codec->bank_base_capture));
+ ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, virt_to_bus(codec->bank_base_effect));
+ ymfpci_writel(codec, YDSXGR_WORKBASE, virt_to_bus(codec->work_base));
+ ymfpci_writel(codec, YDSXGR_WORKSIZE, codec->work_size >> 2);
+
+ /* S/PDIF output initialization */
+ ymfpci_writew(codec, YDSXGR_SPDIFOUTCTRL, 0);
+ ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS,
+ SND_PCM_AES0_CON_EMPHASIS_NONE |
+ (SND_PCM_AES1_CON_ORIGINAL << 8) |
+ (SND_PCM_AES1_CON_PCM_CODER << 8));
+
+ /* S/PDIF input initialization */
+ ymfpci_writew(codec, YDSXGR_SPDIFINCTRL, 0);
+
+ /* move this volume setup to mixer */
+ ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff);
+ ymfpci_writel(codec, YDSXGR_BUF441OUTVOL, 0x3fff3fff);
+ ymfpci_writel(codec, YDSXGR_NATIVEADCINVOL, 0x3fff3fff);
+ ymfpci_writel(codec, YDSXGR_NATIVEDACINVOL, 0x3fff3fff);
+
+ return 0;
+}
+
+static void ymfpci_memfree(ymfpci_t *codec)
+{
+ ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, 0);
+ ymfpci_writel(codec, YDSXGR_RECCTRLBASE, 0);
+ ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, 0);
+ ymfpci_writel(codec, YDSXGR_WORKBASE, 0);
+ ymfpci_writel(codec, YDSXGR_WORKSIZE, 0);
+ kfree(codec->work_ptr);
+}
+
+static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
+{
+ struct ac97_codec *codec;
+ u16 eid;
+
+ if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ memset(codec, 0, sizeof(struct ac97_codec));
+
+ /* initialize some basic codec information, other fields will be filled
+ in ac97_probe_codec */
+ codec->private_data = card;
+ codec->id = num_ac97;
+
+ codec->codec_read = ymfpci_codec_read;
+ codec->codec_write = ymfpci_codec_write;
+
+ if (ac97_probe_codec(codec) == 0) {
+ printk("ymfpci: ac97_probe_codec failed\n");
+ goto out_kfree;
+ }
+
+ eid = ymfpci_codec_read(codec, AC97_EXTENDED_ID);
+ if (eid==0xFFFFFF) {
+ printk(KERN_WARNING "ymfpci: no codec attached ?\n");
+ goto out_kfree;
+ }
+
+ card->ac97_features = eid;
+
+ if ((codec->dev_mixer = register_sound_mixer(&ymf_mixer_fops, -1)) < 0) {
+ printk(KERN_ERR "ymfpci: couldn't register mixer!\n");
+ goto out_kfree;
+ }
+
+ card->ac97_codec[num_ac97] = codec;
+
+ return 0;
+ out_kfree:
+ kfree(codec);
+ return -ENODEV;
+}
+
+static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_device_id *ent)
+{
+ u16 ctrl;
+ ymfpci_t *codec;
+
+ int err;
+
+ if (pci_enable_device(pcidev) < 0) {
+ printk(KERN_ERR "ymfpci: pci_enable_device failed\n");
+ return -ENODEV;
+ }
+
+ if ((codec = kmalloc(sizeof(ymfpci_t), GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR "ymfpci: no core\n");
+ return -ENOMEM;
+ }
+ memset(codec, 0, sizeof(*codec));
+
+ spin_lock_init(&codec->reg_lock);
+ spin_lock_init(&codec->voice_lock);
+ init_MUTEX(&codec->open_sem);
+ codec->pci = pcidev;
+
+ pci_read_config_byte(pcidev, PCI_REVISION_ID, &codec->rev);
+ codec->reg_area_virt = ioremap(pci_resource_start(pcidev, 0), 0x8000);
+
+ printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",
+ (char *)ent->driver_data, pci_resource_start(pcidev, 0), pcidev->irq);
+
+ ymfpci_aclink_reset(pcidev);
+ if (ymfpci_codec_ready(codec, 0, 1) < 0)
+ goto out_unmap;
+
+ ymfpci_download_image(codec);
+
+ udelay(100); /* seems we need some delay after downloading image.. */
+
+ if (ymfpci_memalloc(codec) < 0)
+ goto out_disable_dsp;
+
+ /* ymfpci_proc_init(card, codec); */
+
+ if (request_irq(pcidev->irq, ymf_interrupt, SA_SHIRQ, "ymfpci", codec) != 0) {
+ printk(KERN_ERR "ymfpci%d: unable to request IRQ %d\n",
+ codec->dev_audio, pcidev->irq);
+ goto out_memfree;
+ }
+
+ /* register /dev/dsp */
+ if ((codec->dev_audio = register_sound_dsp(&ymf_fops, -1)) < 0) {
+ printk(KERN_ERR "ymfpci%d: unable to register dsp\n",
+ codec->dev_audio);
+ goto out_free_irq;
+ }
+
+ /*
+ * Poke just the primary for the moment.
+ */
+ if ((err = ymf_ac97_init(codec, 0)) != 0)
+ goto out_unregister_sound_dsp;
+
+ /* put it into driver list */
+ list_add_tail(&codec->ymf_devs, &ymf_devs);
+ pci_set_drvdata(pcidev, codec);
+
+ return 0;
+
+ out_unregister_sound_dsp:
+ unregister_sound_dsp(codec->dev_audio);
+ out_free_irq:
+ free_irq(pcidev->irq, codec);
+ out_memfree:
+ ymfpci_memfree(codec);
+ out_disable_dsp:
+ ymfpci_disable_dsp(codec);
+ ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL);
+ ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
+ ymfpci_writel(codec, YDSXGR_STATUS, ~0);
+ out_unmap:
+ iounmap(codec->reg_area_virt);
+ kfree(codec);
+ return -ENODEV;
+}
+
+static void __devexit ymf_remove_one(struct pci_dev *pcidev)
+{
+ __u16 ctrl;
+ ymfpci_t *codec = pci_get_drvdata(pcidev);
+
+ /* remove from list of devices */
+ list_del(&codec->ymf_devs);
+
+ unregister_sound_mixer(codec->ac97_codec[0]->dev_mixer);
+ kfree(codec->ac97_codec[0]);
+ unregister_sound_dsp(codec->dev_audio);
+ free_irq(pcidev->irq, codec);
+ ymfpci_memfree(codec);
+ ymfpci_writel(codec, YDSXGR_STATUS, ~0);
+ ymfpci_disable_dsp(codec);
+ ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL);
+ ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
+ iounmap(codec->reg_area_virt);
+ kfree(codec);
+}
+
+MODULE_AUTHOR("Jaroslav Kysela");
+MODULE_DESCRIPTION("Yamaha YMF7xx PCI Audio");
+
+static struct pci_driver ymfpci_driver = {
+ name: "ymfpci",
+ id_table: ymf_id_tbl,
+ probe: ymf_probe_one,
+ remove: ymf_remove_one,
+};
+
+static int __init ymf_init_module(void)
+{
+ return pci_module_init(&ymfpci_driver);
+}
+
+static void __exit ymf_cleanup_module (void)
+{
+ pci_unregister_driver(&ymfpci_driver);
+}
+
+module_init(ymf_init_module);
+module_exit(ymf_cleanup_module);
diff --git a/drivers/sound/ymfpci.h b/drivers/sound/ymfpci.h
new file mode 100644
index 000000000..6e1a8d5f3
--- /dev/null
+++ b/drivers/sound/ymfpci.h
@@ -0,0 +1,343 @@
+#ifndef __YMFPCI_H
+#define __YMFPCI_H
+
+/*
+ * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ * Definitions for Yahama YMF724/740/744/754 chips
+ *
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Direct registers
+ */
+
+/* #define YMFREG(codec, reg) (codec->port + YDSXGR_##reg) */
+
+#define YDSXGR_INTFLAG 0x0004
+#define YDSXGR_ACTIVITY 0x0006
+#define YDSXGR_GLOBALCTRL 0x0008
+#define YDSXGR_ZVCTRL 0x000A
+#define YDSXGR_TIMERCTRL 0x0010
+#define YDSXGR_TIMERCTRL_TEN 0x0001
+#define YDSXGR_TIMERCTRL_TIEN 0x0002
+#define YDSXGR_TIMERCOUNT 0x0012
+#define YDSXGR_SPDIFOUTCTRL 0x0018
+#define YDSXGR_SPDIFOUTSTATUS 0x001C
+#define YDSXGR_EEPROMCTRL 0x0020
+#define YDSXGR_SPDIFINCTRL 0x0034
+#define YDSXGR_SPDIFINSTATUS 0x0038
+#define YDSXGR_DSPPROGRAMDL 0x0048
+#define YDSXGR_DLCNTRL 0x004C
+#define YDSXGR_GPIOININTFLAG 0x0050
+#define YDSXGR_GPIOININTENABLE 0x0052
+#define YDSXGR_GPIOINSTATUS 0x0054
+#define YDSXGR_GPIOOUTCTRL 0x0056
+#define YDSXGR_GPIOFUNCENABLE 0x0058
+#define YDSXGR_GPIOTYPECONFIG 0x005A
+#define YDSXGR_AC97CMDDATA 0x0060
+#define YDSXGR_AC97CMDADR 0x0062
+#define YDSXGR_PRISTATUSDATA 0x0064
+#define YDSXGR_PRISTATUSADR 0x0066
+#define YDSXGR_SECSTATUSDATA 0x0068
+#define YDSXGR_SECSTATUSADR 0x006A
+#define YDSXGR_SECCONFIG 0x0070
+#define YDSXGR_LEGACYOUTVOL 0x0080
+#define YDSXGR_LEGACYOUTVOLL 0x0080
+#define YDSXGR_LEGACYOUTVOLR 0x0082
+#define YDSXGR_NATIVEDACOUTVOL 0x0084
+#define YDSXGR_NATIVEDACOUTVOLL 0x0084
+#define YDSXGR_NATIVEDACOUTVOLR 0x0086
+#define YDSXGR_SPDIFOUTVOL 0x0088
+#define YDSXGR_SPDIFOUTVOLL 0x0088
+#define YDSXGR_SPDIFOUTVOLR 0x008A
+#define YDSXGR_AC3OUTVOL 0x008C
+#define YDSXGR_AC3OUTVOLL 0x008C
+#define YDSXGR_AC3OUTVOLR 0x008E
+#define YDSXGR_PRIADCOUTVOL 0x0090
+#define YDSXGR_PRIADCOUTVOLL 0x0090
+#define YDSXGR_PRIADCOUTVOLR 0x0092
+#define YDSXGR_LEGACYLOOPVOL 0x0094
+#define YDSXGR_LEGACYLOOPVOLL 0x0094
+#define YDSXGR_LEGACYLOOPVOLR 0x0096
+#define YDSXGR_NATIVEDACLOOPVOL 0x0098
+#define YDSXGR_NATIVEDACLOOPVOLL 0x0098
+#define YDSXGR_NATIVEDACLOOPVOLR 0x009A
+#define YDSXGR_SPDIFLOOPVOL 0x009C
+#define YDSXGR_SPDIFLOOPVOLL 0x009E
+#define YDSXGR_SPDIFLOOPVOLR 0x009E
+#define YDSXGR_AC3LOOPVOL 0x00A0
+#define YDSXGR_AC3LOOPVOLL 0x00A0
+#define YDSXGR_AC3LOOPVOLR 0x00A2
+#define YDSXGR_PRIADCLOOPVOL 0x00A4
+#define YDSXGR_PRIADCLOOPVOLL 0x00A4
+#define YDSXGR_PRIADCLOOPVOLR 0x00A6
+#define YDSXGR_NATIVEADCINVOL 0x00A8
+#define YDSXGR_NATIVEADCINVOLL 0x00A8
+#define YDSXGR_NATIVEADCINVOLR 0x00AA
+#define YDSXGR_NATIVEDACINVOL 0x00AC
+#define YDSXGR_NATIVEDACINVOLL 0x00AC
+#define YDSXGR_NATIVEDACINVOLR 0x00AE
+#define YDSXGR_BUF441OUTVOL 0x00B0
+#define YDSXGR_BUF441OUTVOLL 0x00B0
+#define YDSXGR_BUF441OUTVOLR 0x00B2
+#define YDSXGR_BUF441LOOPVOL 0x00B4
+#define YDSXGR_BUF441LOOPVOLL 0x00B4
+#define YDSXGR_BUF441LOOPVOLR 0x00B6
+#define YDSXGR_SPDIFOUTVOL2 0x00B8
+#define YDSXGR_SPDIFOUTVOL2L 0x00B8
+#define YDSXGR_SPDIFOUTVOL2R 0x00BA
+#define YDSXGR_SPDIFLOOPVOL2 0x00BC
+#define YDSXGR_SPDIFLOOPVOL2L 0x00BC
+#define YDSXGR_SPDIFLOOPVOL2R 0x00BE
+#define YDSXGR_ADCSLOTSR 0x00C0
+#define YDSXGR_RECSLOTSR 0x00C4
+#define YDSXGR_ADCFORMAT 0x00C8
+#define YDSXGR_RECFORMAT 0x00CC
+#define YDSXGR_P44SLOTSR 0x00D0
+#define YDSXGR_STATUS 0x0100
+#define YDSXGR_CTRLSELECT 0x0104
+#define YDSXGR_MODE 0x0108
+#define YDSXGR_SAMPLECOUNT 0x010C
+#define YDSXGR_NUMOFSAMPLES 0x0110
+#define YDSXGR_CONFIG 0x0114
+#define YDSXGR_PLAYCTRLSIZE 0x0140
+#define YDSXGR_RECCTRLSIZE 0x0144
+#define YDSXGR_EFFCTRLSIZE 0x0148
+#define YDSXGR_WORKSIZE 0x014C
+#define YDSXGR_MAPOFREC 0x0150
+#define YDSXGR_MAPOFEFFECT 0x0154
+#define YDSXGR_PLAYCTRLBASE 0x0158
+#define YDSXGR_RECCTRLBASE 0x015C
+#define YDSXGR_EFFCTRLBASE 0x0160
+#define YDSXGR_WORKBASE 0x0164
+#define YDSXGR_DSPINSTRAM 0x1000
+#define YDSXGR_CTRLINSTRAM 0x4000
+
+#define YDSXG_AC97READCMD 0x8000
+#define YDSXG_AC97WRITECMD 0x0000
+
+#define PCIR_DSXGCTRL 0x48
+
+#define YDSXG_DSPLENGTH 0x0080
+#define YDSXG_CTRLLENGTH 0x3000
+
+#define YDSXG_DEFAULT_WORK_SIZE 0x0400
+
+#define YDSXG_PLAYBACK_VOICES 64
+#define YDSXG_CAPTURE_VOICES 2
+#define YDSXG_EFFECT_VOICES 5
+
+/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
+#define NR_AC97 2
+
+#define YMF_SAMPF 256 /* Samples per frame @48000 */
+
+/*
+ * The slot/voice control bank (2 of these per voice)
+ */
+
+typedef struct stru_ymfpci_playback_bank {
+ u32 format;
+ u32 loop_default;
+ u32 base; /* 32-bit address */
+ u32 loop_start; /* 32-bit offset */
+ u32 loop_end; /* 32-bit offset */
+ u32 loop_frac; /* 8-bit fraction - loop_start */
+ u32 delta_end; /* pitch delta end */
+ u32 lpfK_end;
+ u32 eg_gain_end;
+ u32 left_gain_end;
+ u32 right_gain_end;
+ u32 eff1_gain_end;
+ u32 eff2_gain_end;
+ u32 eff3_gain_end;
+ u32 lpfQ;
+ u32 status; /* P3: Always 0 for some reason. */
+ u32 num_of_frames;
+ u32 loop_count;
+ u32 start; /* P3: J. reads this to know where chip is. */
+ u32 start_frac;
+ u32 delta;
+ u32 lpfK;
+ u32 eg_gain;
+ u32 left_gain;
+ u32 right_gain;
+ u32 eff1_gain;
+ u32 eff2_gain;
+ u32 eff3_gain;
+ u32 lpfD1;
+ u32 lpfD2;
+} ymfpci_playback_bank_t;
+
+typedef struct stru_ymfpci_capture_bank {
+ u32 base; /* 32-bit address */
+ u32 loop_end; /* 32-bit offset */
+ u32 start; /* 32-bit offset */
+ u32 num_of_loops; /* counter */
+} ymfpci_capture_bank_t;
+
+typedef struct stru_ymfpci_effect_bank {
+ u32 base; /* 32-bit address */
+ u32 loop_end; /* 32-bit offset */
+ u32 start; /* 32-bit offset */
+ u32 temp;
+} ymfpci_effect_bank_t;
+
+typedef struct stru_ymfpci_voice ymfpci_voice_t;
+typedef struct ymf_pcm ymfpci_pcm_t;
+/*
+ * Throughout the code Yaroslav names YMF unit pointer "codec"
+ * even though it does not correspond to any codec. Must be historic.
+ * We replace it with "unit" over time.
+ * AC97 parts use "codec" to denote a codec, naturally.
+ */
+typedef struct ymf_unit ymfpci_t;
+
+typedef enum {
+ YMFPCI_PCM,
+ YMFPCI_SYNTH,
+ YMFPCI_MIDI
+} ymfpci_voice_type_t;
+
+struct stru_ymfpci_voice {
+ ymfpci_t *codec;
+ int number;
+ int use: 1,
+ pcm: 1,
+ synth: 1,
+ midi: 1;
+ ymfpci_playback_bank_t *bank;
+ void (*interrupt)(ymfpci_t *codec, ymfpci_voice_t *voice);
+ ymfpci_pcm_t *ypcm;
+};
+
+typedef enum {
+ PLAYBACK_VOICE,
+ CAPTURE_REC,
+ CAPTURE_AC97,
+ EFFECT_DRY_LEFT,
+ EFFECT_DRY_RIGHT,
+ EFFECT_EFF1,
+ EFFECT_EFF2,
+ EFFECT_EFF3
+} ymfpci_pcm_type_t;
+
+struct ymf_pcm {
+ ymfpci_t *codec;
+ ymfpci_pcm_type_t type;
+ struct ymf_state *state;
+ ymfpci_voice_t *voices[2]; /* playback only */
+ int running; // +
+ int spdif;
+};
+
+struct ymf_unit {
+ u8 rev; /* PCI revision */
+ void *reg_area_virt;
+ void *work_ptr; // +
+
+ unsigned int bank_size_playback;
+ unsigned int bank_size_capture;
+ unsigned int bank_size_effect;
+ unsigned int work_size;
+
+ void *bank_base_playback; // +
+ void *bank_base_capture; // +
+ void *bank_base_effect; // +
+ void *work_base; // +
+
+ u32 *ctrl_playback;
+ ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2];
+ ymfpci_capture_bank_t *bank_capture[YDSXG_CAPTURE_VOICES][2];
+ ymfpci_effect_bank_t *bank_effect[YDSXG_EFFECT_VOICES][2];
+
+ int start_count;
+
+ u32 active_bank;
+ ymfpci_voice_t voices[64];
+
+ struct ac97_codec *ac97_codec[NR_AC97];
+ u16 ac97_features;
+
+ struct pci_dev *pci;
+
+ spinlock_t reg_lock;
+ spinlock_t voice_lock;
+
+ /* soundcore stuff */
+ int dev_audio;
+ struct semaphore open_sem;
+
+ struct list_head ymf_devs;
+ struct ymf_state *states[1]; // *
+ /* ypcm may be the same thing as state, but not for record, effects. */
+};
+
+/*
+ * "Software" or virtual channel, an instance of opened /dev/dsp.
+ */
+
+struct ymf_dmabuf {
+
+ /* OSS buffer management stuff */
+ void *rawbuf;
+ unsigned buforder;
+ unsigned numfrag;
+ unsigned fragshift;
+
+ /* our buffer acts like a circular ring */
+ unsigned hwptr; /* where dma last started */
+ unsigned swptr; /* where driver last clear/filled */
+ int count; /* fill count */
+ unsigned total_bytes; /* total bytes dmaed by hardware */
+
+ unsigned error; /* number of over/underruns */
+ wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */
+
+ /* redundant, but makes calculations easier */
+ unsigned fragsize;
+ unsigned dmasize; /* Total rawbuf[] size */
+ unsigned fragsamples;
+
+ /* OSS stuff */
+ unsigned mapped:1;
+ unsigned ready:1;
+ unsigned ossfragshift;
+ int ossmaxfrags;
+ unsigned subdivision;
+};
+
+struct ymf_pcm_format {
+ int format; /* OSS format */
+ int rate; /* rate in Hz */
+ int voices; /* number of voices */
+ int shift; /* redundant, computed from the above */
+};
+
+struct ymf_state {
+ struct ymf_unit *unit; /* backpointer */
+
+ /* virtual channel number */
+ int virt; // * unused a.t.m.
+
+ struct ymf_pcm ypcm; // *
+ struct ymf_dmabuf dmabuf; // *
+ struct ymf_pcm_format format; // *
+};
+
+#endif /* __YMFPCI_H */
diff --git a/drivers/sound/ymfpci_image.h b/drivers/sound/ymfpci_image.h
new file mode 100644
index 000000000..2cef1e1d5
--- /dev/null
+++ b/drivers/sound/ymfpci_image.h
@@ -0,0 +1,1565 @@
+#ifndef _HWMCODE_
+#define _HWMCODE_
+
+static unsigned long int DspInst[] = {
+ 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
+ 0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
+ 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
+ 0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+static unsigned long int CntrlInst[] = {
+ 0x000007, 0x240007, 0x0C0007, 0x1C0007,
+ 0x060007, 0x700002, 0x000020, 0x030040,
+ 0x007104, 0x004286, 0x030040, 0x000F0D,
+ 0x000810, 0x20043A, 0x000282, 0x00020D,
+ 0x000810, 0x20043A, 0x001282, 0x200E82,
+ 0x001A82, 0x032D0D, 0x000810, 0x10043A,
+ 0x02D38D, 0x000810, 0x18043A, 0x00010D,
+ 0x020015, 0x0000FD, 0x000020, 0x038860,
+ 0x039060, 0x038060, 0x038040, 0x038040,
+ 0x038040, 0x018040, 0x000A7D, 0x038040,
+ 0x038040, 0x018040, 0x200402, 0x000882,
+ 0x08001A, 0x000904, 0x015986, 0x000007,
+ 0x260007, 0x000007, 0x000007, 0x018A06,
+ 0x000007, 0x030C8D, 0x000810, 0x18043A,
+ 0x260007, 0x00087D, 0x018042, 0x00160A,
+ 0x04A206, 0x000007, 0x00218D, 0x000810,
+ 0x08043A, 0x21C206, 0x000007, 0x0007FD,
+ 0x018042, 0x08000A, 0x000904, 0x029386,
+ 0x000195, 0x090D04, 0x000007, 0x000820,
+ 0x0000F5, 0x000B7D, 0x01F060, 0x0000FD,
+ 0x032206, 0x018040, 0x000A7D, 0x038042,
+ 0x13804A, 0x18000A, 0x001820, 0x059060,
+ 0x058860, 0x018040, 0x0000FD, 0x018042,
+ 0x70000A, 0x000115, 0x071144, 0x032386,
+ 0x030000, 0x007020, 0x034A06, 0x018040,
+ 0x00348D, 0x000810, 0x08043A, 0x21EA06,
+ 0x000007, 0x02D38D, 0x000810, 0x18043A,
+ 0x018206, 0x000007, 0x240007, 0x000F8D,
+ 0x000810, 0x00163A, 0x002402, 0x005C02,
+ 0x0028FD, 0x000020, 0x018040, 0x08000D,
+ 0x000815, 0x510984, 0x000007, 0x00004D,
+ 0x000E5D, 0x000E02, 0x00418D, 0x000810,
+ 0x08043A, 0x2C8A06, 0x000007, 0x00008D,
+ 0x000924, 0x000F02, 0x00458D, 0x000810,
+ 0x08043A, 0x2C8A06, 0x000007, 0x00387D,
+ 0x018042, 0x08000A, 0x001015, 0x010984,
+ 0x018386, 0x000007, 0x01AA06, 0x000007,
+ 0x0008FD, 0x018042, 0x18000A, 0x001904,
+ 0x218086, 0x280007, 0x001810, 0x28043A,
+ 0x280C02, 0x00000D, 0x000810, 0x28143A,
+ 0x08808D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00020D, 0x189904, 0x000007,
+ 0x00402D, 0x0000BD, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x055A86, 0x000007,
+ 0x000100, 0x000A20, 0x00047D, 0x018040,
+ 0x018042, 0x20000A, 0x003015, 0x012144,
+ 0x034986, 0x000007, 0x002104, 0x034986,
+ 0x000007, 0x000F8D, 0x000810, 0x280C3A,
+ 0x023944, 0x06C986, 0x000007, 0x001810,
+ 0x28043A, 0x08810D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x002810, 0x78003A,
+ 0x00688D, 0x000810, 0x08043A, 0x288A06,
+ 0x000007, 0x00400D, 0x001015, 0x189904,
+ 0x292904, 0x393904, 0x000007, 0x060206,
+ 0x000007, 0x0004F5, 0x00007D, 0x000020,
+ 0x00008D, 0x010860, 0x018040, 0x00047D,
+ 0x038042, 0x21804A, 0x18000A, 0x021944,
+ 0x215886, 0x000007, 0x004075, 0x71F104,
+ 0x000007, 0x010042, 0x28000A, 0x002904,
+ 0x212086, 0x000007, 0x003C0D, 0x30A904,
+ 0x000007, 0x00077D, 0x018042, 0x08000A,
+ 0x000904, 0x07DA86, 0x00057D, 0x002820,
+ 0x03B060, 0x07F206, 0x018040, 0x003020,
+ 0x03A860, 0x018040, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x07FA86, 0x000007,
+ 0x00057D, 0x018042, 0x28040A, 0x000E8D,
+ 0x000810, 0x280C3A, 0x00000D, 0x000810,
+ 0x28143A, 0x09000D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x003DFD, 0x000020,
+ 0x018040, 0x00107D, 0x008D8D, 0x000810,
+ 0x08043A, 0x288A06, 0x000007, 0x000815,
+ 0x08001A, 0x010984, 0x095186, 0x00137D,
+ 0x200500, 0x280F20, 0x338F60, 0x3B8F60,
+ 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
+ 0x038A60, 0x018040, 0x007FBD, 0x383DC4,
+ 0x000007, 0x001A7D, 0x001375, 0x018042,
+ 0x09004A, 0x10000A, 0x0B8D04, 0x139504,
+ 0x000007, 0x000820, 0x019060, 0x001104,
+ 0x212086, 0x010040, 0x0017FD, 0x018042,
+ 0x08000A, 0x000904, 0x212286, 0x000007,
+ 0x00197D, 0x038042, 0x09804A, 0x10000A,
+ 0x000924, 0x001664, 0x0011FD, 0x038042,
+ 0x2B804A, 0x19804A, 0x00008D, 0x218944,
+ 0x000007, 0x002244, 0x0AE186, 0x000007,
+ 0x001A64, 0x002A24, 0x00197D, 0x080102,
+ 0x100122, 0x000820, 0x039060, 0x018040,
+ 0x003DFD, 0x00008D, 0x000820, 0x018040,
+ 0x001375, 0x001A7D, 0x010042, 0x09804A,
+ 0x10000A, 0x00021D, 0x0189E4, 0x2992E4,
+ 0x309144, 0x000007, 0x00060D, 0x000A15,
+ 0x000C1D, 0x001025, 0x00A9E4, 0x012BE4,
+ 0x000464, 0x01B3E4, 0x0232E4, 0x000464,
+ 0x000464, 0x000464, 0x000464, 0x00040D,
+ 0x08B1C4, 0x000007, 0x000820, 0x000BF5,
+ 0x030040, 0x00197D, 0x038042, 0x09804A,
+ 0x000A24, 0x08000A, 0x080E64, 0x000007,
+ 0x100122, 0x000820, 0x031060, 0x010040,
+ 0x0064AC, 0x00027D, 0x000020, 0x018040,
+ 0x00107D, 0x018042, 0x0011FD, 0x3B804A,
+ 0x09804A, 0x20000A, 0x000095, 0x1A1144,
+ 0x00A144, 0x0D2086, 0x00040D, 0x00B984,
+ 0x0D2186, 0x0018FD, 0x018042, 0x0010FD,
+ 0x09804A, 0x28000A, 0x000095, 0x010924,
+ 0x002A64, 0x0D1186, 0x000007, 0x002904,
+ 0x0D2286, 0x000007, 0x0D2A06, 0x080002,
+ 0x00008D, 0x00387D, 0x000820, 0x018040,
+ 0x00127D, 0x018042, 0x10000A, 0x003904,
+ 0x0DD186, 0x00080D, 0x7FFFB5, 0x00B984,
+ 0x0DA186, 0x000025, 0x0E7A06, 0x00002D,
+ 0x000015, 0x00082D, 0x02C78D, 0x000820,
+ 0x0EC206, 0x00000D, 0x7F8035, 0x00B984,
+ 0x0E7186, 0x400025, 0x00008D, 0x110944,
+ 0x000007, 0x00018D, 0x109504, 0x000007,
+ 0x009164, 0x000424, 0x000424, 0x000424,
+ 0x100102, 0x280002, 0x02C68D, 0x000820,
+ 0x0EC206, 0x00018D, 0x00042D, 0x00008D,
+ 0x109504, 0x000007, 0x00020D, 0x109184,
+ 0x000007, 0x02C70D, 0x000820, 0x00008D,
+ 0x0038FD, 0x018040, 0x003BFD, 0x001020,
+ 0x03A860, 0x000815, 0x313184, 0x212184,
+ 0x000007, 0x03B060, 0x03A060, 0x018040,
+ 0x0022FD, 0x000095, 0x010924, 0x000424,
+ 0x000424, 0x001264, 0x100102, 0x000820,
+ 0x039060, 0x018040, 0x001924, 0x00FB8D,
+ 0x00397D, 0x000820, 0x058040, 0x038042,
+ 0x09844A, 0x000606, 0x08040A, 0x000424,
+ 0x000424, 0x00117D, 0x018042, 0x08000A,
+ 0x000A24, 0x280502, 0x280C02, 0x09800D,
+ 0x000820, 0x0002FD, 0x018040, 0x200007,
+ 0x0022FD, 0x018042, 0x08000A, 0x000095,
+ 0x280DC4, 0x011924, 0x00197D, 0x018042,
+ 0x0011FD, 0x09804A, 0x10000A, 0x0000B5,
+ 0x113144, 0x0A8D04, 0x000007, 0x080A44,
+ 0x129504, 0x000007, 0x0023FD, 0x001020,
+ 0x038040, 0x101244, 0x000007, 0x000820,
+ 0x039060, 0x018040, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x10FA86, 0x000007,
+ 0x003BFD, 0x000100, 0x000A10, 0x0B807A,
+ 0x13804A, 0x090984, 0x000007, 0x000095,
+ 0x013D04, 0x118086, 0x10000A, 0x100002,
+ 0x090984, 0x000007, 0x038042, 0x11804A,
+ 0x090D04, 0x000007, 0x10000A, 0x090D84,
+ 0x000007, 0x00257D, 0x000820, 0x018040,
+ 0x00010D, 0x000810, 0x28143A, 0x00127D,
+ 0x018042, 0x20000A, 0x00197D, 0x018042,
+ 0x00117D, 0x31804A, 0x10000A, 0x003124,
+ 0x01280D, 0x00397D, 0x000820, 0x058040,
+ 0x038042, 0x09844A, 0x000606, 0x08040A,
+ 0x300102, 0x003124, 0x000424, 0x000424,
+ 0x001224, 0x280502, 0x001A4C, 0x130186,
+ 0x700002, 0x00002D, 0x030000, 0x00387D,
+ 0x018042, 0x10000A, 0x132A06, 0x002124,
+ 0x0000AD, 0x100002, 0x00010D, 0x000924,
+ 0x006B24, 0x01368D, 0x00397D, 0x000820,
+ 0x058040, 0x038042, 0x09844A, 0x000606,
+ 0x08040A, 0x003264, 0x00008D, 0x000A24,
+ 0x001020, 0x00227D, 0x018040, 0x013C0D,
+ 0x000810, 0x08043A, 0x29D206, 0x000007,
+ 0x002820, 0x00207D, 0x018040, 0x00117D,
+ 0x038042, 0x13804A, 0x33800A, 0x00387D,
+ 0x018042, 0x08000A, 0x000904, 0x163A86,
+ 0x000007, 0x00008D, 0x030964, 0x01478D,
+ 0x00397D, 0x000820, 0x058040, 0x038042,
+ 0x09844A, 0x000606, 0x08040A, 0x380102,
+ 0x000424, 0x000424, 0x001224, 0x0002FD,
+ 0x018042, 0x08000A, 0x000904, 0x14A286,
+ 0x000007, 0x280502, 0x001A4C, 0x163986,
+ 0x000007, 0x032164, 0x00632C, 0x003DFD,
+ 0x018042, 0x08000A, 0x000095, 0x090904,
+ 0x000007, 0x000820, 0x001A4C, 0x156186,
+ 0x018040, 0x030000, 0x157A06, 0x002124,
+ 0x00010D, 0x000924, 0x006B24, 0x015B8D,
+ 0x00397D, 0x000820, 0x058040, 0x038042,
+ 0x09844A, 0x000606, 0x08040A, 0x003A64,
+ 0x000095, 0x001224, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x15DA86, 0x000007,
+ 0x01628D, 0x000810, 0x08043A, 0x29D206,
+ 0x000007, 0x14D206, 0x000007, 0x007020,
+ 0x08010A, 0x10012A, 0x0020FD, 0x038860,
+ 0x039060, 0x018040, 0x00227D, 0x018042,
+ 0x003DFD, 0x08000A, 0x31844A, 0x000904,
+ 0x16D886, 0x18008B, 0x00008D, 0x189904,
+ 0x00312C, 0x17AA06, 0x000007, 0x00324C,
+ 0x173386, 0x000007, 0x001904, 0x173086,
+ 0x000007, 0x000095, 0x199144, 0x00222C,
+ 0x003124, 0x00636C, 0x000E3D, 0x001375,
+ 0x000BFD, 0x010042, 0x09804A, 0x10000A,
+ 0x038AEC, 0x0393EC, 0x00224C, 0x17A986,
+ 0x000007, 0x00008D, 0x189904, 0x00226C,
+ 0x00322C, 0x30050A, 0x301DAB, 0x002083,
+ 0x0018FD, 0x018042, 0x08000A, 0x018924,
+ 0x300502, 0x001083, 0x001875, 0x010042,
+ 0x10000A, 0x00008D, 0x010924, 0x001375,
+ 0x330542, 0x330CCB, 0x332CCB, 0x3334CB,
+ 0x333CCB, 0x3344CB, 0x334CCB, 0x3354CB,
+ 0x305C8B, 0x006083, 0x0002F5, 0x010042,
+ 0x08000A, 0x000904, 0x187A86, 0x000007,
+ 0x001E2D, 0x0005FD, 0x018042, 0x08000A,
+ 0x028924, 0x280502, 0x00060D, 0x000810,
+ 0x280C3A, 0x00008D, 0x000810, 0x28143A,
+ 0x0A808D, 0x000820, 0x0002F5, 0x010040,
+ 0x220007, 0x001275, 0x030042, 0x21004A,
+ 0x00008D, 0x1A0944, 0x000007, 0x01980D,
+ 0x000810, 0x08043A, 0x2B2206, 0x000007,
+ 0x0001F5, 0x030042, 0x0D004A, 0x10000A,
+ 0x089144, 0x000007, 0x000820, 0x010040,
+ 0x0025F5, 0x0A3144, 0x000007, 0x000820,
+ 0x032860, 0x030040, 0x00217D, 0x038042,
+ 0x0B804A, 0x10000A, 0x000820, 0x031060,
+ 0x030040, 0x00008D, 0x000124, 0x00012C,
+ 0x000E64, 0x001A64, 0x00636C, 0x08010A,
+ 0x10012A, 0x000820, 0x031060, 0x030040,
+ 0x0020FD, 0x018042, 0x08000A, 0x00227D,
+ 0x018042, 0x10000A, 0x000820, 0x031060,
+ 0x030040, 0x00197D, 0x018042, 0x08000A,
+ 0x0022FD, 0x038042, 0x10000A, 0x000820,
+ 0x031060, 0x030040, 0x090D04, 0x000007,
+ 0x000820, 0x030040, 0x038042, 0x0B804A,
+ 0x10000A, 0x000820, 0x031060, 0x030040,
+ 0x038042, 0x13804A, 0x19804A, 0x110D04,
+ 0x198D04, 0x000007, 0x08000A, 0x001020,
+ 0x031860, 0x030860, 0x030040, 0x00008D,
+ 0x0B0944, 0x000007, 0x000820, 0x010040,
+ 0x0005F5, 0x030042, 0x08000A, 0x000820,
+ 0x010040, 0x0000F5, 0x010042, 0x08000A,
+ 0x000904, 0x1C6086, 0x001E75, 0x030042,
+ 0x01044A, 0x000C0A, 0x1C7206, 0x000007,
+ 0x000402, 0x000C02, 0x00177D, 0x001AF5,
+ 0x018042, 0x03144A, 0x031C4A, 0x03244A,
+ 0x032C4A, 0x03344A, 0x033C4A, 0x03444A,
+ 0x004C0A, 0x00043D, 0x0013F5, 0x001AFD,
+ 0x030042, 0x0B004A, 0x1B804A, 0x13804A,
+ 0x20000A, 0x089144, 0x19A144, 0x0389E4,
+ 0x0399EC, 0x005502, 0x005D0A, 0x030042,
+ 0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
+ 0x089144, 0x19A144, 0x0389E4, 0x0399EC,
+ 0x006502, 0x006D0A, 0x030042, 0x0B004A,
+ 0x19004A, 0x2B804A, 0x13804A, 0x21804A,
+ 0x30000A, 0x089144, 0x19A144, 0x2AB144,
+ 0x0389E4, 0x0399EC, 0x007502, 0x007D0A,
+ 0x03A9E4, 0x000702, 0x00107D, 0x000415,
+ 0x018042, 0x08000A, 0x0109E4, 0x000F02,
+ 0x002AF5, 0x0019FD, 0x010042, 0x09804A,
+ 0x10000A, 0x000934, 0x001674, 0x0029F5,
+ 0x010042, 0x10000A, 0x00917C, 0x002075,
+ 0x010042, 0x08000A, 0x000904, 0x1ED286,
+ 0x0026F5, 0x0027F5, 0x030042, 0x09004A,
+ 0x10000A, 0x000A3C, 0x00167C, 0x001A75,
+ 0x000BFD, 0x010042, 0x51804A, 0x48000A,
+ 0x160007, 0x001075, 0x010042, 0x282C0A,
+ 0x281D12, 0x282512, 0x001F32, 0x1E0007,
+ 0x0E0007, 0x001975, 0x010042, 0x002DF5,
+ 0x0D004A, 0x10000A, 0x009144, 0x1FB286,
+ 0x010042, 0x28340A, 0x000E5D, 0x00008D,
+ 0x000375, 0x000820, 0x010040, 0x05D2F4,
+ 0x54D104, 0x00735C, 0x205386, 0x000007,
+ 0x0C0007, 0x080007, 0x0A0007, 0x02040D,
+ 0x000810, 0x08043A, 0x332206, 0x000007,
+ 0x205A06, 0x000007, 0x080007, 0x002275,
+ 0x010042, 0x20000A, 0x002104, 0x212086,
+ 0x001E2D, 0x0002F5, 0x010042, 0x08000A,
+ 0x000904, 0x209286, 0x000007, 0x002010,
+ 0x30043A, 0x00057D, 0x0180C3, 0x08000A,
+ 0x028924, 0x280502, 0x280C02, 0x0A810D,
+ 0x000820, 0x0002F5, 0x010040, 0x220007,
+ 0x0004FD, 0x018042, 0x70000A, 0x030000,
+ 0x007020, 0x06FA06, 0x018040, 0x02180D,
+ 0x000810, 0x08043A, 0x2B2206, 0x000007,
+ 0x0002FD, 0x018042, 0x08000A, 0x000904,
+ 0x218A86, 0x000007, 0x01F206, 0x000007,
+ 0x000875, 0x0009FD, 0x00010D, 0x220A06,
+ 0x000295, 0x000B75, 0x00097D, 0x00000D,
+ 0x000515, 0x010042, 0x18000A, 0x001904,
+ 0x287886, 0x0006F5, 0x001020, 0x010040,
+ 0x0004F5, 0x000820, 0x010040, 0x000775,
+ 0x010042, 0x09804A, 0x10000A, 0x001124,
+ 0x000904, 0x22BA86, 0x000815, 0x080102,
+ 0x101204, 0x22DA06, 0x000575, 0x081204,
+ 0x000007, 0x100102, 0x000575, 0x000425,
+ 0x021124, 0x100102, 0x000820, 0x031060,
+ 0x010040, 0x001924, 0x287886, 0x00008D,
+ 0x000464, 0x009D04, 0x278886, 0x180102,
+ 0x000575, 0x010042, 0x28040A, 0x00018D,
+ 0x000924, 0x280D02, 0x00000D, 0x000924,
+ 0x281502, 0x10000D, 0x000820, 0x0002F5,
+ 0x010040, 0x200007, 0x001175, 0x0002FD,
+ 0x018042, 0x08000A, 0x000904, 0x23C286,
+ 0x000007, 0x000100, 0x080B20, 0x130B60,
+ 0x1B0B60, 0x030A60, 0x010040, 0x050042,
+ 0x3D004A, 0x35004A, 0x2D004A, 0x20000A,
+ 0x0006F5, 0x010042, 0x28140A, 0x0004F5,
+ 0x010042, 0x08000A, 0x000315, 0x010D04,
+ 0x24CA86, 0x004015, 0x000095, 0x010D04,
+ 0x24B886, 0x100022, 0x10002A, 0x24E206,
+ 0x000007, 0x333104, 0x2AA904, 0x000007,
+ 0x032124, 0x280502, 0x001124, 0x000424,
+ 0x000424, 0x003224, 0x00292C, 0x00636C,
+ 0x25F386, 0x000007, 0x02B164, 0x000464,
+ 0x000464, 0x00008D, 0x000A64, 0x280D02,
+ 0x10008D, 0x000820, 0x0002F5, 0x010040,
+ 0x220007, 0x00008D, 0x38B904, 0x000007,
+ 0x03296C, 0x30010A, 0x0002F5, 0x010042,
+ 0x08000A, 0x000904, 0x25BA86, 0x000007,
+ 0x02312C, 0x28050A, 0x00008D, 0x01096C,
+ 0x280D0A, 0x10010D, 0x000820, 0x0002F5,
+ 0x010040, 0x220007, 0x001124, 0x000424,
+ 0x000424, 0x003224, 0x300102, 0x032944,
+ 0x267A86, 0x000007, 0x300002, 0x0004F5,
+ 0x010042, 0x08000A, 0x000315, 0x010D04,
+ 0x26C086, 0x003124, 0x000464, 0x300102,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x26CA86, 0x000007, 0x003124, 0x300502,
+ 0x003924, 0x300583, 0x000883, 0x0005F5,
+ 0x010042, 0x28040A, 0x00008D, 0x008124,
+ 0x280D02, 0x00008D, 0x008124, 0x281502,
+ 0x10018D, 0x000820, 0x0002F5, 0x010040,
+ 0x220007, 0x001025, 0x000575, 0x030042,
+ 0x09004A, 0x10000A, 0x0A0904, 0x121104,
+ 0x000007, 0x001020, 0x050860, 0x050040,
+ 0x0006FD, 0x018042, 0x09004A, 0x10000A,
+ 0x0000A5, 0x0A0904, 0x121104, 0x000007,
+ 0x000820, 0x019060, 0x010040, 0x0002F5,
+ 0x010042, 0x08000A, 0x000904, 0x284286,
+ 0x000007, 0x230A06, 0x000007, 0x000606,
+ 0x000007, 0x0002F5, 0x010042, 0x08000A,
+ 0x000904, 0x289286, 0x000007, 0x000100,
+ 0x080B20, 0x138B60, 0x1B8B60, 0x238B60,
+ 0x2B8B60, 0x338B60, 0x3B8B60, 0x438B60,
+ 0x4B8B60, 0x538B60, 0x5B8B60, 0x638B60,
+ 0x6B8B60, 0x738B60, 0x7B8B60, 0x038F60,
+ 0x0B8F60, 0x138F60, 0x1B8F60, 0x238F60,
+ 0x2B8F60, 0x338F60, 0x3B8F60, 0x438F60,
+ 0x4B8F60, 0x538F60, 0x5B8F60, 0x638F60,
+ 0x6B8F60, 0x738F60, 0x7B8F60, 0x038A60,
+ 0x000606, 0x018040, 0x00008D, 0x000A64,
+ 0x280D02, 0x000A24, 0x00027D, 0x018042,
+ 0x10000A, 0x001224, 0x0003FD, 0x018042,
+ 0x08000A, 0x000904, 0x2A8286, 0x000007,
+ 0x00018D, 0x000A24, 0x000464, 0x000464,
+ 0x080102, 0x000924, 0x000424, 0x000424,
+ 0x100102, 0x02000D, 0x009144, 0x2AD986,
+ 0x000007, 0x0001FD, 0x018042, 0x08000A,
+ 0x000A44, 0x2ABB86, 0x018042, 0x0A000D,
+ 0x000820, 0x0002FD, 0x018040, 0x200007,
+ 0x00027D, 0x001020, 0x000606, 0x018040,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x2B2A86, 0x000007, 0x00037D, 0x018042,
+ 0x08000A, 0x000904, 0x2B5A86, 0x000007,
+ 0x000075, 0x002E7D, 0x010042, 0x0B804A,
+ 0x000020, 0x000904, 0x000686, 0x010040,
+ 0x31844A, 0x30048B, 0x000883, 0x00008D,
+ 0x000810, 0x28143A, 0x00008D, 0x000810,
+ 0x280C3A, 0x000675, 0x010042, 0x08000A,
+ 0x003815, 0x010924, 0x280502, 0x0B000D,
+ 0x000820, 0x0002F5, 0x010040, 0x000606,
+ 0x220007, 0x000464, 0x000464, 0x000606,
+ 0x000007, 0x000134, 0x007F8D, 0x00093C,
+ 0x281D12, 0x282512, 0x001F32, 0x0E0007,
+ 0x00010D, 0x00037D, 0x000820, 0x018040,
+ 0x05D2F4, 0x000007, 0x080007, 0x00037D,
+ 0x018042, 0x08000A, 0x000904, 0x2D0286,
+ 0x000007, 0x000606, 0x000007, 0x000007,
+ 0x000012, 0x100007, 0x320007, 0x600007,
+ 0x100080, 0x48001A, 0x004904, 0x2D6186,
+ 0x000007, 0x001210, 0x58003A, 0x000145,
+ 0x5C5D04, 0x000007, 0x000080, 0x48001A,
+ 0x004904, 0x2DB186, 0x000007, 0x001210,
+ 0x50003A, 0x005904, 0x2E0886, 0x000045,
+ 0x0000C5, 0x7FFFF5, 0x7FFF7D, 0x07D524,
+ 0x004224, 0x500102, 0x200502, 0x000082,
+ 0x40001A, 0x004104, 0x2E3986, 0x000007,
+ 0x003865, 0x40001A, 0x004020, 0x00104D,
+ 0x04C184, 0x301B86, 0x000040, 0x040007,
+ 0x000165, 0x000145, 0x004020, 0x000040,
+ 0x000765, 0x080080, 0x40001A, 0x004104,
+ 0x2EC986, 0x000007, 0x001210, 0x40003A,
+ 0x004104, 0x2F2286, 0x00004D, 0x0000CD,
+ 0x004810, 0x20043A, 0x000882, 0x40001A,
+ 0x004104, 0x2F3186, 0x000007, 0x004820,
+ 0x005904, 0x300886, 0x000040, 0x0007E5,
+ 0x200480, 0x2816A0, 0x3216E0, 0x3A16E0,
+ 0x4216E0, 0x021260, 0x000040, 0x000032,
+ 0x400075, 0x00007D, 0x07D574, 0x200512,
+ 0x000082, 0x40001A, 0x004104, 0x2FE186,
+ 0x000007, 0x037206, 0x640007, 0x060007,
+ 0x0000E5, 0x000020, 0x000040, 0x000A65,
+ 0x000020, 0x020040, 0x020040, 0x000040,
+ 0x000165, 0x000042, 0x70000A, 0x007104,
+ 0x30A286, 0x000007, 0x018206, 0x640007,
+ 0x050000, 0x007020, 0x000040, 0x037206,
+ 0x640007, 0x000007, 0x00306D, 0x028860,
+ 0x029060, 0x08000A, 0x028860, 0x008040,
+ 0x100012, 0x00100D, 0x009184, 0x314186,
+ 0x000E0D, 0x009184, 0x325186, 0x000007,
+ 0x300007, 0x001020, 0x003B6D, 0x008040,
+ 0x000080, 0x08001A, 0x000904, 0x316186,
+ 0x000007, 0x001220, 0x000DED, 0x008040,
+ 0x008042, 0x10000A, 0x40000D, 0x109544,
+ 0x000007, 0x001020, 0x000DED, 0x008040,
+ 0x008042, 0x20040A, 0x000082, 0x08001A,
+ 0x000904, 0x31F186, 0x000007, 0x003B6D,
+ 0x008042, 0x08000A, 0x000E15, 0x010984,
+ 0x329B86, 0x600007, 0x08001A, 0x000C15,
+ 0x010984, 0x328386, 0x000020, 0x1A0007,
+ 0x0002ED, 0x008040, 0x620007, 0x00306D,
+ 0x028042, 0x0A804A, 0x000820, 0x0A804A,
+ 0x000606, 0x10804A, 0x000007, 0x282512,
+ 0x001F32, 0x05D2F4, 0x54D104, 0x00735C,
+ 0x000786, 0x000007, 0x0C0007, 0x0A0007,
+ 0x1C0007, 0x003465, 0x020040, 0x004820,
+ 0x025060, 0x40000A, 0x024060, 0x000040,
+ 0x454944, 0x000007, 0x004020, 0x003AE5,
+ 0x000040, 0x0028E5, 0x000042, 0x48000A,
+ 0x004904, 0x386886, 0x002C65, 0x000042,
+ 0x40000A, 0x0000D5, 0x454104, 0x000007,
+ 0x000655, 0x054504, 0x34F286, 0x0001D5,
+ 0x054504, 0x34F086, 0x002B65, 0x000042,
+ 0x003AE5, 0x50004A, 0x40000A, 0x45C3D4,
+ 0x000007, 0x454504, 0x000007, 0x0000CD,
+ 0x444944, 0x000007, 0x454504, 0x000007,
+ 0x00014D, 0x554944, 0x000007, 0x045144,
+ 0x34E986, 0x002C65, 0x000042, 0x48000A,
+ 0x4CD104, 0x000007, 0x04C144, 0x34F386,
+ 0x000007, 0x160007, 0x002CE5, 0x040042,
+ 0x40000A, 0x004020, 0x000040, 0x002965,
+ 0x000042, 0x40000A, 0x004104, 0x356086,
+ 0x000007, 0x002402, 0x36A206, 0x005C02,
+ 0x0025E5, 0x000042, 0x40000A, 0x004274,
+ 0x002AE5, 0x000042, 0x40000A, 0x004274,
+ 0x500112, 0x0029E5, 0x000042, 0x40000A,
+ 0x004234, 0x454104, 0x000007, 0x004020,
+ 0x000040, 0x003EE5, 0x000020, 0x000040,
+ 0x002DE5, 0x400152, 0x50000A, 0x045144,
+ 0x364A86, 0x0000C5, 0x003EE5, 0x004020,
+ 0x000040, 0x002BE5, 0x000042, 0x40000A,
+ 0x404254, 0x000007, 0x002AE5, 0x004020,
+ 0x000040, 0x500132, 0x040134, 0x005674,
+ 0x0029E5, 0x020042, 0x42000A, 0x000042,
+ 0x50000A, 0x05417C, 0x0028E5, 0x000042,
+ 0x48000A, 0x0000C5, 0x4CC144, 0x371086,
+ 0x0026E5, 0x0027E5, 0x020042, 0x40004A,
+ 0x50000A, 0x00423C, 0x00567C, 0x0028E5,
+ 0x004820, 0x000040, 0x281D12, 0x282512,
+ 0x001F72, 0x002965, 0x000042, 0x40000A,
+ 0x004104, 0x37AA86, 0x0E0007, 0x160007,
+ 0x1E0007, 0x003EE5, 0x000042, 0x40000A,
+ 0x004104, 0x37E886, 0x002D65, 0x000042,
+ 0x28340A, 0x003465, 0x020042, 0x42004A,
+ 0x004020, 0x4A004A, 0x50004A, 0x05D2F4,
+ 0x54D104, 0x00735C, 0x385186, 0x000007,
+ 0x000606, 0x080007, 0x0C0007, 0x080007,
+ 0x0A0007, 0x0001E5, 0x020045, 0x004020,
+ 0x000060, 0x000365, 0x000040, 0x002E65,
+ 0x001A20, 0x0A1A60, 0x000040, 0x003465,
+ 0x020042, 0x42004A, 0x004020, 0x4A004A,
+ 0x000606, 0x50004A, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000
+};
+
+// --------------------------------------------
+// DS-1E Controller InstructionRAM Code
+// 1999/06/21
+// Buf441 slot is Enabled.
+// --------------------------------------------
+// 04/09 creat
+// 04/12 stop nise fix
+// 06/21 WorkingOff timming
+static unsigned long int CntrlInst1E[] = {
+ 0x000007, 0x240007, 0x0C0007, 0x1C0007,
+ 0x060007, 0x700002, 0x000020, 0x030040,
+ 0x007104, 0x004286, 0x030040, 0x000F0D,
+ 0x000810, 0x20043A, 0x000282, 0x00020D,
+ 0x000810, 0x20043A, 0x001282, 0x200E82,
+ 0x00800D, 0x000810, 0x20043A, 0x001A82,
+ 0x03460D, 0x000810, 0x10043A, 0x02EC0D,
+ 0x000810, 0x18043A, 0x00010D, 0x020015,
+ 0x0000FD, 0x000020, 0x038860, 0x039060,
+ 0x038060, 0x038040, 0x038040, 0x038040,
+ 0x018040, 0x000A7D, 0x038040, 0x038040,
+ 0x018040, 0x200402, 0x000882, 0x08001A,
+ 0x000904, 0x017186, 0x000007, 0x260007,
+ 0x400007, 0x000007, 0x03258D, 0x000810,
+ 0x18043A, 0x260007, 0x284402, 0x00087D,
+ 0x018042, 0x00160A, 0x05A206, 0x000007,
+ 0x440007, 0x00230D, 0x000810, 0x08043A,
+ 0x22FA06, 0x000007, 0x0007FD, 0x018042,
+ 0x08000A, 0x000904, 0x02AB86, 0x000195,
+ 0x090D04, 0x000007, 0x000820, 0x0000F5,
+ 0x000B7D, 0x01F060, 0x0000FD, 0x033A06,
+ 0x018040, 0x000A7D, 0x038042, 0x13804A,
+ 0x18000A, 0x001820, 0x059060, 0x058860,
+ 0x018040, 0x0000FD, 0x018042, 0x70000A,
+ 0x000115, 0x071144, 0x033B86, 0x030000,
+ 0x007020, 0x036206, 0x018040, 0x00360D,
+ 0x000810, 0x08043A, 0x232206, 0x000007,
+ 0x02EC0D, 0x000810, 0x18043A, 0x019A06,
+ 0x000007, 0x240007, 0x000F8D, 0x000810,
+ 0x00163A, 0x002402, 0x005C02, 0x0028FD,
+ 0x000020, 0x018040, 0x08000D, 0x000815,
+ 0x510984, 0x000007, 0x00004D, 0x000E5D,
+ 0x000E02, 0x00430D, 0x000810, 0x08043A,
+ 0x2E1206, 0x000007, 0x00008D, 0x000924,
+ 0x000F02, 0x00470D, 0x000810, 0x08043A,
+ 0x2E1206, 0x000007, 0x480480, 0x001210,
+ 0x28043A, 0x00778D, 0x000810, 0x280C3A,
+ 0x00068D, 0x000810, 0x28143A, 0x284402,
+ 0x03258D, 0x000810, 0x18043A, 0x07FF8D,
+ 0x000820, 0x0002FD, 0x018040, 0x260007,
+ 0x200007, 0x0002FD, 0x018042, 0x08000A,
+ 0x000904, 0x051286, 0x000007, 0x240007,
+ 0x02EC0D, 0x000810, 0x18043A, 0x00387D,
+ 0x018042, 0x08000A, 0x001015, 0x010984,
+ 0x019B86, 0x000007, 0x01B206, 0x000007,
+ 0x0008FD, 0x018042, 0x18000A, 0x001904,
+ 0x22B886, 0x280007, 0x001810, 0x28043A,
+ 0x280C02, 0x00000D, 0x000810, 0x28143A,
+ 0x08808D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00020D, 0x189904, 0x000007,
+ 0x00402D, 0x0000BD, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x065A86, 0x000007,
+ 0x000100, 0x000A20, 0x00047D, 0x018040,
+ 0x018042, 0x20000A, 0x003015, 0x012144,
+ 0x036186, 0x000007, 0x002104, 0x036186,
+ 0x000007, 0x000F8D, 0x000810, 0x280C3A,
+ 0x023944, 0x07C986, 0x000007, 0x001810,
+ 0x28043A, 0x08810D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x002810, 0x78003A,
+ 0x00788D, 0x000810, 0x08043A, 0x2A1206,
+ 0x000007, 0x00400D, 0x001015, 0x189904,
+ 0x292904, 0x393904, 0x000007, 0x070206,
+ 0x000007, 0x0004F5, 0x00007D, 0x000020,
+ 0x00008D, 0x010860, 0x018040, 0x00047D,
+ 0x038042, 0x21804A, 0x18000A, 0x021944,
+ 0x229086, 0x000007, 0x004075, 0x71F104,
+ 0x000007, 0x010042, 0x28000A, 0x002904,
+ 0x225886, 0x000007, 0x003C0D, 0x30A904,
+ 0x000007, 0x00077D, 0x018042, 0x08000A,
+ 0x000904, 0x08DA86, 0x00057D, 0x002820,
+ 0x03B060, 0x08F206, 0x018040, 0x003020,
+ 0x03A860, 0x018040, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x08FA86, 0x000007,
+ 0x00057D, 0x018042, 0x28040A, 0x000E8D,
+ 0x000810, 0x280C3A, 0x00000D, 0x000810,
+ 0x28143A, 0x09000D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x003DFD, 0x000020,
+ 0x018040, 0x00107D, 0x009D8D, 0x000810,
+ 0x08043A, 0x2A1206, 0x000007, 0x000815,
+ 0x08001A, 0x010984, 0x0A5186, 0x00137D,
+ 0x200500, 0x280F20, 0x338F60, 0x3B8F60,
+ 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
+ 0x038A60, 0x018040, 0x00107D, 0x018042,
+ 0x08000A, 0x000215, 0x010984, 0x3A8186,
+ 0x000007, 0x007FBD, 0x383DC4, 0x000007,
+ 0x001A7D, 0x001375, 0x018042, 0x09004A,
+ 0x10000A, 0x0B8D04, 0x139504, 0x000007,
+ 0x000820, 0x019060, 0x001104, 0x225886,
+ 0x010040, 0x0017FD, 0x018042, 0x08000A,
+ 0x000904, 0x225A86, 0x000007, 0x00197D,
+ 0x038042, 0x09804A, 0x10000A, 0x000924,
+ 0x001664, 0x0011FD, 0x038042, 0x2B804A,
+ 0x19804A, 0x00008D, 0x218944, 0x000007,
+ 0x002244, 0x0C1986, 0x000007, 0x001A64,
+ 0x002A24, 0x00197D, 0x080102, 0x100122,
+ 0x000820, 0x039060, 0x018040, 0x003DFD,
+ 0x00008D, 0x000820, 0x018040, 0x001375,
+ 0x001A7D, 0x010042, 0x09804A, 0x10000A,
+ 0x00021D, 0x0189E4, 0x2992E4, 0x309144,
+ 0x000007, 0x00060D, 0x000A15, 0x000C1D,
+ 0x001025, 0x00A9E4, 0x012BE4, 0x000464,
+ 0x01B3E4, 0x0232E4, 0x000464, 0x000464,
+ 0x000464, 0x000464, 0x00040D, 0x08B1C4,
+ 0x000007, 0x000820, 0x000BF5, 0x030040,
+ 0x00197D, 0x038042, 0x09804A, 0x000A24,
+ 0x08000A, 0x080E64, 0x000007, 0x100122,
+ 0x000820, 0x031060, 0x010040, 0x0064AC,
+ 0x00027D, 0x000020, 0x018040, 0x00107D,
+ 0x018042, 0x0011FD, 0x3B804A, 0x09804A,
+ 0x20000A, 0x000095, 0x1A1144, 0x00A144,
+ 0x0E5886, 0x00040D, 0x00B984, 0x0E5986,
+ 0x0018FD, 0x018042, 0x0010FD, 0x09804A,
+ 0x28000A, 0x000095, 0x010924, 0x002A64,
+ 0x0E4986, 0x000007, 0x002904, 0x0E5A86,
+ 0x000007, 0x0E6206, 0x080002, 0x00008D,
+ 0x00387D, 0x000820, 0x018040, 0x00127D,
+ 0x018042, 0x10000A, 0x003904, 0x0F0986,
+ 0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986,
+ 0x000025, 0x0FB206, 0x00002D, 0x000015,
+ 0x00082D, 0x02E00D, 0x000820, 0x0FFA06,
+ 0x00000D, 0x7F8035, 0x00B984, 0x0FA986,
+ 0x400025, 0x00008D, 0x110944, 0x000007,
+ 0x00018D, 0x109504, 0x000007, 0x009164,
+ 0x000424, 0x000424, 0x000424, 0x100102,
+ 0x280002, 0x02DF0D, 0x000820, 0x0FFA06,
+ 0x00018D, 0x00042D, 0x00008D, 0x109504,
+ 0x000007, 0x00020D, 0x109184, 0x000007,
+ 0x02DF8D, 0x000820, 0x00008D, 0x0038FD,
+ 0x018040, 0x003BFD, 0x001020, 0x03A860,
+ 0x000815, 0x313184, 0x212184, 0x000007,
+ 0x03B060, 0x03A060, 0x018040, 0x0022FD,
+ 0x000095, 0x010924, 0x000424, 0x000424,
+ 0x001264, 0x100102, 0x000820, 0x039060,
+ 0x018040, 0x001924, 0x010F0D, 0x00397D,
+ 0x000820, 0x058040, 0x038042, 0x09844A,
+ 0x000606, 0x08040A, 0x000424, 0x000424,
+ 0x00117D, 0x018042, 0x08000A, 0x000A24,
+ 0x280502, 0x280C02, 0x09800D, 0x000820,
+ 0x0002FD, 0x018040, 0x200007, 0x0022FD,
+ 0x018042, 0x08000A, 0x000095, 0x280DC4,
+ 0x011924, 0x00197D, 0x018042, 0x0011FD,
+ 0x09804A, 0x10000A, 0x0000B5, 0x113144,
+ 0x0A8D04, 0x000007, 0x080A44, 0x129504,
+ 0x000007, 0x0023FD, 0x001020, 0x038040,
+ 0x101244, 0x000007, 0x000820, 0x039060,
+ 0x018040, 0x0002FD, 0x018042, 0x08000A,
+ 0x000904, 0x123286, 0x000007, 0x003BFD,
+ 0x000100, 0x000A10, 0x0B807A, 0x13804A,
+ 0x090984, 0x000007, 0x000095, 0x013D04,
+ 0x12B886, 0x10000A, 0x100002, 0x090984,
+ 0x000007, 0x038042, 0x11804A, 0x090D04,
+ 0x000007, 0x10000A, 0x090D84, 0x000007,
+ 0x00257D, 0x000820, 0x018040, 0x00010D,
+ 0x000810, 0x28143A, 0x00127D, 0x018042,
+ 0x20000A, 0x00197D, 0x018042, 0x00117D,
+ 0x31804A, 0x10000A, 0x003124, 0x013B8D,
+ 0x00397D, 0x000820, 0x058040, 0x038042,
+ 0x09844A, 0x000606, 0x08040A, 0x300102,
+ 0x003124, 0x000424, 0x000424, 0x001224,
+ 0x280502, 0x001A4C, 0x143986, 0x700002,
+ 0x00002D, 0x030000, 0x00387D, 0x018042,
+ 0x10000A, 0x146206, 0x002124, 0x0000AD,
+ 0x100002, 0x00010D, 0x000924, 0x006B24,
+ 0x014A0D, 0x00397D, 0x000820, 0x058040,
+ 0x038042, 0x09844A, 0x000606, 0x08040A,
+ 0x003264, 0x00008D, 0x000A24, 0x001020,
+ 0x00227D, 0x018040, 0x014F8D, 0x000810,
+ 0x08043A, 0x2B5A06, 0x000007, 0x002820,
+ 0x00207D, 0x018040, 0x00117D, 0x038042,
+ 0x13804A, 0x33800A, 0x00387D, 0x018042,
+ 0x08000A, 0x000904, 0x177286, 0x000007,
+ 0x00008D, 0x030964, 0x015B0D, 0x00397D,
+ 0x000820, 0x058040, 0x038042, 0x09844A,
+ 0x000606, 0x08040A, 0x380102, 0x000424,
+ 0x000424, 0x001224, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x15DA86, 0x000007,
+ 0x280502, 0x001A4C, 0x177186, 0x000007,
+ 0x032164, 0x00632C, 0x003DFD, 0x018042,
+ 0x08000A, 0x000095, 0x090904, 0x000007,
+ 0x000820, 0x001A4C, 0x169986, 0x018040,
+ 0x030000, 0x16B206, 0x002124, 0x00010D,
+ 0x000924, 0x006B24, 0x016F0D, 0x00397D,
+ 0x000820, 0x058040, 0x038042, 0x09844A,
+ 0x000606, 0x08040A, 0x003A64, 0x000095,
+ 0x001224, 0x0002FD, 0x018042, 0x08000A,
+ 0x000904, 0x171286, 0x000007, 0x01760D,
+ 0x000810, 0x08043A, 0x2B5A06, 0x000007,
+ 0x160A06, 0x000007, 0x007020, 0x08010A,
+ 0x10012A, 0x0020FD, 0x038860, 0x039060,
+ 0x018040, 0x00227D, 0x018042, 0x003DFD,
+ 0x08000A, 0x31844A, 0x000904, 0x181086,
+ 0x18008B, 0x00008D, 0x189904, 0x00312C,
+ 0x18E206, 0x000007, 0x00324C, 0x186B86,
+ 0x000007, 0x001904, 0x186886, 0x000007,
+ 0x000095, 0x199144, 0x00222C, 0x003124,
+ 0x00636C, 0x000E3D, 0x001375, 0x000BFD,
+ 0x010042, 0x09804A, 0x10000A, 0x038AEC,
+ 0x0393EC, 0x00224C, 0x18E186, 0x000007,
+ 0x00008D, 0x189904, 0x00226C, 0x00322C,
+ 0x30050A, 0x301DAB, 0x002083, 0x0018FD,
+ 0x018042, 0x08000A, 0x018924, 0x300502,
+ 0x001083, 0x001875, 0x010042, 0x10000A,
+ 0x00008D, 0x010924, 0x001375, 0x330542,
+ 0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB,
+ 0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B,
+ 0x006083, 0x0002F5, 0x010042, 0x08000A,
+ 0x000904, 0x19B286, 0x000007, 0x001E2D,
+ 0x0005FD, 0x018042, 0x08000A, 0x028924,
+ 0x280502, 0x00060D, 0x000810, 0x280C3A,
+ 0x00008D, 0x000810, 0x28143A, 0x0A808D,
+ 0x000820, 0x0002F5, 0x010040, 0x220007,
+ 0x001275, 0x030042, 0x21004A, 0x00008D,
+ 0x1A0944, 0x000007, 0x01AB8D, 0x000810,
+ 0x08043A, 0x2CAA06, 0x000007, 0x0001F5,
+ 0x030042, 0x0D004A, 0x10000A, 0x089144,
+ 0x000007, 0x000820, 0x010040, 0x0025F5,
+ 0x0A3144, 0x000007, 0x000820, 0x032860,
+ 0x030040, 0x00217D, 0x038042, 0x0B804A,
+ 0x10000A, 0x000820, 0x031060, 0x030040,
+ 0x00008D, 0x000124, 0x00012C, 0x000E64,
+ 0x001A64, 0x00636C, 0x08010A, 0x10012A,
+ 0x000820, 0x031060, 0x030040, 0x0020FD,
+ 0x018042, 0x08000A, 0x00227D, 0x018042,
+ 0x10000A, 0x000820, 0x031060, 0x030040,
+ 0x00197D, 0x018042, 0x08000A, 0x0022FD,
+ 0x038042, 0x10000A, 0x000820, 0x031060,
+ 0x030040, 0x090D04, 0x000007, 0x000820,
+ 0x030040, 0x038042, 0x0B804A, 0x10000A,
+ 0x000820, 0x031060, 0x030040, 0x038042,
+ 0x13804A, 0x19804A, 0x110D04, 0x198D04,
+ 0x000007, 0x08000A, 0x001020, 0x031860,
+ 0x030860, 0x030040, 0x00008D, 0x0B0944,
+ 0x000007, 0x000820, 0x010040, 0x0005F5,
+ 0x030042, 0x08000A, 0x000820, 0x010040,
+ 0x0000F5, 0x010042, 0x08000A, 0x000904,
+ 0x1D9886, 0x001E75, 0x030042, 0x01044A,
+ 0x000C0A, 0x1DAA06, 0x000007, 0x000402,
+ 0x000C02, 0x00177D, 0x001AF5, 0x018042,
+ 0x03144A, 0x031C4A, 0x03244A, 0x032C4A,
+ 0x03344A, 0x033C4A, 0x03444A, 0x004C0A,
+ 0x00043D, 0x0013F5, 0x001AFD, 0x030042,
+ 0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
+ 0x089144, 0x19A144, 0x0389E4, 0x0399EC,
+ 0x005502, 0x005D0A, 0x030042, 0x0B004A,
+ 0x1B804A, 0x13804A, 0x20000A, 0x089144,
+ 0x19A144, 0x0389E4, 0x0399EC, 0x006502,
+ 0x006D0A, 0x030042, 0x0B004A, 0x19004A,
+ 0x2B804A, 0x13804A, 0x21804A, 0x30000A,
+ 0x089144, 0x19A144, 0x2AB144, 0x0389E4,
+ 0x0399EC, 0x007502, 0x007D0A, 0x03A9E4,
+ 0x000702, 0x00107D, 0x000415, 0x018042,
+ 0x08000A, 0x0109E4, 0x000F02, 0x002AF5,
+ 0x0019FD, 0x010042, 0x09804A, 0x10000A,
+ 0x000934, 0x001674, 0x0029F5, 0x010042,
+ 0x10000A, 0x00917C, 0x002075, 0x010042,
+ 0x08000A, 0x000904, 0x200A86, 0x0026F5,
+ 0x0027F5, 0x030042, 0x09004A, 0x10000A,
+ 0x000A3C, 0x00167C, 0x001A75, 0x000BFD,
+ 0x010042, 0x51804A, 0x48000A, 0x160007,
+ 0x001075, 0x010042, 0x282C0A, 0x281D12,
+ 0x282512, 0x001F32, 0x1E0007, 0x0E0007,
+ 0x001975, 0x010042, 0x002DF5, 0x0D004A,
+ 0x10000A, 0x009144, 0x20EA86, 0x010042,
+ 0x28340A, 0x000E5D, 0x00008D, 0x000375,
+ 0x000820, 0x010040, 0x05D2F4, 0x54D104,
+ 0x00735C, 0x218B86, 0x000007, 0x0C0007,
+ 0x080007, 0x0A0007, 0x02178D, 0x000810,
+ 0x08043A, 0x34B206, 0x000007, 0x219206,
+ 0x000007, 0x080007, 0x002275, 0x010042,
+ 0x20000A, 0x002104, 0x225886, 0x001E2D,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x21CA86, 0x000007, 0x002010, 0x30043A,
+ 0x00057D, 0x0180C3, 0x08000A, 0x028924,
+ 0x280502, 0x280C02, 0x0A810D, 0x000820,
+ 0x0002F5, 0x010040, 0x220007, 0x0004FD,
+ 0x018042, 0x70000A, 0x030000, 0x007020,
+ 0x07FA06, 0x018040, 0x022B8D, 0x000810,
+ 0x08043A, 0x2CAA06, 0x000007, 0x0002FD,
+ 0x018042, 0x08000A, 0x000904, 0x22C286,
+ 0x000007, 0x020206, 0x000007, 0x000875,
+ 0x0009FD, 0x00010D, 0x234206, 0x000295,
+ 0x000B75, 0x00097D, 0x00000D, 0x000515,
+ 0x010042, 0x18000A, 0x001904, 0x2A0086,
+ 0x0006F5, 0x001020, 0x010040, 0x0004F5,
+ 0x000820, 0x010040, 0x000775, 0x010042,
+ 0x09804A, 0x10000A, 0x001124, 0x000904,
+ 0x23F286, 0x000815, 0x080102, 0x101204,
+ 0x241206, 0x000575, 0x081204, 0x000007,
+ 0x100102, 0x000575, 0x000425, 0x021124,
+ 0x100102, 0x000820, 0x031060, 0x010040,
+ 0x001924, 0x2A0086, 0x00008D, 0x000464,
+ 0x009D04, 0x291086, 0x180102, 0x000575,
+ 0x010042, 0x28040A, 0x00018D, 0x000924,
+ 0x280D02, 0x00000D, 0x000924, 0x281502,
+ 0x10000D, 0x000820, 0x0002F5, 0x010040,
+ 0x200007, 0x001175, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x24FA86, 0x000007,
+ 0x000100, 0x080B20, 0x130B60, 0x1B0B60,
+ 0x030A60, 0x010040, 0x050042, 0x3D004A,
+ 0x35004A, 0x2D004A, 0x20000A, 0x0006F5,
+ 0x010042, 0x28140A, 0x0004F5, 0x010042,
+ 0x08000A, 0x000315, 0x010D04, 0x260286,
+ 0x004015, 0x000095, 0x010D04, 0x25F086,
+ 0x100022, 0x10002A, 0x261A06, 0x000007,
+ 0x333104, 0x2AA904, 0x000007, 0x032124,
+ 0x280502, 0x284402, 0x001124, 0x400102,
+ 0x000424, 0x000424, 0x003224, 0x00292C,
+ 0x00636C, 0x277386, 0x000007, 0x02B164,
+ 0x000464, 0x000464, 0x00008D, 0x000A64,
+ 0x280D02, 0x10008D, 0x000820, 0x0002F5,
+ 0x010040, 0x220007, 0x00008D, 0x38B904,
+ 0x000007, 0x03296C, 0x30010A, 0x0002F5,
+ 0x010042, 0x08000A, 0x000904, 0x270286,
+ 0x000007, 0x00212C, 0x28050A, 0x00316C,
+ 0x00046C, 0x00046C, 0x28450A, 0x001124,
+ 0x006B64, 0x100102, 0x00008D, 0x01096C,
+ 0x280D0A, 0x10010D, 0x000820, 0x0002F5,
+ 0x010040, 0x220007, 0x004124, 0x000424,
+ 0x000424, 0x003224, 0x300102, 0x032944,
+ 0x27FA86, 0x000007, 0x300002, 0x0004F5,
+ 0x010042, 0x08000A, 0x000315, 0x010D04,
+ 0x284086, 0x003124, 0x000464, 0x300102,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x284A86, 0x000007, 0x284402, 0x003124,
+ 0x300502, 0x003924, 0x300583, 0x000883,
+ 0x0005F5, 0x010042, 0x28040A, 0x00008D,
+ 0x008124, 0x280D02, 0x00008D, 0x008124,
+ 0x281502, 0x10018D, 0x000820, 0x0002F5,
+ 0x010040, 0x220007, 0x001025, 0x000575,
+ 0x030042, 0x09004A, 0x10000A, 0x0A0904,
+ 0x121104, 0x000007, 0x001020, 0x050860,
+ 0x050040, 0x0006FD, 0x018042, 0x09004A,
+ 0x10000A, 0x0000A5, 0x0A0904, 0x121104,
+ 0x000007, 0x000820, 0x019060, 0x010040,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x29CA86, 0x000007, 0x244206, 0x000007,
+ 0x000606, 0x000007, 0x0002F5, 0x010042,
+ 0x08000A, 0x000904, 0x2A1A86, 0x000007,
+ 0x000100, 0x080B20, 0x138B60, 0x1B8B60,
+ 0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60,
+ 0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60,
+ 0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60,
+ 0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60,
+ 0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60,
+ 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
+ 0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60,
+ 0x038A60, 0x000606, 0x018040, 0x00008D,
+ 0x000A64, 0x280D02, 0x000A24, 0x00027D,
+ 0x018042, 0x10000A, 0x001224, 0x0003FD,
+ 0x018042, 0x08000A, 0x000904, 0x2C0A86,
+ 0x000007, 0x00018D, 0x000A24, 0x000464,
+ 0x000464, 0x080102, 0x000924, 0x000424,
+ 0x000424, 0x100102, 0x02000D, 0x009144,
+ 0x2C6186, 0x000007, 0x0001FD, 0x018042,
+ 0x08000A, 0x000A44, 0x2C4386, 0x018042,
+ 0x0A000D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00027D, 0x001020, 0x000606,
+ 0x018040, 0x0002F5, 0x010042, 0x08000A,
+ 0x000904, 0x2CB286, 0x000007, 0x00037D,
+ 0x018042, 0x08000A, 0x000904, 0x2CE286,
+ 0x000007, 0x000075, 0x002E7D, 0x010042,
+ 0x0B804A, 0x000020, 0x000904, 0x000686,
+ 0x010040, 0x31844A, 0x30048B, 0x000883,
+ 0x00008D, 0x000810, 0x28143A, 0x00008D,
+ 0x000810, 0x280C3A, 0x000675, 0x010042,
+ 0x08000A, 0x003815, 0x010924, 0x280502,
+ 0x0B000D, 0x000820, 0x0002F5, 0x010040,
+ 0x000606, 0x220007, 0x000464, 0x000464,
+ 0x000606, 0x000007, 0x000134, 0x007F8D,
+ 0x00093C, 0x281D12, 0x282512, 0x001F32,
+ 0x0E0007, 0x00010D, 0x00037D, 0x000820,
+ 0x018040, 0x05D2F4, 0x000007, 0x080007,
+ 0x00037D, 0x018042, 0x08000A, 0x000904,
+ 0x2E8A86, 0x000007, 0x000606, 0x000007,
+ 0x000007, 0x000012, 0x100007, 0x320007,
+ 0x600007, 0x460007, 0x100080, 0x48001A,
+ 0x004904, 0x2EF186, 0x000007, 0x001210,
+ 0x58003A, 0x000145, 0x5C5D04, 0x000007,
+ 0x000080, 0x48001A, 0x004904, 0x2F4186,
+ 0x000007, 0x001210, 0x50003A, 0x005904,
+ 0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5,
+ 0x7FFF7D, 0x07D524, 0x004224, 0x500102,
+ 0x200502, 0x000082, 0x40001A, 0x004104,
+ 0x2FC986, 0x000007, 0x003865, 0x40001A,
+ 0x004020, 0x00104D, 0x04C184, 0x31AB86,
+ 0x000040, 0x040007, 0x000165, 0x000145,
+ 0x004020, 0x000040, 0x000765, 0x080080,
+ 0x40001A, 0x004104, 0x305986, 0x000007,
+ 0x001210, 0x40003A, 0x004104, 0x30B286,
+ 0x00004D, 0x0000CD, 0x004810, 0x20043A,
+ 0x000882, 0x40001A, 0x004104, 0x30C186,
+ 0x000007, 0x004820, 0x005904, 0x319886,
+ 0x000040, 0x0007E5, 0x200480, 0x2816A0,
+ 0x3216E0, 0x3A16E0, 0x4216E0, 0x021260,
+ 0x000040, 0x000032, 0x400075, 0x00007D,
+ 0x07D574, 0x200512, 0x000082, 0x40001A,
+ 0x004104, 0x317186, 0x000007, 0x038A06,
+ 0x640007, 0x0000E5, 0x000020, 0x000040,
+ 0x000A65, 0x000020, 0x020040, 0x020040,
+ 0x000040, 0x000165, 0x000042, 0x70000A,
+ 0x007104, 0x323286, 0x000007, 0x060007,
+ 0x019A06, 0x640007, 0x050000, 0x007020,
+ 0x000040, 0x038A06, 0x640007, 0x000007,
+ 0x00306D, 0x028860, 0x029060, 0x08000A,
+ 0x028860, 0x008040, 0x100012, 0x00100D,
+ 0x009184, 0x32D186, 0x000E0D, 0x009184,
+ 0x33E186, 0x000007, 0x300007, 0x001020,
+ 0x003B6D, 0x008040, 0x000080, 0x08001A,
+ 0x000904, 0x32F186, 0x000007, 0x001220,
+ 0x000DED, 0x008040, 0x008042, 0x10000A,
+ 0x40000D, 0x109544, 0x000007, 0x001020,
+ 0x000DED, 0x008040, 0x008042, 0x20040A,
+ 0x000082, 0x08001A, 0x000904, 0x338186,
+ 0x000007, 0x003B6D, 0x008042, 0x08000A,
+ 0x000E15, 0x010984, 0x342B86, 0x600007,
+ 0x08001A, 0x000C15, 0x010984, 0x341386,
+ 0x000020, 0x1A0007, 0x0002ED, 0x008040,
+ 0x620007, 0x00306D, 0x028042, 0x0A804A,
+ 0x000820, 0x0A804A, 0x000606, 0x10804A,
+ 0x000007, 0x282512, 0x001F32, 0x05D2F4,
+ 0x54D104, 0x00735C, 0x000786, 0x000007,
+ 0x0C0007, 0x0A0007, 0x1C0007, 0x003465,
+ 0x020040, 0x004820, 0x025060, 0x40000A,
+ 0x024060, 0x000040, 0x454944, 0x000007,
+ 0x004020, 0x003AE5, 0x000040, 0x0028E5,
+ 0x000042, 0x48000A, 0x004904, 0x39F886,
+ 0x002C65, 0x000042, 0x40000A, 0x0000D5,
+ 0x454104, 0x000007, 0x000655, 0x054504,
+ 0x368286, 0x0001D5, 0x054504, 0x368086,
+ 0x002B65, 0x000042, 0x003AE5, 0x50004A,
+ 0x40000A, 0x45C3D4, 0x000007, 0x454504,
+ 0x000007, 0x0000CD, 0x444944, 0x000007,
+ 0x454504, 0x000007, 0x00014D, 0x554944,
+ 0x000007, 0x045144, 0x367986, 0x002C65,
+ 0x000042, 0x48000A, 0x4CD104, 0x000007,
+ 0x04C144, 0x368386, 0x000007, 0x160007,
+ 0x002CE5, 0x040042, 0x40000A, 0x004020,
+ 0x000040, 0x002965, 0x000042, 0x40000A,
+ 0x004104, 0x36F086, 0x000007, 0x002402,
+ 0x383206, 0x005C02, 0x0025E5, 0x000042,
+ 0x40000A, 0x004274, 0x002AE5, 0x000042,
+ 0x40000A, 0x004274, 0x500112, 0x0029E5,
+ 0x000042, 0x40000A, 0x004234, 0x454104,
+ 0x000007, 0x004020, 0x000040, 0x003EE5,
+ 0x000020, 0x000040, 0x002DE5, 0x400152,
+ 0x50000A, 0x045144, 0x37DA86, 0x0000C5,
+ 0x003EE5, 0x004020, 0x000040, 0x002BE5,
+ 0x000042, 0x40000A, 0x404254, 0x000007,
+ 0x002AE5, 0x004020, 0x000040, 0x500132,
+ 0x040134, 0x005674, 0x0029E5, 0x020042,
+ 0x42000A, 0x000042, 0x50000A, 0x05417C,
+ 0x0028E5, 0x000042, 0x48000A, 0x0000C5,
+ 0x4CC144, 0x38A086, 0x0026E5, 0x0027E5,
+ 0x020042, 0x40004A, 0x50000A, 0x00423C,
+ 0x00567C, 0x0028E5, 0x004820, 0x000040,
+ 0x281D12, 0x282512, 0x001F72, 0x002965,
+ 0x000042, 0x40000A, 0x004104, 0x393A86,
+ 0x0E0007, 0x160007, 0x1E0007, 0x003EE5,
+ 0x000042, 0x40000A, 0x004104, 0x397886,
+ 0x002D65, 0x000042, 0x28340A, 0x003465,
+ 0x020042, 0x42004A, 0x004020, 0x4A004A,
+ 0x50004A, 0x05D2F4, 0x54D104, 0x00735C,
+ 0x39E186, 0x000007, 0x000606, 0x080007,
+ 0x0C0007, 0x080007, 0x0A0007, 0x0001E5,
+ 0x020045, 0x004020, 0x000060, 0x000365,
+ 0x000040, 0x002E65, 0x001A20, 0x0A1A60,
+ 0x000040, 0x003465, 0x020042, 0x42004A,
+ 0x004020, 0x4A004A, 0x000606, 0x50004A,
+ 0x0017FD, 0x018042, 0x08000A, 0x000904,
+ 0x225A86, 0x000007, 0x00107D, 0x018042,
+ 0x0011FD, 0x33804A, 0x19804A, 0x20000A,
+ 0x000095, 0x2A1144, 0x01A144, 0x3B9086,
+ 0x00040D, 0x00B184, 0x3B9186, 0x0018FD,
+ 0x018042, 0x0010FD, 0x09804A, 0x38000A,
+ 0x000095, 0x010924, 0x003A64, 0x3B8186,
+ 0x000007, 0x003904, 0x3B9286, 0x000007,
+ 0x3B9A06, 0x00000D, 0x00008D, 0x000820,
+ 0x00387D, 0x018040, 0x700002, 0x00117D,
+ 0x018042, 0x00197D, 0x29804A, 0x30000A,
+ 0x380002, 0x003124, 0x000424, 0x000424,
+ 0x002A24, 0x280502, 0x00068D, 0x000810,
+ 0x28143A, 0x00750D, 0x00B124, 0x002264,
+ 0x3D0386, 0x284402, 0x000810, 0x280C3A,
+ 0x0B800D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00758D, 0x00B124, 0x100102,
+ 0x012144, 0x3E4986, 0x001810, 0x10003A,
+ 0x00387D, 0x018042, 0x08000A, 0x000904,
+ 0x3E4886, 0x030000, 0x3E4A06, 0x0000BD,
+ 0x00008D, 0x023164, 0x000A64, 0x280D02,
+ 0x0B808D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00387D, 0x018042, 0x08000A,
+ 0x000904, 0x3E3286, 0x030000, 0x0002FD,
+ 0x018042, 0x08000A, 0x000904, 0x3D8286,
+ 0x000007, 0x002810, 0x28043A, 0x00750D,
+ 0x030924, 0x002264, 0x280D02, 0x02316C,
+ 0x28450A, 0x0B810D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x00008D, 0x000A24,
+ 0x3E4A06, 0x100102, 0x001810, 0x10003A,
+ 0x0000BD, 0x003810, 0x30043A, 0x00187D,
+ 0x018042, 0x0018FD, 0x09804A, 0x20000A,
+ 0x0000AD, 0x028924, 0x07212C, 0x001010,
+ 0x300583, 0x300D8B, 0x3014BB, 0x301C83,
+ 0x002083, 0x00137D, 0x038042, 0x33844A,
+ 0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB,
+ 0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083,
+ 0x001E0D, 0x0005FD, 0x018042, 0x20000A,
+ 0x020924, 0x00068D, 0x00A96C, 0x00009D,
+ 0x0002FD, 0x018042, 0x08000A, 0x000904,
+ 0x3F6A86, 0x000007, 0x280502, 0x280D0A,
+ 0x284402, 0x001810, 0x28143A, 0x0C008D,
+ 0x000820, 0x0002FD, 0x018040, 0x220007,
+ 0x003904, 0x225886, 0x001E0D, 0x00057D,
+ 0x018042, 0x20000A, 0x020924, 0x0000A5,
+ 0x0002FD, 0x018042, 0x08000A, 0x000904,
+ 0x402A86, 0x000007, 0x280502, 0x280C02,
+ 0x002010, 0x28143A, 0x0C010D, 0x000820,
+ 0x0002FD, 0x018040, 0x225A06, 0x220007,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000
+};
+
+#endif //_HWMCODE_
diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in
index d4feefa21..e263e6a6d 100644
--- a/drivers/usb/Config.in
+++ b/drivers/usb/Config.in
@@ -25,56 +25,16 @@ comment 'USB Controllers'
fi
dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
-comment 'USB Devices'
- dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
- dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
- fi
+ comment 'USB Device Class drivers'
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
- dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
- dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
- if [ "$CONFIG_USB_SERIAL" != "n" ]; then
- bool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC
- dep_tristate ' USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
- dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
- if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
- dep_tristate ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL
- dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL
- dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL
- dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL
- if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then
- bool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28
- bool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X
- bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
- bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X
- bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
- fi
- dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL
- dep_tristate ' USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL
- fi
- bool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG
- fi
- dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
- dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
- dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB
- fi
+ dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
if [ "$CONFIG_USB_STORAGE" != "n" ]; then
bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG
+ bool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM
fi
- dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
- dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET
- dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET
- dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB
- dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV
- dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB
- dep_tristate ' NetChip 1080-based USB Host-to-Host Link (EXPERIMENTAL)' CONFIG_USB_NET1080 $CONFIG_USB $CONFIG_NET
- fi
+ dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
+ dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
comment 'USB Human Interface Devices (HID)'
if [ "$CONFIG_INPUT" = "n" ]; then
@@ -87,6 +47,30 @@ comment 'USB Devices'
fi
dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
fi
+
+ comment 'USB Imaging devices'
+ dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
+ dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
+ dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
+
+ comment 'USB Multimedia devices'
+ dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
+ dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
+ 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
+
+ comment 'USB Network adaptors'
+ dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+ dep_tristate ' NetChip 1080-based USB Host-to-Host Link (EXPERIMENTAL)' CONFIG_USB_NET1080 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+
+ comment 'USB port drivers'
+ dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
+ source drivers/usb/serial/Config.in
+
+ comment 'USB misc drivers'
+ dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
fi
endmenu
diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c
index 1736c503b..881129966 100644
--- a/drivers/usb/acm.c
+++ b/drivers/usb/acm.c
@@ -1,5 +1,5 @@
/*
- * acm.c Version 0.16
+ * acm.c Version 0.18
*
* Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
@@ -19,6 +19,8 @@
* v0.14 - sized down struct acm
* v0.15 - fixed flow control again - characters could be lost
* v0.16 - added code for modems with swapped data and control interfaces
+ * v0.17 - added new style probing
+ * v0.18 - fixed new style probing for devices with more configurations
*/
/*
@@ -144,7 +146,7 @@ struct acm {
static struct usb_driver acm_driver;
static struct tty_driver acm_tty_driver;
-static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, /* .... */ };
+static struct acm *acm_table[ACM_TTY_MINORS];
#define ACM_READY(acm) (acm && acm->dev && acm->used)
@@ -185,7 +187,7 @@ static void acm_ctrl_irq(struct urb *urb)
switch (dr->request) {
case ACM_IRQ_NETWORK:
-
+
dbg("%s network", data[0] ? "connected to" : "disconnected from");
return;
@@ -267,7 +269,7 @@ static void acm_softint(void *private)
struct acm *acm = private;
struct tty_struct *tty = acm->tty;
- if (!ACM_READY(acm)) return;
+ if (!ACM_READY(acm)) return;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup)(tty);
@@ -420,15 +422,15 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int
case TIOCMBIS: newctrl |= mask; break;
case TIOCMBIC: newctrl &= ~mask; break;
}
-
- if (acm->ctrlout == newctrl) return 0;
+
+ if (acm->ctrlout == newctrl) return 0;
return acm_set_control(acm, acm->ctrlout = newctrl);
}
return -ENOIOCTLCMD;
}
-static __u32 acm_tty_speed[] = {
+static __u32 acm_tty_speed[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600,
1200, 1800, 2400, 4800, 9600, 19200, 38400,
57600, 115200, 230400, 460800, 500000, 576000,
@@ -457,7 +459,7 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_
newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
acm->clocal = termios->c_cflag & CLOCAL;
-
+
if (!newline.speed) {
newline.speed = acm->line.speed;
newctrl &= ~ACM_CTRL_DTR;
@@ -484,106 +486,114 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum,
struct usb_config_descriptor *cfacm;
struct usb_interface_descriptor *ifcom, *ifdata;
struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
- int readsize, ctrlsize, minor;
+ int readsize, ctrlsize, minor, i;
unsigned char *buf;
- /* Since 0 is treated as a wildcard by the USB pattern matching,
- we explicitly check bDeviceSubClass and bDeviceProtocol
- here. */
- if (dev->descriptor.bDeviceSubClass != 0
- || dev->descriptor.bDeviceProtocol != 0) return NULL;
+/*
+ * Since 0 is treated as a wildcard by the USB pattern matching,
+ * we explicitly check bDeviceSubClass and bDeviceProtocol here.
+ */
- cfacm = dev->actconfig;
+ if (dev->descriptor.bDeviceSubClass != 0 ||
+ dev->descriptor.bDeviceProtocol != 0)
+ return NULL;
- dbg("probing config %d", cfacm->bConfigurationValue);
+ for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
- if (cfacm->bNumInterfaces != 2 ||
- usb_interface_claimed(cfacm->interface + 0) ||
- usb_interface_claimed(cfacm->interface + 1))
- return NULL;
+ cfacm = dev->config + i;
- ifcom = cfacm->interface[0].altsetting + 0;
- ifdata = cfacm->interface[1].altsetting + 0;
+ dbg("probing config %d", cfacm->bConfigurationValue);
- if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints != 2) {
- ifcom = cfacm->interface[1].altsetting + 0;
- ifdata = cfacm->interface[0].altsetting + 0;
- if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints !=2)
- return NULL;
- }
+ if (cfacm->bNumInterfaces != 2 ||
+ usb_interface_claimed(cfacm->interface + 0) ||
+ usb_interface_claimed(cfacm->interface + 1))
+ continue;
- if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
- ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1)
- return NULL;
+ ifcom = cfacm->interface[0].altsetting + 0;
+ ifdata = cfacm->interface[1].altsetting + 0;
- epctrl = ifcom->endpoint + 0;
- epread = ifdata->endpoint + 0;
- epwrite = ifdata->endpoint + 1;
+ if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) {
+ ifcom = cfacm->interface[1].altsetting + 0;
+ ifdata = cfacm->interface[0].altsetting + 0;
+ if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2)
+ continue;
+ }
- if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
- (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
- ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
- return NULL;
+ if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
+ ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints < 1)
+ continue;
- if ((epread->bEndpointAddress & 0x80) != 0x80) {
- epread = ifdata->endpoint + 1;
- epwrite = ifdata->endpoint + 0;
- }
+ epctrl = ifcom->endpoint + 0;
+ epread = ifdata->endpoint + 0;
+ epwrite = ifdata->endpoint + 1;
- usb_set_configuration(dev, cfacm->bConfigurationValue);
+ if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
+ (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
+ ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
+ continue;
- for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
- if (acm_table[minor]) {
- err("no more free acm devices");
- return NULL;
- }
+ if ((epread->bEndpointAddress & 0x80) != 0x80) {
+ epread = ifdata->endpoint + 1;
+ epwrite = ifdata->endpoint + 0;
+ }
- if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
- err("out of memory");
- return NULL;
- }
- memset(acm, 0, sizeof(struct acm));
+ usb_set_configuration(dev, cfacm->bConfigurationValue);
- ctrlsize = epctrl->wMaxPacketSize;
- readsize = epread->wMaxPacketSize;
- acm->writesize = epwrite->wMaxPacketSize;
- acm->iface = cfacm->interface;
- acm->minor = minor;
- acm->dev = dev;
+ for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+ if (acm_table[minor]) {
+ err("no more free acm devices");
+ return NULL;
+ }
- acm->tqueue.routine = acm_softint;
- acm->tqueue.data = acm;
+ if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
+ err("out of memory");
+ return NULL;
+ }
+ memset(acm, 0, sizeof(struct acm));
- if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
- err("out of memory");
- kfree(acm);
- return NULL;
- }
+ ctrlsize = epctrl->wMaxPacketSize;
+ readsize = epread->wMaxPacketSize;
+ acm->writesize = epwrite->wMaxPacketSize;
+ acm->iface = cfacm->interface;
+ acm->minor = minor;
+ acm->dev = dev;
- FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
- buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
+ acm->tqueue.routine = acm_softint;
+ acm->tqueue.data = acm;
- FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
- buf += ctrlsize, readsize, acm_read_bulk, acm);
- acm->readurb.transfer_flags |= USB_NO_FSBR;
+ if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
+ err("out of memory");
+ kfree(acm);
+ return NULL;
+ }
+
+ FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
+ buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
- FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
- buf += readsize, acm->writesize, acm_write_bulk, acm);
- acm->writeurb.transfer_flags |= USB_NO_FSBR;
+ FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
+ buf += ctrlsize, readsize, acm_read_bulk, acm);
+ acm->readurb.transfer_flags |= USB_NO_FSBR;
- printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
+ FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
+ buf += readsize, acm->writesize, acm_write_bulk, acm);
+ acm->writeurb.transfer_flags |= USB_NO_FSBR;
- acm_set_control(acm, acm->ctrlout);
+ printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
- acm->line.speed = cpu_to_le32(9600);
- acm->line.databits = 8;
- acm_set_line(acm, &acm->line);
+ acm_set_control(acm, acm->ctrlout);
- usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
- usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
+ acm->line.speed = cpu_to_le32(9600);
+ acm->line.databits = 8;
+ acm_set_line(acm, &acm->line);
+
+ usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
+ usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
+
+ tty_register_devfs(&acm_tty_driver, 0, minor);
+ return acm_table[minor] = acm;
+ }
- tty_register_devfs(&acm_tty_driver, 0, minor);
- return acm_table[minor] = acm;
+ return NULL;
}
static void acm_disconnect(struct usb_device *dev, void *ptr)
@@ -621,10 +631,9 @@ static void acm_disconnect(struct usb_device *dev, void *ptr)
* USB driver structure.
*/
-static struct usb_device_id acm_ids [] = {
- { bDeviceClass: 2},
- { bInterfaceClass: 2, bInterfaceSubClass: 2, bInterfaceProtocol: 1},
- { } /* Terminating entry */
+static struct usb_device_id acm_ids[] = {
+ { bDeviceClass: 2, bDeviceSubClass: 0, bDeviceProtocol: 0},
+ { }
};
MODULE_DEVICE_TABLE (usb, acm_ids);
diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c
index 065d31942..81b3707ef 100644
--- a/drivers/usb/audio.c
+++ b/drivers/usb/audio.c
@@ -89,6 +89,9 @@
* Somewhat peculiar due to OSS interface limitations. Only works
* for channels where a "slider" is already in front of it (i.e.
* a MIXER unit or a FEATURE unit with volume capability).
+ * 2000-11-26: Thomas Sailer
+ * Workaround for Dallas DS4201. The DS4201 uses PCM8 as format tag for
+ * its 8 bit modes, but expects signed data (and should therefore have used PCM).
*
*/
@@ -191,6 +194,7 @@
#define SND_DEV_DSP16 5
+#define dprintk(x)
/* --------------------------------------------------------------------- */
@@ -472,10 +476,10 @@ static int dmabuf_init(struct dmabuf *db)
}
db->bufsize = nr << PAGE_SHIFT;
db->ready = 1;
- printk(KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d "
- "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x\n",
- bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize,
- db->numfrag, db->dmasize, db->bufsize, db->format);
+ dprintk((KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d "
+ "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x\n",
+ bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize,
+ db->numfrag, db->dmasize, db->bufsize, db->format));
return 0;
}
@@ -829,7 +833,7 @@ static int usbin_retire_desc(struct usbin *u, purb_t urb)
for (i = 0; i < DESCFRAMES; i++) {
cp = ((unsigned char *)urb->transfer_buffer) + urb->iso_frame_desc[i].offset;
if (urb->iso_frame_desc[i].status) {
- printk(KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status);
+ dprintk((KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
continue;
}
scnt = urb->iso_frame_desc[i].actual_length >> ufmtsh;
@@ -921,7 +925,7 @@ static int usbin_sync_retire_desc(struct usbin *u, purb_t urb)
for (i = 0; i < SYNCFRAMES; i++)
if (urb->iso_frame_desc[0].status)
- printk(KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status);
+ dprintk((KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
return 0;
}
@@ -954,7 +958,7 @@ static void usbin_sync_completed(struct urb *urb)
} else {
u->flags &= ~(mask | FLG_RUNNING);
wake_up(&u->dma.wait);
- printk(KERN_DEBUG "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret);
+ dprintk((KERN_DEBUG "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
}
spin_unlock_irqrestore(&as->lock, flags);
}
@@ -1211,7 +1215,7 @@ static int usbout_retire_desc(struct usbout *u, purb_t urb)
for (i = 0; i < DESCFRAMES; i++) {
if (urb->iso_frame_desc[i].status) {
- printk(KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status);
+ dprintk((KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
continue;
}
}
@@ -1247,7 +1251,7 @@ static void usbout_completed(struct urb *urb)
} else {
u->flags &= ~(mask | FLG_RUNNING);
wake_up(&u->dma.wait);
- printk(KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret);
+ dprintk((KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
}
spin_unlock_irqrestore(&as->lock, flags);
}
@@ -1273,11 +1277,11 @@ static int usbout_sync_retire_desc(struct usbout *u, purb_t urb)
for (i = 0; i < SYNCFRAMES; i++, cp += 3) {
if (urb->iso_frame_desc[i].status) {
- printk(KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status);
+ dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
continue;
}
if (urb->iso_frame_desc[i].actual_length < 3) {
- printk(KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length);
+ dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length));
continue;
}
f = cp[0] | (cp[1] << 8) | (cp[2] << 16);
@@ -1319,7 +1323,7 @@ static void usbout_sync_completed(struct urb *urb)
} else {
u->flags &= ~(mask | FLG_RUNNING);
wake_up(&u->dma.wait);
- printk(KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret);
+ dprintk((KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
}
spin_unlock_irqrestore(&as->lock, flags);
}
@@ -1520,9 +1524,7 @@ static int set_format_in(struct usb_audiodev *as)
d->srate = fmt->sratelo;
if (d->srate > fmt->sratehi)
d->srate = fmt->sratehi;
-#if 1
- printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting);
-#endif
+ dprintk((KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting));
if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) {
printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
dev->devnum, u->interface, fmt->altsetting);
@@ -1558,10 +1560,11 @@ static int set_format_in(struct usb_audiodev *as)
ret, dev->devnum, u->interface, ep);
return -1;
}
- printk(KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n",
- dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16));
+ dprintk((KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n",
+ dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)));
d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
}
+ dprintk((KERN_DEBUG "usbaudio: set_format_in: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate));
return 0;
}
@@ -1616,9 +1619,7 @@ static int set_format_out(struct usb_audiodev *as)
d->srate = fmt->sratelo;
if (d->srate > fmt->sratehi)
d->srate = fmt->sratehi;
-#if 1
- printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting);
-#endif
+ dprintk((KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting));
if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {
printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
dev->devnum, u->interface, fmt->altsetting);
@@ -1654,10 +1655,11 @@ static int set_format_out(struct usb_audiodev *as)
ret, dev->devnum, u->interface, ep);
return -1;
}
- printk(KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n",
- dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16));
+ dprintk((KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n",
+ dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)));
d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
}
+ dprintk((KERN_DEBUG "usbaudio: set_format_out: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate));
return 0;
}
@@ -2902,6 +2904,9 @@ static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *b
continue;
}
format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8);
+ /* Dallas DS4201 workaround */
+ if (dev->descriptor.idVendor == 0x04fa && dev->descriptor.idProduct == 0x4201)
+ format = (AFMT_S16_LE | AFMT_S8);
fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifout, i);
if (!fmt) {
printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n",
@@ -3705,11 +3710,11 @@ static void usb_audio_disconnect(struct usb_device *dev, void *ptr)
/* we get called with -1 for every audiostreaming interface registered */
if (s == (struct usb_audio_state *)-1) {
- printk(KERN_DEBUG "usb_audio_disconnect: called with -1\n");
+ dprintk((KERN_DEBUG "usb_audio_disconnect: called with -1\n"));
return;
}
if (!s->usbdev) {
- printk(KERN_DEBUG "usb_audio_disconnect: already called for %p!\n", s);
+ dprintk((KERN_DEBUG "usb_audio_disconnect: already called for %p!\n", s));
return;
}
down(&open_sem);
diff --git a/drivers/usb/bluetooth.c b/drivers/usb/bluetooth.c
index 0509f2347..616058acc 100644
--- a/drivers/usb/bluetooth.c
+++ b/drivers/usb/bluetooth.c
@@ -1,11 +1,15 @@
/*
- * bluetooth.c Version 0.6
+ * bluetooth.c Version 0.7
*
* Copyright (c) 2000 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu>
*
* USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
*
+ * (11/29/2000) Version 0.7 gkh
+ * Fixed problem with overrunning the tty flip buffer.
+ * Removed unneeded NULL pointer initialization.
+ *
* (10/05/2000) Version 0.6 gkh
* Fixed bug with urb->dev not being set properly, now that the usb
* core needs it.
@@ -211,8 +215,7 @@ static struct tty_driver bluetooth_tty_driver;
static struct tty_struct * bluetooth_tty[BLUETOOTH_TTY_MINORS];
static struct termios * bluetooth_termios[BLUETOOTH_TTY_MINORS];
static struct termios * bluetooth_termios_locked[BLUETOOTH_TTY_MINORS];
-static struct usb_bluetooth *bluetooth_table[BLUETOOTH_TTY_MINORS] = {NULL, };
-
+static struct usb_bluetooth *bluetooth_table[BLUETOOTH_TTY_MINORS];
static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function)
@@ -327,6 +330,11 @@ static int bluetooth_open (struct tty_struct *tty, struct file * filp)
tty->driver_data = bluetooth;
bluetooth->tty = tty;
+ /* force low_latency on so that our tty_push actually forces the data through,
+ * otherwise it is scheduled, and with high data rates (like with OHCI) data
+ * can get lost. */
+ bluetooth->tty->low_latency = 1;
+
bluetooth->active = 1;
/* Reset the packet position counters */
@@ -786,9 +794,14 @@ static void bluetooth_int_callback (struct urb *urb)
return;
}
- if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos){
- for (i = 0; i < bluetooth->int_packet_pos; ++i)
+ if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) {
+ for (i = 0; i < bluetooth->int_packet_pos; ++i) {
+ /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */
+ if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(bluetooth->tty);
+ }
tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0);
+ }
tty_flip_buffer_push(bluetooth->tty);
bluetooth->int_packet_pos = 0;
@@ -900,8 +913,13 @@ static void bluetooth_read_bulk_callback (struct urb *urb)
}
if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) {
- for (i = 0; i < bluetooth->bulk_packet_pos; ++i)
+ for (i = 0; i < bluetooth->bulk_packet_pos; ++i) {
+ /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
+ if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(bluetooth->tty);
+ }
tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0);
+ }
tty_flip_buffer_push(bluetooth->tty);
bluetooth->bulk_packet_pos = 0;
}
diff --git a/drivers/usb/hid.c b/drivers/usb/hid.c
index 5acdded23..f3901d24a 100644
--- a/drivers/usb/hid.c
+++ b/drivers/usb/hid.c
@@ -856,7 +856,7 @@ static void hid_configure_usage(struct hid_device *device, struct hid_field *fie
case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
switch (usage->hid & HID_USAGE) {
-
+ case 0x000: usage->code = 0; break;
case 0x034: usage->code = KEY_SLEEP; break;
case 0x036: usage->code = BTN_MISC; break;
case 0x08a: usage->code = KEY_WWW; break;
@@ -981,6 +981,9 @@ static void hid_process_event(struct input_dev *input, int *quirks, struct hid_f
input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
}
+ if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */
+ return;
+
input_event(input, usage->type, usage->code, value);
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
diff --git a/drivers/usb/hub.h b/drivers/usb/hub.h
index 626869736..422533b44 100644
--- a/drivers/usb/hub.h
+++ b/drivers/usb/hub.h
@@ -95,8 +95,8 @@ struct usb_hub {
struct urb *urb; /* Interrupt polling pipe */
- char buffer[USB_MAXCHILDREN / 8];
-
+ 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;
diff --git a/drivers/usb/plusb.c b/drivers/usb/plusb.c
index d247c0b28..681709a61 100644
--- a/drivers/usb/plusb.c
+++ b/drivers/usb/plusb.c
@@ -28,7 +28,7 @@
*
* Expect speeds of around 330Kbytes/second over a UHCI host controller.
* OHCI should be faster. Increase the MTU for faster transfers of large
- * files. (16384 is a good size)
+ * files (up-to 800Kbytes/second). (16384 is a good size)
*
* $Id: plusb.c,v 1.18 2000/02/14 10:38:58 fliegl Exp $
*
@@ -136,6 +136,10 @@
//#define DEBUG 1
#include <linux/usb.h>
+#if (LINUX_VERSION_CODE < 0x020300)
+#define dev_kfree_skb_any dev_kfree_skb
+#endif
+
/* Definitions formerly in plusb.h relocated. No need to export them -EZA */
#define _PLUSB_INTPIPE 0x1
@@ -401,11 +405,9 @@ static void plusb_write_bulk_complete(urb_t *purb)
skb_list->state=0;
- if( purb->status == -EPIPE ) {
-
+ if( purb->status == -EPIPE )
printk(KERN_CRIT "%s: plusb_write_bulk_complete: got -EPIPE and don't know what to do!\n",
s->net_dev.name);
- }
if(!purb->status) {
s->net_stats.tx_packets++;
@@ -421,15 +423,10 @@ static void plusb_write_bulk_complete(urb_t *purb)
dbg("plusb_bh: dev_kfree_skb");
-
-#if (LINUX_VERSION_CODE < 0x020300)
- dev_kfree_skb(skb_list->skb);
-#else
/* NOTE: In 2.4 it's a problem to call dev_kfree_skb() in a hard IRQ:
Oct 28 23:42:14 bug kernel: Warning: kfree_skb on hard IRQ c023329a
*/
dev_kfree_skb_any(skb_list->skb);
-#endif
skb_list->skb = NULL;
if (plusb_add_buf_tail (s, &s->free_skb_list, &s->tx_skb_list)) {
@@ -463,12 +460,10 @@ static void plusb_read_bulk_complete(urb_t *purb)
if(!s->connected)
return;
- if( purb->status == -EPIPE ) {
-
+ if( purb->status == -EPIPE )
printk(KERN_CRIT "%s: plusb_read_bulk_complete: got -EPIPE and I don't know what to do!\n",
s->net_dev.name);
-
- } else if (!purb->status) {
+ else if (!purb->status) {
struct sk_buff *skb;
unsigned char *dst;
int len=purb->transfer_buffer_length;
@@ -651,11 +646,7 @@ static void plusb_free_all(plusb_t *s)
skb_list = list_entry (skb, skb_list_t, skb_list);
if (skb_list->skb) {
dbg ("Freeing SKB in queue");
-#if (LINUX_VERSION_CODE < 0x020300)
- dev_kfree_skb(skb_list->skb);
-#else
dev_kfree_skb_any(skb_list->skb);
-#endif
skb_list->skb = NULL;
}
kfree(skb_list);
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index c77ba35e2..58061ec90 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -82,6 +82,7 @@ struct usblp {
int readcount; /* Counter for reads */
int ifnum; /* Interface number */
int minor; /* minor number of device */
+ unsigned int quirks; /* quirks flags */
unsigned char used; /* True if open */
unsigned char bidir; /* interface is bidirectional */
unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */
@@ -90,6 +91,26 @@ struct usblp {
static struct usblp *usblp_table[USBLP_MINORS];
+/* Quirks: various printer quirks are handled by this table & its flags. */
+
+struct quirk_printer_struct {
+ __u16 vendorId;
+ __u16 productId;
+ unsigned int quirks;
+};
+
+#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */
+#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
+
+static struct quirk_printer_struct quirk_printers[] = {
+ { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
+ { 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
+ { 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
+ { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
+ { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
+ { 0, 0 }
+};
+
/*
* Functions for usblp control messages.
*/
@@ -325,8 +346,17 @@ static ssize_t usblp_write(struct file *file, const char *buffer, size_t count,
return -ENODEV;
if (usblp->writeurb.status) {
- err = usblp_check_status(usblp, err);
- continue;
+ if (usblp->quirks & USBLP_QUIRK_BIDIR) {
+ if (usblp->writeurb.status != -EINPROGRESS)
+ err("usblp%d: error %d writing to printer",
+ usblp->minor, usblp->writeurb.status);
+ err = usblp->writeurb.status;
+ continue;
+ }
+ else {
+ err = usblp_check_status(usblp, err);
+ continue;
+ }
}
writecount += usblp->writeurb.transfer_buffer_length;
@@ -393,13 +423,42 @@ static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t
return count;
}
+/*
+ * Checks for printers that have quirks, such as requiring unidirectional
+ * communication but reporting bidirectional; currently some HP printers
+ * have this flaw (HP 810, 880, 895, etc.), or needing an init string
+ * sent at each open (like some Epsons).
+ * Returns 1 if found, 0 if not found.
+ *
+ * HP recommended that we use the bidirectional interface but
+ * don't attempt any bulk IN transfers from the IN endpoint.
+ * Here's some more detail on the problem:
+ * The problem is not that it isn't bidirectional though. The problem
+ * is that if you request a device ID, or status information, while
+ * the buffers are full, the return data will end up in the print data
+ * buffer. For example if you make sure you never request the device ID
+ * while you are sending print data, and you don't try to query the
+ * printer status every couple of milliseconds, you will probably be OK.
+ */
+static unsigned int usblp_quirks (__u16 vendor, __u16 product)
+{
+ int i;
+
+ for (i = 0; quirk_printers[i].vendorId; i++) {
+ if (vendor == quirk_printers[i].vendorId &&
+ product == quirk_printers[i].productId)
+ return quirk_printers[i].quirks;
+ }
+ return 0;
+}
+
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *epread, *epwrite;
struct usblp *usblp;
- int minor, i, bidir = 0;
+ int minor, i, bidir = 0, quirks;
int alts = dev->actconfig->interface[ifnum].act_altsetting;
int length, err;
char *buf;
@@ -453,10 +512,21 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
}
memset(usblp, 0, sizeof(struct usblp));
+ /* lookup quirks for this printer */
+ quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
+
+ if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
+ bidir = 0;
+ epread = NULL;
+ info ("Disabling reads from problem bidirectional printer on usblp%d",
+ minor);
+ }
+
usblp->dev = dev;
usblp->ifnum = ifnum;
usblp->minor = minor;
usblp->bidir = bidir;
+ usblp->quirks = quirks;
init_waitqueue_head(&usblp->wait);
diff --git a/drivers/usb/scanner.c b/drivers/usb/scanner.c
index 2ee4ba127..2a7e887d9 100644
--- a/drivers/usb/scanner.c
+++ b/drivers/usb/scanner.c
@@ -252,6 +252,7 @@ static struct usb_device_id scanner_device_ids [] = {
{ idVendor: 0x04a5, idProduct: 0x2022 },/* Vuego Scan Brisa 340U */
/* Agfa */
{ idVendor: 0x06bd, idProduct: 0x0001 }, /* SnapScan 1212U */
+ { idVendor: 0x06bd, idProduct: 0x0002 }, /* SnapScan 1236U */
{ idVendor: 0x06bd, idProduct: 0x2061 }, /* Another SnapScan 1212U (?)*/
{ idVendor: 0x06bd, idProduct: 0x0100 }, /* SnapScan Touch */
/* Colorado -- See Primax/Colorado below */
@@ -300,10 +301,10 @@ static struct usb_device_id scanner_device_ids [] = {
{ idVendor: 0x04b8, idProduct: 0x0101 },/* Perfection 636U and 636Photo */
{ idVendor: 0x04b8, idProduct: 0x0103 },/* Perfection 610 */
{ idVendor: 0x04b8, idProduct: 0x0104 },/* Perfection 1200U and 1200Photo*/
+ { idVendor: 0x04b8, idProduct: 0x0106 },/* Stylus Scan 2500 */
{ idVendor: 0x04b8, idProduct: 0x0107 },/* Expression 1600 */
/* Umax */
{ idVendor: 0x1606, idProduct: 0x0010 }, /* Astra 1220U */
- { idVendor: 0x1606, idProduct: 0x0002 }, /* Astra 1236U */
{ idVendor: 0x1606, idProduct: 0x0030 }, /* Astra 2000U */
{ idVendor: 0x1606, idProduct: 0x0230 }, /* Astra 2200U */
/* Visioneer */
diff --git a/drivers/usb/serial/Config.in b/drivers/usb/serial/Config.in
new file mode 100644
index 000000000..6d949bc0b
--- /dev/null
+++ b/drivers/usb/serial/Config.in
@@ -0,0 +1,30 @@
+#
+# USB Serial device configuration
+#
+mainmenu_option next_comment
+comment 'USB Serial Converter support'
+
+tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
+if [ "$CONFIG_USB_SERIAL" != "n" ]; then
+ bool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG
+ bool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC
+ dep_tristate ' USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
+ 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 Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
+ dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then
+ bool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28
+ bool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X
+ bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
+ bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X
+ bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
+ fi
+ dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+ dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+fi
+
+endmenu
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index b90d4f52d..97b5516aa 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -22,6 +22,8 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN) += keyspan.o
obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
+obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
+obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
# Objects that export symbols.
export-objs := usbserial.o
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 197752224..060ee5a69 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -601,7 +601,7 @@ static void digi_wakeup_write_lock( struct usb_serial_port *port )
spin_lock_irqsave( &priv->dp_port_lock, flags );
digi_wakeup_write( port );
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
-
+ MOD_DEC_USE_COUNT;
}
static void digi_wakeup_write( struct usb_serial_port *port )
@@ -1409,7 +1409,9 @@ dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
/* also queue up a wakeup at scheduler time, in case we */
/* lost the race in write_chan(). */
- queue_task( &priv->dp_wakeup_task, &tq_scheduler );
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&priv->dp_wakeup_task) == 0)
+ MOD_DEC_USE_COUNT;
spin_unlock( &priv->dp_port_lock );
@@ -1736,7 +1738,7 @@ dbg( "digi_startup: TOP" );
init_waitqueue_head( &priv->dp_flush_wait );
priv->dp_in_close = 0;
init_waitqueue_head( &priv->dp_close_wait );
- priv->dp_wakeup_task.next = NULL;
+ INIT_LIST_HEAD(&priv->dp_wakeup_task.list);
priv->dp_wakeup_task.sync = 0;
priv->dp_wakeup_task.routine = (void *)digi_wakeup_write_lock;
priv->dp_wakeup_task.data = (void *)(&serial->port[i]);
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
new file mode 100644
index 000000000..63b5458e5
--- /dev/null
+++ b/drivers/usb/serial/empeg.c
@@ -0,0 +1,648 @@
+/*
+ * USB Empeg empeg-car player driver
+ *
+ * Copyright (C) 2000
+ * Gary Brubaker (xavyer@ix.netcom.com)
+ *
+ * Copyright (C) 1999, 2000
+ * Greg Kroah-Hartman (greg@kroah.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, as published by
+ * the Free Software Foundation, version 2.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * (12/03/2000) gb
+ * Added port->tty->ldisc.set_termios(port->tty, NULL) to empeg_open()
+ * This notifies the tty driver that the termios have changed.
+ *
+ * (11/13/2000) gb
+ * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open()
+ * (It only needs to be set once - Doh!)
+ *
+ * (11/11/2000) gb
+ * Updated to work with id_table structure.
+ *
+ * (11/04/2000) gb
+ * Forked this from visor.c, and hacked it up to work with an
+ * Empeg ltd. empeg-car player. Constructive criticism welcomed.
+ * I would like to say, 'Thank You' to Greg Kroah-Hartman for the
+ * use of his code, and for his guidance, advice and patience. :)
+ * A 'Thank You' is in order for John Ripley of Empeg ltd for his
+ * advice, and patience too.
+ *
+ */
+
+#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/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#ifdef CONFIG_USB_SERIAL_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb-serial.h"
+
+#define EMPEG_VENDOR_ID 0x084f
+#define EMPEG_PRODUCT_ID 0x0001
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+/* function prototypes for an empeg-car player */
+static int empeg_open (struct usb_serial_port *port, struct file *filp);
+static void empeg_close (struct usb_serial_port *port, struct file *filp);
+static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static void empeg_throttle (struct usb_serial_port *port);
+static void empeg_unthrottle (struct usb_serial_port *port);
+static int empeg_startup (struct usb_serial *serial);
+static void empeg_shutdown (struct usb_serial *serial);
+static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void empeg_write_bulk_callback (struct urb *urb);
+static void empeg_read_bulk_callback (struct urb *urb);
+
+static __devinitdata struct usb_device_id id_table [] = {
+ { idVendor: EMPEG_VENDOR_ID, idProduct: EMPEG_PRODUCT_ID },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+struct usb_serial_device_type empeg_device = {
+ name: "Empeg",
+ id_table: id_table,
+ needs_interrupt_in: MUST_HAVE_NOT, /* must not have an interrupt in endpoint */
+ needs_bulk_in: MUST_HAVE, /* must have a bulk in endpoint */
+ needs_bulk_out: MUST_HAVE, /* must have a bulk out endpoint */
+ num_interrupt_in: 0,
+ num_bulk_in: 1,
+ num_bulk_out: 1,
+ num_ports: 1,
+ open: empeg_open,
+ close: empeg_close,
+ throttle: empeg_throttle,
+ unthrottle: empeg_unthrottle,
+ startup: empeg_startup,
+ shutdown: empeg_shutdown,
+ ioctl: empeg_ioctl,
+ set_termios: empeg_set_termios,
+ write: empeg_write,
+ write_bulk_callback: empeg_write_bulk_callback,
+ read_bulk_callback: empeg_read_bulk_callback,
+};
+
+#define NUM_URBS 16
+#define URB_TRANSFER_BUFFER_SIZE 4096
+
+static struct urb *write_urb_pool[NUM_URBS];
+static spinlock_t write_urb_pool_lock;
+static int bytes_in;
+static int bytes_out;
+
+/******************************************************************************
+ * Empeg specific driver functions
+ ******************************************************************************/
+static int empeg_open (struct usb_serial_port *port, struct file *filp)
+{
+ struct usb_serial *serial = port->serial;
+ unsigned long flags;
+ int result;
+
+ if (port_paranoia_check (port, __FUNCTION__))
+ return -ENODEV;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ spin_lock_irqsave (&port->port_lock, flags);
+
+ ++port->open_count;
+ MOD_INC_USE_COUNT;
+
+ /* gb - 2000/11/05
+ *
+ * personally, I think these termios should be set in
+ * empeg_startup(), but it appears doing so leads to one
+ * of those chicken/egg problems. :)
+ *
+ */
+ port->tty->termios->c_iflag
+ &= ~(IGNBRK
+ | BRKINT
+ | PARMRK
+ | ISTRIP
+ | INLCR
+ | IGNCR
+ | ICRNL
+ | IXON);
+
+ port->tty->termios->c_oflag
+ &= ~OPOST;
+
+ port->tty->termios->c_lflag
+ &= ~(ECHO
+ | ECHONL
+ | ICANON
+ | ISIG
+ | IEXTEN);
+
+ port->tty->termios->c_cflag
+ &= ~(CSIZE
+ | PARENB);
+
+ port->tty->termios->c_cflag
+ |= CS8;
+
+ /* gb - 2000/12/03
+ *
+ * Contributed by Borislav Deianov
+ *
+ * Notify the tty driver that the termios have changed!!
+ *
+ */
+ port->tty->ldisc.set_termios(port->tty, NULL);
+
+ /* gb - 2000/11/05
+ *
+ * force low_latency on
+ *
+ * The tty_flip_buffer_push()'s in empeg_read_bulk_callback() will actually
+ * force the data through if low_latency is set. Otherwise the pushes are
+ * scheduled; this is bad as it opens up the possibility of dropping bytes
+ * on the floor. We are trying to sustain high data transfer rates; and
+ * don't want to drop bytes on the floor.
+ * Moral: use low_latency - drop no bytes - life is good. :)
+ *
+ */
+ port->tty->low_latency = 1;
+
+ if (!port->active) {
+ port->active = 1;
+ bytes_in = 0;
+ bytes_out = 0;
+
+ /* 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,
+ empeg_read_bulk_callback,
+ port);
+
+ port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+
+ result = usb_submit_urb(port->read_urb);
+
+ if (result)
+ err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+
+ }
+
+ spin_unlock_irqrestore (&port->port_lock, flags);
+
+ return 0;
+}
+
+
+static void empeg_close (struct usb_serial_port *port, struct file * filp)
+{
+ struct usb_serial *serial;
+ unsigned char *transfer_buffer;
+ unsigned long flags;
+
+ if (port_paranoia_check (port, __FUNCTION__))
+ return;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ serial = get_usb_serial (port, __FUNCTION__);
+ if (!serial)
+ return;
+
+ spin_lock_irqsave (&port->port_lock, flags);
+
+ --port->open_count;
+ MOD_DEC_USE_COUNT;
+
+ if (port->open_count <= 0) {
+ transfer_buffer = kmalloc (0x12, GFP_KERNEL);
+
+ if (!transfer_buffer) {
+ err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
+ } else {
+ kfree (transfer_buffer);
+ }
+
+ /* shutdown our bulk read */
+ usb_unlink_urb (port->read_urb);
+ port->active = 0;
+ port->open_count = 0;
+ }
+
+ spin_unlock_irqrestore (&port->port_lock, flags);
+
+ /* 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 int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+{
+ struct usb_serial *serial = port->serial;
+ struct urb *urb;
+ const unsigned char *current_position = buf;
+ unsigned long flags;
+ int status;
+ int i;
+ int bytes_sent = 0;
+ int transfer_size;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf);
+
+ while (count > 0) {
+
+ /* try to find a free urb in our list of them */
+ urb = NULL;
+
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
+
+ for (i = 0; i < NUM_URBS; ++i) {
+ if (write_urb_pool[i]->status != -EINPROGRESS) {
+ urb = write_urb_pool[i];
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore (&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;
+ }
+ }
+
+ transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE);
+
+ if (from_user) {
+ copy_from_user (urb->transfer_buffer, current_position, transfer_size);
+ } else {
+ memcpy (urb->transfer_buffer, current_position, transfer_size);
+ }
+
+ count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+ /* build up our urb */
+ FILL_BULK_URB (
+ urb,
+ serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
+ urb->transfer_buffer,
+ transfer_size,
+ empeg_write_bulk_callback,
+ port);
+
+ urb->transfer_flags |= USB_QUEUE_BULK;
+
+ /* send it down the pipe */
+ status = usb_submit_urb(urb);
+ if (status)
+ dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
+
+ current_position += transfer_size;
+ bytes_sent += transfer_size;
+ count -= transfer_size;
+ bytes_out += transfer_size;
+
+ }
+
+exit:
+ return bytes_sent;
+
+}
+
+
+static void empeg_write_bulk_callback (struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+
+ 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);
+ return;
+ }
+
+ queue_task(&port->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+
+ return;
+
+}
+
+
+static void empeg_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;
+ int 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) {
+ /* gb - 2000/11/13
+ * If we insert too many characters we'll overflow the buffer.
+ * This means we'll lose bytes - Decidedly bad.
+ */
+ if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ }
+ /* gb - 2000/11/13
+ * This doesn't push the data through unless tty->low_latency is set.
+ */
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ /* gb - 2000/11/13
+ * Goes straight through instead of scheduling - if tty->low_latency is set.
+ */
+ 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,
+ empeg_read_bulk_callback,
+ port);
+
+ port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+
+ result = usb_submit_urb(port->read_urb);
+
+ if (result)
+ err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+
+ return;
+
+}
+
+
+static void empeg_throttle (struct usb_serial_port *port)
+{
+ unsigned long flags;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ spin_lock_irqsave (&port->port_lock, flags);
+
+ usb_unlink_urb (port->read_urb);
+
+ spin_unlock_irqrestore (&port->port_lock, flags);
+
+ return;
+
+}
+
+
+static void empeg_unthrottle (struct usb_serial_port *port)
+{
+ unsigned long flags;
+ int result;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ spin_lock_irqsave (&port->port_lock, flags);
+
+ 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);
+
+ spin_unlock_irqrestore (&port->port_lock, flags);
+
+ return;
+
+}
+
+
+static int empeg_startup (struct usb_serial *serial)
+{
+
+ dbg(__FUNCTION__);
+
+ dbg(__FUNCTION__ " - Set config to 1");
+ usb_set_configuration (serial->dev, 1);
+
+ /* continue on with initialization */
+ return 0;
+
+}
+
+
+static void empeg_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) {
+ empeg_close (&serial->port[i], NULL);
+ }
+ }
+
+}
+
+
+static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+{
+ dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
+
+ return -ENOIOCTLCMD;
+}
+
+
+/* This function is all nice and good, but we don't change anything based on it :) */
+static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+{
+ unsigned int cflag = port->tty->termios->c_cflag;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ /* check that they really want us to change something */
+ if (old_termios) {
+ if ((cflag == old_termios->c_cflag) &&
+ (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
+ dbg(__FUNCTION__ " - nothing to change...");
+ return;
+ }
+ }
+
+ if ((!port->tty) || (!port->tty->termios)) {
+ dbg(__FUNCTION__" - no tty structures");
+ return;
+ }
+
+ /* get the byte size */
+ switch (cflag & CSIZE) {
+ case CS5: dbg(__FUNCTION__ " - data bits = 5"); break;
+ case CS6: dbg(__FUNCTION__ " - data bits = 6"); break;
+ case CS7: dbg(__FUNCTION__ " - data bits = 7"); break;
+ default:
+ case CS8: dbg(__FUNCTION__ " - data bits = 8"); break;
+ }
+
+ /* determine the parity */
+ if (cflag & PARENB)
+ if (cflag & PARODD)
+ dbg(__FUNCTION__ " - parity = odd");
+ else
+ dbg(__FUNCTION__ " - parity = even");
+ else
+ dbg(__FUNCTION__ " - parity = none");
+
+ /* figure out the stop bits requested */
+ if (cflag & CSTOPB)
+ dbg(__FUNCTION__ " - stop bits = 2");
+ else
+ dbg(__FUNCTION__ " - stop bits = 1");
+
+ /* figure out the flow control settings */
+ if (cflag & CRTSCTS)
+ dbg(__FUNCTION__ " - RTS/CTS is enabled");
+ else
+ dbg(__FUNCTION__ " - RTS/CTS is disabled");
+
+ /* determine software flow control */
+ if (I_IXOFF(port->tty))
+ dbg(__FUNCTION__ " - XON/XOFF is enabled, XON = %2x, XOFF = %2x", START_CHAR(port->tty), STOP_CHAR(port->tty));
+ else
+ dbg(__FUNCTION__ " - XON/XOFF is disabled");
+
+ /* get the baud rate wanted */
+ dbg(__FUNCTION__ " - baud rate = %d", tty_get_baud_rate(port->tty));
+
+ return;
+
+}
+
+
+static int __init empeg_init (void)
+{
+ struct urb *urb;
+ int i;
+
+ usb_serial_register (&empeg_device);
+
+ /* create our write urb pool and transfer buffers */
+ spin_lock_init (&write_urb_pool_lock);
+ for (i = 0; i < NUM_URBS; ++i) {
+ urb = usb_alloc_urb(0);
+ 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;
+ }
+ }
+
+ return 0;
+
+}
+
+
+static void __exit empeg_exit (void)
+{
+ int i;
+ unsigned long flags;
+
+ usb_serial_deregister (&empeg_device);
+
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
+
+ for (i = 0; i < NUM_URBS; ++i) {
+ if (write_urb_pool[i]) {
+ /* 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_urb_pool[i]); */
+ if (write_urb_pool[i]->transfer_buffer)
+ kfree(write_urb_pool[i]->transfer_buffer);
+ usb_free_urb (write_urb_pool[i]);
+ }
+ }
+
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+
+}
+
+
+module_init(empeg_init);
+module_exit(empeg_exit);
+
+MODULE_AUTHOR("Gary Brubaker <xavyer@ix.netcom.com>");
+MODULE_DESCRIPTION("USB Empeg Mark I/II Driver");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index fcdf71e84..c52ad0b37 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -12,9 +12,20 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info
+ * and extra documentation
+ *
+ * (12/3/2000) Bill Ryder
+ * Added support for 8U232AM device.
+ * Moved PID and VIDs into header file only.
+ * Turned on low-latency for the tty (device will do high baudrates)
+ * Added shutdown routine to close files when device removed.
+ * More debug and error message cleanups.
+ *
+ *
* (11/13/2000) Bill Ryder
* Added spinlock protected open code and close code.
- * Multiple opens work (sort of - see webpage).
+ * Multiple opens work (sort of - see webpage mentioned above).
* Cleaned up comments. Removed multiple PID/VID definitions.
* Factorised cts/dtr code
* Made use of __FUNCTION__ in dbg's
@@ -34,11 +45,11 @@
* driver is a loadable module now.
*
* (04/04/2000) Bill Ryder
- * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
- * handled elsewhere in the serial driver chain).
+ * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
+ * handled elsewhere in the tty io driver chain).
*
* (03/30/2000) Bill Ryder
- * Implemented lots of ioctls
+ * Implemented lots of ioctls
* Fixed a race condition in write
* Changed some dbg's to errs
*
@@ -50,6 +61,7 @@
/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
/* Thanx to FTDI for so kindly providing details of the protocol required */
/* to talk to the device */
+/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */
#include <linux/config.h>
@@ -78,20 +90,42 @@
#include "ftdi_sio.h"
-#define FTDI_VENDOR_ID FTDI_VID
-#define FTDI_SIO_SERIAL_CONVERTER_ID FTDI_SIO_PID
-#define FTDI_8U232AM_PID 0x6001
static __devinitdata struct usb_device_id id_table_sio [] = {
{ idVendor: FTDI_VID, idProduct: FTDI_SIO_PID },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_sio);
+/* THe 8U232AM has the same API as the sio - but it can support MUCH
+ higher baudrates (921600 at 48MHz/230400 at 12MHz
+ so .. it's baudrate setting codes are different */
+
+
+static __devinitdata struct usb_device_id id_table_8U232AM [] = {
+ { idVendor: FTDI_VID, idProduct: FTDI_8U232AM_PID },
+ { } /* Terminating entry */
+};
+
+
+static __devinitdata struct usb_device_id id_table_combined [] = {
+ { idVendor: FTDI_VID, idProduct: FTDI_SIO_PID },
+ { idVendor: FTDI_VID, idProduct: FTDI_8U232AM_PID },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table_combined);
+struct ftdi_private {
+ ftdi_type_t ftdi_type;
+ char last_status_byte; /* device sends this every 40ms when open */
+
+
+};
/* function prototypes for a FTDI serial converter */
static int ftdi_sio_startup (struct usb_serial *serial);
+static int ftdi_8U232AM_startup (struct usb_serial *serial);
+static void ftdi_sio_shutdown (struct usb_serial *serial);
static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp);
static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp);
static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
@@ -100,13 +134,15 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb);
static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old);
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-/* All of the device info needed for the FTDI SIO serial converter */
+/* Should rename most ftdi_sio's to ftdi_ now since there are two devices
+ which share common code */
+
struct usb_serial_device_type ftdi_sio_device = {
name: "FTDI SIO",
id_table: id_table_sio,
- needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
- needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
- needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
+ needs_interrupt_in: MUST_HAVE_NOT,
+ needs_bulk_in: MUST_HAVE,
+ needs_bulk_out: MUST_HAVE,
num_interrupt_in: 0,
num_bulk_in: 1,
num_bulk_out: 1,
@@ -119,17 +155,35 @@ struct usb_serial_device_type ftdi_sio_device = {
ioctl: ftdi_sio_ioctl,
set_termios: ftdi_sio_set_termios,
startup: ftdi_sio_startup,
+ shutdown: ftdi_sio_shutdown,
};
+struct usb_serial_device_type ftdi_8U232AM_device = {
+ name: "FTDI 8U232AM",
+ id_table: id_table_8U232AM,
+ needs_interrupt_in: DONT_CARE,
+ needs_bulk_in: MUST_HAVE,
+ needs_bulk_out: MUST_HAVE,
+ num_interrupt_in: 0,
+ num_bulk_in: 1,
+ num_bulk_out: 1,
+ num_ports: 1,
+ open: ftdi_sio_open,
+ close: ftdi_sio_close,
+ write: ftdi_sio_write,
+ read_bulk_callback: ftdi_sio_read_bulk_callback,
+ write_bulk_callback: ftdi_sio_write_bulk_callback,
+ ioctl: ftdi_sio_ioctl,
+ set_termios: ftdi_sio_set_termios,
+ startup: ftdi_8U232AM_startup,
+ shutdown: ftdi_sio_shutdown,
+};
+
+
/*
* ***************************************************************************
* FTDI SIO Serial Converter specific driver functions
* ***************************************************************************
- *
- * See the webpage http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date
- * testing information
- *
- *
*/
#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
@@ -165,15 +219,59 @@ static int set_dtr(struct usb_device *dev,
}
-/* do some startup allocations not currently performed by usb_serial_probe() */
+
static int ftdi_sio_startup (struct usb_serial *serial)
{
+ struct ftdi_private *priv;
+
init_waitqueue_head(&serial->port[0].write_wait);
+
+ priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+ if (!priv){
+ err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private));
+ return -ENOMEM;
+ }
+ priv->ftdi_type = sio;
return (0);
}
+
+static int ftdi_8U232AM_startup (struct usb_serial *serial)
+{
+ struct ftdi_private *priv;
+
+ init_waitqueue_head(&serial->port[0].write_wait);
+
+ priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+ if (!priv){
+ err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private));
+ return -ENOMEM;
+ }
+
+ priv->ftdi_type = F8U232AM;
+
+ return (0);
+}
+
+static void ftdi_sio_shutdown (struct usb_serial *serial)
+{
+
+ dbg (__FUNCTION__);
+
+ /* Close ports if they are open */
+ while (serial->port[0].open_count > 0) {
+ ftdi_sio_close (&serial->port[0], NULL);
+ }
+ if (serial->port->private){
+ kfree(serial->port->private);
+ serial->port->private = NULL;
+ }
+}
+
+
+
static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
{ /* ftdi_sio_open */
struct termios tmp_termios;
@@ -182,7 +280,7 @@ static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
int result;
char buf[1]; /* Needed for the usb_control_msg I think */
- dbg(__FUNCTION__ " port %d", port->number);
+ dbg(__FUNCTION__);
spin_lock_irqsave (&port->port_lock, flags);
@@ -191,29 +289,33 @@ static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
if (!port->active){
port->active = 1;
+
spin_unlock_irqrestore (&port->port_lock, flags);
+ /* do not allow a task to be queued to deliver received data */
+ port->tty->low_latency = 1;
+
+ /* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE,
FTDI_SIO_RESET_SIO,
0, buf, 0, WDR_TIMEOUT);
- /* Setup termios */
+ /* Setup termios defaults. According to tty_io.c the
+ settings are driver specific */
port->tty->termios->c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
/* ftdi_sio_set_termios will send usb control messages */
- /* ftdi_sio_set_termios will set up port according to above list */
-
ftdi_sio_set_termios(port, &tmp_termios);
- /* Turn on RTS and DTR since we are not flow controlling*/
+ /* Turn on RTS and DTR since we are not flow controlling by default */
if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) {
- err("Error from DTR HIGH urb");
+ err(__FUNCTION__ " Error from DTR HIGH urb");
}
if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){
- err("Error from RTS HIGH urb");
+ err(__FUNCTION__ " Error from RTS HIGH urb");
}
/* Start reading from the device */
@@ -224,7 +326,7 @@ static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
result = usb_submit_urb(port->read_urb);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
- } else { /* the port was already active - so no initialisation was done */
+ } else { /* the port was already active - so no initialisation is done */
spin_unlock_irqrestore (&port->port_lock, flags);
}
@@ -239,7 +341,7 @@ static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
char buf[1];
unsigned long flags;
- dbg( __FUNCTION__ " port %d", port->number);
+ dbg( __FUNCTION__);
spin_lock_irqsave (&port->port_lock, flags);
--port->open_count;
@@ -271,14 +373,18 @@ static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
usb_unlink_urb (port->read_urb);
port->active = 0;
port->open_count = 0;
- } else {
+ } else {
spin_unlock_irqrestore (&port->port_lock, flags);
+
+ /* Send a HUP if necessary */
+ if (!(port->tty->termios->c_cflag & CLOCAL)){
+ tty_hangup(port->tty);
+ }
+
}
MOD_DEC_USE_COUNT;
-
-
} /* ftdi_sio_close */
@@ -292,7 +398,8 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count)
{ /* ftdi_sio_write */
struct usb_serial *serial = port->serial;
- const int data_offset = 1;
+ struct ftdi_private *priv = (struct ftdi_private *)port->private;
+ int data_offset ;
int rc;
int result;
DECLARE_WAITQUEUE(wait, current);
@@ -303,24 +410,25 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
err("write request of 0 bytes");
return 0;
}
+
+ if (priv->ftdi_type == sio){
+ data_offset = 1;
+ } else {
+ data_offset = 0;
+ }
+ dbg("data_offset set to %d",data_offset);
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
unsigned char *first_byte = port->write_urb->transfer_buffer;
/* Was seeing a race here, got a read callback, then write callback before
- hitting interuptible_sleep_on - so wrapping in add_wait_queue stuff */
+ hitting interuptible_sleep_on - so wrapping in a wait_queue */
add_wait_queue(&port->write_wait, &wait);
set_current_state (TASK_INTERRUPTIBLE);
while (port->write_urb->status == -EINPROGRESS) {
dbg(__FUNCTION__ " write in progress - retrying");
- if (0 /* file->f_flags & O_NONBLOCK */) {
- remove_wait_queue(&port->write_wait, &wait);
- set_current_state(TASK_RUNNING);
- rc = -EAGAIN;
- goto err;
- }
if (signal_pending(current)) {
current->state = TASK_RUNNING;
remove_wait_queue(&port->write_wait, &wait);
@@ -328,7 +436,6 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
goto err;
}
schedule();
- set_current_state (TASK_INTERRUPTIBLE);
}
remove_wait_queue(&port->write_wait, &wait);
set_current_state(TASK_RUNNING);
@@ -349,11 +456,13 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
buf, count - data_offset );
}
- /* Write the control byte at the front of the packet*/
first_byte = port->write_urb->transfer_buffer;
- *first_byte = 1 | ((count-data_offset) << 2) ;
+ if (data_offset > 0){
+ /* Write the control byte at the front of the packet*/
+ *first_byte = 1 | ((count-data_offset) << 2) ;
+ }
- dbg(__FUNCTION__ "Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]);
+ dbg(__FUNCTION__ " Bytes: %d, First Byte: 0o%03o",count, first_byte[0]);
usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
/* send the data out the bulk port */
@@ -412,6 +521,7 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb)
static void ftdi_sio_read_bulk_callback (struct urb *urb)
{ /* ftdi_sio_serial_buld_callback */
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct ftdi_private *priv = (struct ftdi_private *)port->private;
struct usb_serial *serial;
struct tty_struct *tty = port->tty ;
unsigned char *data = urb->transfer_buffer;
@@ -443,8 +553,10 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
dbg("Just status");
}
+ priv->last_status_byte = data[0]; /* this has modem control lines */
+
/* TO DO -- check for hung up line and handle appropriately: */
- /* send hangup (need to find out how to do this) */
+ /* send hangup */
/* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */
/* if CD is dropped and the line is not CLOCAL then we should hangup */
@@ -469,6 +581,53 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
return;
} /* ftdi_sio_serial_read_bulk_callback */
+
+__u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type)
+{ /* translate_baudrate_to_ftdi */
+
+ __u16 urb_value = ftdi_sio_b9600;
+
+ if (ftdi_type == sio){
+ switch(cflag & CBAUD){
+ case B0: break; /* ignored by this */
+ case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break;
+ case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break;
+ case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break;
+ case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break;
+ case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break;
+ case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break;
+ case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break;
+ case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break;
+ case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break;
+ case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break;
+ default: dbg(__FUNCTION__ " FTDI_SIO does not support the baudrate (%d) requested",
+ (cflag & CBAUD));
+ break;
+ }
+ } else { /* it is 8U232AM */
+ switch(cflag & CBAUD){
+ case B0: break; /* ignored by this */
+ case B300: urb_value = ftdi_8U232AM_48MHz_b300; dbg("Set to 300"); break;
+ case B600: urb_value = ftdi_8U232AM_48MHz_b600; dbg("Set to 600") ; break;
+ case B1200: urb_value = ftdi_8U232AM_48MHz_b1200; dbg("Set to 1200") ; break;
+ case B2400: urb_value = ftdi_8U232AM_48MHz_b2400; dbg("Set to 2400") ; break;
+ case B4800: urb_value = ftdi_8U232AM_48MHz_b4800; dbg("Set to 4800") ; break;
+ case B9600: urb_value = ftdi_8U232AM_48MHz_b9600; dbg("Set to 9600") ; break;
+ case B19200: urb_value = ftdi_8U232AM_48MHz_b19200; dbg("Set to 19200") ; break;
+ case B38400: urb_value = ftdi_8U232AM_48MHz_b38400; dbg("Set to 38400") ; break;
+ case B57600: urb_value = ftdi_8U232AM_48MHz_b57600; dbg("Set to 57600") ; break;
+ case B115200: urb_value = ftdi_8U232AM_48MHz_b115200; dbg("Set to 115200") ; break;
+ case B230400: urb_value = ftdi_8U232AM_48MHz_b230400; dbg("Set to 230400") ; break;
+ case B460800: urb_value = ftdi_8U232AM_48MHz_b460800; dbg("Set to 460800") ; break;
+ case B921600: urb_value = ftdi_8U232AM_48MHz_b921600; dbg("Set to 921600") ; break;
+ default: dbg(__FUNCTION__ " The baudrate (%d) requested is not implemented",
+ (cflag & CBAUD));
+ break;
+ }
+ }
+ return(urb_value);
+}
+
/* As I understand this - old_termios contains the original termios settings */
/* and tty->termios contains the new setting to be used */
/* */
@@ -478,10 +637,12 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
{ /* ftdi_sio_set_termios */
struct usb_serial *serial = port->serial;
unsigned int cflag = port->tty->termios->c_cflag;
+ struct ftdi_private *priv = (struct ftdi_private *)port->private;
__u16 urb_value; /* will hold the new flags */
char buf[1]; /* Perhaps I should dynamically alloc this? */
- dbg(__FUNCTION__ " port %d", port->number);
+
+ dbg(__FUNCTION__);
/* FIXME -For this cut I don't care if the line is really changing or
@@ -515,26 +676,12 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
FTDI_SIO_SET_DATA_REQUEST_TYPE,
urb_value , 0,
buf, 0, 100) < 0) {
- err("FAILED to set databits/stopbits/parity");
+ err(__FUNCTION__ " FAILED to set databits/stopbits/parity");
}
/* Now do the baudrate */
-
- switch(cflag & CBAUD){
- case B0: break; /* Handled below */
- case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break;
- case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break;
- case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break;
- case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break;
- case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break;
- case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break;
- case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break;
- case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break;
- case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break;
- case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break;
- default: dbg(__FUNCTION__ "FTDI_SIO does not support the baudrate requested");
- /* FIXME - how to return an error for this? */ break;
- }
+ urb_value = translate_baudrate_to_ftdi((cflag & CBAUD), priv->ftdi_type);
+
if ((cflag & CBAUD) == B0 ) {
/* Disable flow control */
if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
@@ -542,30 +689,31 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, 0,
buf, 0, WDR_TIMEOUT) < 0) {
- err("error from disable flowcontrol urb");
+ err(__FUNCTION__ " error from disable flowcontrol urb");
}
/* Drop RTS and DTR */
if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
- err("Error from DTR LOW urb");
+ err(__FUNCTION__ " Error from DTR LOW urb");
}
if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
- err("Error from RTS LOW urb");
+ err(__FUNCTION__ " Error from RTS LOW urb");
}
} else {
+ /* set the baudrate determined before */
if (usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
FTDI_SIO_SET_BAUDRATE_REQUEST,
FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
urb_value, 0,
buf, 0, 100) < 0) {
- err("urb failed to set baurdrate");
+ err(__FUNCTION__ " urb failed to set baurdrate");
}
}
/* Set flow control */
/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
if (cflag & CRTSCTS) {
- dbg(__FUNCTION__ "Setting to CRTSCTS flow control");
+ dbg(__FUNCTION__ " Setting to CRTSCTS flow control");
if (usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
@@ -576,9 +724,8 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
}
} else {
- /* CHECK Assuming XON/XOFF handled by stack - not by device */
- /* Disable flow control */
- dbg(__FUNCTION__ "Turning off hardware flow control");
+ /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+ dbg(__FUNCTION__ " Turning off hardware flow control");
if (usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
@@ -595,6 +742,7 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
struct usb_serial *serial = port->serial;
+ struct ftdi_private *priv = (struct ftdi_private *)port->private;
__u16 urb_value=0; /* Will hold the new flags */
char buf[1];
int ret, mask;
@@ -605,16 +753,27 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
switch (cmd) {
case TIOCMGET:
- dbg(__FUNCTION__ "TIOCMGET");
- /* Request the status from the device */
- if ((ret = usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- FTDI_SIO_GET_MODEM_STATUS_REQUEST,
- FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
- 0, 0,
- buf, 1, HZ * 5)) < 0 ) {
- dbg(__FUNCTION__ "Get not get modem status of device");
- return(ret);
+ dbg(__FUNCTION__ " TIOCMGET");
+ /* The MODEM_STATUS_REQUEST works for the sio but not the 232 */
+ if (priv->ftdi_type == sio){
+ /* TO DECIDE - use the 40ms status packets or not? */
+ /* PRO: No need to send urb */
+ /* CON: Could be 40ms out of date */
+
+ /* Request the status from the device */
+ if ((ret = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, 0,
+ buf, 1, WDR_TIMEOUT)) < 0 ) {
+ err(__FUNCTION__ " Could not get modem status of device - err: %d",
+ ret);
+ return(ret);
+ }
+ } else {
+ /* This gets updated every 40ms - so just copy it in */
+ buf[0] = priv->last_status_byte;
}
return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
@@ -625,32 +784,20 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
- dbg(__FUNCTION__ "TIOCMSET");
+ dbg(__FUNCTION__ " TIOCMSET");
if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
- urb_value = ((mask & TIOCM_DTR) ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW);
- if ((ret = usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- FTDI_SIO_SET_MODEM_CTRL_REQUEST,
- FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
- urb_value , 0,
- buf, 0, WDR_TIMEOUT)) < 0){
- err("Urb to set DTR failed");
- return(ret);
- }
- urb_value = ((mask & TIOCM_RTS) ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW);
- if ((ret = usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- FTDI_SIO_SET_MODEM_CTRL_REQUEST,
- FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
- urb_value , 0,
- buf, 0, WDR_TIMEOUT)) < 0){
- err("Urb to set RTS failed");
- return(ret);
+ urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
+ if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
+ err("Error from DTR set urb (TIOCMSET)");
}
+ urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
+ if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
+ err("Error from RTS set urb (TIOCMSET)");
+ }
break;
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
- dbg(__FUNCTION__ "TIOCMBIS");
+ dbg(__FUNCTION__ " TIOCMBIS");
if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
if (mask & TIOCM_DTR){
if ((ret = set_dtr(serial->dev,
@@ -671,7 +818,7 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
break;
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
- dbg(__FUNCTION__ "TIOCMBIC");
+ dbg(__FUNCTION__ " TIOCMBIC");
if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
if (mask & TIOCM_DTR){
if ((ret = set_dtr(serial->dev,
@@ -704,25 +851,28 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
/* This is not an error - turns out the higher layers will do
* some ioctls itself (see comment above)
*/
- dbg(__FUNCTION__ "arg not supported - it was 0x%04x",cmd);
+ dbg(__FUNCTION__ " arg not supported - it was 0x%04x",cmd);
return(-ENOIOCTLCMD);
break;
}
- dbg(__FUNCTION__ " returning 0");
return 0;
} /* ftdi_sio_ioctl */
static int __init ftdi_sio_init (void)
{
+ dbg(__FUNCTION__);
usb_serial_register (&ftdi_sio_device);
+ usb_serial_register (&ftdi_8U232AM_device);
return 0;
}
static void __exit ftdi_sio_exit (void)
{
+ dbg(__FUNCTION__);
usb_serial_deregister (&ftdi_sio_device);
+ usb_serial_deregister (&ftdi_8U232AM_device);
}
@@ -730,4 +880,4 @@ module_init(ftdi_sio_init);
module_exit(ftdi_sio_exit);
MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>");
-MODULE_DESCRIPTION("USB FTDI SIO driver");
+MODULE_DESCRIPTION("USB FTDI RS232 converters driver");
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index fe5f545db..626aeb677 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -20,9 +20,9 @@
*/
#define FTDI_VID 0x0403 /* Vendor Id */
-#define FTDI_SIO_PID 0x8372 /* Product Id */
+#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */
+#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
-/* Vendor Request Interface */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */
@@ -86,6 +86,12 @@
*/
typedef enum {
+ sio = 1,
+ F8U232AM = 2,
+} ftdi_type_t;
+
+
+typedef enum {
ftdi_sio_b300 = 0,
ftdi_sio_b600 = 1,
ftdi_sio_b1200 = 2,
@@ -98,6 +104,38 @@ typedef enum {
ftdi_sio_b115200 = 9
} FTDI_SIO_baudrate_t ;
+
+typedef enum {
+ ftdi_8U232AM_12MHz_b300 = 0x09c4,
+ ftdi_8U232AM_12MHz_b600 = 0x04E2,
+ ftdi_8U232AM_12MHz_b1200 = 0x0271,
+ ftdi_8U232AM_12MHz_b2400 = 0x4138,
+ ftdi_8U232AM_12MHz_b4800 = 0x809c,
+ ftdi_8U232AM_12MHz_b9600 = 0xc04e,
+ ftdi_8U232AM_12MHz_b19200 = 0x0027,
+ ftdi_8U232AM_12MHz_b38400 = 0x4013,
+ ftdi_8U232AM_12MHz_b57600 = 0x000d,
+ ftdi_8U232AM_12MHz_b115200 = 0x4006,
+ ftdi_8U232AM_12MHz_b230400 = 0x8003,
+} FTDI_8U232AM_12MHz_baudrate_t;
+/* Apparently all devices are 48MHz */
+typedef enum {
+ ftdi_8U232AM_48MHz_b300 = 0x2710,
+ ftdi_8U232AM_48MHz_b600 = 0x1388,
+ ftdi_8U232AM_48MHz_b1200 = 0x09c4,
+ ftdi_8U232AM_48MHz_b2400 = 0x04e2,
+ ftdi_8U232AM_48MHz_b4800 = 0x0271,
+ ftdi_8U232AM_48MHz_b9600 = 0x4138,
+ ftdi_8U232AM_48MHz_b19200 = 0x809c,
+ ftdi_8U232AM_48MHz_b38400 = 0xc04e,
+ ftdi_8U232AM_48MHz_b57600 = 0x0034,
+ ftdi_8U232AM_48MHz_b115200 = 0x001a,
+ ftdi_8U232AM_48MHz_b230400 = 0x000d,
+ ftdi_8U232AM_48MHz_b460800 = 0x4006,
+ ftdi_8U232AM_48MHz_b921600 = 0x8003,
+
+} FTDI_8U232AM_48MHz_baudrate_t;
+
#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 )
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 885108cd0..8d7c9c035 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -19,28 +19,36 @@
and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
Thanks Guys :)
+ Thanks to Paulus for miscellaneous tidy ups, some largish chunks
+ of much nicer and/or completely new code and (perhaps most uniquely)
+ having the patience to sit down and explain why and where he'd changed
+ stuff.
+
Tip 'o the hat to Linuxcare for supporting staff in their work on
open source projects.
- (11/01/2000) Adam J. Richter
+ Change History
+ (11/01/2000) Adam J. Richter
usb_device_id table support.
+
+ Tue Oct 10 23:15:33 EST 2000 Hugh
+ Merged Paul's changes with my USA-49W mods. Work in progress
+ still...
+
+ Wed Jul 19 14:00:42 EST 2000 gkh
+ Added module_init and module_exit functions to handle the fact that
+ this driver is a loadable module now.
- (10/05/2000) gkh
- Fixed bug with urb->dev not being set properly, now that the usb
- core needs it.
-
- Wed Jul 19 14:00:42 EST 2000 gkh
- Added module_init and module_exit functions to handle the fact that this
- driver is a loadable module now.
-
- Tue Jul 18 16:14:52 EST 2000 Hugh
- Basic character input/output for USA-19 now mostly works,
- fixed at 9600 baud for the moment.
+ Tue Jul 18 16:14:52 EST 2000 Hugh
+ Basic character input/output for USA-19 now mostly works,
+ fixed at 9600 baud for the moment.
+ Sat Jul 8 11:11:48 EST 2000 Hugh
+ First public release - nothing works except the firmware upload.
+ Tested on PPC and x86 architectures, seems to behave...
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
@@ -55,53 +63,130 @@
#include <linux/module.h>
#include <linux/spinlock.h>
-#ifdef CONFIG_USB_SERIAL_DEBUG
+#define DEBUG
+/* #ifdef CONFIG_USB_SERIAL_DEBUG */
#define DEBUG
-#else
- #undef DEBUG
-#endif
+/* #endif */
#include <linux/usb.h>
#include "usb-serial.h"
#include "keyspan.h"
+#define INSTAT_BUFLEN 32
+#define GLOCONT_BUFLEN 64
+
/* Per device and per port private data */
struct keyspan_serial_private {
- struct urb *in_urbs[8];
- struct urb *out_urbs[8];
- char out_buffer[64];
- char in_buffer[64];
+ /* number of active ports */
+ atomic_t active_count;
+
+ const keyspan_device_details *device_details;
+
+ urb_t *instat_urb;
+ char instat_buf[INSTAT_BUFLEN];
+
+ /* XXX this one probably will need a lock */
+ urb_t *glocont_urb;
+ char glocont_buf[GLOCONT_BUFLEN];
};
struct keyspan_port_private {
- /* Keep track of which output endpoint to use */
+ /* Keep track of which input & output endpoints to use */
+ int in_flip;
int out_flip;
- /* Settings for the port */
+ /* Keep duplicate of device details in each port
+ structure as well - simplifies some of the
+ callback functions etc. */
+ const keyspan_device_details *device_details;
+
+ /* Input endpoints and buffer for this port */
+ urb_t *in_urbs[2];
+ char in_buffer[2][64];
+ /* Output endpoints and buffer for this port */
+ urb_t *out_urbs[2];
+ char out_buffer[2][64];
+
+ /* Input ack endpoint */
+ urb_t *inack_urb;
+ char inack_buffer[1];
+
+ /* Output control endpoint */
+ urb_t *outcont_urb;
+ char outcont_buffer[64];
+
+ /* Settings for the port */
int baud;
int old_baud;
- enum {parity_none, parity_odd, parity_even} parity;
+ unsigned int cflag;
enum {flow_none, flow_cts, flow_xon} flow_control;
- int rts_state;
+ int rts_state; /* Handshaking pins (outputs) */
int dtr_state;
+ int cts_state; /* Handshaking pins (inputs) */
+ int dsr_state;
+ int dcd_state;
+ int ri_state;
+ unsigned long tx_start_time[2];
+ int resend_cont; /* need to resend control packet */
};
-
- /* FIXME this will break if multiple physical interfaces used */
-static wait_queue_head_t out_wait;
- /* Include Keyspan message headers (not both yet, need some tweaks
- to get clean build) */
-/*#include "keyspan_usa26msg.h"*/
+/* Include Keyspan message headers. All current Keyspan Adapters
+ make use of one of three message formats which are referred
+ to as USA-26, USA-28 and USA-49 by Keyspan and within this driver. */
+#include "keyspan_usa26msg.h"
#include "keyspan_usa28msg.h"
+#include "keyspan_usa49msg.h"
- /* If you don't get debugging output, uncomment the following
- two lines to enable cheat. */
-#undef dbg
-#define dbg printk
+/* If you don't get debugging output, uncomment the following
+ two lines to enable cheat. */
+#if 0
+ #undef dbg
+ #define dbg printk
+#endif
+
+static void keyspan_send_setup(struct usb_serial_port *port);
+
+/* Functions used by new usb-serial code. */
+int keyspan_init (void)
+{
+ usb_serial_register (&keyspan_usa18x_pre_device);
+ usb_serial_register (&keyspan_usa19_pre_device);
+ usb_serial_register (&keyspan_usa19w_pre_device);
+ usb_serial_register (&keyspan_usa28_pre_device);
+ usb_serial_register (&keyspan_usa28x_pre_device);
+ usb_serial_register (&keyspan_usa49w_pre_device);
+
+ usb_serial_register (&keyspan_usa18x_device);
+ usb_serial_register (&keyspan_usa19_device);
+ usb_serial_register (&keyspan_usa19w_device);
+ usb_serial_register (&keyspan_usa28_device);
+ usb_serial_register (&keyspan_usa28x_device);
+ usb_serial_register (&keyspan_usa49w_device);
+ return 0;
+}
+
+void keyspan_exit (void)
+{
+ usb_serial_deregister (&keyspan_usa18x_pre_device);
+ usb_serial_deregister (&keyspan_usa19_pre_device);
+ usb_serial_deregister (&keyspan_usa19w_pre_device);
+ usb_serial_deregister (&keyspan_usa28_pre_device);
+ usb_serial_deregister (&keyspan_usa28x_pre_device);
+ usb_serial_deregister (&keyspan_usa49w_pre_device);
+
+ usb_serial_deregister (&keyspan_usa18x_device);
+ usb_serial_deregister (&keyspan_usa19_device);
+ usb_serial_deregister (&keyspan_usa19w_device);
+ usb_serial_deregister (&keyspan_usa28_device);
+ usb_serial_deregister (&keyspan_usa28x_device);
+ usb_serial_deregister (&keyspan_usa49w_device);
+}
+
+module_init(keyspan_init);
+module_exit(keyspan_exit);
- /* Functions - mostly stubs for now */
static void keyspan_rx_throttle (struct usb_serial_port *port)
{
dbg("keyspan_rx_throttle port %d", port->number);
@@ -123,194 +208,597 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
static void keyspan_set_termios (struct usb_serial_port *port,
struct termios *old_termios)
{
- dbg("keyspan_set_termios");
+ int baud_rate;
+ struct keyspan_port_private *p_priv;
+ const keyspan_device_details *d_details;
+ unsigned int cflag;
+
+ /* dbg(__FUNCTION__ "."); */
+
+ p_priv = (struct keyspan_port_private *)(port->private);
+ d_details = p_priv->device_details;
+ cflag = port->tty->termios->c_cflag;
+
+ /* Baud rate calculation takes baud rate as an integer
+ so other rates can be generated if desired. */
+ baud_rate = tty_get_baud_rate(port->tty);
+ /* If no match or invalid, don't change */
+ if (baud_rate >= 0
+ && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
+ NULL, NULL, NULL) == KEYSPAN_BAUD_RATE_OK) {
+ /* FIXME - more to do here to ensure rate changes cleanly */
+ p_priv->baud = baud_rate;
+ }
+
+ /* set CTS/RTS handshake etc. */
+ p_priv->cflag = cflag;
+ p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
+
+ keyspan_send_setup(port);
}
static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{
- unsigned int value;
+ unsigned int value, set;
+ struct keyspan_port_private *p_priv;
- dbg("keyspan_ioctl_info");
+ p_priv = (struct keyspan_port_private *)(port->private);
switch (cmd) {
case TIOCMGET:
- value = TIOCM_DTR | TIOCM_RNG;
- if (copy_to_user((unsigned int *)arg, &value, sizeof(int))) {
+ value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
+ ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
+ ((p_priv->cts_state) ? TIOCM_CTS : 0) |
+ ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
+ ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
+ ((p_priv->ri_state) ? TIOCM_RNG : 0);
+
+ if (put_user(value, (unsigned int *) arg))
return -EFAULT;
- }
- else {
- return 0;
- }
-
- default:
- return -ENOIOCTLCMD;
+ return 0;
+
+ case TIOCMSET:
+ if (get_user(value, (unsigned int *) arg))
+ return -EFAULT;
+ p_priv->rts_state = ((value & TIOCM_RTS) ? 1 : 0);
+ p_priv->dtr_state = ((value & TIOCM_DTR) ? 1 : 0);
+ keyspan_send_setup(port);
+ return 0;
+
+ case TIOCMBIS:
+ case TIOCMBIC:
+ if (get_user(value, (unsigned int *) arg))
+ return -EFAULT;
+ set = (cmd == TIOCMBIS);
+ if (value & TIOCM_RTS)
+ p_priv->rts_state = set;
+ if (value & TIOCM_DTR)
+ p_priv->dtr_state = set;
+ keyspan_send_setup(port);
+ return 0;
}
return -ENOIOCTLCMD;
}
+ /* Write function is generic for the three protocols used
+ with only a minor change for usa49 required */
static int keyspan_write(struct usb_serial_port *port, int from_user,
- const unsigned char *buf, int count)
+ const unsigned char *buf, int count)
{
- struct usb_serial *serial = port->serial;
- struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
- int current_urb;
- int i;
+ const keyspan_device_details *d_details;
+ int flip;
+ int left, todo;
+ urb_t *this_urb;
+ int err;
- s_priv = (struct keyspan_serial_private *)(serial->private);
p_priv = (struct keyspan_port_private *)(port->private);
-
- if (p_priv->out_flip == 0) {
- current_urb = 0;
- p_priv->out_flip = 1;
- }
- else {
- current_urb = 1;
- p_priv->out_flip = 0;
- }
+ d_details = p_priv->device_details;
- dbg("keyspan_write called for port %d (%d) chars {", port->number, count);
- for (i = 0; i < count ; i++) {
- dbg("%02x ", buf[i]);
- }
- dbg("}\n");
+#if 0
+ dbg(__FUNCTION__ " for port %d (%d chars [%x]), flip=%d",
+ port->number, count, buf[0], p_priv->out_flip);
+#endif
- if (count == 0) {
- dbg("write request of 0 bytes");
- return (0);
- }
+ for (left = count; left > 0; left -= todo) {
+ todo = left;
+ if (todo > 63)
+ todo = 63;
- /* only send data if we have a bulk out endpoint */
- if (s_priv->out_urbs[current_urb]) {
- while (s_priv->out_urbs[current_urb]->status == -EINPROGRESS) {
- dbg (__FUNCTION__ " INPROGRES\n");
- interruptible_sleep_on(&out_wait);
- if (signal_pending(current)) {
- dbg (__FUNCTION__ " signal\n");
- return (-ERESTARTSYS);
- }
+ flip = p_priv->out_flip;
+
+ /* Check we have a valid urb/endpoint before we use it... */
+ if ((this_urb = p_priv->out_urbs[flip]) == 0) {
+ /* no bulk out, so return 0 bytes written */
+ dbg(__FUNCTION__ " no output urb :(");
+ return count;
+ }
+
+ if (this_urb->status == -EINPROGRESS) {
+ if (this_urb->transfer_flags & USB_ASYNC_UNLINK)
+ break;
+ if (jiffies - p_priv->tx_start_time[flip] < 10 * HZ)
+ break;
+ this_urb->transfer_flags |= USB_ASYNC_UNLINK;
+ usb_unlink_urb(this_urb);
+ break;
}
- /*if (s_priv->out_urbs[current_urb]->status == -EINPROGRESS) {
- dbg ("already writing");
- return (-EAGAIN);
- }*/
- /* First byte in buffer is "last flag" - unused so
- for now so set to zero */
- memset(s_priv->out_urbs[current_urb]->transfer_buffer, 0, 1);
+
+ /* First byte in buffer is "last flag" - unused so
+ for now so set to zero */
+ ((char *)this_urb->transfer_buffer)[0] = 0;
if (from_user) {
- copy_from_user(s_priv->out_urbs[current_urb]->transfer_buffer + 1, buf, count);
+ copy_from_user(this_urb->transfer_buffer + 1, buf, todo);
+ } else {
+ memcpy (this_urb->transfer_buffer + 1, buf, todo);
}
- else {
- memcpy (s_priv->out_urbs[current_urb]->transfer_buffer + 1, buf, count);
- }
+ buf += todo;
/* send the data out the bulk port */
- s_priv->out_urbs[current_urb]->transfer_buffer_length = count + 1;
- s_priv->out_urbs[current_urb]->dev = serial->dev;
+ this_urb->transfer_buffer_length = todo + 1;
- if (usb_submit_urb(s_priv->out_urbs[current_urb])) {
- dbg("usb_submit_urb(write bulk) failed");
+ this_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
+ this_urb->dev = port->serial->dev;
+ if ((err = usb_submit_urb(this_urb)) != 0) {
+ dbg("usb_submit_urb(write bulk) failed (%d)", err);
}
+ p_priv->tx_start_time[flip] = jiffies;
- return (count);
+ /* Flip for next time if usa26 or usa28 interface
+ (not used on usa49) */
+ p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
}
-
- /* no bulk out, so return 0 bytes written */
- return (0);
-}
+ return count - left;
+}
-static void keyspan_write_bulk_callback (struct urb *urb)
+static void usa26_indat_callback(struct urb *urb)
{
- int endpoint;
-
+ int i, err;
+ int endpoint;
+ struct usb_serial_port *port;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+
+ /* dbg (__FUNCTION__); */
+
endpoint = usb_pipeendpoint(urb->pipe);
- dbg("keyspan_write_bulk_callback for endpoint %d\n", endpoint);
+ if (urb->status) {
+ dbg(__FUNCTION__ "nonzero status: %x on endpoint %d.",
+ urb->status, endpoint);
+ return;
+ }
+
+ port = (struct usb_serial_port *) urb->context;
+ tty = port->tty;
+ if (urb->actual_length) {
+ if (data[0] == 0) {
+ /* no error on any byte */
+ for (i = 1; i < urb->actual_length ; ++i) {
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ } else {
+ /* some bytes had errors, every byte has status */
+ for (i = 0; i + 1 < urb->actual_length; i += 2) {
+ int stat = data[i], flag = 0;
+ if (stat & RXERROR_OVERRUN)
+ flag |= TTY_OVERRUN;
+ if (stat & RXERROR_FRAMING)
+ flag |= TTY_FRAME;
+ if (stat & RXERROR_PARITY)
+ flag |= TTY_PARITY;
+ /* XXX should handle break (0x10) */
+ tty_insert_flip_char(tty, data[i+1], flag);
+ }
+ }
+ tty_flip_buffer_push(tty);
+ }
+
+ /* Resubmit urb so we continue receiving */
+ urb->dev = port->serial->dev;
+ if ((err = usb_submit_urb(urb)) != 0) {
+ dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err);
+ }
+ return;
+}
+
+ /* Outdat handling is common for usa26, usa28 and usa49 messages */
+static void usa2x_outdat_callback(struct urb *urb)
+{
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+
+ port = (struct usb_serial_port *) urb->context;
+ p_priv = (struct keyspan_port_private *)(port->private);
+ /* dbg (__FUNCTION__ " urb %d", urb == p_priv->out_urbs[1]); */
- /* Only do wakeup if this callback is from one of the data
- endpoints. */
- if (endpoint == 2 || endpoint == 3) {
- wake_up_interruptible(&out_wait);
+ if (port->active) {
+ queue_task(&port->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
}
+}
+static void usa26_inack_callback(struct urb *urb)
+{
+ dbg (__FUNCTION__);
+
}
+static void usa26_outcont_callback(struct urb *urb)
+{
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+
+ port = (struct usb_serial_port *) urb->context;
+ p_priv = (struct keyspan_port_private *)(port->private);
+
+ if (p_priv->resend_cont) {
+ /* dbg (__FUNCTION__ " sending setup"); */
+ keyspan_usa26_send_setup(port->serial, port);
+ }
+}
-static void keyspan_read_bulk_callback (struct urb *urb)
+static void usa26_instat_callback(struct urb *urb)
{
- struct usb_serial *serial = (struct usb_serial *)urb->context;
- struct usb_serial_port *port;
- int i;
- int endpoint;
- struct tty_struct *tty;
- unsigned char *data = urb->transfer_buffer;
+ unsigned char *data = urb->transfer_buffer;
+ keyspan_usa26_portStatusMessage *msg;
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+ int old_dcd_state, err;
+
+ serial = (struct usb_serial *) urb->context;
- if (serial_paranoia_check (serial, __FUNCTION__))
+ if (urb->status) {
+ dbg(__FUNCTION__ " nonzero status: %x", urb->status);
return;
- port = &serial->port[0];
- if (port_paranoia_check (port, __FUNCTION__))
+ }
+ if (urb->actual_length != 9) {
+ dbg(__FUNCTION__ " %d byte report??", urb->actual_length);
+ goto exit;
+ }
+
+ msg = (keyspan_usa26_portStatusMessage *)data;
+
+#if 0
+ dbg(__FUNCTION__ " port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
+ msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
+ msg->_txXoff, msg->rxEnabled, msg->controlResponse);
+#endif
+
+ /* Now do something useful with the data */
+
+
+ /* Check port number from message and retrieve private data */
+ if (msg->port >= serial->num_ports) {
+ dbg ("Unexpected port number %d", msg->port);
+ goto exit;
+ }
+ port = &serial->port[msg->port];
+ p_priv = (struct keyspan_port_private *)(port->private);
+
+ /* Update handshaking pin state information */
+ old_dcd_state = p_priv->dcd_state;
+ p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
+ p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
+ p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
+ p_priv->ri_state = ((msg->ri) ? 1 : 0);
+
+ if (port->tty && !C_CLOCAL(port->tty)
+ && old_dcd_state != p_priv->dcd_state) {
+ if (old_dcd_state)
+ tty_hangup(port->tty);
+ /* else */
+ /* wake_up_interruptible(&p_priv->open_wait); */
+ }
+
+exit:
+ /* Resubmit urb so we continue receiving */
+ urb->dev = serial->dev;
+ if ((err = usb_submit_urb(urb)) != 0) {
+ dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err);
+ }
+}
+
+static void usa26_glocont_callback(struct urb *urb)
+{
+ dbg (__FUNCTION__);
+
+}
+
+
+static void usa28_indat_callback(struct urb *urb)
+{
+ int i, err;
+ struct usb_serial_port *port;
+ struct tty_struct *tty;
+ unsigned char *data;
+ struct keyspan_port_private *p_priv;
+
+ /* dbg (__FUNCTION__); */
+
+ port = (struct usb_serial_port *) urb->context;
+ p_priv = (struct keyspan_port_private *)(port->private);
+ data = urb->transfer_buffer;
+
+ if (urb != p_priv->in_urbs[p_priv->in_flip])
return;
+ do {
+ if (urb->status) {
+ dbg(__FUNCTION__ "nonzero status: %x on endpoint
+%d.",
+ urb->status, usb_pipeendpoint(urb->pipe));
+ return;
+ }
+
+ port = (struct usb_serial_port *) urb->context;
+ p_priv = (struct keyspan_port_private *)(port->private);
+ data = urb->transfer_buffer;
+
+ tty = port->tty;
+ if (urb->actual_length) {
+ for (i = 0; i < urb->actual_length ; ++i) {
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ tty_flip_buffer_push(tty);
+ }
+
+ /* Resubmit urb so we continue receiving */
+ urb->dev = port->serial->dev;
+ if ((err = usb_submit_urb(urb)) != 0) {
+ dbg(__FUNCTION__ "resubmit read urb failed. (%d)",
+err);
+ }
+ p_priv->in_flip ^= 1;
+
+ urb = p_priv->in_urbs[p_priv->in_flip];
+ } while (urb->status != -EINPROGRESS);
+}
+
+static void usa28_inack_callback(struct urb *urb)
+{
+ dbg (__FUNCTION__);
+}
+
+static void usa28_outcont_callback(struct urb *urb)
+{
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+
+ port = (struct usb_serial_port *) urb->context;
+ p_priv = (struct keyspan_port_private *)(port->private);
+
+ if (p_priv->resend_cont) {
+ dbg (__FUNCTION__ " sending setup");
+ keyspan_usa28_send_setup(port->serial, port);
+ }
+}
+
+static void usa28_instat_callback(struct urb *urb)
+{
+ int err;
+ unsigned char *data = urb->transfer_buffer;
+ keyspan_usa28_portStatusMessage *msg;
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+ int old_dcd_state;
+
+ serial = (struct usb_serial *) urb->context;
+
if (urb->status) {
- dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+ dbg(__FUNCTION__ " nonzero status: %x", urb->status);
return;
}
- usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+ if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
+ dbg(__FUNCTION__ " bad length %d", urb->actual_length);
+ goto exit;
+ }
- endpoint = usb_pipeendpoint(urb->pipe);
+ /*dbg(__FUNCTION__ " %x %x %x %x %x %x %x %x %x %x %x %x",
+ data[0], data[1], data[2], data[3], data[4], data[5],
+ data[6], data[7], data[8], data[9], data[10], data[11]);*/
+
+ /* Now do something useful with the data */
+ msg = (keyspan_usa28_portStatusMessage *)data;
+
+
+ /* Check port number from message and retrieve private data */
+ if (msg->port >= serial->num_ports) {
+ dbg ("Unexpected port number %d", msg->port);
+ goto exit;
+ }
+ port = &serial->port[msg->port];
+ p_priv = (struct keyspan_port_private *)(port->private);
+
+ /* Update handshaking pin state information */
+ old_dcd_state = p_priv->dcd_state;
+ p_priv->cts_state = ((msg->cts) ? 1 : 0);
+ p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
+ p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
+ p_priv->ri_state = ((msg->ri) ? 1 : 0);
+
+ if (port->tty && !C_CLOCAL(port->tty)
+ && old_dcd_state != p_priv->dcd_state) {
+ if (old_dcd_state)
+ tty_hangup(port->tty);
+ /* else */
+ /* wake_up_interruptible(&p_priv->open_wait); */
+ }
+exit:
+ /* Resubmit urb so we continue receiving */
+ urb->dev = serial->dev;
+ if ((err = usb_submit_urb(urb)) != 0) {
+ dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err);
+ }
+}
+
+static void usa28_glocont_callback(struct urb *urb)
+{
+ dbg (__FUNCTION__);
+}
+
+
+static void usa49_glocont_callback(struct urb *urb)
+{
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+ int i;
+
+ /* dbg (__FUNCTION__); */
+
+ serial = (struct usb_serial *) urb->context;
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = &serial->port[i];
+ p_priv = (struct keyspan_port_private *)(port->private);
+
+ if (p_priv->resend_cont) {
+ /* dbg (__FUNCTION__ " sending setup"); */
+ keyspan_usa49_send_setup(serial, port);
+ break;
+ }
+ }
+}
+
+ /* This is actually called glostat in the Keyspan
+ doco */
+static void usa49_instat_callback(struct urb *urb)
+{
+ int err;
+ unsigned char *data = urb->transfer_buffer;
+ keyspan_usa49_portStatusMessage *msg;
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+ int old_dcd_state;
+
+ /* dbg (__FUNCTION__); */
+
+ serial = (struct usb_serial *) urb->context;
if (urb->status) {
- dbg(__FUNCTION__ "nonzero status: %x on endpoint %d.\n",
- urb->status, endpoint);
+ dbg(__FUNCTION__ " nonzero status: %x", urb->status);
return;
}
- switch (endpoint) {
+ if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
+ dbg(__FUNCTION__ " bad length %d", urb->actual_length);
+ goto exit;
+ }
- /* If this is one of the data endpoints, stuff it's
- contents into the tty flip_buffer. */
- case 1:
- case 2:
- tty = port->tty;
- if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
- tty_flip_buffer_push(tty);
- }
- break;
+ /*dbg(__FUNCTION__ " %x %x %x %x %x %x %x %x %x %x %x",
+ data[0], data[1], data[2], data[3], data[4], data[5],
+ data[6], data[7], data[8], data[9], data[10]);*/
+
+ /* Now do something useful with the data */
+ msg = (keyspan_usa49_portStatusMessage *)data;
- /* INACK endpoint */
- case 3: dbg(__FUNCTION__ " callback for INACK endpoint\n");
- break;
+ /* Check port number from message and retrieve private data */
+ if (msg->portNumber >= serial->num_ports) {
+ dbg ("Unexpected port number %d", msg->portNumber);
+ goto exit;
+ }
+ port = &serial->port[msg->portNumber];
+ p_priv = (struct keyspan_port_private *)(port->private);
+
+ /* Update handshaking pin state information */
+ old_dcd_state = p_priv->dcd_state;
+ p_priv->cts_state = ((msg->cts) ? 1 : 0);
+ p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
+ p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
+ p_priv->ri_state = ((msg->ri) ? 1 : 0);
+
+ if (port->tty && !C_CLOCAL(port->tty)
+ && old_dcd_state != p_priv->dcd_state) {
+ if (old_dcd_state)
+ tty_hangup(port->tty);
+ /* else */
+ /* wake_up_interruptible(&p_priv->open_wait); */
+ }
- /* INSTAT endpoint */
- case 4: dbg(__FUNCTION__ " callback for INSTAT endpoint\n");
- break;
-
- default:
- dbg(__FUNCTION__ " callback for unknown endpoint!\n");
- break;
+exit:
+ /* Resubmit urb so we continue receiving */
+ urb->dev = serial->dev;
+
+ if ((err = usb_submit_urb(urb)) != 0) {
+ dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err);
+ }
+}
+
+static void usa49_inack_callback(struct urb *urb)
+{
+ dbg (__FUNCTION__);
+}
+
+static void usa49_indat_callback(struct urb *urb)
+{
+ int i, err;
+ int endpoint;
+ struct usb_serial_port *port;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+
+ /* dbg (__FUNCTION__); */
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+
+ if (urb->status) {
+ dbg(__FUNCTION__ "nonzero status: %x on endpoint %d.",
+ urb->status, endpoint);
+ return;
+ }
+
+ port = (struct usb_serial_port *) urb->context;
+ tty = port->tty;
+ if (urb->actual_length) {
+ if (data[0] == 0) {
+ /* no error on any byte */
+ for (i = 1; i < urb->actual_length ; ++i) {
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ } else {
+ /* some bytes had errors, every byte has status */
+ for (i = 0; i + 1 < urb->actual_length; i += 2) {
+ int stat = data[i], flag = 0;
+ if (stat & RXERROR_OVERRUN)
+ flag |= TTY_OVERRUN;
+ if (stat & RXERROR_FRAMING)
+ flag |= TTY_FRAME;
+ if (stat & RXERROR_PARITY)
+ flag |= TTY_PARITY;
+ /* XXX should handle break (0x10) */
+ tty_insert_flip_char(tty, data[i+1], flag);
+ }
+ }
+ tty_flip_buffer_push(tty);
}
- /* Resubmit urb so we continue receiving */
- urb->dev = serial->dev;
- if (usb_submit_urb(urb)) {
- dbg(__FUNCTION__ "resubmit read urb failed.\n");
+ /* Resubmit urb so we continue receiving */
+ urb->dev = port->serial->dev;
+ if ((err = usb_submit_urb(urb)) != 0) {
+ dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err);
}
- return;
-
}
+/* not used, usa-49 doesn't have per-port control endpoints */
+static void usa49_outcont_callback(struct urb *urb)
+{
+ dbg (__FUNCTION__);
+}
+
+
+
static int keyspan_write_room (struct usb_serial_port *port)
{
-// dbg("keyspan_write_room called\n");
+// dbg("keyspan_write_room called");
return (32);
}
@@ -327,63 +815,103 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
struct keyspan_port_private *p_priv;
struct keyspan_serial_private *s_priv;
struct usb_serial *serial = port->serial;
- int i;
+ const keyspan_device_details *d_details;
+ int i, already_active, err;
+ unsigned long flags;
+ urb_t *urb;
s_priv = (struct keyspan_serial_private *)(serial->private);
p_priv = (struct keyspan_port_private *)(port->private);
+ d_details = s_priv->device_details;
- dbg("keyspan_open called.\n");
-
- if (port->active) {
- dbg(__FUNCTION__ "port->active already true!\n");
- return (-EINVAL);
- }
+ /* dbg("keyspan_open called."); */
+ MOD_INC_USE_COUNT;
- p_priv = (struct keyspan_port_private *)(port->private);
-
- p_priv->out_flip = 0;
+ spin_lock_irqsave (&port->port_lock, flags);
+ ++port->open_count;
+ already_active = port->active;
port->active = 1;
+ spin_unlock_irqrestore (&port->port_lock, flags);
- /* Start reading from port */
- for (i = 0; i < 4; i++) {
- if (s_priv->in_urbs[i]) {
- s_priv->in_urbs[i]->dev = serial->dev;
- if (usb_submit_urb(s_priv->in_urbs[i])) {
- dbg(__FUNCTION__ " submit in urb %d failed", i);
- }
- }
+ if (already_active)
+ return 0;
+
+ p_priv = (struct keyspan_port_private *)(port->private);
+ /* Set some sane defaults */
+ p_priv->baud = 9600;
+ p_priv->cflag = CREAD | CLOCAL;
+ p_priv->flow_control = flow_none;
+ p_priv->rts_state = 1;
+ p_priv->dtr_state = 1;
+
+ /* Start reading from endpoints */
+ for (i = 0; i < 2; i++) {
+ if ((urb = p_priv->in_urbs[i]) == NULL)
+ continue;
+ urb->dev = serial->dev;
+ if ((err = usb_submit_urb(urb)) != 0) {
+ dbg(__FUNCTION__ " submit urb %d failed (%d)", i, err);
+ }
}
-
- keyspan_usa19_send_setup(serial, port);
+/* Now done in startup routine
+ if (atomic_inc_return(&s_priv->active_count) == 1) {
+ s_priv->instat_urb->dev = serial->dev;
+ if ((err = usb_submit_urb(s_priv->instat_urb)) != 0) {
+ dbg(__FUNCTION__ " submit instat urb failed %d", err);
+ }
+ }
+*/
+
+ keyspan_send_setup(port);
return (0);
}
+static inline void stop_urb(urb_t *urb)
+{
+ if (urb && urb->status == -EINPROGRESS) {
+ urb->transfer_flags &= ~USB_ASYNC_UNLINK;
+ usb_unlink_urb(urb);
+ }
+}
static void keyspan_close(struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial; /* FIXME should so sanity check */
struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+ unsigned long flags;
+ /* dbg("keyspan_close called"); */
s_priv = (struct keyspan_serial_private *)(serial->private);
-
- /* Stop reading/writing urbs */
- for (i = 0; i < 4; i++) {
- if (s_priv->in_urbs[i]) {
- usb_unlink_urb(s_priv->in_urbs[i]);
- }
+ p_priv = (struct keyspan_port_private *)(port->private);
- }
- for (i = 0; i < 3; i++) {
- if (s_priv->out_urbs[i]) {
- usb_unlink_urb(s_priv->out_urbs[i]);
- }
+ spin_lock_irqsave (&port->port_lock, flags);
+ if (--port->open_count <= 0) {
+ if (port->active) {
+ /* Stop reading/writing urbs */
+ stop_urb(p_priv->inack_urb);
+ stop_urb(p_priv->outcont_urb);
+ for (i = 0; i < 2; i++) {
+ stop_urb(p_priv->in_urbs[i]);
+ stop_urb(p_priv->out_urbs[i]);
+ }
+ /* Now done in shutdown
+ if (atomic_dec_return(&s_priv->active_count) <= 0) {
+ stop_urb(s_priv->instat_urb);
+ stop_urb(s_priv->glocont_urb);
+ } */
+ }
+ port->active = 0;
+ port->open_count = 0;
+ port->tty = 0;
}
- port->active = 0;
- dbg("keyspan_close called\n");
+ spin_unlock_irqrestore (&port->port_lock, flags);
+
+ MOD_DEC_USE_COUNT;
}
@@ -394,47 +922,59 @@ static int keyspan_fake_startup (struct usb_serial *serial)
const struct ezusb_hex_record *record;
char *fw_name;
- dbg("Keyspan startup version %04x product %04x\n", serial->dev->descriptor.bcdDevice,
- serial->dev->descriptor.idProduct);
+ dbg("Keyspan startup version %04x product %04x",
+ serial->dev->descriptor.bcdDevice,
+ serial->dev->descriptor.idProduct);
if ((serial->dev->descriptor.bcdDevice & 0x8000) != 0x8000) {
- dbg("Firmware already loaded. Quitting.\n");
+ dbg("Firmware already loaded. Quitting.");
return(1);
}
/* Select firmware image on the basis of idProduct */
switch (serial->dev->descriptor.idProduct) {
- case 0x0101: record = &keyspan_usa28_firmware[0];
- fw_name = "USA28";
- break;
-
- case 0x0102: record = &keyspan_usa28x_firmware[0];
- fw_name = "USA28X";
- break;
-
- case 0x0103: record = &keyspan_usa19_firmware[0];
- fw_name = "USA19";
- break;
+ case 0x0101:
+ record = &keyspan_usa28_firmware[0];
+ fw_name = "USA28";
+ break;
+
+ case 0x0102:
+ record = &keyspan_usa28x_firmware[0];
+ fw_name = "USA28X";
+ break;
+
+ case 0x0103:
+ record = &keyspan_usa19_firmware[0];
+ fw_name = "USA19";
+ break;
- case 0x0105: record = &keyspan_usa18x_firmware[0];
- fw_name = "USA18X";
- break;
+ case 0x0105:
+ record = &keyspan_usa18x_firmware[0];
+ fw_name = "USA18X";
+ break;
- case 0x0106: record = &keyspan_usa19w_firmware[0];
- fw_name = "USA19W";
- break;
+ case 0x0106:
+ record = &keyspan_usa19w_firmware[0];
+ fw_name = "USA19W";
+ break;
- default: record = NULL;
- fw_name = "Unknown";
- break;
+ case 0x0109:
+ record = &keyspan_usa49w_firmware[0];
+ fw_name = "USA49W";
+ break;
+
+ default:
+ record = NULL;
+ fw_name = "Unknown";
+ break;
}
if (record == NULL) {
- err("Required keyspan firmware image (%s) unavailable.\n", fw_name);
+ err("Required keyspan firmware image (%s) unavailable.", fw_name);
return(1);
}
- dbg("Uploading Keyspan %s firmware.\n", fw_name);
+ dbg("Uploading Keyspan %s firmware.", fw_name);
/* download the firmware image */
response = ezusb_set_reset(serial, 1);
@@ -456,72 +996,165 @@ static int keyspan_fake_startup (struct usb_serial *serial)
moment and the new device will bind to the real driver */
response = ezusb_set_reset(serial, 0);
- /* we don't want this device to have a driver assigned to it. */
+ /* we don't want this device to have a driver assigned to it. */
return (1);
}
- /* USA-19 uses three output endpoints and four input
- endpoints. First two output endpoints are for
- data (used in an alternating fashion), the third is
- output control. First two input endpoints are for
- data (again alternating), the third is the ACK
- endpoint, the fourth is input status. */
-static void keyspan_usa19_setup_urbs(struct usb_serial *serial)
+/* Helper functions used by keyspan_setup_urbs */
+static urb_t *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
+ int dir, void *ctx, char *buf, int len,
+ void (*callback)(urb_t *))
{
- struct keyspan_serial_private *s_priv;
- int i;
+ urb_t *urb;
- s_priv = (struct keyspan_serial_private *)(serial->private);
+ if (endpoint == -1)
+ return NULL; /* endpoint not needed */
- /* Output urbs first */
- dbg(__FUNCTION__ "Allocating output urbs.\n");
- for (i = 0; i < 3; i++) {
+ /* dbg (__FUNCTION__ " alloc for endpoint %d.", endpoint); */
+ urb = usb_alloc_urb(0); /* No ISO */
+ if (urb == NULL) {
+ dbg (__FUNCTION__ " alloc for endpoint %d failed.", endpoint);
+ return NULL;
+ }
- s_priv->out_urbs[i] = usb_alloc_urb (0); /* No ISO */
- if (!s_priv->out_urbs[i]) {
- dbg (__FUNCTION__ "Alloc for %d out urb failed.\n", i);
- return;
- }
+ /* Fill URB using supplied data. */
+ FILL_BULK_URB(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, endpoint) | dir,
+ buf, len, callback, ctx);
+
+ return urb;
+}
- FILL_BULK_URB(s_priv->out_urbs[i], serial->dev,
- usb_sndbulkpipe(serial->dev, i + 1),
- &s_priv->out_buffer[i], sizeof(s_priv->out_buffer[i]),
- keyspan_write_bulk_callback,
- serial);
+struct callbacks {
+ void (*instat_callback)(urb_t *);
+ void (*glocont_callback)(urb_t *);
+ void (*indat_callback)(urb_t *);
+ void (*outdat_callback)(urb_t *);
+ void (*inack_callback)(urb_t *);
+ void (*outcont_callback)(urb_t *);
+} keyspan_callbacks[] = {
+ {
+ /* msg_usa26 callbacks */
+ instat_callback: usa26_instat_callback,
+ glocont_callback: usa26_glocont_callback,
+ indat_callback: usa26_indat_callback,
+ outdat_callback: usa2x_outdat_callback,
+ inack_callback: usa26_inack_callback,
+ outcont_callback: usa26_outcont_callback,
+ }, {
+ /* msg_usa28 callbacks */
+ instat_callback: usa28_instat_callback,
+ glocont_callback: usa28_glocont_callback,
+ indat_callback: usa28_indat_callback,
+ outdat_callback: usa2x_outdat_callback,
+ inack_callback: usa28_inack_callback,
+ outcont_callback: usa28_outcont_callback,
+ }, {
+ /* msg_usa49 callbacks */
+ instat_callback: usa49_instat_callback,
+ glocont_callback: usa49_glocont_callback,
+ indat_callback: usa49_indat_callback,
+ outdat_callback: usa2x_outdat_callback,
+ inack_callback: usa49_inack_callback,
+ outcont_callback: usa49_outcont_callback,
}
+};
+
+ /* Generic setup urbs function that uses
+ data in device_details */
+static void keyspan_setup_urbs(struct usb_serial *serial)
+{
+ int i, j;
+ struct keyspan_serial_private *s_priv;
+ const keyspan_device_details *d_details;
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+ struct callbacks *cback;
+ int endp;
- /* Now input urbs */
- dbg(__FUNCTION__ "Allocating input urbs.\n");
- for (i = 0; i < 4; i++) {
+ /* dbg (__FUNCTION__); */
- s_priv->in_urbs[i] = usb_alloc_urb (0); /* No ISO */
- if (!s_priv->in_urbs[i]) {
- dbg (__FUNCTION__ "Alloc for %d in urb failed.\n", i);
- return;
+ s_priv = (struct keyspan_serial_private *)(serial->private);
+ d_details = s_priv->device_details;
+
+ /* Setup values for the various callback routines */
+ cback = &keyspan_callbacks[d_details->msg_format];
+
+ /* Allocate and set up urbs for each one that is in use,
+ starting with instat endpoints */
+ s_priv->instat_urb = keyspan_setup_urb
+ (serial, d_details->instat_endpoint, USB_DIR_IN,
+ serial, s_priv->instat_buf, INSTAT_BUFLEN,
+ cback->instat_callback);
+
+ s_priv->glocont_urb = keyspan_setup_urb
+ (serial, d_details->glocont_endpoint, USB_DIR_OUT,
+ serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
+ cback->glocont_callback);
+
+ /* Setup endpoints for each port specific thing */
+ for (i = 0; i < d_details->num_ports; i ++) {
+ port = &serial->port[i];
+ p_priv = (struct keyspan_port_private *)(port->private);
+
+ /* Do indat endpoints first, once for each flip */
+ endp = d_details->indat_endpoints[i];
+ for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
+ p_priv->in_urbs[j] = keyspan_setup_urb
+ (serial, endp, USB_DIR_IN, port,
+ p_priv->in_buffer[j], 64,
+ cback->indat_callback);
+ }
+ for (; j < 2; ++j)
+ p_priv->in_urbs[j] = NULL;
+
+ /* outdat endpoints also have flip */
+ endp = d_details->outdat_endpoints[i];
+ for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
+ p_priv->out_urbs[j] = keyspan_setup_urb
+ (serial, endp, USB_DIR_OUT, port,
+ p_priv->out_buffer[j], 64,
+ cback->outdat_callback);
}
+ for (; j < 2; ++j)
+ p_priv->out_urbs[j] = NULL;
+
+ /* inack endpoint */
+ p_priv->inack_urb = keyspan_setup_urb
+ (serial, d_details->inack_endpoints[i], USB_DIR_IN,
+ port, p_priv->inack_buffer, 1, cback->inack_callback);
+
+ /* outcont endpoint */
+ p_priv->outcont_urb = keyspan_setup_urb
+ (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
+ port, p_priv->outcont_buffer, 64,
+ cback->outcont_callback);
+ }
- FILL_BULK_URB(s_priv->in_urbs[i], serial->dev,
- usb_rcvbulkpipe(serial->dev, i + 0x81),
- &s_priv->in_buffer[i], sizeof(s_priv->in_buffer[i]),
- keyspan_read_bulk_callback,
- serial);
- }
-
}
-static int keyspan_usa19_calc_baud(u32 baud_rate, u8 *rate_hi, u8 *rate_low)
+/* usa19 function doesn't require prescaler */
+static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk,
+ u8 *rate_hi, u8 *rate_low, u8 *prescaler)
{
- u32 b16, /* baud rate times 16 (actual rate used internally) */
+ u32 b16, /* baud rate times 16 (actual rate used internally) */
div, /* divisor */
cnt; /* inverse of divisor (programmed into 8051) */
+
/* prevent divide by zero... */
if( (b16 = (baud_rate * 16L)) == 0) {
return (KEYSPAN_INVALID_BAUD_RATE);
}
+ /* Any "standard" rate over 57k6 is marginal on the USA-19
+ as we run out of divisor resolution. */
+ if (baud_rate > 57600) {
+ return (KEYSPAN_INVALID_BAUD_RATE);
+ }
+
/* calculate the divisor and the counter (its inverse) */
- if( (div = (USA19_BAUDCLK / b16)) == 0) {
+ if( (div = (baudclk / b16)) == 0) {
return (KEYSPAN_INVALID_BAUD_RATE);
}
else {
@@ -532,217 +1165,520 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u8 *rate_hi, u8 *rate_low)
return (KEYSPAN_INVALID_BAUD_RATE);
}
- /* return the counter values */
- *rate_low = (u8) (cnt & 0xff);
- *rate_hi = (u8) ((cnt >> 8) & 0xff);
+ /* return the counter values if non-null */
+ if (rate_low) {
+ *rate_low = (u8) (cnt & 0xff);
+ }
+ if (rate_hi) {
+ *rate_hi = (u8) ((cnt >> 8) & 0xff);
+ }
+ if (rate_low && rate_hi) {
+ dbg (__FUNCTION__ " %d %02x %02x.", baud_rate, *rate_hi, *rate_low);
+ }
- dbg(__FUNCTION__ " Baud rate of %d is %02x %02x.\n", baud_rate, *rate_hi, *rate_low);
+ return (KEYSPAN_BAUD_RATE_OK);
+}
+static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk,
+ u8 *rate_hi, u8 *rate_low, u8 *prescaler)
+{
+ u32 b16, /* baud rate times 16 (actual rate used internally) */
+ clk, /* clock with 13/8 prescaler */
+ div, /* divisor using 13/8 prescaler */
+ res, /* resulting baud rate using 13/8 prescaler */
+ diff, /* error using 13/8 prescaler */
+ smallest_diff;
+ u8 best_prescaler;
+ int i;
+
+ /* dbg (__FUNCTION__ " %d.", baud_rate); */
+
+ /* prevent divide by zero */
+ if( (b16 = baud_rate * 16L) == 0) {
+ return (KEYSPAN_INVALID_BAUD_RATE);
+ }
+
+ /* Calculate prescaler by trying them all and looking
+ for best fit */
+
+ /* start with largest possible difference */
+ smallest_diff = 0xffffffff;
+
+ /* 0 is an invalid prescaler, used as a flag */
+ best_prescaler = 0;
+
+ for(i = 8; i <= 0xff; ++i)
+ {
+ clk = (baudclk * 8) / (u32) i;
+
+ if( (div = clk / b16) == 0) {
+ continue;
+ }
+
+ res = clk / div;
+ diff= (res > b16) ? (res-b16) : (b16-res);
+
+ if(diff < smallest_diff)
+ {
+ best_prescaler = i;
+ smallest_diff = diff;
+ }
+ }
+
+ if(best_prescaler == 0) {
+ return (KEYSPAN_INVALID_BAUD_RATE);
+ }
+
+ clk = (baudclk * 8) / (u32) best_prescaler;
+ div = clk / b16;
+
+ /* return the divisor and prescaler if non-null */
+ if (rate_low) {
+ *rate_low = (u8) (div & 0xff);
+ }
+ if (rate_hi) {
+ *rate_hi = (u8) ((div >> 8) & 0xff);
+ }
+ if (prescaler) {
+ *prescaler = best_prescaler;
+ /* dbg(__FUNCTION__ " %d %d", *prescaler, div); */
+ }
return (KEYSPAN_BAUD_RATE_OK);
}
-static int keyspan_usa19_send_setup(struct usb_serial *serial, struct usb_serial_port *port)
+static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ struct usb_serial_port *port)
{
- struct portControlMessage msg;
- struct keyspan_serial_private *s_priv;
- struct keyspan_port_private *p_priv;
+ struct keyspan_usa26_portControlMessage msg;
+ struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+ const keyspan_device_details *d_details;
+ int outcont_urb;
+ urb_t *this_urb;
+ int err;
+
+ /* dbg (__FUNCTION__); */
s_priv = (struct keyspan_serial_private *)(serial->private);
p_priv = (struct keyspan_port_private *)(port->private);
+ d_details = s_priv->device_details;
+
+ outcont_urb = d_details->outcont_endpoints[port->number];
+ this_urb = p_priv->outcont_urb;
+
+ /* Make sure we have an urb then send the message */
+ if (this_urb == NULL) {
+ dbg(__FUNCTION__ " oops no urb.");
+ return -1;
+ }
+
+ p_priv->resend_cont = 1;
+ if (this_urb->status == -EINPROGRESS) {
+ /* dbg (__FUNCTION__ " already writing"); */
+ return(-1);
+ }
+
+ memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage));
+
+ /* Only set baud rate if it's changed */
+ if (p_priv->old_baud != p_priv->baud) {
+ p_priv->old_baud = p_priv->baud;
+ msg.setClocking = 0xff;
+ if (d_details->calculate_baud_rate
+ (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ &msg.baudLo, &msg.prescaler) == KEYSPAN_INVALID_BAUD_RATE ) {
+ dbg(__FUNCTION__ "Invalid baud rate %d requested, using 9600.",
+ p_priv->baud);
+ msg.baudLo = 0;
+ msg.baudHi = 125; /* Values for 9600 baud */
+ msg.prescaler = 10;
+ }
+ msg.setPrescaler = 0xff;
+ }
- //memset(msg, 0, sizeof (struct portControlMessage));
+ msg.lcr = USA_DATABITS_8 | STOPBITS_5678_1;
+ if (p_priv->cflag & PARENB) {
+ /* note USA_PARITY_NONE == 0 */
+ msg.lcr |= (p_priv->cflag & PARODD)?
+ USA_PARITY_ODD: USA_PARITY_EVEN;
+ }
+ msg.setLcr = 0xff;
+
+ msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
+ msg.xonFlowControl = 0;
+ msg.setFlowControl = 0xff;
+
+ msg.forwardingLength = 1;
+ msg.xonChar = 17;
+ msg.xoffChar = 19;
+
+ msg._txOn = 1;
+ msg._txOff = 0;
+ msg.txFlush = 0;
+ msg.txBreak = 0;
+ msg.rxOn = 1;
+ msg.rxOff = 0;
+ msg.rxFlush = 0;
+ msg.rxForward = 0;
+ /*msg.returnStatus = 1;
+ msg.resetDataToggle = 0xff;*/
+
+ /* Do handshaking outputs */
+ msg.setTxTriState_setRts = 0xff;
+ msg.txTriState_rts = p_priv->rts_state;
+
+ msg.setHskoa_setDtr = 0xff;
+ msg.hskoa_dtr = p_priv->dtr_state;
+ p_priv->resend_cont = 0;
+ memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
+
+ /* send the data out the device on control endpoint */
+ this_urb->transfer_buffer_length = sizeof(msg);
+
+ this_urb->dev = serial->dev;
+ if ((err = usb_submit_urb(this_urb)) != 0) {
+ dbg(__FUNCTION__ " usb_submit_urb(setup) failed (%d)", err);
+ }
+#if 0
+ else {
+ dbg(__FUNCTION__ " usb_submit_urb(%d) OK %d bytes (end %d)",
+ outcont_urb, this_urb->transfer_buffer_length,
+ usb_pipeendpoint(this_urb->pipe));
+ }
+#endif
+
+ return (0);
+}
+
+static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ struct usb_serial_port *port)
+{
+ struct keyspan_usa28_portControlMessage msg;
+ struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+ const keyspan_device_details *d_details;
+ urb_t *this_urb;
+ int err;
+
+ s_priv = (struct keyspan_serial_private *)(serial->private);
+ p_priv = (struct keyspan_port_private *)(port->private);
+ d_details = s_priv->device_details;
+
+ /* only do something if we have a bulk out endpoint */
+ if ((this_urb = p_priv->outcont_urb) == NULL) {
+ dbg(__FUNCTION__ " oops no urb.");
+ return -1;
+ }
+
+ p_priv->resend_cont = 1;
+ if (this_urb->status == -EINPROGRESS) {
+ dbg (__FUNCTION__ " already writing");
+ return(-1);
+ }
+
+ memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage));
+
msg.setBaudRate = 1;
- if (keyspan_usa19_calc_baud(9600, &msg.baudHi, &msg.baudLo) ==
- KEYSPAN_INVALID_BAUD_RATE ) {
- dbg(__FUNCTION__ "Invalid baud rate requested %d.\n", 9600);
+ if (keyspan_usa19_calc_baud(p_priv->baud, d_details->baudclk,
+ &msg.baudHi, &msg.baudLo, NULL) == KEYSPAN_INVALID_BAUD_RATE ) {
+ dbg(__FUNCTION__ "Invalid baud rate requested %d.", 9600);
msg.baudLo = 0xff;
msg.baudHi = 0xb2; /* Values for 9600 baud */
}
- /* If parity is enabled, we must calculate it ourselves. */
- if (p_priv->parity) {
- msg.parity = 1;
+ /* If parity is enabled, we must calculate it ourselves. */
+ msg.parity = 0; /* XXX for now */
+
+ msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
+ msg.xonFlowControl = 0;
+
+ /* Do handshaking outputs, DTR is inverted relative to RTS */
+ msg.rts = p_priv->rts_state;
+ msg.dtr = p_priv->dtr_state;
+
+ msg.forwardingLength = 1;
+ msg.forwardMs = 10;
+ msg.breakThreshold = 45;
+ msg.xonChar = 17;
+ msg.xoffChar = 19;
+
+ msg._txOn = 1;
+ msg._txOff = 0;
+ msg.txFlush = 0;
+ msg.txForceXoff = 0;
+ msg.txBreak = 0;
+ msg.rxOn = 1;
+ msg.rxOff = 0;
+ msg.rxFlush = 0;
+ msg.rxForward = 0;
+ /*msg.returnStatus = 1;
+ msg.resetDataToggle = 0xff;*/
+
+ p_priv->resend_cont = 0;
+ memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
+
+ /* send the data out the device on control endpoint */
+ this_urb->transfer_buffer_length = sizeof(msg);
+
+ this_urb->dev = serial->dev;
+ if ((err = usb_submit_urb(this_urb)) != 0) {
+ dbg(__FUNCTION__ " usb_submit_urb(setup) failed");
}
+#if 0
else {
- msg.parity = 0;
+ dbg(__FUNCTION__ " usb_submit_urb(setup) OK %d bytes",
+ this_urb->transfer_buffer_length);
}
+#endif
+
+ return (0);
+}
- msg.ctsFlowControl = 0;
+static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ struct usb_serial_port *port)
+{
+ struct keyspan_usa49_portControlMessage msg;
+ struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+ const keyspan_device_details *d_details;
+ int glocont_urb;
+ urb_t *this_urb;
+ int err;
+
+ /* dbg (__FUNCTION__); */
+
+ s_priv = (struct keyspan_serial_private *)(serial->private);
+ p_priv = (struct keyspan_port_private *)(port->private);
+ d_details = s_priv->device_details;
+
+ glocont_urb = d_details->glocont_endpoint;
+ this_urb = s_priv->glocont_urb;
+
+ /* dbg(__FUNCTION__ " port %d\n", port->number); */
+
+ /* Make sure we have an urb then send the message */
+ if (this_urb == NULL) {
+ dbg(__FUNCTION__ " oops no urb for port %d.", port->number);
+ return -1;
+ }
+
+ p_priv->resend_cont = 1;
+ if (this_urb->status == -EINPROGRESS) {
+ /* dbg (__FUNCTION__ " already writing"); */
+ return(-1);
+ }
+
+ memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage));
+
+ msg.portNumber = port->number;
+
+ /* Only set baud rate if it's changed */
+ if (p_priv->old_baud != p_priv->baud) {
+ p_priv->old_baud = p_priv->baud;
+ msg.setClocking = 0xff;
+ if (d_details->calculate_baud_rate
+ (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ &msg.baudLo, &msg.prescaler) == KEYSPAN_INVALID_BAUD_RATE ) {
+ dbg(__FUNCTION__ "Invalid baud rate %d requested, using 9600.",
+ p_priv->baud);
+ msg.baudLo = 0;
+ msg.baudHi = 125; /* Values for 9600 baud */
+ msg.prescaler = 10;
+ }
+ //msg.setPrescaler = 0xff;
+ }
+
+ msg.lcr = USA_DATABITS_8 | STOPBITS_5678_1;
+ if (p_priv->cflag & PARENB) {
+ /* note USA_PARITY_NONE == 0 */
+ msg.lcr |= (p_priv->cflag & PARODD)?
+ USA_PARITY_ODD: USA_PARITY_EVEN;
+ }
+ msg.setLcr = 0xff;
+
+ msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
msg.xonFlowControl = 0;
- msg.rts = 1;
- msg.dtr = 0;
+ msg.setFlowControl = 0xff;
msg.forwardingLength = 1;
- msg.forwardMs = 10;
- msg.breakThreshold = 45;
msg.xonChar = 17;
msg.xoffChar = 19;
msg._txOn = 1;
msg._txOff = 0;
msg.txFlush = 0;
- msg.txForceXoff = 0;
msg.txBreak = 0;
msg.rxOn = 1;
msg.rxOff = 0;
msg.rxFlush = 0;
msg.rxForward = 0;
- msg.returnStatus = 1;
- msg.resetDataToggle = 1;
+ msg.enablePort = 0xff;
+ msg.disablePort = 0;
+ /* Do handshaking outputs */
+ msg.setRts = 0xff;
+ msg.rts = p_priv->rts_state;
+
+ msg.setDtr = 0xff;
+ msg.dtr = p_priv->dtr_state;
- /* only do something if we have a bulk out endpoint */
- if (s_priv->out_urbs[2]) {
- if (s_priv->out_urbs[2]->status == -EINPROGRESS) {
- dbg (__FUNCTION__ " already writing");
- return(-1);
- }
- memcpy (s_priv->out_urbs[2]->transfer_buffer, &msg, sizeof(msg));
+ p_priv->resend_cont = 0;
+ memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
- /* send the data out the device on control endpoint */
- s_priv->out_urbs[2]->transfer_buffer_length = sizeof(msg);
- s_priv->out_urbs[2]->dev = serial->dev;
+ /* send the data out the device on control endpoint */
+ this_urb->transfer_buffer_length = sizeof(msg);
- if (usb_submit_urb(s_priv->out_urbs[2])) {
- dbg(__FUNCTION__ " usb_submit_urb(setup) failed\n");
- }
- else {
- dbg(__FUNCTION__ " usb_submit_urb(setup) OK %d bytes\n", s_priv->out_urbs[2]->transfer_buffer_length);
- }
-
+ this_urb->dev = serial->dev;
+ if ((err = usb_submit_urb(this_urb)) != 0) {
+ dbg(__FUNCTION__ " usb_submit_urb(setup) failed (%d)", err);
}
+#if 0
+ else {
+ dbg(__FUNCTION__ " usb_submit_urb(%d) OK %d bytes (end %d)",
+ outcont_urb, this_urb->transfer_buffer_length,
+ usb_pipeendpoint(this_urb->pipe));
+ }
+#endif
+
return (0);
}
+static void keyspan_send_setup(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct keyspan_serial_private *s_priv;
+ const keyspan_device_details *d_details;
+
+ s_priv = (struct keyspan_serial_private *)(serial->private);
+ d_details = s_priv->device_details;
+
+ switch (d_details->msg_format) {
+ case msg_usa26:
+ keyspan_usa26_send_setup(serial, port);
+ break;
+ case msg_usa28:
+ keyspan_usa28_send_setup(serial, port);
+ break;
+ case msg_usa49:
+ keyspan_usa49_send_setup(serial, port);
+ break;
+ }
+}
- /* Gets called by the "real" driver (ie once firmware is loaded
- and renumeration has taken place. */
+/* Gets called by the "real" driver (ie once firmware is loaded
+ and renumeration has taken place. */
static int keyspan_startup (struct usb_serial *serial)
{
- int i;
- struct usb_serial_port *port;
+ int i, err;
+ struct usb_serial_port *port;
+ struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+ const keyspan_device_details *d_details;
- dbg("keyspan_startup called.\n");
+ /* dbg("keyspan_startup called."); */
+
+ for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
+ if (d_details->product_id == serial->dev->descriptor.idProduct)
+ break;
+ if (d_details == NULL) {
+ printk(KERN_ERR __FUNCTION__ ": unknown product id %x\n",
+ serial->dev->descriptor.idProduct);
+ return 1;
+ }
- /* Setup private data for serial driver */
- serial->private = kmalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
+ /* Setup private data for serial driver */
+ serial->private = kmalloc(sizeof(struct keyspan_serial_private),
+ GFP_KERNEL);
if (!serial->private) {
- dbg(__FUNCTION__ "kmalloc for keyspan_serial_private failed!.\n");
+ dbg(__FUNCTION__ "kmalloc for keyspan_serial_private failed.");
return (1);
}
memset(serial->private, 0, sizeof(struct keyspan_serial_private));
+
+ s_priv = (struct keyspan_serial_private *)(serial->private);
+ s_priv->device_details = d_details;
- init_waitqueue_head(&out_wait);
-
- /* Now setup per port private data */
+ /* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = &serial->port[i];
- port->private = kmalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
+ port->private = kmalloc(sizeof(struct keyspan_port_private),
+ GFP_KERNEL);
if (!port->private) {
- dbg(__FUNCTION__ "kmalloc for keyspan_port_private (%d) failed!.\n", i);
+ dbg(__FUNCTION__ "kmalloc for keyspan_port_private (%d) failed!.", i);
return (1);
}
memset(port->private, 0, sizeof(struct keyspan_port_private));
+ p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv->device_details = d_details;
}
-
-
- switch (serial->dev->descriptor.idProduct) {
- case 0x0107: keyspan_usa19_setup_urbs(serial);
- //keyspan_send_usa19_setup(serial);
- break;
+ keyspan_setup_urbs(serial);
- default: break;
+ s_priv->instat_urb->dev = serial->dev;
+ if ((err = usb_submit_urb(s_priv->instat_urb)) != 0) {
+ dbg(__FUNCTION__ " submit instat urb failed %d", err);
}
-
return (0);
}
static void keyspan_shutdown (struct usb_serial *serial)
{
- int i;
+ int i, j;
struct usb_serial_port *port;
struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
- dbg("keyspan_shutdown called freeing ");
+ /* dbg("keyspan_shutdown called"); */
s_priv = (struct keyspan_serial_private *)(serial->private);
- /* Stop reading/writing urbs */
- for (i = 0; i < 4; i++) {
- if (s_priv->in_urbs[i]) {
- usb_unlink_urb(s_priv->in_urbs[i]);
+ /* Stop reading/writing urbs */
+ stop_urb(s_priv->instat_urb);
+ stop_urb(s_priv->glocont_urb);
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = &serial->port[i];
+ p_priv = (struct keyspan_port_private *)(port->private);
+ stop_urb(p_priv->inack_urb);
+ stop_urb(p_priv->outcont_urb);
+ for (j = 0; j < 2; j++) {
+ stop_urb(p_priv->in_urbs[j]);
+ stop_urb(p_priv->out_urbs[j]);
}
-
}
- for (i = 0; i < 3; i++) {
- if (s_priv->out_urbs[i]) {
- usb_unlink_urb(s_priv->out_urbs[i]);
- }
- }
- /* Now free them */
- for (i = 0; i < 7; i ++) {
- if (s_priv->in_urbs[i] != NULL) {
- dbg("in%d ", i);
- usb_free_urb(s_priv->in_urbs[i]);
- }
-
- if (s_priv->out_urbs[i] != NULL) {
- dbg("out%d ", i);
- usb_free_urb(s_priv->out_urbs[i]);
+ /* Now free them */
+ if (s_priv->instat_urb)
+ usb_free_urb(s_priv->instat_urb);
+ if (s_priv->glocont_urb)
+ usb_free_urb(s_priv->glocont_urb);
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = &serial->port[i];
+ p_priv = (struct keyspan_port_private *)(port->private);
+ if (p_priv->inack_urb)
+ usb_free_urb(p_priv->inack_urb);
+ if (p_priv->outcont_urb)
+ usb_free_urb(p_priv->outcont_urb);
+ for (j = 0; j < 2; j++) {
+ if (p_priv->in_urbs[j])
+ usb_free_urb(p_priv->in_urbs[j]);
+ if (p_priv->out_urbs[j])
+ usb_free_urb(p_priv->out_urbs[j]);
}
}
- dbg("urbs.\n");
- dbg("Freeing serial->private.\n");
+ /* dbg("Freeing serial->private."); */
kfree(serial->private);
- dbg("Freeing port->private.\n");
- /* Now free per port private data */
+ /* dbg("Freeing port->private."); */
+ /* Now free per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = &serial->port[i];
+ while (port->open_count > 0) {
+ --port->open_count;
+ MOD_DEC_USE_COUNT;
+ }
kfree(port->private);
}
-
-}
-
-
-static int __init keyspan_init (void)
-{
- usb_serial_register (&keyspan_usa18x_pre_device);
- usb_serial_register (&keyspan_usa19_pre_device);
- usb_serial_register (&keyspan_usa19w_pre_device);
- usb_serial_register (&keyspan_usa28_pre_device);
- usb_serial_register (&keyspan_usa28x_pre_device);
- usb_serial_register (&keyspan_usa18x_device);
- usb_serial_register (&keyspan_usa19_device);
- usb_serial_register (&keyspan_usa19w_device);
- usb_serial_register (&keyspan_usa28_device);
- usb_serial_register (&keyspan_usa28x_device);
- return 0;
-}
-
-
-static void __exit keyspan_exit (void)
-{
- usb_serial_deregister (&keyspan_usa18x_pre_device);
- usb_serial_deregister (&keyspan_usa19_pre_device);
- usb_serial_deregister (&keyspan_usa19w_pre_device);
- usb_serial_deregister (&keyspan_usa28_pre_device);
- usb_serial_deregister (&keyspan_usa28x_pre_device);
- usb_serial_deregister (&keyspan_usa18x_device);
- usb_serial_deregister (&keyspan_usa19_device);
- usb_serial_deregister (&keyspan_usa19w_device);
- usb_serial_deregister (&keyspan_usa28_device);
- usb_serial_deregister (&keyspan_usa28x_device);
}
-
-
-module_init(keyspan_init);
-module_exit(keyspan_exit);
-
-MODULE_AUTHOR("Hugh Blemings <hugh@linuxcare.com>");
-MODULE_DESCRIPTION("Keyspan USB to Serial Converter driver");
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 8d249916c..0cd2a70b0 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -19,6 +19,11 @@
and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
Thanks Guys :)
+ Thanks to Paulus for miscellaneous tidy ups, some largish chunks
+ of much nicer and/or completely new code and (perhaps most uniquely)
+ having the patience to sit down and explain why and where he'd changed
+ stuff.
+
Tip 'o the hat to Linuxcare for supporting staff in their work on
open source projects.
@@ -41,12 +46,18 @@ static void keyspan_shutdown (struct usb_serial *serial);
static void keyspan_rx_throttle (struct usb_serial_port *port);
static void keyspan_rx_unthrottle (struct usb_serial_port *port);
static int keyspan_write_room (struct usb_serial_port *port);
+
static int keyspan_write (struct usb_serial_port *port,
int from_user,
const unsigned char *buf,
int count);
+
+#if 0
static void keyspan_write_bulk_callback (struct urb *urb);
-static void keyspan_read_bulk_callback (struct urb *urb);
+#endif
+
+//static void keyspan_usa26_read_int_callback (struct urb *urb);
+//static void keyspan_usa28_read_int_callback (struct urb *urb);
static int keyspan_chars_in_buffer (struct usb_serial_port *port);
static int keyspan_ioctl (struct usb_serial_port *port,
struct file *file,
@@ -58,12 +69,20 @@ static void keyspan_break_ctl (struct usb_serial_port *port,
int break_state);
static int keyspan_fake_startup (struct usb_serial *serial);
-static int keyspan_usa19_calc_baud (u32 baud_rate, u8 *rate_hi,
- u8 *rate_low);
-static void keyspan_usa19_setup_urbs (struct usb_serial *serial);
-static int keyspan_usa19_send_setup (struct usb_serial *serial,
- struct usb_serial_port *port);
+static int keyspan_usa19_calc_baud (u32 baud_rate, u32 baudclk,
+ u8 *rate_hi, u8 *rate_low, u8 *prescaler);
+static int keyspan_usa19w_calc_baud (u32 baud_rate, u32 baudclk,
+ u8 *rate_hi, u8 *rate_low, u8 *prescaler);
+
+//static void keyspan_usa19_setup_urbs (struct usb_serial *serial);
+
+static int keyspan_usa28_send_setup (struct usb_serial *serial,
+ struct usb_serial_port *port);
+static int keyspan_usa26_send_setup (struct usb_serial *serial,
+ struct usb_serial_port *port);
+static int keyspan_usa49_send_setup (struct usb_serial *serial,
+ struct usb_serial_port *port);
/* Functions from usbserial.c for ezusb firmware handling */
extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
@@ -109,13 +128,162 @@ struct ezusb_hex_record {
static const struct ezusb_hex_record *keyspan_usa19w_firmware = NULL;
#endif
-
+#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA49W
+ #include "keyspan_usa49w_fw.h"
+#else
+ static const struct ezusb_hex_record *keyspan_usa49w_firmware = NULL;
+#endif
+
/* Values used for baud rate calculation - device specific */
#define KEYSPAN_INVALID_BAUD_RATE (-1)
#define KEYSPAN_BAUD_RATE_OK (0)
-#define USA19_BAUDCLK (12000000L)
+#define KEYSPAN_USA18X_BAUDCLK (12000000L) /* a guess */
+#define KEYSPAN_USA19_BAUDCLK (12000000L)
+#define KEYSPAN_USA19W_BAUDCLK (24000000L)
+#define KEYSPAN_USA28X_BAUDCLK (12000000L)
+#define KEYSPAN_USA49W_BAUDCLK (48000000L)
+
+ /* Some constants used to characterise each device.
+ There is a four port device due later in the year,
+ we allow for it now in the following */
+#define KEYSPAN_MAX_NUM_PORTS (4)
+#define KEYSPAN_MAX_FLIPS (2)
+
+typedef struct {
+ /* product ID value */
+ int product_id;
+
+ enum {msg_usa26, msg_usa28, msg_usa49} msg_format;
+
+ /* Number of physical ports */
+ int num_ports;
+
+ /* 1 if endpoint flipping used on input, 0 if not */
+ int indat_endp_flip;
+
+ /* 1 if endpoint flipping used on output, 0 if not */
+ int outdat_endp_flip;
+
+ /* Table mapping input data endpoint IDs to physical
+ port number and flip if used */
+ int indat_endpoints[KEYSPAN_MAX_NUM_PORTS];
+
+ /* Same for output endpoints */
+ int outdat_endpoints[KEYSPAN_MAX_NUM_PORTS];
+
+ /* Input acknowledge endpoints */
+ int inack_endpoints[KEYSPAN_MAX_NUM_PORTS];
+
+ /* Output control endpoints */
+ int outcont_endpoints[KEYSPAN_MAX_NUM_PORTS];
+
+ /* Endpoint used for input status */
+ int instat_endpoint;
+
+ /* Endpoint used for global control functions */
+ int glocont_endpoint;
+
+ int (*calculate_baud_rate) (u32 baud_rate, u32 baudclk,
+ u8 *rate_hi, u8 *rate_low, u8 *prescaler);
+ u32 baudclk;
+
+} keyspan_device_details;
+
+ /* Now for each device type we setup the device detail
+ structure with the appropriate information (provided
+ in Keyspan's documentation) */
+
+static const keyspan_device_details usa18x_device_details = {
+ 0x112, /* product ID */
+ msg_usa26, /* msg type*/
+ 1, /* num ports */
+ 0, /* indat endpoint flip */
+ 1, /* outdat endpoint flip */
+ {0x81}, /* per port indat */
+ {0x01}, /* per port outdat */
+ {0x85}, /* per port inack */
+ {0x05}, /* per port outcont */
+ 0x87, /* instat endpoint */
+ 0x07, /* glocont endpoint */
+ keyspan_usa19w_calc_baud, /* calc baud rate */
+ KEYSPAN_USA18X_BAUDCLK /* base baud clock */
+};
+
+static const keyspan_device_details usa19_device_details = {
+ 0x107, /* product ID */
+ msg_usa28, /* msg type*/
+ 1, /* num ports */
+ 1, /* indat endpoint flip */
+ 1, /* outdat endpoint flip */
+ {0x81}, /* per port indat */
+ {0x01}, /* per port outdat */
+ {0x83}, /* per port inack */
+ {0x03}, /* per port outcont */
+ 0x84, /* instat endpoint */
+ -1, /* glocont endpoint */
+ keyspan_usa19_calc_baud, /* calc baud rate */
+ KEYSPAN_USA19_BAUDCLK /* base baud clock */
+};
+
+static const keyspan_device_details usa19w_device_details = {
+ 0x108, /* product ID */
+ msg_usa26, /* msg type*/
+ 1, /* num ports */
+ 0, /* indat endpoint flip */
+ 1, /* outdat endpoint flip */
+ {0x81}, /* per port indat */
+ {0x01}, /* per port outdat */
+ {0x85}, /* per port inack */
+ {0x05}, /* per port outcont */
+ 0x87, /* instat endpoint */
+ 0x07, /* glocont endpoint */
+ keyspan_usa19w_calc_baud, /* calc baud rate */
+ KEYSPAN_USA19W_BAUDCLK /* base baud clock */
+};
+
+static const keyspan_device_details usa28x_device_details = {
+ 0x110, /* product ID */
+ msg_usa26, /* msg type*/
+ 2, /* num ports */
+ 0, /* indat endpoint flip */
+ 1, /* outdat endpoint flip */
+ {0x81, 0x83}, /* per port indat */
+ {0x01, 0x03}, /* per port outdat */
+ {0x85, 0x86}, /* per port inack */
+ {0x05, 0x06}, /* per port outcont */
+ 0x87, /* instat endpoint */
+ 0x07, /* glocont endpoint */
+ keyspan_usa19w_calc_baud, /* calc baud rate */
+ KEYSPAN_USA28X_BAUDCLK
+};
+
+static const keyspan_device_details usa49w_device_details = {
+ 0x010a, /* product ID */
+ msg_usa49, /* msg type*/
+ 4, /* num ports */
+ 0, /* indat endpoint flip */
+ 0, /* outdat endpoint flip */
+ { 0x81, 0x82, 0x83, 0x84}, /* per port indat */
+ { 0x01, 0x02, 0x03, 0x04}, /* per port outdat */
+ {-1, -1, -1, -1}, /* per port inack */
+ {-1, -1, -1, -1}, /* per port outcont */
+ 0x87, /* instat endpoint */
+ 0x07, /* glocont endpoint */
+ keyspan_usa19w_calc_baud, /* calc baud rate */
+ KEYSPAN_USA49W_BAUDCLK
+};
- /* Device info for the Keyspan serial converter */
+static const keyspan_device_details *keyspan_devices[] = {
+ &usa18x_device_details,
+ &usa19_device_details,
+ &usa19w_device_details,
+ &usa28x_device_details,
+ &usa49w_device_details,
+ NULL
+};
+
+ /* Device info for the Keyspan serial converter, used
+ by the overall usb-serial probe function */
#define KEYSPAN_VENDOR_ID (0x06cd)
/* Product IDs for the five products supported, pre-renumeration */
@@ -124,6 +292,7 @@ struct ezusb_hex_record {
#define keyspan_usa19w_pre_product_id 0x0106
#define keyspan_usa28_pre_product_id 0x0101
#define keyspan_usa28x_pre_product_id 0x0102
+#define keyspan_usa49w_pre_product_id 0x0109
/* Product IDs post-renumeration */
#define keyspan_usa18x_product_id 0x0112
@@ -131,6 +300,7 @@ struct ezusb_hex_record {
#define keyspan_usa19w_product_id 0x0108
#define keyspan_usa28_product_id 0x010f
#define keyspan_usa28x_product_id 0x0110
+#define keyspan_usa49w_product_id 0x010a
static __devinitdata struct usb_device_id keyspan_ids_combined[] = {
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa18x_pre_product_id},
@@ -138,11 +308,13 @@ static __devinitdata struct usb_device_id keyspan_ids_combined[] = {
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19w_pre_product_id},
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28_pre_product_id},
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28x_pre_product_id},
+ {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa49w_pre_product_id},
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa18x_product_id},
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19_product_id},
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19w_product_id},
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28_product_id},
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28x_product_id},
+ {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa49w_product_id},
{ } /* Terminating entry */
};
@@ -177,6 +349,11 @@ static __devinitdata struct usb_device_id keyspan_usa28x_pre_ids[] = {
{ } /* Terminating entry */
};
+static __devinitdata struct usb_device_id keyspan_usa49w_pre_ids[] = {
+ {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa49w_pre_product_id},
+ { } /* Terminating entry */
+};
+
static __devinitdata struct usb_device_id keyspan_usa18x_ids[] = {
{idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa18x_product_id},
{ } /* Terminating entry */
@@ -202,10 +379,15 @@ static __devinitdata struct usb_device_id keyspan_usa28x_ids[] = {
{ } /* Terminating entry */
};
+static __devinitdata struct usb_device_id keyspan_usa49w_ids[] = {
+ {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa49w_product_id},
+ { } /* Terminating entry */
+};
+
/* Structs for the devices, pre and post renumeration.
These are incomplete at present - HAB 20000708 */
struct usb_serial_device_type keyspan_usa18x_pre_device = {
- name: "Keyspan USA18X - (prerenumeration)",
+ name: "Keyspan USA18X - (without firmware)",
id_table: keyspan_usa18x_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
@@ -218,7 +400,7 @@ struct usb_serial_device_type keyspan_usa18x_pre_device = {
};
struct usb_serial_device_type keyspan_usa19_pre_device = {
- name: "Keyspan USA19 - (prerenumeration)",
+ name: "Keyspan USA19 - (without firmware)",
id_table: keyspan_usa19_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
@@ -232,7 +414,7 @@ struct usb_serial_device_type keyspan_usa19_pre_device = {
struct usb_serial_device_type keyspan_usa19w_pre_device = {
- name: "Keyspan USA19W - (prerenumeration)",
+ name: "Keyspan USA19W - (without firmware)",
id_table: keyspan_usa19w_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
@@ -246,7 +428,7 @@ struct usb_serial_device_type keyspan_usa19w_pre_device = {
struct usb_serial_device_type keyspan_usa28_pre_device = {
- name: "Keyspan USA28 - (prerenumeration)",
+ name: "Keyspan USA28 - (without firmware)",
id_table: keyspan_usa28_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
@@ -259,7 +441,7 @@ struct usb_serial_device_type keyspan_usa28_pre_device = {
};
struct usb_serial_device_type keyspan_usa28x_pre_device = {
- name: "Keyspan USA28X - (prerenumeration)",
+ name: "Keyspan USA28X - (without firmware)",
id_table: keyspan_usa28x_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
@@ -271,22 +453,43 @@ struct usb_serial_device_type keyspan_usa28x_pre_device = {
startup: keyspan_fake_startup
};
+struct usb_serial_device_type keyspan_usa49w_pre_device = {
+ name: "Keyspan USA49W - (without firmware)",
+ id_table: keyspan_usa49w_pre_ids,
+ needs_interrupt_in: DONT_CARE,
+ needs_bulk_in: DONT_CARE,
+ needs_bulk_out: DONT_CARE,
+ num_interrupt_in: NUM_DONT_CARE,
+ num_bulk_in: NUM_DONT_CARE,
+ num_bulk_out: NUM_DONT_CARE,
+ num_ports: 4,
+ startup: keyspan_fake_startup
+};
struct usb_serial_device_type keyspan_usa18x_device = {
name: "Keyspan USA18X",
id_table: keyspan_usa18x_ids,
needs_interrupt_in: DONT_CARE,
- needs_bulk_in: DONT_CARE,
- needs_bulk_out: DONT_CARE,
+ needs_bulk_in: MUST_HAVE,
+ needs_bulk_out: MUST_HAVE,
num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
+ num_bulk_in: 3,
+ num_bulk_out: 4,
num_ports: 1,
open: keyspan_open,
close: keyspan_close,
+ write: keyspan_write,
+ write_room: keyspan_write_room,
+ //write_bulk_callback: Not used - we define our own herbs
+ //read_int_callback: keyspan_usa26_read_int_callback,
+ chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
+ ioctl: keyspan_ioctl,
set_termios: keyspan_set_termios,
+ break_ctl: keyspan_break_ctl,
+ startup: keyspan_startup,
+ shutdown: keyspan_shutdown,
};
struct usb_serial_device_type keyspan_usa19_device = {
@@ -303,8 +506,8 @@ struct usb_serial_device_type keyspan_usa19_device = {
close: keyspan_close,
write: keyspan_write,
write_room: keyspan_write_room,
- write_bulk_callback: keyspan_write_bulk_callback,
- read_int_callback: keyspan_read_bulk_callback,
+// write_bulk_callback: keyspan_write_bulk_callback,
+// read_int_callback: keyspan_usa28_read_int_callback,
chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
@@ -320,17 +523,26 @@ struct usb_serial_device_type keyspan_usa19w_device = {
name: "Keyspan USA19W",
id_table: keyspan_usa19w_ids,
needs_interrupt_in: DONT_CARE,
- needs_bulk_in: DONT_CARE,
- needs_bulk_out: DONT_CARE,
+ needs_bulk_in: MUST_HAVE,
+ needs_bulk_out: MUST_HAVE,
num_interrupt_in: NUM_DONT_CARE,
- num_bulk_in: NUM_DONT_CARE,
- num_bulk_out: NUM_DONT_CARE,
+ num_bulk_in: 3,
+ num_bulk_out: 4,
num_ports: 1,
open: keyspan_open,
close: keyspan_close,
+ write: keyspan_write,
+ write_room: keyspan_write_room,
+ //write_bulk_callback: Not used - we define our own herbs
+ //read_int_callback: keyspan_usa26_read_int_callback,
+ chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
+ ioctl: keyspan_ioctl,
set_termios: keyspan_set_termios,
+ break_ctl: keyspan_break_ctl,
+ startup: keyspan_startup,
+ shutdown: keyspan_shutdown,
};
@@ -366,8 +578,8 @@ struct usb_serial_device_type keyspan_usa28x_device = {
close: keyspan_close,
write: keyspan_write,
write_room: keyspan_write_room,
- write_bulk_callback: keyspan_write_bulk_callback,
- read_int_callback: keyspan_read_bulk_callback,
+// write_bulk_callback: keyspan_write_bulk_callback,
+// read_int_callback: keyspan_usa26_read_int_callback,
chars_in_buffer: keyspan_chars_in_buffer,
throttle: keyspan_rx_throttle,
unthrottle: keyspan_rx_unthrottle,
@@ -377,10 +589,34 @@ struct usb_serial_device_type keyspan_usa28x_device = {
startup: keyspan_startup,
shutdown: keyspan_shutdown,
+};
+struct usb_serial_device_type keyspan_usa49w_device = {
+ name: "Keyspan USA49W",
+ id_table: keyspan_usa49w_ids,
+ needs_interrupt_in: DONT_CARE,
+ needs_bulk_in: MUST_HAVE,
+ needs_bulk_out: MUST_HAVE,
+ num_interrupt_in: NUM_DONT_CARE,
+ num_bulk_in: 5,
+ num_bulk_out: 5,
+ num_ports: 4,
+ open: keyspan_open,
+ close: keyspan_close,
+ write: keyspan_write,
+ write_room: keyspan_write_room,
+ //write_bulk_callback: Not used - we define our own herbs
+ //read_int_callback: keyspan_usa26_read_int_callback,
+ chars_in_buffer: keyspan_chars_in_buffer,
+ throttle: keyspan_rx_throttle,
+ unthrottle: keyspan_rx_unthrottle,
+ ioctl: keyspan_ioctl,
+ set_termios: keyspan_set_termios,
+ break_ctl: keyspan_break_ctl,
+ startup: keyspan_startup,
+ shutdown: keyspan_shutdown,
};
-
#endif
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 3114322c8..b94c9766a 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -130,7 +130,7 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port )
/* wake up other tty processes */
wake_up_interruptible( &tty->write_wait );
/* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */
-
+ MOD_DEC_USE_COUNT;
}
static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
@@ -149,7 +149,7 @@ static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
NULL,
0,
2*HZ);
-
+ MOD_DEC_USE_COUNT;
}
@@ -198,7 +198,9 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
tty = serial->port[0].tty;
priv->tx_throttled = 0;
/* queue up a wakeup at scheduler time */
- queue_task( &priv->wakeup_task, &tq_scheduler );
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&priv->wakeup_task) == 0)
+ MOD_DEC_USE_COUNT;
break;
default:
break;
@@ -540,7 +542,9 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
if (request_unthrottle) {
priv->tx_throttled = 1; /* block writers */
- queue_task( &priv->unthrottle_task, &tq_scheduler );
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&priv->unthrottle_task) == 0)
+ MOD_DEC_USE_COUNT;
}
spin_unlock_irqrestore (&port->port_lock, flags);
@@ -566,8 +570,9 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb)
}
/* queue up a wakeup at scheduler time */
- queue_task( &priv->wakeup_task, &tq_scheduler );
-
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&priv->wakeup_task) == 0)
+ MOD_DEC_USE_COUNT;
}
@@ -737,11 +742,11 @@ static int keyspan_pda_startup (struct usb_serial *serial)
if (!priv)
return (1); /* error */
init_waitqueue_head(&serial->port[0].write_wait);
- priv->wakeup_task.next = NULL;
+ INIT_LIST_HEAD(&priv->wakeup_task.list);
priv->wakeup_task.sync = 0;
priv->wakeup_task.routine = (void *)keyspan_pda_wakeup_write;
priv->wakeup_task.data = (void *)(&serial->port[0]);
- priv->unthrottle_task.next = NULL;
+ INIT_LIST_HEAD(&priv->unthrottle_task.list);
priv->unthrottle_task.sync = 0;
priv->unthrottle_task.routine = (void *)keyspan_pda_request_unthrottle;
priv->unthrottle_task.data = (void *)(serial);
diff --git a/drivers/usb/serial/keyspan_usa26msg.h b/drivers/usb/serial/keyspan_usa26msg.h
index 8f53c96e8..403fd47ad 100644
--- a/drivers/usb/serial/keyspan_usa26msg.h
+++ b/drivers/usb/serial/keyspan_usa26msg.h
@@ -92,16 +92,8 @@
#ifndef __USA26MSG__
#define __USA26MSG__
-#ifndef __stubs__
-#include "datadefs.h"
-#endif
-
-typedef struct txAckMessage
-{
- u8 dummy;
-} txAckMessage;
-typedef struct portControlMessage
+typedef struct keyspan_usa26_portControlMessage
{
/*
there are three types of "commands" sent in the control message:
@@ -172,7 +164,7 @@ typedef struct portControlMessage
returnStatus, // BOTH: return current status (even if it hasn't changed)
resetDataToggle;// BOTH: reset data toggle state to DATA0
-} portControlMessage;
+} keyspan_usa26_portControlMessage;
// defines for bits in lcr
#define USA_DATABITS_5 0x00
@@ -190,7 +182,7 @@ typedef struct portControlMessage
// all things called "StatusMessage" are sent on the status endpoint
-typedef struct portStatusMessage // one for each port
+typedef struct keyspan_usa26_portStatusMessage // one for each port
{
u8 port, // BOTH: 0=first, 1=second, other=see below
hskia_cts, // USA26: reports HSKIA pin
@@ -203,7 +195,7 @@ typedef struct portStatusMessage // one for each port
_txXoff, // port is in XOFF state (either host or RX XOFF)
rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off
controlResponse;// 1=a control message has been processed
-} portStatusMessage;
+} keyspan_usa26_portStatusMessage;
// bits in RX data message when STAT byte is included
#define RXERROR_OVERRUN 0x02
@@ -211,28 +203,28 @@ typedef struct portStatusMessage // one for each port
#define RXERROR_FRAMING 0x08
#define RXERROR_BREAK 0x10
-typedef struct globalControlMessage
+typedef struct keyspan_usa26_globalControlMessage
{
u8 sendGlobalStatus, // 2=request for two status responses
resetStatusToggle, // 1=reset global status toggle
resetStatusCount; // a cycling value
-} globalControlMessage;
+} keyspan_usa26_globalControlMessage;
-typedef struct globalStatusMessage
+typedef struct keyspan_usa26_globalStatusMessage
{
u8 port, // 3
sendGlobalStatus, // from request, decremented
resetStatusCount; // as in request
-} globalStatusMessage;
+} keyspan_usa26_globalStatusMessage;
-typedef struct globalDebugMessage
+typedef struct keyspan_usa26_globalDebugMessage
{
u8 port, // 2
a,
b,
c,
d;
-} globalDebugMessage;
+} keyspan_usa26_globalDebugMessage;
// ie: the maximum length of an EZUSB endpoint buffer
#define MAX_DATA_LEN 64
diff --git a/drivers/usb/serial/keyspan_usa28msg.h b/drivers/usb/serial/keyspan_usa28msg.h
index 6378bc5b0..ad03c9c44 100644
--- a/drivers/usb/serial/keyspan_usa28msg.h
+++ b/drivers/usb/serial/keyspan_usa28msg.h
@@ -94,16 +94,8 @@
#ifndef __USA28MSG__
#define __USA28MSG__
-/*#ifndef STUBS
-#include "datadefs.h"
-#endif*/
-typedef struct txAckMessage
-{
- u8 dummy;
-} txAckMessage;
-
-typedef struct portControlMessage
+typedef struct keyspan_usa28_portControlMessage
{
/*
there are four types of "commands" sent in the control message:
@@ -153,9 +145,9 @@ typedef struct portControlMessage
returnStatus, // return current status n times (1 or 2)
resetDataToggle;// reset data toggle state to DATA0
-} portControlMessage;
+} keyspan_usa28_portControlMessage;
-typedef struct portStatusMessage
+typedef struct keyspan_usa28_portStatusMessage
{
u8 port, // 0=first, 1=second, 2=global (see below)
cts,
@@ -171,32 +163,32 @@ typedef struct portStatusMessage
rxBreak, // 1=we're in break state
rs232invalid, // 1=no valid signals on rs-232 inputs
controlResponse;// 1=a control messages has been processed
-} portStatusMessage;
+} keyspan_usa28_portStatusMessage;
// bit defines in txState
#define TX_OFF 0x01 // requested by host txOff command
#define TX_XOFF 0x02 // either real, or simulated by host
-typedef struct globalControlMessage
+typedef struct keyspan_usa28_globalControlMessage
{
u8 sendGlobalStatus, // 2=request for two status responses
resetStatusToggle, // 1=reset global status toggle
resetStatusCount; // a cycling value
-} globalControlMessage;
+} keyspan_usa28_globalControlMessage;
-typedef struct globalStatusMessage
+typedef struct keyspan_usa28_globalStatusMessage
{
u8 port, // 3
sendGlobalStatus, // from request, decremented
resetStatusCount; // as in request
-} globalStatusMessage;
+} keyspan_usa28_globalStatusMessage;
-typedef struct globalDebugMessage
+typedef struct keyspan_usa28_globalDebugMessage
{
u8 port, // 2
n, // typically a count/status byte
b; // typically a data byte
-} globalDebugMessage;
+} keyspan_usa28_globalDebugMessage;
// ie: the maximum length of an EZUSB endpoint buffer
#define MAX_DATA_LEN 64
diff --git a/drivers/usb/serial/keyspan_usa49msg.h b/drivers/usb/serial/keyspan_usa49msg.h
new file mode 100644
index 000000000..16ef1057e
--- /dev/null
+++ b/drivers/usb/serial/keyspan_usa49msg.h
@@ -0,0 +1,255 @@
+/*
+ usa49msg.h
+
+ Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved
+ This file is available under a BSD-style copyright
+
+ Keyspan USB Async Firmware to run on Anchor EZ-USB
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ 1. Redistributions of source code must retain this licence text
+ without modification, this list of conditions, and the following
+ disclaimer. The following copyright notice must appear immediately at
+ the beginning of all source files:
+
+ Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved
+
+ This file is available under a BSD-style copyright
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The name of InnoSys Incorprated may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+ 4th revision: USA49W version
+
+ See usa26msg.h for description of message formats
+
+ Third revision: USA28X version (aka USA26)
+
+ Buffer formats for RX/TX data messages are not defined by
+ a structure, but are described here:
+
+ USB OUT (host -> USA26, transmit) messages contain a
+ REQUEST_ACK indicator (set to 0xff to request an ACK at the
+ completion of transmit; 0x00 otherwise), followed by data:
+
+ RQSTACK DAT DAT DAT ...
+
+ with a total data length of 63.
+
+ USB IN (USA26 -> host, receive) messages contain either a zero
+ flag (indicating no error in any data bytes):
+
+ 00 DAT DAT DAT ...
+
+ for a total of 63 data bytes, or a non-zero status flag (indicating
+ that all data bytes will be preceded by status flag):
+
+ STAT DAT STAT DAT STAT DAT ...
+
+ for a total of 32 data bytes. The valid bits in the STAT bytes are:
+
+ OVERRUN 0x02
+ PARITY 0x04
+ FRAMING 0x08
+ BREAK 0x10
+
+ Notes:
+
+ 1. a "no status" RX data message (first byte zero) can serve as
+ a "break off" indicator.
+ 2. a control message specifying disablePort will be answered
+ with a status message, but no further status will be sent
+ until a control messages with enablePort is sent
+
+ revision history:
+
+ 1999feb10 add reportHskiaChanges to allow us to ignore them
+ 1999feb10 add txAckThreshold for fast+loose throughput enhancement
+ 1999mar30 beef up support for RX error reporting
+ 1999apr14 add resetDataToggle to control message
+ 2000jan04 merge with usa17msg.h
+ 2000mar08 clone from usa26msg.h -> usa49msg.h
+ 2000mar09 change to support 4 ports
+ 2000may03 change external clocking to match USA-49W hardware
+ 2000jun01 add extended BSD-style copyright text
+*/
+
+#ifndef __USA49MSG__
+#define __USA49MSG__
+
+
+/*
+ Host->device messages sent on the global control endpoint:
+
+ portNumber message
+ ---------- --------------------
+ 0,1,2,3 portControlMessage
+ 0x80 globalControlMessage
+*/
+
+typedef struct keyspan_usa49_portControlMessage
+{
+ /*
+ 0. 0/1/2/3 port control message follows
+ 0x80 set non-port control message follows
+ */
+ u8 portNumber,
+
+ /*
+ there are three types of "commands" sent in the control message:
+
+ 1. configuration changes which must be requested by setting
+ the corresponding "set" flag (and should only be requested
+ when necessary, to reduce overhead on the USA26):
+ */
+ setClocking, // host requests baud rate be set
+ baudLo, // host does baud divisor calculation
+ baudHi, // baudHi is only used for first port (gives lower rates)
+ prescaler, // specified as N/8; values 8-ff are valid
+ // must be set any time internal baud rate is set;
+ txClocking, // 0=internal, 1=external/DSR
+ rxClocking, // 0=internal, 1=external/DSR
+
+ setLcr, // host requests lcr be set
+ lcr, // use PARITY, STOPBITS, DATABITS below
+
+ setFlowControl, // host requests flow control be set
+ ctsFlowControl, // 1=use CTS flow control, 0=don't
+ xonFlowControl, // 1=use XON/XOFF flow control, 0=don't
+ xonChar, // specified in current character format
+ xoffChar, // specified in current character format
+
+ setRts, // host requests RTS output be set
+ rts, // 1=active, 0=inactive
+
+ setDtr, // host requests DTR output be set
+ dtr; // 1=on, 0=off
+
+
+ /*
+ 3. configuration data which is simply used as is (no overhead,
+ but must be specified correctly in every host message).
+ */
+ u8 forwardingLength, // forward when this number of chars available
+ dsrFlowControl, // 1=use DSR flow control, 0=don't
+ txAckThreshold, // 0=not allowed, 1=normal, 2-255 deliver ACK faster
+ loopbackMode; // 0=no loopback, 1=loopback enabled
+
+ /*
+ 4. commands which are flags only; these are processed in order
+ (so that, e.g., if both _txOn and _txOff flags are set, the
+ port ends in a TX_OFF state); any non-zero value is respected
+ */
+ u8 _txOn, // enable transmitting (and continue if there's data)
+ _txOff, // stop transmitting
+ txFlush, // toss outbound data
+ txBreak, // turn on break (cleared by _txOn)
+ rxOn, // turn on receiver
+ rxOff, // turn off receiver
+ rxFlush, // toss inbound data
+ rxForward, // forward all inbound data, NOW (as if fwdLen==1)
+ returnStatus, // return current status (even if it hasn't changed)
+ resetDataToggle,// reset data toggle state to DATA0
+ enablePort, // start servicing port (move data, check status)
+ disablePort; // stop servicing port (does implicit tx/rx flush/off)
+
+} keyspan_usa49_portControlMessage;
+
+// defines for bits in lcr
+#define USA_DATABITS_5 0x00
+#define USA_DATABITS_6 0x01
+#define USA_DATABITS_7 0x02
+#define USA_DATABITS_8 0x03
+#define STOPBITS_5678_1 0x00 // 1 stop bit for all byte sizes
+#define STOPBITS_5_1p5 0x04 // 1.5 stop bits for 5-bit byte
+#define STOPBITS_678_2 0x04 // 2 stop bits for 6/7/8-bit byte
+#define USA_PARITY_NONE 0x00
+#define USA_PARITY_ODD 0x08
+#define USA_PARITY_EVEN 0x18
+#define PARITY_1 0x28
+#define PARITY_0 0x38
+
+typedef struct keyspan_usa49_globalControlMessage
+{
+ u8 portNumber, // 0x80
+ sendGlobalStatus, // 1/2=number of status responses requested
+ resetStatusToggle, // 1=reset global status toggle
+ resetStatusCount, // a cycling value
+ remoteWakeupEnable; // 0x10=P1, 0x20=P2, 0x40=P3, 0x80=P3
+} keyspan_usa49_globalControlMessage;
+
+/*
+ Device->host messages send on the global status endpoint
+
+ portNumber message
+ ---------- --------------------
+ 0x00,0x01,0x02,0x03 portStatusMessage
+ 0x80 globalStatusMessage
+ 0x81 globalDebugMessage
+*/
+
+typedef struct keyspan_usa49_portStatusMessage // one for each port
+{
+ u8 portNumber, // 0,1,2,3
+ cts, // reports CTS pin
+ dcd, // reports DCD pin
+ dsr, // reports DSR pin
+ ri, // reports RI pin
+ _txOff, // transmit has been disabled (by host)
+ _txXoff, // transmit is in XOFF state (either host or RX XOFF)
+ rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off
+ controlResponse,// 1=a control message has been processed
+ txAck, // ACK (data TX complete)
+ rs232valid; // RS-232 signal valid
+} keyspan_usa49_portStatusMessage;
+
+// bits in RX data message when STAT byte is included
+#define RXERROR_OVERRUN 0x02
+#define RXERROR_PARITY 0x04
+#define RXERROR_FRAMING 0x08
+#define RXERROR_BREAK 0x10
+
+typedef struct keyspan_usa49_globalStatusMessage
+{
+ u8 portNumber, // 0x80=globalStatusMessage
+ sendGlobalStatus, // from request, decremented
+ resetStatusCount; // as in request
+} keyspan_usa49_globalStatusMessage;
+
+typedef struct keyspan_usa49_globalDebugMessage
+{
+ u8 portNumber, // 0x81=globalDebugMessage
+ n, // typically a count/status byte
+ b; // typically a data byte
+} keyspan_usa49_globalDebugMessage;
+
+// ie: the maximum length of an EZUSB endpoint buffer
+#define MAX_DATA_LEN 64
+
+// update status approx. 60 times a second (16.6666 ms)
+#define STATUS_UPDATE_INTERVAL 16
+
+// status rationing tuning value (each port gets checked each n ms)
+#define STATUS_RATION 10
+
+#endif
diff --git a/drivers/usb/serial/keyspan_usa49w_fw.h b/drivers/usb/serial/keyspan_usa49w_fw.h
new file mode 100644
index 000000000..4e01712f1
--- /dev/null
+++ b/drivers/usb/serial/keyspan_usa49w_fw.h
@@ -0,0 +1,457 @@
+/* keyspan_usa49w_fw.h
+
+ Generated from Keyspan firmware image Thu Sep 28 09:13:26 2000 EST
+ This firmware is for the Keyspan USA-49W Serial Adaptor
+
+ "The firmware contained herein as keyspan_usa49w_fw.h is
+ Copyright (C) 1999-2000 Keyspan, A division of InnoSys Incorporated
+ ("Keyspan"), as an unpublished work. This notice does not imply
+ unrestricted or public access to this firmware which is a trade secret of
+ Keyspan, and which may not be reproduced, used, sold or transferred to any
+ third party without Keyspan's prior written consent. All Rights Reserved.
+
+ This firmware may not be modified and may only be used with the Keyspan
+ USA-49W Serial Adapter. Distribution and/or Modification of the
+ keyspan.c driver which includes this firmware, in whole or in part,
+ requires the inclusion of this statement."
+
+*/
+
+static const struct ezusb_hex_record keyspan_usa49w_firmware[] = {
+{ 0x0000, 3, {0x02, 0x10, 0x36} },
+{ 0x0003, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} },
+{ 0x0013, 16, {0x01, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24} },
+{ 0x0023, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} },
+{ 0x0033, 3, {0x02, 0x17, 0xf0} },
+{ 0x0036, 12, {0x90, 0x78, 0x41, 0x74, 0x01, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} },
+{ 0x0043, 3, {0x02, 0x18, 0x00} },
+{ 0x0046, 16, {0xe4, 0xff, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xe0, 0xfe, 0xe5, 0x27} },
+{ 0x0056, 16, {0x24, 0x04, 0xfd, 0xe4, 0x35, 0x26, 0xfa, 0xa9, 0x05, 0x7b, 0x01, 0xef, 0x7c, 0x00, 0x29, 0xf9} },
+{ 0x0066, 16, {0xec, 0x3a, 0xfa, 0xee, 0x12, 0x11, 0x90, 0x0f, 0xbf, 0x22, 0xd7, 0xe5, 0x27, 0x24, 0x05, 0xf5} },
+{ 0x0076, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02, 0x01, 0x4f, 0x7f, 0x01, 0xe5, 0x27} },
+{ 0x0086, 16, {0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x15, 0x3d, 0xe5, 0x27} },
+{ 0x0096, 16, {0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x15, 0x6c, 0xe5, 0x27} },
+{ 0x00a6, 16, {0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x00, 0x03, 0xe5, 0x27} },
+{ 0x00b6, 16, {0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x30, 0xf0, 0x7d, 0x04, 0x44} },
+{ 0x00c6, 16, {0x20, 0xf0, 0xe5, 0x27, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x12} },
+{ 0x00d6, 16, {0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xdf, 0xf0, 0x43} },
+{ 0x00e6, 16, {0x05, 0xc0, 0xe5, 0x27, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x14} },
+{ 0x00f6, 16, {0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xdf, 0xf0, 0x43} },
+{ 0x0106, 16, {0x05, 0x0b, 0x80, 0x03, 0x43, 0x05, 0x02, 0x7f, 0x03, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24, 0x39} },
+{ 0x0116, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x04} },
+{ 0x0126, 16, {0xf0, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00} },
+{ 0x0136, 16, {0xf0, 0x90, 0x78, 0x41, 0x74, 0x02, 0xf0, 0xe5, 0x27, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0146, 16, {0xf5, 0x83, 0xe0, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x0b, 0xf5, 0x82, 0xe4} },
+{ 0x0156, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x32, 0xe5, 0x27, 0x24, 0x0c, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0166, 16, {0xf5, 0x83, 0xe0, 0x54, 0x3f, 0xff, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x0176, 16, {0x83, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4} },
+{ 0x0186, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x0d, 0xf5, 0x82, 0xe4} },
+{ 0x0196, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02, 0x02, 0x6a, 0xe5, 0x27, 0x24, 0x17, 0xf5, 0x82} },
+{ 0x01a6, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x01b6, 16, {0x26, 0xf5, 0x83, 0xe0, 0x44, 0x04, 0xf0, 0x80, 0x0f, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4} },
+{ 0x01c6, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xfb, 0xf0, 0xe4, 0xff, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82} },
+{ 0x01d6, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24, 0x0e, 0xf5, 0x82} },
+{ 0x01e6, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x01f6, 16, {0x26, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x0f, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4} },
+{ 0x0206, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x0216, 16, {0x26, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x27, 0x24, 0x0f, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0226, 16, {0xf5, 0x83, 0xe0, 0x60, 0x2f, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} },
+{ 0x0236, 16, {0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x27, 0x24, 0x10, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x0246, 16, {0xff, 0x12, 0x14, 0xdd, 0xe5, 0x27, 0x24, 0x11, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x0256, 16, {0xff, 0x12, 0x15, 0x0d, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x0266, 16, {0xff, 0x12, 0x14, 0xad, 0xe5, 0x27, 0x24, 0x14, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x0276, 16, {0x60, 0x44, 0xe5, 0x27, 0x24, 0x15, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x11} },
+{ 0x0286, 16, {0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80} },
+{ 0x0296, 16, {0x0f, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xf0} },
+{ 0x02a6, 16, {0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x02b6, 16, {0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x12, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x02c6, 16, {0x83, 0xe0, 0x60, 0x44, 0xe5, 0x27, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x02d6, 16, {0x60, 0x11, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x02} },
+{ 0x02e6, 16, {0xf0, 0x80, 0x0f, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54} },
+{ 0x02f6, 16, {0xfd, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x0306, 16, {0x26, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x16, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x0316, 16, {0x26, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x27, 0x24, 0x35, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} },
+{ 0x0326, 16, {0xef, 0xf0, 0xe5, 0x27, 0x24, 0x17, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30, 0xe0} },
+{ 0x0336, 16, {0x11, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x40, 0xf0} },
+{ 0x0346, 16, {0x80, 0x0f, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xbf} },
+{ 0x0356, 16, {0xf0, 0xe5, 0x27, 0x24, 0x18, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x27} },
+{ 0x0366, 16, {0x24, 0x3b, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x27, 0x24, 0x19, 0xf5} },
+{ 0x0376, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4} },
+{ 0x0386, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0f, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82} },
+{ 0x0396, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0xe5} },
+{ 0x03a6, 16, {0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5} },
+{ 0x03b6, 16, {0x27, 0x24, 0x1a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x6b, 0xe5, 0x27, 0x24} },
+{ 0x03c6, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} },
+{ 0x03d6, 16, {0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f} },
+{ 0x03e6, 16, {0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x01, 0xf0, 0x12, 0x00, 0x36, 0xef, 0x54, 0xfe} },
+{ 0x03f6, 16, {0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x0406, 16, {0x54, 0xfd, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24, 0x2c, 0xf5, 0x82} },
+{ 0x0416, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x27, 0x24, 0x2b, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0426, 16, {0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x28, 0x42, 0x25, 0xe5, 0x27, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x0436, 16, {0x26, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x27, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x0446, 16, {0x83, 0xe0, 0x60, 0x28, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x0456, 16, {0x44, 0x02, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24, 0x2b, 0xf5, 0x82} },
+{ 0x0466, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x28, 0x42, 0x25, 0xe5, 0x27, 0x24, 0x1c} },
+{ 0x0476, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x27, 0x24, 0x25, 0xf5, 0x82} },
+{ 0x0486, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x2c, 0x90, 0x78, 0x41, 0x74, 0x02, 0xf0, 0xe5, 0x27} },
+{ 0x0496, 16, {0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x04, 0x90, 0xc0, 0x00, 0xf0} },
+{ 0x04a6, 16, {0xe4, 0xff, 0x12, 0x14, 0x0c, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} },
+{ 0x04b6, 16, {0xe0, 0x54, 0x7f, 0xf0, 0xe5, 0x27, 0x24, 0x1d, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x04c6, 16, {0x60, 0x27, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x40} },
+{ 0x04d6, 16, {0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x04e6, 16, {0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x1e, 0xf5, 0x82, 0xe4} },
+{ 0x04f6, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x28, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0506, 16, {0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24} },
+{ 0x0516, 16, {0x2d, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x28, 0x42, 0x25, 0xe5} },
+{ 0x0526, 16, {0x27, 0x24, 0x1f, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x27, 0x24} },
+{ 0x0536, 16, {0x25, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x27, 0xe5, 0x27, 0x24, 0x32, 0xf5} },
+{ 0x0546, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x15} },
+{ 0x0556, 16, {0x3d, 0xe5, 0x27, 0x24, 0x2d, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x28} },
+{ 0x0566, 16, {0x42, 0x25, 0xe5, 0x27, 0x24, 0x20, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x0e} },
+{ 0x0576, 16, {0xe5, 0x27, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x18, 0x90, 0x78} },
+{ 0x0586, 16, {0x41, 0x74, 0x02, 0xf0, 0xe5, 0x27, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x0596, 16, {0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x21, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x05a6, 16, {0x83, 0xe0, 0x60, 0x0f, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x05b6, 16, {0x44, 0x02, 0xf0, 0xe5, 0x27, 0x24, 0x22, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60} },
+{ 0x05c6, 16, {0x1f, 0xe5, 0x27, 0x24, 0x2e, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5} },
+{ 0x05d6, 16, {0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x28, 0x42, 0x25} },
+{ 0x05e6, 16, {0xe5, 0x27, 0x24, 0x23, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0x12, 0x17} },
+{ 0x05f6, 16, {0x4e, 0xe5, 0x27, 0x24, 0x24, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x1b, 0xe5} },
+{ 0x0606, 16, {0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x90, 0x7f} },
+{ 0x0616, 16, {0x98, 0xe0, 0xff, 0xe5, 0x28, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0xe5, 0x27, 0x24, 0x25, 0xf5, 0x82} },
+{ 0x0626, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x16, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x0636, 14, {0x26, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x7f, 0x98, 0xe0, 0x45, 0x28, 0xf0} },
+{ 0x0644, 1, {0x22} },
+{ 0x0645, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x11, 0xa2, 0x07, 0x42, 0x00, 0x07, 0xb6, 0x01, 0x08, 0x22, 0x03} },
+{ 0x0655, 16, {0x06, 0x68, 0x06, 0x07, 0x35, 0x08, 0x07, 0x2f, 0x09, 0x07, 0x17, 0x0a, 0x07, 0x26, 0x0b, 0x00} },
+{ 0x0665, 16, {0x00, 0x08, 0x71, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x19, 0x14, 0x60, 0x77, 0x24, 0x02} },
+{ 0x0675, 16, {0x60, 0x03, 0x02, 0x07, 0x0d, 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5} },
+{ 0x0685, 16, {0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xea, 0xe0, 0x04, 0x75, 0x82, 0x17, 0x75, 0x83, 0x19, 0xf0} },
+{ 0x0695, 16, {0x90, 0x7f, 0xea, 0xe0, 0x30, 0xe0, 0x04, 0x7f, 0x03, 0x80, 0x02, 0x7f, 0x02, 0x75, 0x82, 0x82} },
+{ 0x06a5, 16, {0x75, 0x83, 0x19, 0xef, 0xf0, 0x75, 0x82, 0x6d, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, 0x66, 0x75} },
+{ 0x06b5, 16, {0x83, 0x19, 0xf0, 0x75, 0x82, 0x5f, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, 0x58, 0x75, 0x83, 0x19} },
+{ 0x06c5, 16, {0xf0, 0x90, 0x7f, 0xea, 0xe0, 0x30, 0xe1, 0x04, 0x7f, 0x64, 0x80, 0x02, 0x7f, 0x32, 0x75, 0x82} },
+{ 0x06d5, 16, {0x1a, 0x75, 0x83, 0x19, 0xef, 0xf0, 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x12, 0x90, 0x7f} },
+{ 0x06e5, 16, {0xd5, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x13, 0x54, 0xea, 0x49, 0x60} },
+{ 0x06f5, 16, {0x0d, 0xea, 0x90, 0x7f, 0xd4, 0xf0, 0xe9, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f} },
+{ 0x0705, 16, {0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02} },
+{ 0x0715, 16, {0x08, 0x78, 0x90, 0x7f, 0x00, 0xe5, 0x0a, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x08} },
+{ 0x0725, 16, {0x78, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0a, 0x02, 0x08, 0x78, 0x12, 0x0a, 0x6a, 0x02, 0x08, 0x78} },
+{ 0x0735, 16, {0x90, 0x7f, 0x00, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xe8} },
+{ 0x0745, 16, {0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2, 0x00, 0xe4, 0x33} },
+{ 0x0755, 16, {0xff, 0x25, 0xe0, 0xff, 0xa2, 0x06, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0} },
+{ 0x0765, 16, {0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0x78, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0} },
+{ 0x0775, 16, {0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80} },
+{ 0x0785, 16, {0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4} },
+{ 0x0795, 16, {0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f} },
+{ 0x07a5, 16, {0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08} },
+{ 0x07b5, 16, {0x78, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x08, 0x78} },
+{ 0x07c5, 16, {0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xb4, 0xe0} },
+{ 0x07d5, 16, {0x44, 0x01, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0} },
+{ 0x07e5, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} },
+{ 0x07f5, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff} },
+{ 0x0805, 16, {0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44} },
+{ 0x0815, 16, {0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x56, 0x90, 0x7f, 0xe8} },
+{ 0x0825, 16, {0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} },
+{ 0x0835, 16, {0xd2, 0x00, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x36, 0x90, 0x7f, 0xea} },
+{ 0x0845, 16, {0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} },
+{ 0x0855, 16, {0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} },
+{ 0x0865, 16, {0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0} },
+{ 0x0875, 10, {0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} },
+{ 0x087f, 1, {0x22} },
+{ 0x0880, 16, {0xe5, 0x23, 0x54, 0x0f, 0x70, 0x03, 0x02, 0x09, 0x5f, 0x12, 0x15, 0x9b, 0xef, 0x20, 0xe1, 0x63} },
+{ 0x0890, 16, {0x12, 0x15, 0xf9, 0xef, 0x14, 0xf5, 0x1a, 0x12, 0x17, 0xc1, 0xef, 0x25, 0x1a, 0xff, 0xe4, 0x33} },
+{ 0x08a0, 16, {0xfe, 0xc3, 0xef, 0x94, 0x80, 0xee, 0x64, 0x80, 0x94, 0x80, 0x50, 0x47, 0x85, 0x27, 0x82, 0x85} },
+{ 0x08b0, 16, {0x26, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x30, 0xe0, 0x11, 0xe5} },
+{ 0x08c0, 16, {0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x0f} },
+{ 0x08d0, 16, {0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0x85} },
+{ 0x08e0, 16, {0x1a, 0x08, 0xef, 0x24, 0x01, 0xf5, 0x10, 0xe4, 0x3e, 0xf5, 0x0f, 0x12, 0x13, 0xd6, 0xe4, 0xff} },
+{ 0x08f0, 16, {0x12, 0x14, 0x0c, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30} },
+{ 0x0900, 16, {0xe7, 0x5d, 0x12, 0x17, 0xc1, 0xe5, 0x27, 0x24, 0x3b, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} },
+{ 0x0910, 16, {0xe0, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x48, 0xe5, 0x27, 0x24, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0920, 16, {0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} },
+{ 0x0930, 16, {0xe0, 0x54, 0x7f, 0xf0, 0xe5, 0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4} },
+{ 0x0940, 16, {0xf0, 0xe5, 0x28, 0x42, 0x25, 0x90, 0x7f, 0xc2, 0xe0, 0x30, 0xe1, 0x10, 0xe5, 0x27, 0x24, 0x26} },
+{ 0x0950, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xf5, 0x09, 0x80, 0x03, 0x12, 0x12, 0x3d, 0x12} },
+{ 0x0960, 16, {0x15, 0xca, 0xef, 0x30, 0xe1, 0x03, 0x02, 0x0a, 0x69, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4} },
+{ 0x0970, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x80, 0xf0, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x0980, 16, {0x26, 0xf5, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfe, 0x12, 0x17, 0xcd, 0xee, 0x4f, 0xd0, 0x82} },
+{ 0x0990, 16, {0xd0, 0x83, 0xf0, 0x12, 0x16, 0xd1, 0x8f, 0x1a, 0xe5, 0x27, 0x24, 0x35, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x09a0, 16, {0x26, 0xf5, 0x83, 0xe0, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x28, 0x12, 0x17, 0xa9, 0xef, 0x30, 0xe0} },
+{ 0x09b0, 16, {0x21, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x20, 0xe7, 0x12} },
+{ 0x09c0, 16, {0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x20, 0xe1, 0x03, 0x02} },
+{ 0x09d0, 16, {0x0a, 0x69, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xfd} },
+{ 0x09e0, 16, {0xf0, 0xe5, 0x1a, 0x70, 0x0e, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} },
+{ 0x09f0, 16, {0xe4, 0xf0, 0x22, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff} },
+{ 0x0a00, 16, {0x30, 0xe7, 0x29, 0xe5, 0x1a, 0xd3, 0x94, 0x20, 0x40, 0x03, 0x75, 0x1a, 0x20, 0x85, 0x1a, 0x08} },
+{ 0x0a10, 16, {0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0x8c, 0x0f, 0xf5, 0x10} },
+{ 0x0a20, 16, {0x12, 0x13, 0x06, 0xe5, 0x1a, 0x25, 0xe0, 0xff, 0x12, 0x14, 0x42, 0x22, 0xe5, 0x1a, 0xd3, 0x94} },
+{ 0x0a30, 16, {0x3f, 0x40, 0x03, 0x75, 0x1a, 0x3f, 0x85, 0x1a, 0x08, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0xa3} },
+{ 0x0a40, 16, {0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x85, 0x27, 0x82, 0x85, 0x26} },
+{ 0x0a50, 16, {0x83, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0x24, 0x01, 0xf5, 0x10, 0xe4, 0x3e, 0xf5, 0x0f, 0x12} },
+{ 0x0a60, 9, {0x13, 0x95, 0xe5, 0x1a, 0x04, 0xff, 0x12, 0x14, 0x42} },
+{ 0x0a69, 1, {0x22} },
+{ 0x0a6a, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xf0, 0xf0, 0x90, 0x7f, 0x96, 0xf0, 0xe4} },
+{ 0x0a7a, 16, {0x90, 0x7f, 0x94, 0xf0, 0x90, 0x78, 0x4a, 0x04, 0xf0, 0xf5, 0x8e, 0x90, 0x7f, 0x95, 0x74, 0xc0} },
+{ 0x0a8a, 16, {0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x1f, 0xf0, 0x90, 0x78, 0x43} },
+{ 0x0a9a, 16, {0x74, 0xff, 0xf0, 0xe4, 0x90, 0x78, 0x41, 0xf0, 0x90, 0x7f, 0xdf, 0x74, 0x9f, 0xf0, 0x90, 0x7f} },
+{ 0x0aaa, 16, {0xde, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0x44, 0x02, 0xf0, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b} },
+{ 0x0aba, 16, {0x75, 0x27, 0xc0, 0x90, 0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75, 0x28, 0x01, 0x12, 0x0e, 0xb3, 0x7e} },
+{ 0x0aca, 16, {0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b, 0x75, 0x27, 0xc0, 0x90, 0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75} },
+{ 0x0ada, 16, {0x28, 0x01, 0xe5, 0x27, 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0, 0x7e} },
+{ 0x0aea, 16, {0x7e, 0x7f, 0x40, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0x74, 0x7e, 0xf0, 0xa3, 0x74, 0x40, 0xf0} },
+{ 0x0afa, 16, {0x7e, 0x7e, 0x7f, 0x80, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0xa3, 0xa3, 0x74, 0x7e, 0xf0, 0xa3} },
+{ 0x0b0a, 16, {0x74, 0x80, 0xf0, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x00, 0x90, 0x7f, 0x96} },
+{ 0x0b1a, 16, {0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0x12, 0x0e, 0xb3, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c} },
+{ 0x0b2a, 16, {0x75, 0x27, 0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0xe5, 0x27, 0x24, 0x26} },
+{ 0x0b3a, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x7e, 0x7d, 0x7f, 0xc0, 0x85, 0x27} },
+{ 0x0b4a, 16, {0x82, 0x85, 0x26, 0x83, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0xc0, 0xf0, 0x7e, 0x7e, 0x7f, 0x00, 0x85} },
+{ 0x0b5a, 16, {0x27, 0x82, 0x85, 0x26, 0x83, 0xa3, 0xa3, 0x74, 0x7e, 0xf0, 0xa3, 0x74, 0x00, 0xf0, 0x7e, 0x7c} },
+{ 0x0b6a, 16, {0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f, 0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28} },
+{ 0x0b7a, 16, {0x04, 0x12, 0x0e, 0xb3, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f} },
+{ 0x0b8a, 16, {0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28, 0x04, 0xe5, 0x27, 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0b9a, 16, {0xf5, 0x83, 0x74, 0x02, 0xf0, 0x7e, 0x7d, 0x7f, 0x40, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0x74} },
+{ 0x0baa, 16, {0x7d, 0xf0, 0xa3, 0x74, 0x40, 0xf0, 0x7e, 0x7d, 0x7f, 0x80, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83} },
+{ 0x0bba, 16, {0xa3, 0xa3, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0x80, 0xf0, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c} },
+{ 0x0bca, 16, {0x75, 0x27, 0x80, 0x90, 0x7f, 0x96, 0x74, 0x7f, 0xf0, 0x75, 0x28, 0x08, 0x12, 0x0e, 0xb3, 0x7e} },
+{ 0x0bda, 16, {0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x80, 0x90, 0x7f, 0x96, 0x74, 0x7f, 0xf0, 0x75} },
+{ 0x0bea, 16, {0x28, 0x08, 0xe5, 0x27, 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x03, 0xf0} },
+{ 0x0bfa, 16, {0x7e, 0x7c, 0x7f, 0xc0, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0x74, 0x7c, 0xf0, 0xa3, 0x74, 0xc0} },
+{ 0x0c0a, 16, {0xf0, 0x7e, 0x7d, 0x7f, 0x00, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0xa3, 0xa3, 0x74, 0x7d, 0xf0} },
+{ 0x0c1a, 7, {0xa3, 0x74, 0x00, 0xf0, 0xd2, 0x02, 0x22} },
+{ 0x0c21, 16, {0xe5, 0x22, 0x04, 0x54, 0x03, 0xf5, 0x22, 0x14, 0x60, 0x1f, 0x14, 0x60, 0x31, 0x14, 0x60, 0x43} },
+{ 0x0c31, 16, {0x24, 0x03, 0x70, 0x52, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b, 0x75, 0x27, 0xc0, 0x90, 0x7f} },
+{ 0x0c41, 16, {0x96, 0x74, 0xef, 0xf0, 0x75, 0x28, 0x01, 0x80, 0x3d, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c} },
+{ 0x0c51, 16, {0x75, 0x27, 0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0x80, 0x28, 0x7e, 0x7c} },
+{ 0x0c61, 16, {0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f, 0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28} },
+{ 0x0c71, 16, {0x04, 0x80, 0x13, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x80, 0x90, 0x7f, 0x96} },
+{ 0x0c81, 16, {0x74, 0x7f, 0xf0, 0x75, 0x28, 0x08, 0xe5, 0x15, 0x55, 0x28, 0x70, 0x03, 0x02, 0x0d, 0xbf, 0xe5} },
+{ 0x0c91, 16, {0x28, 0xf4, 0xff, 0x52, 0x15, 0xe5, 0x0b, 0x54, 0x7f, 0xfe, 0x70, 0x0f, 0xe5, 0x0d, 0x55, 0x28} },
+{ 0x0ca1, 16, {0x60, 0x24, 0x90, 0x7f, 0x98, 0xe0, 0x45, 0x28, 0xf0, 0x80, 0x1b, 0xbe, 0x20, 0x18, 0xe5, 0x27} },
+{ 0x0cb1, 16, {0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30, 0xe3, 0x09, 0xe4, 0xf5, 0x0d} },
+{ 0x0cc1, 16, {0x90, 0x7f, 0x98, 0xe0, 0x5f, 0xf0, 0xe5, 0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x0cd1, 16, {0x83, 0xe0, 0x60, 0x03, 0xe0, 0x14, 0xf0, 0xe5, 0x27, 0x24, 0x34, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0ce1, 16, {0xf5, 0x83, 0xe0, 0x60, 0x03, 0xe0, 0x14, 0xf0, 0xe0, 0x60, 0x03, 0x02, 0x0d, 0xbf, 0x74, 0x0a} },
+{ 0x0cf1, 16, {0xf0, 0x12, 0x00, 0x36, 0xef, 0x54, 0x01, 0xff, 0xf5, 0x1a, 0xe5, 0x27, 0x24, 0x2c, 0xf5, 0x82} },
+{ 0x0d01, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x6f, 0x60, 0x07, 0xe5, 0x1a, 0xf0, 0xe5, 0x28, 0x42, 0x25} },
+{ 0x0d11, 16, {0x12, 0x17, 0xd9, 0x8f, 0x1a, 0xe5, 0x27, 0x24, 0x27, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} },
+{ 0x0d21, 16, {0xe0, 0xff, 0xe5, 0x1a, 0x54, 0x10, 0xfe, 0x6f, 0x60, 0x06, 0xee, 0xf0, 0xe5, 0x28, 0x42, 0x25} },
+{ 0x0d31, 16, {0xe5, 0x27, 0x24, 0x28, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x1a, 0x54} },
+{ 0x0d41, 16, {0x80, 0xfe, 0x6f, 0x60, 0x06, 0xee, 0xf0, 0xe5, 0x28, 0x42, 0x25, 0xe5, 0x27, 0x24, 0x29, 0xf5} },
+{ 0x0d51, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x1a, 0x54, 0x20, 0xfe, 0x6f, 0x60, 0x15} },
+{ 0x0d61, 16, {0xee, 0xf0, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30, 0xe4} },
+{ 0x0d71, 16, {0x04, 0xe5, 0x28, 0x42, 0x25, 0xe5, 0x24, 0x55, 0x28, 0xff, 0xf5, 0x1a, 0xe5, 0x27, 0x24, 0x2a} },
+{ 0x0d81, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x6f, 0x60, 0x16, 0xe5, 0x1a, 0xf0, 0xe5, 0x27} },
+{ 0x0d91, 16, {0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30, 0xe5, 0x04, 0xe5, 0x28, 0x42} },
+{ 0x0da1, 16, {0x25, 0xe5, 0x29, 0x55, 0x28, 0xff, 0xf5, 0x1a, 0xe5, 0x27, 0x24, 0x30, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x0db1, 14, {0x26, 0xf5, 0x83, 0xe0, 0x6f, 0x60, 0x07, 0xe5, 0x1a, 0xf0, 0xe5, 0x28, 0x42, 0x25} },
+{ 0x0dbf, 1, {0x22} },
+{ 0x0dc0, 16, {0xe5, 0x09, 0x14, 0x60, 0x2a, 0x14, 0x60, 0x41, 0x14, 0x60, 0x58, 0x14, 0x60, 0x6f, 0x24, 0x04} },
+{ 0x0dd0, 16, {0x60, 0x03, 0x02, 0x0e, 0x77, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b, 0x75, 0x27, 0xc0, 0x90} },
+{ 0x0de0, 16, {0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75, 0x28, 0x01, 0x12, 0x12, 0x3d, 0x75, 0x09, 0x01, 0x22, 0x7e} },
+{ 0x0df0, 16, {0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75} },
+{ 0x0e00, 16, {0x28, 0x02, 0x12, 0x12, 0x3d, 0x75, 0x09, 0x02, 0x22, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x26, 0x7c} },
+{ 0x0e10, 16, {0x75, 0x27, 0x40, 0x90, 0x7f, 0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28, 0x04, 0x12, 0x12, 0x3d, 0x75} },
+{ 0x0e20, 16, {0x09, 0x03, 0x22, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x80, 0x90, 0x7f, 0x96} },
+{ 0x0e30, 16, {0x74, 0x7f, 0xf0, 0x75, 0x28, 0x08, 0x12, 0x12, 0x3d, 0x75, 0x09, 0x04, 0x22, 0x30, 0x04, 0x33} },
+{ 0x0e40, 16, {0xc2, 0x04, 0x53, 0x25, 0xdf, 0xe4, 0xf5, 0x1a, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x11, 0x25, 0x1a} },
+{ 0x0e50, 16, {0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x11, 0x4a, 0xff, 0x74, 0x80, 0x25, 0x1a, 0xf5, 0x82, 0xe4} },
+{ 0x0e60, 16, {0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x1a, 0xe5, 0x1a, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3} },
+{ 0x0e70, 16, {0x74, 0x03, 0xf0, 0x75, 0x09, 0x05, 0x22, 0xe5, 0x17, 0x60, 0x34, 0xd5, 0x17, 0x03, 0x53, 0x25} },
+{ 0x0e80, 16, {0xef, 0xe4, 0xf5, 0x1a, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x16, 0x25, 0x1a, 0xf9, 0xee, 0x34, 0x00} },
+{ 0x0e90, 16, {0xfa, 0x12, 0x11, 0x4a, 0xff, 0x74, 0x80, 0x25, 0x1a, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83} },
+{ 0x0ea0, 16, {0xef, 0xf0, 0x05, 0x1a, 0xe5, 0x1a, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0xe4} },
+{ 0x0eb0, 2, {0xf5, 0x09} },
+{ 0x0eb2, 1, {0x22} },
+{ 0x0eb3, 16, {0xe4, 0xf5, 0x19, 0x7e, 0x00, 0x7b, 0x01, 0xe5, 0x27, 0x25, 0x19, 0xf9, 0xee, 0x35, 0x26, 0xfa} },
+{ 0x0ec3, 16, {0xe4, 0x12, 0x11, 0x90, 0x05, 0x19, 0xe5, 0x19, 0xb4, 0x3c, 0xe8, 0xe5, 0x27, 0x24, 0x35, 0xf5} },
+{ 0x0ed3, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5} },
+{ 0x0ee3, 16, {0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00} },
+{ 0x0ef3, 16, {0xf0, 0x7f, 0x0c, 0xe4, 0xfd, 0x12, 0x15, 0x3d, 0x7f, 0x10, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82} },
+{ 0x0f03, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x14, 0xad, 0x90, 0x78, 0x41, 0x74, 0x02, 0xf0} },
+{ 0x0f13, 16, {0x7f, 0x01, 0xe5, 0x27, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xef, 0xf0, 0x44} },
+{ 0x0f23, 16, {0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0xe5, 0x27, 0x24, 0x39, 0xf5} },
+{ 0x0f33, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x90, 0xc0, 0x00, 0xf0, 0x0f, 0xe4, 0xfd} },
+{ 0x0f43, 16, {0x12, 0x15, 0x3d, 0xe4, 0xff, 0x7e, 0xa3, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26} },
+{ 0x0f53, 16, {0xf5, 0x83, 0xee, 0xf0, 0xfd, 0x12, 0x15, 0x3d, 0x90, 0x78, 0x41, 0x74, 0x01, 0xf0, 0x90, 0xc0} },
+{ 0x0f63, 16, {0x00, 0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f, 0x12, 0x15, 0x3d, 0x7f, 0x01, 0x12, 0x14, 0x78, 0x7f} },
+{ 0x0f73, 6, {0x03, 0x7d, 0x07, 0x12, 0x15, 0x3d} },
+{ 0x0f79, 1, {0x22} },
+{ 0x0f7a, 16, {0x53, 0x25, 0x3f, 0x90, 0x7b, 0xf1, 0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x26} },
+{ 0x0f8a, 16, {0x7b, 0x75, 0x27, 0xc0, 0x90, 0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75, 0x28, 0x01, 0x12, 0x08, 0x80} },
+{ 0x0f9a, 16, {0x90, 0x7c, 0x31, 0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c, 0x75, 0x27} },
+{ 0x0faa, 16, {0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0x12, 0x08, 0x80, 0x90, 0x7c, 0x71} },
+{ 0x0fba, 16, {0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f} },
+{ 0x0fca, 16, {0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28, 0x04, 0x12, 0x08, 0x80, 0x90, 0x7c, 0xb1, 0xe0, 0x30, 0xe3} },
+{ 0x0fda, 16, {0x16, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x80, 0x90, 0x7f, 0x96, 0x74, 0x7f} },
+{ 0x0fea, 16, {0xf0, 0x75, 0x28, 0x08, 0x12, 0x08, 0x80, 0x05, 0x23, 0xe5, 0x23, 0x54, 0x0f, 0xf5, 0x19, 0x70} },
+{ 0x0ffa, 16, {0x1f, 0x90, 0x78, 0x41, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x7f, 0x99, 0xe0, 0xf5, 0x29, 0x90, 0x78} },
+{ 0x100a, 16, {0x41, 0xe0, 0x44, 0x08, 0xf0, 0x90, 0x7f, 0x99, 0xe0, 0xf4, 0xf5, 0x24, 0x12, 0x10, 0xc2, 0x22} },
+{ 0x101a, 16, {0xe5, 0x19, 0xb4, 0x01, 0x04, 0x12, 0x0c, 0x21, 0x22, 0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x08} },
+{ 0x102a, 11, {0xe5, 0x25, 0x60, 0x04, 0x12, 0x0d, 0xc0, 0x22, 0x12, 0x0c, 0x21} },
+{ 0x1035, 1, {0x22} },
+{ 0x1036, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x29, 0x02, 0x10, 0x7d} },
+{ 0x1042, 16, {0x02, 0x11, 0xc8, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
+{ 0x1052, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
+{ 0x1062, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
+{ 0x1072, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x17, 0x67, 0xe4, 0x7e} },
+{ 0x1082, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
+{ 0x1092, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
+{ 0x10a2, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
+{ 0x10b2, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
+{ 0x10c2, 16, {0x90, 0x7f, 0xd2, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x11, 0x49, 0x90, 0x7b, 0x40, 0xe0, 0x14, 0x60} },
+{ 0x10d2, 16, {0x26, 0x14, 0x60, 0x3b, 0x14, 0x60, 0x50, 0x24, 0x83, 0x60, 0x64, 0x24, 0x80, 0x70, 0x63, 0x7e} },
+{ 0x10e2, 16, {0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b, 0x75, 0x27, 0xc0, 0x90, 0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75} },
+{ 0x10f2, 16, {0x28, 0x01, 0x12, 0x00, 0x46, 0x80, 0x4b, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c, 0x75, 0x27} },
+{ 0x1102, 16, {0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0x12, 0x00, 0x46, 0x80, 0x33, 0x7e} },
+{ 0x1112, 16, {0x7c, 0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f, 0x96, 0x74, 0xbf, 0xf0, 0x75} },
+{ 0x1122, 16, {0x28, 0x04, 0x12, 0x00, 0x46, 0x80, 0x1b, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27} },
+{ 0x1132, 16, {0x80, 0x90, 0x7f, 0x96, 0x74, 0x7f, 0xf0, 0x75, 0x28, 0x08, 0x12, 0x00, 0x46, 0x80, 0x03, 0x12} },
+{ 0x1142, 8, {0x16, 0x56, 0xe4, 0x90, 0x7f, 0xd3, 0xf0, 0x22} },
+{ 0x114a, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
+{ 0x115a, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x1163, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
+{ 0x1173, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
+{ 0x1183, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x1190, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01} },
+{ 0x11a0, 2, {0xf3, 0x22} },
+{ 0x11a2, 16, {0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3} },
+{ 0x11b2, 16, {0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60} },
+{ 0x11c2, 6, {0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf} },
+{ 0x11c8, 16, {0x90, 0x7f, 0xae, 0xe0, 0xff, 0xd3, 0x92, 0x00, 0xe4, 0x33, 0xfe, 0xef, 0x4e, 0xf0, 0xd2, 0xe8} },
+{ 0x11d8, 16, {0x43, 0xd8, 0x20, 0x90, 0x7f, 0xde, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab} },
+{ 0x11e8, 16, {0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x11f8, 16, {0xaf, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0x74, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0x09, 0x12, 0x17} },
+{ 0x1208, 16, {0x13, 0xc2, 0x01, 0xe4, 0xf5, 0x0e, 0xf5, 0x14, 0xc2, 0x07, 0xc2, 0x02, 0x90, 0x7f, 0xd8, 0xe0} },
+{ 0x1218, 16, {0x65, 0x0b, 0x60, 0x06, 0x75, 0x15, 0x0f, 0xe0, 0xf5, 0x0b, 0x30, 0x02, 0x03, 0x12, 0x0f, 0x7a} },
+{ 0x1228, 16, {0x30, 0x01, 0x07, 0xc2, 0x01, 0x12, 0x06, 0x45, 0x80, 0xe2, 0x30, 0x08, 0xdf, 0xc2, 0x08, 0x12} },
+{ 0x1238, 5, {0x17, 0x95, 0x80, 0xd8, 0x22} },
+{ 0x123d, 16, {0xe5, 0x25, 0x55, 0x28, 0x60, 0x6a, 0xe5, 0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x124d, 16, {0x83, 0xe0, 0x70, 0x5c, 0xe5, 0x28, 0xf4, 0x52, 0x25, 0xe5, 0x27, 0x24, 0x26, 0xff, 0xe4, 0x35} },
+{ 0x125d, 16, {0x26, 0xfe, 0xe4, 0xfd, 0x0f, 0xef, 0xaa, 0x06, 0x70, 0x01, 0x0e, 0x14, 0xf5, 0x82, 0x8a, 0x83} },
+{ 0x126d, 16, {0xe0, 0xfc, 0x74, 0x80, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xec, 0xf0, 0x0d, 0xbd} },
+{ 0x127d, 16, {0x0b, 0xe2, 0x90, 0x7f, 0xc3, 0x74, 0x0b, 0xf0, 0xe5, 0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x128d, 16, {0x26, 0xf5, 0x83, 0x74, 0x10, 0xf0, 0xe5, 0x27, 0x24, 0x2e, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x129d, 16, {0x83, 0xe4, 0xf0, 0xe5, 0x27, 0x24, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0} },
+{ 0x12ad, 1, {0x22} },
+{ 0x12ae, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xf0, 0xf0, 0x90, 0x7f, 0x96, 0xf0, 0xe4} },
+{ 0x12be, 16, {0x90, 0x78, 0x4a, 0xf0, 0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0xe4, 0x90} },
+{ 0x12ce, 16, {0x7f, 0x97, 0xf0, 0xe5, 0x0c, 0x54, 0xf0, 0x44, 0x08, 0x90, 0x78, 0x41, 0xf0, 0xe4, 0x90, 0x7f} },
+{ 0x12de, 16, {0x98, 0xf0, 0x90, 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x98} },
+{ 0x12ee, 16, {0xf0, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xf0, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0} },
+{ 0x12fe, 8, {0x90, 0x7f, 0x92, 0xe0, 0x54, 0xfd, 0xf0, 0x22} },
+{ 0x1306, 16, {0x8f, 0x1b, 0x05, 0x10, 0xe5, 0x10, 0xae, 0x0f, 0x70, 0x02, 0x05, 0x0f, 0x14, 0xf5, 0x82, 0x8e} },
+{ 0x1316, 16, {0x83, 0xe5, 0x1b, 0xf0, 0x12, 0x17, 0xe5, 0x05, 0x10, 0xe5, 0x10, 0xac, 0x0f, 0x70, 0x02, 0x05} },
+{ 0x1326, 16, {0x0f, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x15, 0x08, 0xe5, 0x08, 0x60, 0x1f, 0xe5, 0x27} },
+{ 0x1336, 16, {0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfe, 0x12} },
+{ 0x1346, 14, {0x17, 0xcd, 0x8f, 0x1b, 0xee, 0x4f, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x80, 0xb5, 0x22} },
+{ 0x1354, 2, {0x8f, 0x19} },
+{ 0x1356, 16, {0xe4, 0xf5, 0x1a, 0x75, 0x1b, 0xff, 0x75, 0x1c, 0x19, 0x75, 0x1d, 0x86, 0xab, 0x1b, 0xaa, 0x1c} },
+{ 0x1366, 16, {0xa9, 0x1d, 0x90, 0x00, 0x01, 0x12, 0x11, 0x63, 0xb4, 0x03, 0x1d, 0xaf, 0x1a, 0x05, 0x1a, 0xef} },
+{ 0x1376, 16, {0xb5, 0x19, 0x01, 0x22, 0x12, 0x11, 0x4a, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
+{ 0x1386, 14, {0x1b, 0xff, 0xf5, 0x1c, 0x89, 0x1d, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x1394, 1, {0x22} },
+{ 0x1395, 16, {0xe4, 0x90, 0x78, 0x41, 0xf0, 0x90, 0x78, 0x4f, 0x74, 0xc0, 0xf0, 0xe4, 0x90, 0x78, 0x50, 0xf0} },
+{ 0x13a5, 16, {0xe5, 0x0f, 0x90, 0x78, 0x51, 0xf0, 0xae, 0x0f, 0xe5, 0x10, 0x90, 0x78, 0x52, 0xf0, 0x90, 0x78} },
+{ 0x13b5, 16, {0x54, 0xe5, 0x08, 0xf0, 0x90, 0x78, 0x57, 0x74, 0x04, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x10} },
+{ 0x13c5, 16, {0xf0, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0x90, 0x78, 0x55, 0xf0, 0x90, 0x78, 0x55, 0xe0, 0x60, 0xfa} },
+{ 0x13d5, 1, {0x22} },
+{ 0x13d6, 16, {0xe4, 0x90, 0x78, 0x41, 0xf0, 0xe5, 0x0f, 0x90, 0x78, 0x4f, 0xf0, 0xae, 0x0f, 0xe5, 0x10, 0x90} },
+{ 0x13e6, 16, {0x78, 0x50, 0xf0, 0x90, 0x78, 0x51, 0x74, 0xc0, 0xf0, 0xe4, 0x90, 0x78, 0x52, 0xf0, 0x90, 0x78} },
+{ 0x13f6, 16, {0x54, 0xe5, 0x08, 0xf0, 0x90, 0x78, 0x57, 0x74, 0x04, 0xf0, 0xe4, 0x90, 0x78, 0x55, 0xf0, 0x90} },
+{ 0x1406, 6, {0x78, 0x55, 0xe0, 0x60, 0xfa, 0x22} },
+{ 0x140c, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0f, 0x14} },
+{ 0x141c, 16, {0x60, 0x13, 0x14, 0x60, 0x17, 0x80, 0x00, 0x90, 0x7f, 0xc7, 0xef, 0xf0, 0x80, 0x13, 0x90, 0x7f} },
+{ 0x142c, 16, {0xc9, 0xef, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xcb, 0xef, 0xf0, 0x80, 0x05, 0x90, 0x7f, 0xcd, 0xef} },
+{ 0x143c, 6, {0xf0, 0xe5, 0x28, 0x42, 0x0d, 0x22} },
+{ 0x1442, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0f, 0x14} },
+{ 0x1452, 16, {0x60, 0x13, 0x14, 0x60, 0x17, 0x80, 0x00, 0x90, 0x7f, 0xb7, 0xef, 0xf0, 0x80, 0x13, 0x90, 0x7f} },
+{ 0x1462, 16, {0xb9, 0xef, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xbb, 0xef, 0xf0, 0x80, 0x05, 0x90, 0x7f, 0xbd, 0xef} },
+{ 0x1472, 6, {0xf0, 0xe5, 0x28, 0x42, 0x0d, 0x22} },
+{ 0x1478, 16, {0xae, 0x07, 0xe4, 0xff, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} },
+{ 0x1488, 16, {0x54, 0x7f, 0xfd, 0x12, 0x15, 0x3d, 0x90, 0x78, 0x41, 0x74, 0x01, 0xf0, 0x90, 0xc0, 0x00, 0xee} },
+{ 0x1498, 16, {0xf0, 0xe4, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x80} },
+{ 0x14a8, 5, {0xfd, 0x12, 0x15, 0x3d, 0x22} },
+{ 0x14ad, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} },
+{ 0x14bd, 16, {0x02, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24} },
+{ 0x14cd, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} },
+{ 0x14dd, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} },
+{ 0x14ed, 16, {0x04, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24} },
+{ 0x14fd, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} },
+{ 0x150d, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} },
+{ 0x151d, 16, {0x06, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24} },
+{ 0x152d, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} },
+{ 0x153d, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} },
+{ 0x154d, 16, {0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x07, 0xf0, 0x90, 0xc0} },
+{ 0x155d, 15, {0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x05, 0xf0, 0x90, 0xc0, 0x00, 0xed, 0xf0, 0x22} },
+{ 0x156c, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0xe4, 0x90, 0x78, 0x41} },
+{ 0x157c, 16, {0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37} },
+{ 0x158c, 15, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} },
+{ 0x159b, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0e, 0x14} },
+{ 0x15ab, 16, {0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xc6, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xc8} },
+{ 0x15bb, 15, {0xe0, 0xff, 0x22, 0x90, 0x7f, 0xca, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcc, 0xe0, 0xff, 0x22} },
+{ 0x15ca, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0e, 0x14} },
+{ 0x15da, 16, {0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xb6, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xb8} },
+{ 0x15ea, 15, {0xe0, 0xff, 0x22, 0x90, 0x7f, 0xba, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xbc, 0xe0, 0xff, 0x22} },
+{ 0x15f9, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0e, 0x14} },
+{ 0x1609, 16, {0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xc7, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xc9} },
+{ 0x1619, 15, {0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcb, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcd, 0xe0, 0xff, 0x22} },
+{ 0x1628, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x30} },
+{ 0x1638, 16, {0x05, 0x04, 0xc2, 0x05, 0x80, 0x02, 0xd2, 0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} },
+{ 0x1648, 14, {0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x1656, 16, {0x90, 0x7b, 0x41, 0xe0, 0xf5, 0x17, 0x43, 0x25, 0x10, 0xa3, 0xe0, 0x60, 0x09, 0x90, 0x7f, 0xd7} },
+{ 0x1666, 16, {0x74, 0x17, 0xf0, 0x74, 0x37, 0xf0, 0x90, 0x7b, 0x43, 0xe0, 0xf5, 0x18, 0x30, 0x00, 0x07, 0xa3} },
+{ 0x1676, 10, {0xe0, 0x54, 0xf0, 0xf5, 0x0c, 0x22, 0xe4, 0xf5, 0x0c, 0x22} },
+{ 0x1680, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90} },
+{ 0x1690, 16, {0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0} },
+{ 0x16a0, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x16aa, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2} },
+{ 0x16ba, 16, {0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85} },
+{ 0x16ca, 7, {0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x16d1, 16, {0x12, 0x17, 0xb5, 0xae, 0x07, 0x12, 0x17, 0xb5, 0xad, 0x07, 0xee, 0x6d, 0x60, 0x10, 0x12, 0x17} },
+{ 0x16e1, 16, {0xb5, 0xae, 0x07, 0xee, 0x6d, 0x60, 0x07, 0x12, 0x17, 0xb5, 0xad, 0x07, 0x80, 0xec, 0xaf, 0x06} },
+{ 0x16f1, 1, {0x22} },
+{ 0x16f2, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
+{ 0x1702, 1, {0x22} },
+{ 0x1703, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} },
+{ 0x1713, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x04, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x09, 0x04, 0xe0, 0x44} },
+{ 0x1723, 16, {0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x17, 0x34, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
+{ 0x1733, 1, {0x22} },
+{ 0x1734, 16, {0x8e, 0x19, 0x8f, 0x1a, 0xe5, 0x1a, 0x15, 0x1a, 0xae, 0x19, 0x70, 0x02, 0x15, 0x19, 0x4e, 0x60} },
+{ 0x1744, 10, {0x08, 0x12, 0x16, 0xf2, 0x12, 0x16, 0xf2, 0x80, 0xeb, 0x22} },
+{ 0x174e, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x04, 0xff, 0x44, 0x10} },
+{ 0x175e, 9, {0x90, 0x7f, 0xd7, 0xf0, 0xef, 0x44, 0x30, 0xf0, 0x22} },
+{ 0x1767, 16, {0x03, 0x16, 0x80, 0x00, 0x00, 0x03, 0x11, 0x81, 0x00, 0x00, 0xc1, 0x85, 0xc1, 0x81, 0xc1, 0x08} },
+{ 0x1777, 7, {0xc1, 0x00, 0xc1, 0x86, 0x01, 0x09, 0x00} },
+{ 0x177e, 1, {0x00} },
+{ 0x177f, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x0d, 0x7e, 0x00, 0x12, 0x17, 0x34, 0x90, 0x7f} },
+{ 0x178f, 6, {0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} },
+{ 0x1795, 16, {0x12, 0x12, 0xae, 0x12, 0x17, 0x03, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x03, 0x12, 0x17, 0x7f} },
+{ 0x17a5, 4, {0x12, 0x0a, 0x6a, 0x22} },
+{ 0x17a9, 12, {0x90, 0x78, 0x41, 0x74, 0x02, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} },
+{ 0x17b5, 12, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} },
+{ 0x17c1, 12, {0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} },
+{ 0x17cd, 12, {0x90, 0x78, 0x41, 0x74, 0x05, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} },
+{ 0x17d9, 12, {0x90, 0x78, 0x41, 0x74, 0x06, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} },
+{ 0x17e5, 11, {0xe4, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} },
+{ 0x17f0, 4, {0x53, 0xd8, 0xef, 0x32} },
+{ 0x1800, 15, {0x02, 0x16, 0xaa, 0x00, 0x02, 0x18, 0x04, 0x00, 0x02, 0x16, 0x80, 0x00, 0x02, 0x16, 0x28} },
+{ 0x1900, 16, {0x12, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x40, 0xcd, 0x06, 0x0a, 0x01, 0x00, 0x00, 0x01, 0x02} },
+{ 0x1910, 16, {0x00, 0x04, 0x09, 0x02, 0x74, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x0e} },
+{ 0x1920, 16, {0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} },
+{ 0x1930, 16, {0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00} },
+{ 0x1940, 16, {0x07, 0x05, 0x05, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x06, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} },
+{ 0x1950, 16, {0x07, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x82, 0x02} },
+{ 0x1960, 16, {0x40, 0x00, 0x01, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00} },
+{ 0x1970, 16, {0x01, 0x07, 0x05, 0x85, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x01, 0x07} },
+{ 0x1980, 16, {0x05, 0x87, 0x02, 0x40, 0x00, 0x01, 0x04, 0x03, 0x09, 0x04, 0x48, 0x03, 0x4b, 0x00, 0x65, 0x00} },
+{ 0x1990, 16, {0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00} },
+{ 0x19a0, 16, {0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x76, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00} },
+{ 0x19b0, 16, {0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x6e, 0x00} },
+{ 0x19c0, 16, {0x6f, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} },
+{ 0x19d0, 16, {0x2e, 0x00, 0x36, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00} },
+{ 0x19e0, 16, {0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00} },
+{ 0x19f0, 16, {0x72, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x64, 0x00, 0x61, 0x00} },
+{ 0x1a00, 10, {0x70, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00} },
+{ 0xffff, 0, {0x00} }
+};
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
new file mode 100644
index 000000000..490f6226c
--- /dev/null
+++ b/drivers/usb/serial/mct_u232.c
@@ -0,0 +1,774 @@
+/*
+ * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver
+ *
+ * Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch)
+ *
+ * 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 largely derived from the Belkin USB Serial Adapter Driver
+ * (see belkin_sa.[ch]). All of the information about the device was acquired
+ * by using SniffUSB on Windows98. For technical details see mct_u232.h.
+ *
+ * William G. Greathouse and Greg Kroah-Hartman provided great help on how to
+ * do the reverse engineering and how to write a USB serial device driver.
+ *
+ * TO BE DONE, TO BE CHECKED:
+ * DTR/RTS signal handling may be incomplete or incorrect. I have mainly
+ * implemented what I have seen with SniffUSB or found in belkin_sa.c.
+ * For further TODOs check also belkin_sa.c.
+ *
+ * TEST STATUS:
+ * Basic tests have been performed with minicom/zmodem transfers and
+ * modem dialing under Linux 2.4.0-test10 (for me it works fine).
+ *
+ * 29-Nov-2000 Greg Kroah-Hartman
+ * - Added device id table to fit with 2.4.0-test11 structure.
+ * - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed
+ * (lots of things will change if/when the usb-serial core changes to
+ * handle these issues.
+ *
+ * 27-Nov-2000 Wolfgang Grandegger
+ * A version for kernel 2.4.0-test10 released to the Linux community
+ * (via linux-usb-devel).
+ */
+
+#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/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb-serial.h"
+#include "mct_u232.h"
+
+
+/*
+ * Some not properly written applications do not handle the return code of
+ * write() correctly. This can result in character losses. A work-a-round
+ * can be compiled in with the following definition. This work-a-round
+ * should _NOT_ be part of an 'official' kernel release, of course!
+ */
+#undef FIX_WRITE_RETURN_CODE_PROBLEM
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+static int write_blocking = 0; /* disabled by default */
+#endif
+
+/*
+ * Function prototypes
+ */
+static int mct_u232_startup (struct usb_serial *serial);
+static void mct_u232_shutdown (struct usb_serial *serial);
+static int mct_u232_open (struct usb_serial_port *port,
+ struct file *filp);
+static void mct_u232_close (struct usb_serial_port *port,
+ struct file *filp);
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+static int mct_u232_write (struct usb_serial_port *port,
+ int from_user,
+ const unsigned char *buf,
+ int count);
+static void mct_u232_write_bulk_callback (struct urb *urb);
+#endif
+static void mct_u232_read_int_callback (struct urb *urb);
+static void mct_u232_set_termios (struct usb_serial_port *port,
+ struct termios * old);
+static int mct_u232_ioctl (struct usb_serial_port *port,
+ struct file * file,
+ unsigned int cmd,
+ unsigned long arg);
+static void mct_u232_break_ctl (struct usb_serial_port *port,
+ int break_state );
+
+/*
+ * All of the device info needed for the MCT USB-RS232 converter.
+ */
+static __devinitdata struct usb_device_id id_table [] = {
+ { idVendor: MCT_U232_VID, idProduct: MCT_U232_PID },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+
+struct usb_serial_device_type mct_u232_device = {
+ name: "Magic Control Technology USB-RS232",
+ id_table: id_table,
+ needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */
+ needs_bulk_in: MUST_HAVE_NOT, /* no bulk-in endpoint */
+ needs_bulk_out: MUST_HAVE, /* 1 bulk-out endpoint */
+ num_interrupt_in: 2,
+ num_bulk_in: 0,
+ num_bulk_out: 1,
+ num_ports: 1,
+ open: mct_u232_open,
+ close: mct_u232_close,
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+ write: mct_u232_write,
+ write_bulk_callback: mct_u232_write_bulk_callback,
+#endif
+ read_int_callback: mct_u232_read_int_callback,
+ ioctl: mct_u232_ioctl,
+ set_termios: mct_u232_set_termios,
+ break_ctl: mct_u232_break_ctl,
+ startup: mct_u232_startup,
+ shutdown: mct_u232_shutdown,
+};
+
+struct mct_u232_private {
+ unsigned long control_state; /* Modem Line Setting (TIOCM) */
+ unsigned char last_lcr; /* Line Control Register */
+ unsigned char last_lsr; /* Line Status Register */
+ unsigned char last_msr; /* Modem Status Register */
+};
+
+/*
+ * Handle vendor specific USB requests
+ */
+
+#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+
+static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
+{
+ unsigned int divisor;
+ int rc;
+ divisor = MCT_U232_BAUD_RATE(value);
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_BAUD_RATE_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
+ WDR_TIMEOUT);
+ if (rc < 0)
+ err("Set BAUD RATE %d failed (error = %d)", value, rc);
+ dbg("set_baud_rate: 0x%x", divisor);
+ return rc;
+} /* mct_u232_set_baud_rate */
+
+static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
+{
+ int rc;
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_LINE_CTRL_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
+ WDR_TIMEOUT);
+ if (rc < 0)
+ err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
+ dbg("set_line_ctrl: 0x%x", lcr);
+ return rc;
+} /* mct_u232_set_line_ctrl */
+
+static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
+ unsigned long control_state)
+{
+ int rc;
+ unsigned char mcr = MCT_U232_MCR_NONE;
+
+ if (control_state & TIOCM_DTR)
+ mcr |= MCT_U232_MCR_DTR;
+ if (control_state & TIOCM_RTS)
+ mcr |= MCT_U232_MCR_RTS;
+
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_MODEM_CTRL_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
+ WDR_TIMEOUT);
+ if (rc < 0)
+ err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
+ dbg("set_modem_ctrl: state=0x%lx ==> mcr=0x%x", control_state, mcr);
+
+ return rc;
+} /* mct_u232_set_modem_ctrl */
+
+static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
+{
+ int rc;
+ rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCT_U232_GET_MODEM_STAT_REQUEST,
+ MCT_U232_GET_REQUEST_TYPE,
+ 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
+ WDR_TIMEOUT);
+ if (rc < 0) {
+ err("Get MODEM STATus failed (error = %d)", rc);
+ *msr = 0;
+ }
+ dbg("get_modem_stat: 0x%x", *msr);
+ return rc;
+} /* mct_u232_get_modem_stat */
+
+static void mct_u232_msr_to_state(unsigned long *control_state, unsigned char msr)
+{
+ /* Translate Control Line states */
+ if (msr & MCT_U232_MSR_DSR)
+ *control_state |= TIOCM_DSR;
+ else
+ *control_state &= ~TIOCM_DSR;
+ if (msr & MCT_U232_MSR_CTS)
+ *control_state |= TIOCM_CTS;
+ else
+ *control_state &= ~TIOCM_CTS;
+ if (msr & MCT_U232_MSR_RI)
+ *control_state |= TIOCM_RI;
+ else
+ *control_state &= ~TIOCM_RI;
+ if (msr & MCT_U232_MSR_CD)
+ *control_state |= TIOCM_CD;
+ else
+ *control_state &= ~TIOCM_CD;
+ dbg("msr_to_state: msr=0x%x ==> state=0x%lx", msr, *control_state);
+} /* mct_u232_msr_to_state */
+
+/*
+ * Driver's tty interface functions
+ */
+
+static int mct_u232_startup (struct usb_serial *serial)
+{
+ struct mct_u232_private *priv;
+
+ /* allocate the private data structure */
+ serial->port->private = kmalloc(sizeof(struct mct_u232_private),
+ GFP_KERNEL);
+ if (!serial->port->private)
+ return (-1); /* error */
+ priv = (struct mct_u232_private *)serial->port->private;
+ /* set initial values for control structures */
+ priv->control_state = 0;
+ priv->last_lsr = 0;
+ priv->last_msr = 0;
+
+ init_waitqueue_head(&serial->port->write_wait);
+
+ return (0);
+} /* mct_u232_startup */
+
+
+static void mct_u232_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) {
+ mct_u232_close (&serial->port[i], NULL);
+ }
+ /* My special items, the standard routines free my urbs */
+ if (serial->port->private)
+ kfree(serial->port->private);
+ }
+} /* mct_u232_shutdown */
+
+static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
+{
+ unsigned long flags;
+ struct usb_serial *serial = port->serial;
+ struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+
+ dbg(__FUNCTION__" port %d", port->number);
+
+ spin_lock_irqsave (&port->port_lock, flags);
+
+ ++port->open_count;
+ MOD_INC_USE_COUNT;
+
+ if (!port->active) {
+ port->active = 1;
+
+ /* Do a defined restart: the normal serial device seems to
+ * always turn on DTR and RTS here, so do the same. I'm not
+ * sure if this is really necessary. But it should not harm
+ * either.
+ */
+ if (port->tty->termios->c_cflag & CBAUD)
+ priv->control_state = TIOCM_DTR | TIOCM_RTS;
+ else
+ priv->control_state = 0;
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
+
+ priv->last_lcr = (MCT_U232_DATA_BITS_8 |
+ MCT_U232_PARITY_NONE |
+ MCT_U232_STOP_BITS_1);
+ mct_u232_set_line_ctrl(serial, priv->last_lcr);
+
+ /* Read modem status and update control state */
+ mct_u232_get_modem_stat(serial, &priv->last_msr);
+ mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
+
+ {
+ /* Puh, that's dirty */
+ struct usb_serial_port *rport;
+ rport = &serial->port[1];
+ rport->tty = port->tty;
+ rport->private = port->private;
+ port->read_urb = rport->interrupt_in_urb;
+ }
+
+ port->read_urb->dev = port->serial->dev;
+ if (usb_submit_urb(port->read_urb))
+ err("usb_submit_urb(read bulk) failed");
+
+ port->interrupt_in_urb->dev = port->serial->dev;
+ if (usb_submit_urb(port->interrupt_in_urb))
+ err(" usb_submit_urb(read int) failed");
+
+ }
+
+ spin_unlock_irqrestore (&port->port_lock, flags);
+
+ return 0;
+} /* mct_u232_open */
+
+
+static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+{
+ unsigned long flags;
+
+ dbg(__FUNCTION__" port %d", port->number);
+
+ spin_lock_irqsave (&port->port_lock, flags);
+
+ --port->open_count;
+ MOD_DEC_USE_COUNT;
+
+ if (port->open_count <= 0) {
+ /* shutdown our bulk reads and writes */
+ usb_unlink_urb (port->write_urb);
+ usb_unlink_urb (port->read_urb);
+ /* wgg - do I need this? I think so. */
+ usb_unlink_urb (port->interrupt_in_urb);
+ port->active = 0;
+ }
+
+ spin_unlock_irqrestore (&port->port_lock, flags);
+
+} /* mct_u232_close */
+
+
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+/* The generic routines work fine otherwise */
+
+static int mct_u232_write (struct usb_serial_port *port, int from_user,
+ const unsigned char *buf, int count)
+{
+ struct usb_serial *serial = port->serial;
+ unsigned long flags;
+ int result, bytes_sent, size;
+
+ dbg(__FUNCTION__ " - port %d", port->number);
+
+ if (count == 0) {
+ dbg(__FUNCTION__ " - write request of 0 bytes");
+ return (0);
+ }
+
+ /* only do something if we have a bulk out endpoint */
+ if (!serial->num_bulk_out)
+ return(0);;
+
+ /* another write is still pending? */
+ if (port->write_urb->status == -EINPROGRESS) {
+ dbg (__FUNCTION__ " - already writing");
+ return (0);
+ }
+
+ bytes_sent = 0;
+ while (count > 0) {
+
+ spin_lock_irqsave (&port->port_lock, flags);
+
+ size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+ usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf);
+
+ if (from_user) {
+ copy_from_user(port->write_urb->transfer_buffer, buf, size);
+ }
+ else {
+ memcpy (port->write_urb->transfer_buffer, buf, size);
+ }
+
+ /* set up our urb */
+ FILL_BULK_URB(port->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, size,
+ ((serial->type->write_bulk_callback) ?
+ serial->type->write_bulk_callback :
+ mct_u232_write_bulk_callback),
+ port);
+
+ /* send the data out the bulk port */
+ result = usb_submit_urb(port->write_urb);
+ if (result) {
+ err(__FUNCTION__
+ " - failed submitting write urb, error %d", result);
+ spin_unlock_irqrestore (&port->port_lock, flags);
+ return bytes_sent;
+ }
+
+ spin_unlock_irqrestore (&port->port_lock, flags);
+
+ bytes_sent += size;
+ if (write_blocking)
+ interruptible_sleep_on(&port->write_wait);
+ else
+ break;
+
+ buf += size;
+ count -= size;
+ }
+
+ return bytes_sent;
+} /* mct_u232_write */
+
+static void mct_u232_write_bulk_callback (struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial = port->serial;
+ struct tty_struct *tty = port->tty;
+
+ 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;
+ }
+
+ if (write_blocking) {
+ wake_up_interruptible(&port->write_wait);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ wake_up_interruptible(&tty->write_wait);
+
+ } else {
+ /* from generic_write_bulk_callback */
+ queue_task(&port->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ }
+
+ return;
+} /* mct_u232_write_bulk_callback */
+#endif
+
+static void mct_u232_read_int_callback (struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ struct usb_serial *serial = port->serial;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+
+ 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;
+ }
+
+ usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+
+ /*
+ * Work-a-round: handle the 'usual' bulk-in pipe here
+ */
+ if (urb->transfer_buffer_length > 2) {
+ int i;
+ tty = port->tty;
+ if (urb->actual_length) {
+ for (i = 0; i < urb->actual_length ; ++i) {
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ tty_flip_buffer_push(tty);
+ }
+ /* INT urbs are automatically re-submitted */
+ return;
+ }
+
+ /*
+ * The interrupt-in pipe signals exceptional conditions (modem line
+ * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
+ */
+ priv->last_msr = data[MCT_U232_MSR_INDEX];
+
+ /* Record Control Line states */
+ mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
+
+#if 0
+ /* Not yet handled. See belin_sa.c for further information */
+ /* Now to report any errors */
+ priv->last_lsr = data[MCT_U232_LSR_INDEX];
+ /*
+ * fill in the flip buffer here, but I do not know the relation
+ * to the current/next receive buffer or characters. I need
+ * to look in to this before committing any code.
+ */
+ if (priv->last_lsr & MCT_U232_LSR_ERR) {
+ tty = port->tty;
+ /* Overrun Error */
+ if (priv->last_lsr & MCT_U232_LSR_OE) {
+ }
+ /* Parity Error */
+ if (priv->last_lsr & MCT_U232_LSR_PE) {
+ }
+ /* Framing Error */
+ if (priv->last_lsr & MCT_U232_LSR_FE) {
+ }
+ /* Break Indicator */
+ if (priv->last_lsr & MCT_U232_LSR_BI) {
+ }
+ }
+#endif
+
+ /* INT urbs are automatically re-submitted */
+} /* mct_u232_read_int_callback */
+
+
+static void mct_u232_set_termios (struct usb_serial_port *port,
+ struct termios *old_termios)
+{
+ struct usb_serial *serial = port->serial;
+ struct mct_u232_private *priv = (struct mct_u232_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");
+ 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);
+ }
+
+ switch(cflag & CBAUD) {
+ case B0: /* handled below */
+ break;
+ case B300: mct_u232_set_baud_rate(serial, 300);
+ break;
+ case B600: mct_u232_set_baud_rate(serial, 600);
+ break;
+ case B1200: mct_u232_set_baud_rate(serial, 1200);
+ break;
+ case B2400: mct_u232_set_baud_rate(serial, 2400);
+ break;
+ case B4800: mct_u232_set_baud_rate(serial, 4800);
+ break;
+ case B9600: mct_u232_set_baud_rate(serial, 9600);
+ break;
+ case B19200: mct_u232_set_baud_rate(serial, 19200);
+ break;
+ case B38400: mct_u232_set_baud_rate(serial, 38400);
+ break;
+ case B57600: mct_u232_set_baud_rate(serial, 57600);
+ break;
+ case B115200: mct_u232_set_baud_rate(serial, 115200);
+ break;
+ default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600");
+ mct_u232_set_baud_rate(serial, 9600); break;
+ }
+ if ((cflag & CBAUD) == B0 ) {
+ dbg(__FUNCTION__ ": baud is B0");
+ /* Drop RTS and DTR */
+ priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
+ }
+ }
+
+ /*
+ * Update line control register (LCR)
+ */
+ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
+ || (cflag & CSIZE) != (old_cflag & CSIZE)
+ || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
+
+
+ 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 data bits */
+ switch (cflag & CSIZE) {
+ case CS5:
+ priv->last_lcr |= MCT_U232_DATA_BITS_5; break;
+ case CS6:
+ priv->last_lcr |= MCT_U232_DATA_BITS_6; break;
+ case CS7:
+ priv->last_lcr |= MCT_U232_DATA_BITS_7; break;
+ case CS8:
+ priv->last_lcr |= MCT_U232_DATA_BITS_8; break;
+ default:
+ err("CSIZE was not CS5-CS8, using default of 8");
+ priv->last_lcr |= MCT_U232_DATA_BITS_8;
+ break;
+ }
+
+ /* 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);
+ }
+
+ /*
+ * 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 ((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);
+ }
+} /* mct_u232_set_termios */
+
+
+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 */
+
+
+static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct usb_serial *serial = port->serial;
+ struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ int ret, mask;
+
+ dbg (__FUNCTION__ "cmd=0x%x", cmd);
+
+ /* Based on code from acm.c and others */
+ switch (cmd) {
+ case TIOCMGET:
+ return put_user(priv->control_state, (unsigned long *) arg);
+ break;
+
+ 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 ((ret = get_user(mask, (unsigned long *) arg))) return ret;
+
+ if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
+ /* RTS needs set */
+ if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
+ (cmd == TIOCMBIS) )
+ priv->control_state |= TIOCM_RTS;
+ else
+ priv->control_state &= ~TIOCM_RTS;
+ }
+
+ if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
+ /* DTR needs set */
+ if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
+ (cmd == TIOCMBIS) )
+ priv->control_state |= TIOCM_DTR;
+ else
+ 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 */
+ return( 0 );
+
+ case TIOCGICOUNT:
+ /* return count of modemline transitions */
+ /* TODO */
+ return 0;
+
+ default:
+ dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd);
+ return(-ENOIOCTLCMD);
+ break;
+ }
+ return 0;
+} /* mct_u232_ioctl */
+
+
+static int __init mct_u232_init (void)
+{
+ usb_serial_register (&mct_u232_device);
+
+ return 0;
+}
+
+
+static void __exit mct_u232_exit (void)
+{
+ usb_serial_deregister (&mct_u232_device);
+}
+
+
+module_init (mct_u232_init);
+module_exit(mct_u232_exit);
+
+MODULE_AUTHOR("Wolfgang Grandegger <wolfgang@ces.ch>");
+MODULE_DESCRIPTION("Magic Control Technology USB-RS232 converter driver");
+
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+MODULE_PARM(write_blocking, "i");
+MODULE_PARM_DESC(write_blocking,
+ "The write function will block to write out all data");
+#endif
diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h
new file mode 100644
index 000000000..d96dd6164
--- /dev/null
+++ b/drivers/usb/serial/mct_u232.h
@@ -0,0 +1,362 @@
+/*
+ * Definitions for MCT (Magic Control Technology) USB-RS232 Converter Driver
+ *
+ * Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch)
+ *
+ * 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 device MCT USB-RS232 Converter (25 pin, Model No.
+ * U232-P25) from Magic Control Technology Corp. (there is also a 9 pin
+ * Model No. U232-P9). See http://www.mct.com.tw/p_u232.html for further
+ * information. The properties of this device are listed at the end of this
+ * file. This device is available from various distributors. I know Hana,
+ * http://www.hana.de and D-Link, http://www.dlink.com/products/usb/dsbs25.
+ *
+ * All of the information about the device was acquired by using SniffUSB
+ * on Windows98. The technical details of the reverse engineering are
+ * summarized at the end of this file.
+ */
+
+#ifndef __LINUX_USB_SERIAL_MCT_U232_H
+#define __LINUX_USB_SERIAL_MCT_U232_H
+
+#define MCT_U232_VID 0x0711 /* Vendor Id */
+#define MCT_U232_PID 0x0210 /* Product Id */
+
+/*
+ * Vendor Request Interface
+ */
+#define MCT_U232_SET_REQUEST_TYPE 0x40
+#define MCT_U232_GET_REQUEST_TYPE 0xc0
+
+#define MCT_U232_GET_MODEM_STAT_REQUEST 2 /* Get Modem Status Register (MSR) */
+#define MCT_U232_GET_MODEM_STAT_SIZE 1
+
+#define MCT_U232_GET_LINE_CTRL_REQUEST 6 /* Get Line Control Register (LCR) */
+#define MCT_U232_GET_LINE_CTRL_SIZE 1 /* ... not used by this driver */
+
+#define MCT_U232_SET_BAUD_RATE_REQUEST 5 /* Set Baud Rate Divisor */
+#define MCT_U232_SET_BAUD_RATE_SIZE 4
+
+#define MCT_U232_SET_LINE_CTRL_REQUEST 7 /* Set Line Control Register (LCR) */
+#define MCT_U232_SET_LINE_CTRL_SIZE 1
+
+#define MCT_U232_SET_MODEM_CTRL_REQUEST 10 /* Set Modem Control Register (MCR) */
+#define MCT_U232_SET_MODEM_CTRL_SIZE 1
+
+/*
+ * Baud rate (divisor)
+ */
+#define MCT_U232_BAUD_RATE(b) (115200/b)
+
+/*
+ * Line Control Register (LCR)
+ */
+#define MCT_U232_SET_BREAK 0x40
+
+#define MCT_U232_PARITY_SPACE 0x38
+#define MCT_U232_PARITY_MARK 0x28
+#define MCT_U232_PARITY_EVEN 0x18
+#define MCT_U232_PARITY_ODD 0x08
+#define MCT_U232_PARITY_NONE 0x00
+
+#define MCT_U232_DATA_BITS_5 0x00
+#define MCT_U232_DATA_BITS_6 0x01
+#define MCT_U232_DATA_BITS_7 0x02
+#define MCT_U232_DATA_BITS_8 0x03
+
+#define MCT_U232_STOP_BITS_2 0x04
+#define MCT_U232_STOP_BITS_1 0x00
+
+/*
+ * Modem Control Register (MCR)
+ */
+#define MCT_U232_MCR_NONE 0x8 /* Deactivate DTR and RTS */
+#define MCT_U232_MCR_RTS 0xa /* Activate RTS */
+#define MCT_U232_MCR_DTR 0x9 /* Activate DTR */
+
+/*
+ * Modem Status Register (MSR)
+ */
+#define MCT_U232_MSR_INDEX 0x0 /* data[index] */
+#define MCT_U232_MSR_CD 0x80 /* Current CD */
+#define MCT_U232_MSR_RI 0x40 /* Current RI */
+#define MCT_U232_MSR_DSR 0x20 /* Current DSR */
+#define MCT_U232_MSR_CTS 0x10 /* Current CTS */
+#define MCT_U232_MSR_DCD 0x08 /* Delta CD */
+#define MCT_U232_MSR_DRI 0x04 /* Delta RI */
+#define MCT_U232_MSR_DDSR 0x02 /* Delta DSR */
+#define MCT_U232_MSR_DCTS 0x01 /* Delta CTS */
+
+/*
+ * Line Status Register (LSR)
+ */
+#define MCT_U232_LSR_INDEX 1 /* data[index] */
+#define MCT_U232_LSR_ERR 0x80 /* OE | PE | FE | BI */
+#define MCT_U232_LSR_TEMT 0x40 /* transmit register empty */
+#define MCT_U232_LSR_THRE 0x20 /* transmit holding register empty */
+#define MCT_U232_LSR_BI 0x10 /* break indicator */
+#define MCT_U232_LSR_FE 0x08 /* framing error */
+#define MCT_U232_LSR_OE 0x02 /* overrun error */
+#define MCT_U232_LSR_PE 0x04 /* parity error */
+#define MCT_U232_LSR_OE 0x02 /* overrun error */
+#define MCT_U232_LSR_DR 0x01 /* receive data ready */
+
+
+/* -----------------------------------------------------------------------------
+ * Technical Specification reverse engineered with SniffUSB on Windows98
+ * =====================================================================
+ *
+ * The technical details of the device have been acquired be using "SniffUSB"
+ * and the vendor-supplied device driver (version 2.3A) under Windows98. To
+ * identify the USB vendor-specific requests and to assign them to terminal
+ * settings (flow control, baud rate, etc.) the program "SerialSettings" from
+ * William G. Greathouse has been proven to be very useful. I also used the
+ * Win98 "HyperTerminal" and "usb-robot" on Linux for testing. The results and
+ * observations are summarized below:
+ *
+ * The USB requests seem to be directly mapped to the registers of a 8250,
+ * 16450 or 16550 UART. The FreeBSD handbook (appendix F.4 "Input/Output
+ * devices") contains a comprehensive description of UARTs and its registers.
+ * The bit descriptions are actually taken from there.
+ *
+ *
+ * Baud rate (divisor)
+ * -------------------
+ *
+ * BmRequestType: 0x4 (0100 0000B)
+ * bRequest: 0x5
+ * wValue: 0x0
+ * wIndex: 0x0
+ * wLength: 0x4
+ * Data: divisor = 115200 / baud_rate
+ *
+ *
+ * Line Control Register (LCR)
+ * ---------------------------
+ *
+ * BmRequestType: 0x4 (0100 0000B) 0xc (1100 0000B)
+ * bRequest: 0x7 0x6
+ * wValue: 0x0
+ * wIndex: 0x0
+ * wLength: 0x1
+ * Data: LCR (see below)
+ *
+ * Bit 7: Divisor Latch Access Bit (DLAB). When set, access to the data
+ * transmit/receive register (THR/RBR) and the Interrupt Enable Register
+ * (IER) is disabled. Any access to these ports is now redirected to the
+ * Divisor Latch Registers. Setting this bit, loading the Divisor
+ * Registers, and clearing DLAB should be done with interrupts disabled.
+ * Bit 6: Set Break. When set to "1", the transmitter begins to transmit
+ * continuous Spacing until this bit is set to "0". This overrides any
+ * bits of characters that are being transmitted.
+ * Bit 5: Stick Parity. When parity is enabled, setting this bit causes parity
+ * to always be "1" or "0", based on the value of Bit 4.
+ * Bit 4: Even Parity Select (EPS). When parity is enabled and Bit 5 is "0",
+ * setting this bit causes even parity to be transmitted and expected.
+ * Otherwise, odd parity is used.
+ * Bit 3: Parity Enable (PEN). When set to "1", a parity bit is inserted
+ * between the last bit of the data and the Stop Bit. The UART will also
+ * expect parity to be present in the received data.
+ * Bit 2: Number of Stop Bits (STB). If set to "1" and using 5-bit data words,
+ * 1.5 Stop Bits are transmitted and expected in each data word. For
+ * 6, 7 and 8-bit data words, 2 Stop Bits are transmitted and expected.
+ * When this bit is set to "0", one Stop Bit is used on each data word.
+ * Bit 1: Word Length Select Bit #1 (WLSB1)
+ * Bit 0: Word Length Select Bit #0 (WLSB0)
+ * Together these bits specify the number of bits in each data word.
+ * 1 0 Word Length
+ * 0 0 5 Data Bits
+ * 0 1 6 Data Bits
+ * 1 0 7 Data Bits
+ * 1 1 8 Data Bits
+ *
+ * SniffUSB observations: Bit 7 seems not to be used. There seem to be two bugs
+ * in the Win98 driver: the break does not work (bit 6 is not asserted) and the
+ * sticky parity bit is not cleared when set once. The LCR can also be read
+ * back with USB request 6 but this has never been observed with SniffUSB.
+ *
+ *
+ * Modem Control Register (MCR)
+ * ----------------------------
+ *
+ * BmRequestType: 0x4 (0100 0000B)
+ * bRequest: 0xa
+ * wValue: 0x0
+ * wIndex: 0x0
+ * wLength: 0x1
+ * Data: MCR (Bit 4..7, see below)
+ *
+ * Bit 7: Reserved, always 0.
+ * Bit 6: Reserved, always 0.
+ * Bit 5: Reserved, always 0.
+ * Bit 4: Loop-Back Enable. When set to "1", the UART transmitter and receiver
+ * are internally connected together to allow diagnostic operations. In
+ * addition, the UART modem control outputs are connected to the UART
+ * modem control inputs. CTS is connected to RTS, DTR is connected to
+ * DSR, OUT1 is connected to RI, and OUT 2 is connected to DCD.
+ * Bit 3: OUT 2. An auxiliary output that the host processor may set high or
+ * low. In the IBM PC serial adapter (and most clones), OUT 2 is used
+ * to tri-state (disable) the interrupt signal from the
+ * 8250/16450/16550 UART.
+ * Bit 2: OUT 1. An auxiliary output that the host processor may set high or
+ * low. This output is not used on the IBM PC serial adapter.
+ * Bit 1: Request to Send (RTS). When set to "1", the output of the UART -RTS
+ * line is Low (Active).
+ * Bit 0: Data Terminal Ready (DTR). When set to "1", the output of the UART
+ * -DTR line is Low (Active).
+ *
+ * SniffUSB observations: Bit 2 and 4 seem not to be used but bit 3 has been
+ * seen _always_ set.
+ *
+ *
+ * Modem Status Register (MSR)
+ * ---------------------------
+ *
+ * BmRequestType: 0xc (1100 0000B)
+ * bRequest: 0x2
+ * wValue: 0x0
+ * wIndex: 0x0
+ * wLength: 0x1
+ * Data: MSR (see below)
+ *
+ * Bit 7: Data Carrier Detect (CD). Reflects the state of the DCD line on the
+ * UART.
+ * Bit 6: Ring Indicator (RI). Reflects the state of the RI line on the UART.
+ * Bit 5: Data Set Ready (DSR). Reflects the state of the DSR line on the UART.
+ * Bit 4: Clear To Send (CTS). Reflects the state of the CTS line on the UART.
+ * Bit 3: Delta Data Carrier Detect (DDCD). Set to "1" if the -DCD line has
+ * changed state one more more times since the last time the MSR was
+ * read by the host.
+ * Bit 2: Trailing Edge Ring Indicator (TERI). Set to "1" if the -RI line has
+ * had a low to high transition since the last time the MSR was read by
+ * the host.
+ * Bit 1: Delta Data Set Ready (DDSR). Set to "1" if the -DSR line has changed
+ * state one more more times since the last time the MSR was read by the
+ * host.
+ * Bit 0: Delta Clear To Send (DCTS). Set to "1" if the -CTS line has changed
+ * state one more times since the last time the MSR was read by the
+ * host.
+ *
+ * SniffUSB observations: the MSR is also returned as first byte on the
+ * interrupt-in endpoint 0x83 to signal changes of modem status lines. The USB
+ * request to read MSR cannot be applied during normal device operation.
+ *
+ *
+ * Line Status Register (LSR)
+ * --------------------------
+ *
+ * Bit 7 Error in Receiver FIFO. On the 8250/16450 UART, this bit is zero.
+ * This bit is set to "1" when any of the bytes in the FIFO have one or
+ * more of the following error conditions: PE, FE, or BI.
+ * Bit 6 Transmitter Empty (TEMT). When set to "1", there are no words
+ * remaining in the transmit FIFO or the transmit shift register. The
+ * transmitter is completely idle.
+ * Bit 5 Transmitter Holding Register Empty (THRE). When set to "1", the FIFO
+ * (or holding register) now has room for at least one additional word
+ * to transmit. The transmitter may still be transmitting when this bit
+ * is set to "1".
+ * Bit 4 Break Interrupt (BI). The receiver has detected a Break signal.
+ * Bit 3 Framing Error (FE). A Start Bit was detected but the Stop Bit did not
+ * appear at the expected time. The received word is probably garbled.
+ * Bit 2 Parity Error (PE). The parity bit was incorrect for the word received.
+ * Bit 1 Overrun Error (OE). A new word was received and there was no room in
+ * the receive buffer. The newly-arrived word in the shift register is
+ * discarded. On 8250/16450 UARTs, the word in the holding register is
+ * discarded and the newly- arrived word is put in the holding register.
+ * Bit 0 Data Ready (DR). One or more words are in the receive FIFO that the
+ * host may read. A word must be completely received and moved from the
+ * shift register into the FIFO (or holding register for 8250/16450
+ * designs) before this bit is set.
+ *
+ * SniffUSB observations: the LSR is returned as second byte on the interrupt-in
+ * endpoint 0x83 to signal error conditions. Such errors have been seen with
+ * minicom/zmodem transfers (CRC errors).
+ *
+ *
+ * Flow control
+ * ------------
+ *
+ * SniffUSB observations: no flow control specific requests have been realized
+ * apart from DTR/RTS settings. Both signals are dropped for no flow control
+ * but asserted for hardware or software flow control.
+ *
+ *
+ * Endpoint usage
+ * --------------
+ *
+ * SniffUSB observations: the bulk-out endpoint 0x1 and interrupt-in endpoint
+ * 0x81 is used to transmit and receive characters. The second interrupt-in
+ * endpoint 0x83 signals exceptional conditions like modem line changes and
+ * errors. The first byte returned is the MSR and the second byte the LSR.
+ *
+ *
+ * Other observations
+ * ------------------
+ *
+ * Queued bulk transfers like used in visor.c did not work.
+ *
+ *
+ * Properties of the USB device used (as found in /var/log/messages)
+ * -----------------------------------------------------------------
+ *
+ * Manufacturer: MCT Corporation.
+ * Product: USB-232 Interfact Controller
+ * SerialNumber: U2S22050
+ *
+ * Length = 18
+ * DescriptorType = 01
+ * USB version = 1.00
+ * Vendor:Product = 0711:0210
+ * MaxPacketSize0 = 8
+ * NumConfigurations = 1
+ * Device version = 1.02
+ * Device Class:SubClass:Protocol = 00:00:00
+ * Per-interface classes
+ * Configuration:
+ * bLength = 9
+ * bDescriptorType = 02
+ * wTotalLength = 0027
+ * bNumInterfaces = 01
+ * bConfigurationValue = 01
+ * iConfiguration = 00
+ * bmAttributes = c0
+ * MaxPower = 100mA
+ *
+ * Interface: 0
+ * Alternate Setting: 0
+ * bLength = 9
+ * bDescriptorType = 04
+ * bInterfaceNumber = 00
+ * bAlternateSetting = 00
+ * bNumEndpoints = 03
+ * bInterface Class:SubClass:Protocol = 00:00:00
+ * iInterface = 00
+ * Endpoint:
+ * bLength = 7
+ * bDescriptorType = 05
+ * bEndpointAddress = 81 (in)
+ * bmAttributes = 03 (Interrupt)
+ * wMaxPacketSize = 0040
+ * bInterval = 02
+ * Endpoint:
+ * bLength = 7
+ * bDescriptorType = 05
+ * bEndpointAddress = 01 (out)
+ * bmAttributes = 02 (Bulk)
+ * wMaxPacketSize = 0040
+ * bInterval = 00
+ * Endpoint:
+ * bLength = 7
+ * bDescriptorType = 05
+ * bEndpointAddress = 83 (in)
+ * bmAttributes = 03 (Interrupt)
+ * wMaxPacketSize = 0002
+ * bInterval = 02
+ */
+
+#endif /* __LINUX_USB_SERIAL_MCT_U232_H */
+
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index 6b5d6e7f0..1a07a03d5 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -15,6 +15,9 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (12/29/2000) gkh
+ * Small NULL pointer initialization cleanup which saves a bit of disk image
+ *
* (11/01/2000) Adam J. Richter
* instead of using idVendor/idProduct pairs, usb serial drivers
* now identify their hardware interest with usb_device_id tables,
@@ -346,7 +349,7 @@ static struct tty_driver serial_tty_driver;
static struct tty_struct * serial_tty[SERIAL_TTY_MINORS];
static struct termios * serial_termios[SERIAL_TTY_MINORS];
static struct termios * serial_termios_locked[SERIAL_TTY_MINORS];
-static struct usb_serial *serial_table[SERIAL_TTY_MINORS] = {NULL, };
+static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
LIST_HEAD(usb_serial_driver_list);
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index c078704f0..ee1b73893 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -11,6 +11,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (11/12/2000) gkh
+ * Fixed bug with data being dropped on the floor by forcing tty->low_latency
+ * to be on. Hopefully this fixes the OHCI issue!
+ *
* (11/01/2000) Adam J. Richter
* usb_device_id table support
*
@@ -171,6 +175,11 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
bytes_in = 0;
bytes_out = 0;
+ /* force low_latency on so that our tty_push actually forces the data through,
+ otherwise it is scheduled, and with high data rates (like with OHCI) data
+ can get lost. */
+ port->tty->low_latency = 1;
+
/* Start reading from the device */
FILL_BULK_URB(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
@@ -348,6 +357,11 @@ static void visor_read_bulk_callback (struct urb *urb)
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);
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 912ae94c4..7f4b1ea3e 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.13 2000/10/03 01:06:07 mdharm Exp $
+ * $Id: freecom.c,v 1.14 2000/11/13 22:27:57 mdharm Exp $
*
* Freecom v0.1:
*
@@ -425,7 +425,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
/* Send it out. */
result = usb_stor_bulk_msg (us, fcb, opipe,
FCM_PACKET_LENGTH, &partial);
-
+
/* The Freecom device will only fail if there is something
* wrong in USB land. It returns the status in its own
* registers, which come back in the bulk pipe.
@@ -433,13 +433,13 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
if (result != 0) {
US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
result, partial);
-
+
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
-
+
return USB_STOR_TRANSPORT_ERROR;
}
@@ -455,7 +455,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUG(pdump ((void *) fst, partial));
}
-
+
if (partial != 4 || result != 0) {
return USB_STOR_TRANSPORT_ERROR;
}
@@ -647,7 +647,7 @@ static void pdump (void *ibuffer, int length)
unsigned char *buffer = (unsigned char *) ibuffer;
int i, j;
int from, base;
-
+
offset = 0;
for (i = 0; i < length; i++) {
if ((i & 15) == 0) {
@@ -670,17 +670,17 @@ static void pdump (void *ibuffer, int length)
}
offset += sprintf (line+offset, " %02x", buffer[i] & 0xff);
}
-
+
/* Add the last "chunk" of data. */
from = (length - 1) % 16;
base = ((length - 1) / 16) * 16;
-
+
for (i = from + 1; i < 16; i++)
offset += sprintf (line+offset, " ");
if (from < 8)
offset += sprintf (line+offset, " ");
offset += sprintf (line+offset, " - ");
-
+
for (i = 0; i <= from; i++) {
if (buffer[base+i] >= 32 && buffer[base+i] <= 126)
line[offset++] = buffer[base+i];
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index 00bbdd726..7225dfbb6 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: protocol.c,v 1.6 2000/09/01 22:03:55 mdharm Exp $
+ * $Id: protocol.c,v 1.7 2000/11/13 22:28:33 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -161,7 +161,7 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
srb->cmnd[0] = srb->cmnd[0] | 0x20;
break;
} /* end switch on cmnd[0] */
-
+
/* convert MODE_SELECT data here */
if (old_cmnd == MODE_SELECT)
usb_stor_scsiSense6to10(srb);
@@ -263,7 +263,7 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
usb_stor_invoke_transport(srb, us);
-
+
/* Fix the MODE_SENSE data if we translated the command */
if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD))
usb_stor_scsiSense10to6(srb);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index cf82489de..5c50b578c 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* SCSI layer glue code
*
- * $Id: scsiglue.c,v 1.17 2000/11/02 21:27:49 mdharm Exp $
+ * $Id: scsiglue.c,v 1.19 2000/11/13 22:28:55 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -124,7 +124,7 @@ static int release(struct Scsi_Host *psh)
us->action = US_ACT_EXIT;
wake_up(&(us->wqh));
down(&(us->notify));
-
+
/* remove the pointer to the data structure we were using */
(struct us_data*)psh->hostdata[0] = NULL;
@@ -261,7 +261,7 @@ static int bus_reset( Scsi_Cmnd *srb )
US_DEBUGPX("skipping ourselves.\n");
continue;
}
-
+
/* simulate a disconnect and reconnect for all interfaces */
US_DEBUGPX("simulating disconnect/reconnect.\n");
down(&intf->driver->serialize);
@@ -330,7 +330,7 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
if (!us) {
return -ESRCH;
}
-
+
/* print the controler name */
SPRINTF(" Host scsi%d: usb-storage\n", hostno);
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index cbf3db2ca..e737280f7 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.12 2000/10/03 01:06:07 mdharm Exp $
+ * $Id: sddr09.c,v 1.14 2000/11/21 02:58:26 mdharm Exp $
*
* SDDR09 driver v0.1:
*
@@ -175,7 +175,7 @@ static int sddr09_raw_bulk(struct us_data *us,
US_DEBUGP("us_transfer_partial(): unknown error\n");
return US_BULK_TRANSFER_FAILED;
}
-
+
if (act_len != len) {
US_DEBUGP("Warning: Transferred only %d bytes\n",
act_len);
@@ -355,10 +355,10 @@ int sddr09_read_data(struct us_data *us,
0,
command,
12);
-
+
US_DEBUGP("Result for send_control in read_data %d\n",
result);
-
+
if (result != USB_STOR_TRANSPORT_GOOD) {
if (use_sg)
kfree(buffer);
@@ -426,7 +426,7 @@ int sddr09_read_control(struct us_data *us,
US_DEBUGP("Result for send_control in read_control %d\n",
result);
-
+
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
@@ -461,7 +461,7 @@ int sddr09_read_deviceID(struct us_data *us,
US_DEBUGP("Result of send_control for device ID is %d\n",
result);
-
+
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
@@ -491,7 +491,7 @@ int sddr09_read_status(struct us_data *us,
0,
command,
12);
-
+
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
@@ -517,7 +517,7 @@ int sddr09_reset(struct us_data *us) {
0,
command,
12);
-
+
return result;
}
@@ -579,6 +579,10 @@ unsigned long sddr09_get_capacity(struct us_data *us,
*blocksize = 32;
return 0x02000000;
+ case 0x76: // 64MB
+ *blocksize = 32;
+ return 0x04000000;
+
default: // unknown
return 0;
@@ -656,7 +660,7 @@ int sddr09_read_map(struct us_data *us) {
return -1;
}
-
+
if (info->lba_to_pba)
kfree(info->lba_to_pba);
@@ -691,7 +695,7 @@ int sddr09_read_map(struct us_data *us) {
continue;
if ((ptr[6]>>4)!=0x01)
continue;
-
+
/* ensure even parity */
lba = short_pack(ptr[7], ptr[6]);
@@ -876,7 +880,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
ptr[7] = LSB_of(info->pagesize&0xFFFF);
sddr09_read_map(us);
-
+
return USB_STOR_TRANSPORT_GOOD;
}
@@ -974,7 +978,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
if (srb->request_bufflen == 0)
return USB_STOR_TRANSPORT_GOOD;
-
+
if (srb->sc_data_direction == SCSI_DATA_WRITE ||
srb->sc_data_direction == SCSI_DATA_READ) {
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 5b2a514c7..c0de9c14c 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.10 2000/09/24 00:03:08 groovyjava Exp $
+ * $Id: shuttle_usbat.c,v 1.11 2000/11/13 22:29:36 mdharm Exp $
*
* Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
@@ -169,7 +169,7 @@ static int usbat_raw_bulk(struct us_data *us,
US_DEBUGP("us_transfer_partial(): unknown error\n");
return US_BULK_TRANSFER_FAILED;
}
-
+
if (act_len != len) {
US_DEBUGP("Warning: Transferred only %d bytes\n",
act_len);
@@ -241,7 +241,7 @@ int usbat_read(struct us_data *us,
0,
content,
1);
-
+
return result;
}
@@ -260,7 +260,7 @@ int usbat_write(struct us_data *us,
0,
NULL,
0);
-
+
return result;
}
@@ -286,7 +286,7 @@ int usbat_set_shuttle_features(struct us_data *us,
0,
command,
8);
-
+
return result;
}
@@ -317,7 +317,7 @@ int usbat_read_block(struct us_data *us,
result = usbat_bulk_transport(us,
NULL, 0, SCSI_DATA_READ, content, len, use_sg);
-
+
return result;
}
@@ -605,7 +605,7 @@ int usbat_read_user_io(struct us_data *us,
0,
data_flags,
1);
-
+
return result;
}
@@ -623,7 +623,7 @@ int usbat_write_user_io(struct us_data *us,
0,
NULL,
0);
-
+
return result;
}
@@ -676,7 +676,7 @@ int usbat_handle_read10(struct us_data *us,
srb->transfersize = srb->request_bufflen/len;
}
-
+
len = (65535/srb->transfersize) * srb->transfersize;
US_DEBUGP("Max read is %d bytes\n", len);
buffer = kmalloc(len, GFP_KERNEL);
@@ -694,7 +694,7 @@ int usbat_handle_read10(struct us_data *us,
}
while (transferred != srb->request_bufflen) {
-
+
if (len > srb->request_bufflen - transferred)
len = srb->request_bufflen - transferred;
@@ -711,7 +711,7 @@ int usbat_handle_read10(struct us_data *us,
data[7+6] = 0;
data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
data[7+8] = LSB_of(len / srb->transfersize); // num sectors
-
+
result = usbat_rw_block_test(us, USBAT_ATA,
registers, data, 19,
0x10, 0x17, 0xFD, 0x30,
@@ -1048,7 +1048,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
}
else
len = status;
-
+
result = usbat_read_block(us, USBAT_ATA, 0x10,
srb->request_buffer, len, srb->use_sg);
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index dd72f334c..c46ff24dc 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.32 2000/11/03 00:18:04 mdharm Exp $
+ * $Id: transport.c,v 1.38 2000/11/21 00:52:10 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -90,9 +90,9 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
*/
static char *lengths =
-
+
/* 0123456789ABCDEF 0123456789ABCDEF */
-
+
"00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X" /* 00-1F */
"XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH" /* 20-3F */
"M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX" /* 40-5F */
@@ -213,129 +213,129 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
*/
if (srb->sc_data_direction == SCSI_DATA_WRITE) {
- doDefault = 1;
+ doDefault = 1;
}
else
switch (lengths[srb->cmnd[0]]) {
- case 'L':
- len = srb->cmnd[4];
- break;
-
- case 'M':
- len = srb->cmnd[8];
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- len = lengths[srb->cmnd[0]]-'0';
- break;
-
- case 'G':
- len = (((unsigned int)srb->cmnd[3])<<8) |
- srb->cmnd[4];
- break;
-
- case 'H':
- len = (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
-
- case 'I':
- len = (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
-
- case 'R':
- len = (((unsigned int)srb->cmnd[2])<<16) |
- (((unsigned int)srb->cmnd[3])<<8) |
- srb->cmnd[4];
- break;
-
- case 'S':
- len = (((unsigned int)srb->cmnd[3])<<16) |
- (((unsigned int)srb->cmnd[4])<<8) |
- srb->cmnd[5];
- break;
-
- case 'T':
- len = (((unsigned int)srb->cmnd[6])<<16) |
- (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
-
- case 'U':
- len = (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
-
- case 'C':
- len = (((unsigned int)srb->cmnd[2])<<24) |
- (((unsigned int)srb->cmnd[3])<<16) |
- (((unsigned int)srb->cmnd[4])<<8) |
- srb->cmnd[5];
- break;
-
- case 'D':
- len = (((unsigned int)srb->cmnd[6])<<24) |
- (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
-
- case 'V':
- len = 20;
- break;
-
- case 'W':
- len = 24;
- break;
-
- case 'B':
- /* Use buffer size due to different block sizes */
- doDefault = 1;
- break;
-
- case 'X':
- US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n",
- srb->cmnd[0]);
- doDefault = 1;
- break;
-
- case 'Z':
- /* Use buffer size due to mode dependence */
- doDefault = 1;
- break;
-
- default:
- US_DEBUGP("Error: COMMAND %02X out of range or table inconsistent (%c).\n",
- srb->cmnd[0], lengths[srb->cmnd[0]] );
- doDefault = 1;
+ case 'L':
+ len = srb->cmnd[4];
+ break;
+
+ case 'M':
+ len = srb->cmnd[8];
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ len = lengths[srb->cmnd[0]]-'0';
+ break;
+
+ case 'G':
+ len = (((unsigned int)srb->cmnd[3])<<8) |
+ srb->cmnd[4];
+ break;
+
+ case 'H':
+ len = (((unsigned int)srb->cmnd[7])<<8) |
+ srb->cmnd[8];
+ break;
+
+ case 'I':
+ len = (((unsigned int)srb->cmnd[8])<<8) |
+ srb->cmnd[9];
+ break;
+
+ case 'R':
+ len = (((unsigned int)srb->cmnd[2])<<16) |
+ (((unsigned int)srb->cmnd[3])<<8) |
+ srb->cmnd[4];
+ break;
+
+ case 'S':
+ len = (((unsigned int)srb->cmnd[3])<<16) |
+ (((unsigned int)srb->cmnd[4])<<8) |
+ srb->cmnd[5];
+ break;
+
+ case 'T':
+ len = (((unsigned int)srb->cmnd[6])<<16) |
+ (((unsigned int)srb->cmnd[7])<<8) |
+ srb->cmnd[8];
+ break;
+
+ case 'U':
+ len = (((unsigned int)srb->cmnd[7])<<16) |
+ (((unsigned int)srb->cmnd[8])<<8) |
+ srb->cmnd[9];
+ break;
+
+ case 'C':
+ len = (((unsigned int)srb->cmnd[2])<<24) |
+ (((unsigned int)srb->cmnd[3])<<16) |
+ (((unsigned int)srb->cmnd[4])<<8) |
+ srb->cmnd[5];
+ break;
+
+ case 'D':
+ len = (((unsigned int)srb->cmnd[6])<<24) |
+ (((unsigned int)srb->cmnd[7])<<16) |
+ (((unsigned int)srb->cmnd[8])<<8) |
+ srb->cmnd[9];
+ break;
+
+ case 'V':
+ len = 20;
+ break;
+
+ case 'W':
+ len = 24;
+ break;
+
+ case 'B':
+ /* Use buffer size due to different block sizes */
+ doDefault = 1;
+ break;
+
+ case 'X':
+ US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n",
+ srb->cmnd[0]);
+ doDefault = 1;
+ break;
+
+ case 'Z':
+ /* Use buffer size due to mode dependence */
+ doDefault = 1;
+ break;
+
+ default:
+ US_DEBUGP("Error: COMMAND %02X out of range or table inconsistent (%c).\n",
+ srb->cmnd[0], lengths[srb->cmnd[0]] );
+ doDefault = 1;
}
- if ( doDefault == 1 ) {
- /* Are we going to scatter gather? */
- if (srb->use_sg) {
- /* Add up the sizes of all the sg segments */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++)
- total += sg[i].length;
- len = total;
- }
- else
- /* Just return the length of the buffer */
- len = srb->request_bufflen;
- }
-
- return len;
+ if ( doDefault == 1 ) {
+ /* Are we going to scatter gather? */
+ if (srb->use_sg) {
+ /* Add up the sizes of all the sg segments */
+ sg = (struct scatterlist *) srb->request_buffer;
+ for (i = 0; i < srb->use_sg; i++)
+ total += sg[i].length;
+ len = total;
+ }
+ else
+ /* Just return the length of the buffer */
+ len = srb->request_bufflen;
+ }
+
+return len;
}
/* This is a version of usb_clear_halt() that doesn't read the status from
@@ -423,7 +423,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
if (status) {
/* something went wrong */
up(&(us->current_urb_sem));
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&wqh, &wait);
kfree(dr);
return status;
@@ -481,7 +481,7 @@ int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
if (status) {
/* something went wrong */
up(&(us->current_urb_sem));
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&wqh, &wait);
return status;
}
@@ -538,7 +538,7 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
clear_halt(us->pusb_dev, pipe);
}
-
+
/* did we send all the data? */
if (partial == length) {
US_DEBUGP("usb_stor_transfer_partial(): transfer complete\n");
@@ -824,24 +824,44 @@ void usb_stor_CBI_irq(struct urb *urb)
US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no);
US_DEBUGP("-- IRQ data length is %d\n", urb->actual_length);
US_DEBUGP("-- IRQ state is %d\n", urb->status);
+ US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n",
+ us->irqbuf[0], us->irqbuf[1]);
+
+ /* reject improper IRQs */
+ if (urb->actual_length != 2) {
+ US_DEBUGP("-- IRQ too short\n");
+ return;
+ }
/* is the device removed? */
- if (urb->status != -ENOENT) {
- /* save the data for interpretation later */
- US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n",
- ((unsigned char*)urb->transfer_buffer)[0],
- ((unsigned char*)urb->transfer_buffer)[1]);
-
-
- /* was this a wanted interrupt? */
- if (atomic_read(us->ip_wanted)) {
- atomic_set(us->ip_wanted, 0);
- US_DEBUGP("-- Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count));
- up(&(us->ip_waitq));
- } else
- US_DEBUGP("ERROR: Unwanted interrupt received!\n");
- } else
+ if (urb->status == -ENOENT) {
US_DEBUGP("-- device has been removed\n");
+ return;
+ }
+
+ /* was this a command-completion interrupt? */
+ if (us->irqbuf[0] && (us->subclass != US_SC_UFI)) {
+ US_DEBUGP("-- not a command-completion IRQ\n");
+ return;
+ }
+
+ /* was this a wanted interrupt? */
+ if (!atomic_read(us->ip_wanted)) {
+ US_DEBUGP("ERROR: Unwanted interrupt received!\n");
+ return;
+ }
+
+ /* adjust the flag */
+ atomic_set(us->ip_wanted, 0);
+
+ /* copy the valid data */
+ us->irqdata[0] = us->irqbuf[0];
+ us->irqdata[1] = us->irqbuf[1];
+
+ /* wake up the command thread */
+ US_DEBUGP("-- Current value of ip_waitq is: %d\n",
+ atomic_read(&us->ip_waitq.count));
+ up(&(us->ip_waitq));
}
int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
@@ -903,18 +923,17 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* go to sleep until we get this interrupt */
US_DEBUGP("Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count));
down(&(us->ip_waitq));
-
+
/* if we were woken up by an abort instead of the actual interrupt */
if (atomic_read(us->ip_wanted)) {
US_DEBUGP("Did not get interrupt on CBI\n");
atomic_set(us->ip_wanted, 0);
return USB_STOR_TRANSPORT_ABORTED;
}
-
+
US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
- ((unsigned char*)us->irq_urb->transfer_buffer)[0],
- ((unsigned char*)us->irq_urb->transfer_buffer)[1]);
-
+ us->irqdata[0], us->irqdata[1]);
+
/* UFI gives us ASC and ASCQ, like a request sense
*
* REQUEST_SENSE and INQUIRY don't affect the sense data on UFI
@@ -932,22 +951,24 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
else
return USB_STOR_TRANSPORT_GOOD;
}
-
+
/* If not UFI, we interpret the data as a result code
* The first byte should always be a 0x0
* The second byte & 0x0F should be 0x0 for good, otherwise error
*/
- if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) {
- US_DEBUGP("CBI IRQ data showed reserved bType\n");
+ if (us->irqdata[0]) {
+ US_DEBUGP("CBI IRQ data showed reserved bType %d\n",
+ us->irqdata[0]);
return USB_STOR_TRANSPORT_ERROR;
}
- switch (((unsigned char*)us->irq_urb->transfer_buffer)[1] & 0x0F) {
- case 0x00:
- return USB_STOR_TRANSPORT_GOOD;
- case 0x01:
- return USB_STOR_TRANSPORT_FAILED;
- default:
- return USB_STOR_TRANSPORT_ERROR;
+
+ switch (us->irqdata[1] & 0x0F) {
+ case 0x00:
+ return USB_STOR_TRANSPORT_GOOD;
+ case 0x01:
+ return USB_STOR_TRANSPORT_FAILED;
+ default:
+ return USB_STOR_TRANSPORT_ERROR;
}
/* we should never get here, but if we do, we're in trouble */
@@ -1056,7 +1077,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* if the device was removed, then we're already reset */
if (!us->pusb_dev)
return SUCCESS;
-
+
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));
@@ -1066,14 +1087,14 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
if (us->flags & US_FL_SCM_MULT_TARG)
bcb.Lun |= srb->target << 4;
bcb.Length = srb->cmd_len;
-
+
/* construct the pipe handle */
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
+
/* copy the command payload */
memset(bcb.CDB, 0, sizeof(bcb.CDB));
memcpy(bcb.CDB, srb->cmnd, bcb.Length);
-
+
/* send it to out endpoint */
US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
le32_to_cpu(bcb.Signature), bcb.Tag,
@@ -1082,7 +1103,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN,
&partial);
US_DEBUGP("Bulk command transfer result=%d\n", result);
-
+
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
@@ -1095,7 +1116,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* unknown error -- we've got a problem */
return USB_STOR_TRANSPORT_ERROR;
}
-
+
/* if the command transfered well, then we go to the data stage */
if (result == 0) {
/* send/receive data payload, if there is any */
@@ -1109,14 +1130,14 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_ABORTED;
}
}
-
+
/* See flow chart on pg 15 of the Bulk Only Transport spec for
* an explanation of how this code works.
*/
-
+
/* construct the pipe handle */
pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
-
+
/* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n");
result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN,
@@ -1139,7 +1160,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
-
+
/* if it fails again, we need a reset and return an error*/
if (result == -EPIPE) {
US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);
@@ -1147,13 +1168,13 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_ERROR;
}
}
-
+
/* if we still have a failure at this point, we're in trouble */
US_DEBUGP("Bulk status result = %d\n", result);
if (result) {
return USB_STOR_TRANSPORT_ERROR;
}
-
+
/* check bulk status */
US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
le32_to_cpu(bcs.Signature), bcs.Tag,
@@ -1164,24 +1185,24 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
-
+
/* based on the status code, we report good or bad */
switch (bcs.Status) {
- case US_BULK_STAT_OK:
- /* command good -- note that we could be short on data */
- return USB_STOR_TRANSPORT_GOOD;
+ case US_BULK_STAT_OK:
+ /* command good -- note that data could be short */
+ return USB_STOR_TRANSPORT_GOOD;
- case US_BULK_STAT_FAIL:
- /* command failed */
- return USB_STOR_TRANSPORT_FAILED;
-
- case US_BULK_STAT_PHASE:
- /* phase error -- note that a transport reset will be
- * invoked by the invoke_transport() function
- */
- return USB_STOR_TRANSPORT_ERROR;
+ case US_BULK_STAT_FAIL:
+ /* command failed */
+ return USB_STOR_TRANSPORT_FAILED;
+
+ case US_BULK_STAT_PHASE:
+ /* phase error -- note that a transport reset will be
+ * invoked by the invoke_transport() function
+ */
+ return USB_STOR_TRANSPORT_ERROR;
}
-
+
/* we should never get here, but if we do, we're in trouble */
return USB_STOR_TRANSPORT_ERROR;
}
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index a7129ba25..ce31133b9 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: usb.c,v 1.54 2000/10/31 21:32:10 mdharm Exp $
+ * $Id: usb.c,v 1.57 2000/11/21 02:56:41 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -196,7 +196,7 @@ static int usb_stor_control_thread(void * __us)
action = us->action;
us->action = 0;
us->srb = us->queue_srb;
-
+
/* release the queue lock as fast as possible */
up(&(us->queue_exclusion));
@@ -213,7 +213,7 @@ static int usb_stor_control_thread(void * __us)
us->srb = NULL;
break;
}
-
+
/* reject if target != 0 or if LUN is higher than
* the maximum known LUN
*/
@@ -312,15 +312,15 @@ static int usb_stor_control_thread(void * __us)
US_DEBUGP("-- US_ACT_EXIT command recieved\n");
break;
}
-
- set_current_state(TASK_INTERRUPTIBLE);
} /* for (;;) */
+ /* clean up after ourselves */
+ set_current_state(TASK_INTERRUPTIBLE);
+ remove_wait_queue(&(us->wqh), &wait);
+
/* notify the exit routine that we're actually exiting now */
up(&(us->notify));
- remove_wait_queue(&(us->wqh), &wait);
-
return 0;
}
@@ -489,7 +489,7 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
US_FL_SINGLE_LUN },
#ifdef CONFIG_USB_STORAGE_SDDR09
- { 0x0781, 0x0200, 0x0100, 0x0100,
+ { 0x0781, 0x0200, 0x0100, 0x0208,
"Sandisk",
"ImageMate SDDR-09",
US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
@@ -551,7 +551,7 @@ static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct,
(ptr->bcdDeviceMin <= bcdDevice) &&
(ptr->bcdDeviceMax >= bcdDevice)))
ptr++;
-
+
/* if the search ended because we hit the end record, we failed */
if (ptr->idVendor == 0x0000) {
US_DEBUGP("-- did not find a matching device\n");
@@ -577,7 +577,7 @@ static int usb_stor_allocate_irq(struct us_data *ss)
int result;
US_DEBUGP("Allocating IRQ for CBI transport\n");
-
+
/* lock access to the data structure */
down(&(ss->irq_urb_sem));
@@ -588,18 +588,18 @@ static int usb_stor_allocate_irq(struct us_data *ss)
US_DEBUGP("couldn't allocate interrupt URB");
return 1;
}
-
+
/* calculate the pipe and max packet size */
pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK);
maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe));
if (maxp > sizeof(ss->irqbuf))
maxp = sizeof(ss->irqbuf);
-
+
/* fill in the URB with our data */
FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp,
usb_stor_CBI_irq, ss, ss->ep_int->bInterval);
-
+
/* submit the URB for processing */
result = usb_submit_urb(ss->irq_urb);
US_DEBUGP("usb_submit_urb() returns %d\n", result);
@@ -679,7 +679,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
protocol = altsetting->bInterfaceProtocol;
flags = 0;
}
-
+
/*
* Find the endpoints we need
* We are expecting a minimum of 2 endpoints - in and out (bulk).
@@ -744,7 +744,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
if (dev->descriptor.iSerialNumber && !(flags & US_FL_IGNORE_SER))
usb_string(dev, dev->descriptor.iSerialNumber,
serial, sizeof(serial));
-
+
/* Create a GUID for this device */
if (dev->descriptor.iSerialNumber && serial[0]) {
/* If we have a serial number, and it's a non-NULL string */
@@ -777,7 +777,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
/* establish the connection to the new device upon reconnect */
ss->ifnum = ifnum;
ss->pusb_dev = dev;
-
+
/* copy over the endpoint data */
if (ep_in)
ss->ep_in = ep_in->bEndpointAddress &
@@ -810,7 +810,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
} else {
/* New device -- allocate memory and initialize */
US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
-
+
if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data),
GFP_KERNEL)) == NULL) {
printk(KERN_WARNING USB_STORAGE "Out of memory\n");
@@ -879,7 +879,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
/* copy the GUID we created before */
memcpy(ss->guid, guid, sizeof(guid));
-
+
/*
* Set the handler pointers based on the protocol
* Again, this data is persistant across reattachments
@@ -891,21 +891,21 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
ss->transport_reset = usb_stor_CB_reset;
ss->max_lun = 7;
break;
-
+
case US_PR_CBI:
ss->transport_name = "Control/Bulk/Interrupt";
ss->transport = usb_stor_CBI_transport;
ss->transport_reset = usb_stor_CB_reset;
ss->max_lun = 7;
break;
-
+
case US_PR_BULK:
ss->transport_name = "Bulk";
ss->transport = usb_stor_Bulk_transport;
ss->transport_reset = usb_stor_Bulk_reset;
ss->max_lun = usb_stor_Bulk_max_lun(ss);
break;
-
+
#ifdef CONFIG_USB_STORAGE_HP8200e
case US_PR_SCM_ATAPI:
ss->transport_name = "SCM/ATAPI";
@@ -941,7 +941,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
ss->max_lun = 0;
break;
#endif
-
+
default:
ss->transport_name = "Unknown";
kfree(ss->current_urb);
@@ -1004,7 +1004,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
usb_dec_dev_use(dev);
return NULL;
}
-
+
/*
* Since this is a new device, we need to generate a scsi
* host definition, and register with the higher SCSI layers
@@ -1016,7 +1016,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
/* Grab the next host number */
ss->host_number = my_host_number++;
-
+
/* We abuse this pointer so we can pass the ss pointer to
* the host controler thread in us_detect. But how else are
* we to do it?
@@ -1027,7 +1027,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
* the device if it needs initialization */
if (unusual_dev && unusual_dev->initFunction)
unusual_dev->initFunction(ss);
-
+
/* start up our control thread */
ss->pid = kernel_thread(usb_stor_control_thread, ss,
CLONE_VM);
@@ -1039,14 +1039,14 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
usb_dec_dev_use(dev);
return NULL;
}
-
+
/* wait for the thread to start */
down(&(ss->notify));
-
+
/* now register - our detect function will be called */
ss->htmplt.module = THIS_MODULE;
scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt));
-
+
/* lock access to the data structures */
down(&us_list_semaphore);
@@ -1133,7 +1133,7 @@ int __init usb_stor_init(void)
void __exit usb_stor_exit(void)
{
struct us_data *next;
-
+
US_DEBUGP("usb_stor_exit() called\n");
/* Deregister the driver
@@ -1141,7 +1141,7 @@ void __exit usb_stor_exit(void)
*/
US_DEBUGP("-- calling usb_deregister()\n");
usb_deregister(&usb_storage_driver) ;
-
+
/* While there are still virtual hosts, unregister them
* Note that it's important to do this completely before removing
* the structures because of possible races with the /proc
@@ -1151,7 +1151,7 @@ void __exit usb_stor_exit(void)
US_DEBUGP("-- calling scsi_unregister_module()\n");
scsi_unregister_module(MODULE_SCSI_HA, &(next->htmplt));
}
-
+
/* While there are still structures, free them. Note that we are
* now race-free, since these structures can no longer be accessed
* from either the SCSI command layer or the /proc interface
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 342e94a4e..e0dac568d 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* Main Header File
*
- * $Id: usb.h,v 1.10 2000/10/19 18:44:11 mdharm Exp $
+ * $Id: usb.h,v 1.11 2000/11/13 22:38:55 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -152,7 +152,7 @@ struct us_data {
int host_number; /* to find us */
int host_no; /* allocated by scsi */
Scsi_Cmnd *srb; /* current srb */
-
+
/* thread information */
Scsi_Cmnd *queue_srb; /* the single queue slot */
int action; /* what to do */
@@ -166,6 +166,7 @@ struct us_data {
struct semaphore irq_urb_sem; /* to protect irq_urb */
struct urb *irq_urb; /* for USB int requests */
unsigned char irqbuf[2]; /* buffer for USB IRQ */
+ unsigned char irqdata[2]; /* data from USB IRQ */
/* control and bulk communications data */
struct semaphore current_urb_sem; /* to protect irq_urb */
diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c
index 0a0d32f69..40cf2f746 100644
--- a/drivers/usb/uhci.c
+++ b/drivers/usb/uhci.c
@@ -2,12 +2,16 @@
* Universal Host Controller Interface driver for USB.
*
* (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@sventech.com
+ * (C) Copyright 1999-2000 Johannes Erdfelt, johannes@erdfelt.com
* (C) Copyright 1999 Randy Dunlap
* (C) Copyright 1999 Georg Acher, acher@in.tum.de
* (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
* (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
* (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
+ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+ * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+ * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+ *
*
* Intel documents this fairly well, and as far as I know there
* are no royalties or anything like that, but even so there are
@@ -21,6 +25,7 @@
* - working around the horridness of the rest
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
@@ -46,7 +51,6 @@
#include "uhci-debug.h"
#include <linux/pm.h>
-static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data);
static int debug = 1;
MODULE_PARM(debug, "i");
@@ -56,8 +60,6 @@ static kmem_cache_t *uhci_td_cachep;
static kmem_cache_t *uhci_qh_cachep;
static kmem_cache_t *uhci_up_cachep; /* urb_priv */
-static LIST_HEAD(uhci_list);
-
static int rh_submit_urb(struct urb *urb);
static int rh_unlink_urb(struct urb *urb);
static int uhci_get_current_frame_number(struct usb_device *dev);
@@ -1753,11 +1755,11 @@ static void rh_int_timer_do(unsigned long ptr)
urbp = (struct urb_priv *)u->hcpriv;
if (urbp) {
/* Check if the FSBR timed out */
- if (urbp->fsbr && time_after(urbp->inserttime + IDLE_TIMEOUT, jiffies))
+ if (urbp->fsbr && time_after_eq(jiffies, urbp->inserttime + IDLE_TIMEOUT))
uhci_fsbr_timeout(uhci, u);
/* Check if the URB timed out */
- if (u->timeout && time_after(u->timeout, jiffies)) {
+ if (u->timeout && time_after_eq(jiffies, u->timeout)) {
u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED;
uhci_unlink_urb(u);
}
@@ -2343,9 +2345,7 @@ static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsign
uhci = alloc_uhci(io_addr, io_size);
if (!uhci)
return -ENOMEM;
-
- INIT_LIST_HEAD(&uhci->uhci_list);
- list_add(&uhci->uhci_list, &uhci_list);
+ dev->driver_data = uhci;
request_region(uhci->io_addr, io_size, "usb-uhci");
@@ -2358,21 +2358,13 @@ static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsign
if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci) == 0) {
uhci->irq = irq;
- if (!uhci_start_root_hub(uhci)) {
- struct pm_dev *pmdev;
+ pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
- pmdev = pm_register(PM_PCI_DEV,
- PM_PCI_ID(dev),
- handle_pm_event);
- if (pmdev)
- pmdev->data = uhci;
+ if (!uhci_start_root_hub(uhci))
return 0;
- }
}
/* Couldn't allocate IRQ if we got here */
- list_del(&uhci->uhci_list);
- INIT_LIST_HEAD(&uhci->uhci_list);
reset_hc(uhci);
release_region(uhci->io_addr, uhci->io_size);
@@ -2381,19 +2373,19 @@ static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsign
return retval;
}
-static int found_uhci(struct pci_dev *dev)
+static int __devinit uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int i;
/* disable legacy emulation */
- pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+ pci_write_config_word(dev, USBLEGSUP, 0);
if (pci_enable_device(dev) < 0)
- return -1;
+ return -ENODEV;
if (!dev->irq) {
err("found UHCI device with no IRQ assigned. check BIOS settings!");
- return -1;
+ return -ENODEV;
}
/* Search for the IO base address.. */
@@ -2409,32 +2401,77 @@ static int found_uhci(struct pci_dev *dev)
if (check_region(io_addr, io_size))
break;
+ pci_set_master(dev);
return setup_uhci(dev, dev->irq, io_addr, io_size);
}
- return -1;
+ return -ENODEV;
}
-static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data)
+static void __devexit uhci_pci_remove(struct pci_dev *dev)
{
- struct uhci *uhci = dev->data;
- switch (rqst) {
- case PM_SUSPEND:
- reset_hc(uhci);
- break;
- case PM_RESUME:
- reset_hc(uhci);
- start_hc(uhci);
- break;
- }
- return 0;
+ struct uhci *uhci = dev->driver_data;
+
+ if (uhci->bus->root_hub)
+ usb_disconnect(&uhci->bus->root_hub);
+
+ usb_deregister_bus(uhci->bus);
+
+ reset_hc(uhci);
+ release_region(uhci->io_addr, uhci->io_size);
+
+ uhci_free_pending_qhs(uhci);
+
+ release_uhci(uhci);
+}
+
+static void uhci_pci_suspend(struct pci_dev *dev)
+{
+ reset_hc((struct uhci *) dev->driver_data);
}
-static int __init uhci_init(void)
+static void uhci_pci_resume(struct pci_dev *dev)
+{
+ reset_hc((struct uhci *) dev->driver_data);
+ start_hc((struct uhci *) dev->driver_data);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct pci_device_id __devinitdata uhci_pci_ids [] = { {
+
+ /* handle any USB UHCI controller */
+ class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00),
+ class_mask: ~0,
+
+ /* no matter who makes it */
+ vendor: PCI_ANY_ID,
+ device: PCI_ANY_ID,
+ subvendor: PCI_ANY_ID,
+ subdevice: PCI_ANY_ID,
+
+ }, { /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE (pci, uhci_pci_ids);
+
+static struct pci_driver uhci_pci_driver = {
+ name: "usb-uhci",
+ id_table: &uhci_pci_ids [0],
+
+ probe: uhci_pci_probe,
+ remove: uhci_pci_remove,
+
+#ifdef CONFIG_PM
+ suspend: uhci_pci_suspend,
+ resume: uhci_pci_resume,
+#endif /* PM */
+};
+
+
+static int __init uhci_hcd_init(void)
{
int retval;
- struct pci_dev *dev;
- u8 type;
retval = -ENOMEM;
@@ -2461,25 +2498,8 @@ static int __init uhci_init(void)
if (!uhci_up_cachep)
goto up_failed;
- retval = -ENODEV;
- dev = NULL;
- for (;;) {
- dev = pci_find_class(PCI_CLASS_SERIAL_USB << 8, dev);
- if (!dev)
- break;
-
- /* Is it the UHCI programming interface? */
- pci_read_config_byte(dev, PCI_CLASS_PROG, &type);
- if (type != 0)
- continue;
-
- /* Ok set it up */
- retval = found_uhci(dev);
- }
-
- /* We only want to return an error code if ther was an error */
- /* and we didn't find a UHCI controller */
- if (retval && list_empty(&uhci_list))
+ retval = pci_module_init (&uhci_pci_driver);
+ if (retval)
goto init_failed;
return 0;
@@ -2500,32 +2520,10 @@ td_failed:
return retval;
}
-void uhci_cleanup(void)
+static void __exit uhci_hcd_cleanup (void)
{
- struct list_head *tmp, *head = &uhci_list;
-
- tmp = head->next;
- while (tmp != head) {
- struct uhci *uhci = list_entry(tmp, struct uhci, uhci_list);
-
- tmp = tmp->next;
-
- list_del(&uhci->uhci_list);
- INIT_LIST_HEAD(&uhci->uhci_list);
-
- if (uhci->bus->root_hub)
- usb_disconnect(&uhci->bus->root_hub);
-
- usb_deregister_bus(uhci->bus);
-
- reset_hc(uhci);
- release_region(uhci->io_addr, uhci->io_size);
-
- uhci_free_pending_qhs(uhci);
-
- release_uhci(uhci);
- }
-
+ pci_unregister_driver (&uhci_pci_driver);
+
if (kmem_cache_destroy(uhci_up_cachep))
printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
@@ -2536,14 +2534,8 @@ void uhci_cleanup(void)
printk(KERN_INFO "uhci: not all TD's were freed\n");
}
-static void __exit uhci_exit(void)
-{
- pm_unregister_all(handle_pm_event);
- uhci_cleanup();
-}
-
-module_init(uhci_init);
-module_exit(uhci_exit);
+module_init(uhci_hcd_init);
+module_exit(uhci_hcd_cleanup);
MODULE_AUTHOR("Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
index 4834f25cf..b4cace1dc 100644
--- a/drivers/usb/usb-uhci.c
+++ b/drivers/usb/usb-uhci.c
@@ -5,14 +5,18 @@
* Deti Fliegl, deti@fliegl.de (executive slave) (lead voice)
* Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader)
* Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter)
+ * (c) 2000 Yggdrasil Computing, Inc. (port of new PCI interface support
+ * from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+ * (C) 2000 David Brownell, david-b@pacbell.net (usb-ohci.c)
*
* HW-initalization based on material of
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999 Johannes Erdfelt
* (C) Copyright 1999 Randy Dunlap
+ * (C) Copyright 1999 Gregory P. Smith
*
- * $Id: usb-uhci.c,v 1.242 2000/10/05 21:19:49 acher Exp $
+ * $Id: usb-uhci.c,v 1.251 2000/11/30 09:47:54 acher Exp $
*/
#include <linux/config.h>
@@ -48,7 +52,7 @@
/* This enables an extra UHCI slab for memory debugging */
#define DEBUG_SLAB
-#define VERSTR "$Revision: 1.242 $ time " __TIME__ " " __DATE__
+#define VERSTR "$Revision: 1.251 $ time " __TIME__ " " __DATE__
#include <linux/usb.h>
#include "usb-uhci.h"
@@ -92,27 +96,31 @@ _static int process_transfer (uhci_t *s, urb_t *urb, int mode);
_static int process_interrupt (uhci_t *s, urb_t *urb);
_static int process_iso (uhci_t *s, urb_t *urb, int force);
+// How much URBs with ->next are walked
+#define MAX_NEXT_COUNT 2048
+
static uhci_t *devs = NULL;
/* used by userspace UHCI data structure dumper */
uhci_t **uhci_devices = &devs;
/*-------------------------------------------------------------------*/
-// Cleans up collected QHs
+// Cleans up collected QHs, but not more than 100 in one go
void clean_descs(uhci_t *s, int force)
{
struct list_head *q;
uhci_desc_t *qh;
- int now=UHCI_GET_CURRENT_FRAME(s);
+ int now=UHCI_GET_CURRENT_FRAME(s), n=0;
q=s->free_desc.prev;
- while (q != &s->free_desc) {
- qh = list_entry (q, uhci_desc_t, horizontal);
+ while (q != &s->free_desc && (force || n<100)) {
+ qh = list_entry (q, uhci_desc_t, horizontal);
q=qh->horizontal.prev;
if ((qh->last_used!=now) || force)
delete_qh(s,qh);
+ n++;
}
}
/*-------------------------------------------------------------------*/
@@ -264,7 +272,7 @@ _static int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags)
if (qh == prev ) {
// virgin qh without any tds
- qh->hw.qh.element = virt_to_bus (new);
+ qh->hw.qh.element = virt_to_bus (new) | UHCI_PTR_TERM;
}
else {
// already tds inserted, implicitely remove TERM bit of prev
@@ -409,6 +417,9 @@ _static int unlink_qh (uhci_t *s, uhci_desc_t *element)
prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal);
prev->hw.qh.head = element->hw.qh.head;
+ dbg("unlink qh %p, pqh %p, nxqh %p, to %08x", element, prev,
+ list_entry (element->horizontal.next, uhci_desc_t, horizontal),element->hw.qh.head &~15);
+
list_del(&element->horizontal);
mb ();
@@ -571,6 +582,7 @@ _static int init_skel (uhci_t *s)
fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand)
insert_td (s, qh, td, 0);
+ qh->hw.qh.element &= ~UHCI_PTR_TERM; // remove TERM bit
s->td1ms=td;
dbg("allocating qh: bulk_chain");
@@ -791,14 +803,14 @@ _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb)
{
uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
urb_priv_t *urb_priv = urb->hcpriv;
- uhci_desc_t *qh, *td, *nqh, *bqh;
+ uhci_desc_t *qh, *td, *nqh, *bqh, *first_td=NULL;
unsigned long destination, status;
char *data;
unsigned int pipe = urb->pipe;
int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
int info, len, last;
int depth_first=USE_BULK_DEPTH_FIRST; // UHCI descriptor chasing method
- urb_priv_t *upriv, *bpriv;
+ urb_priv_t *upriv, *bpriv=NULL;
if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)))
return -EPIPE;
@@ -814,7 +826,7 @@ _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb)
queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i",
urb,bulk_urb,urb->pipe,urb->transfer_buffer_length);
- upriv=(urb_priv_t*)urb->hcpriv;
+ upriv = (urb_priv_t*)urb->hcpriv;
if (!bulk_urb) {
alloc_qh (&qh); // get qh for this request
@@ -836,13 +848,10 @@ _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb)
bpriv = (urb_priv_t*)bulk_urb->hcpriv;
qh = bpriv->bottom_qh; // re-use bottom qh and next qh
nqh = bpriv->next_qh;
- upriv->next_qh=nqh;
- bpriv->next_queued_urb=urb;
+ upriv->next_qh=nqh;
upriv->prev_queued_urb=bulk_urb;
}
- queue_dbg("uhci_submit_bulk: qh=%p, nqh=%p\n",bqh,nqh);
-
if (urb->transfer_flags & USB_QUEUE_BULK) {
alloc_qh (&bqh); // "bottom" QH,
@@ -854,11 +863,10 @@ _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb)
return -ENOMEM;
}
bqh->hw.qh.element = UHCI_PTR_TERM;
- bqh->hw.qh.element = virt_to_bus(nqh)|UHCI_PTR_QH;
+ bqh->hw.qh.head = virt_to_bus(nqh) | UHCI_PTR_QH; // element
upriv->bottom_qh = bqh;
- queue_dbg("uhci_submit_bulk: new bqh %p\n",bqh);
}
-
+ queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh);
/* The "pipe" thing contains the destination in bits 8--18. */
destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
@@ -899,25 +907,31 @@ _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb)
td->hw.td.status |= TD_CTRL_IOC; // last one generates INT
insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);
+ if (!first_td)
+ first_td=td;
usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
} while (!last);
+ if (bulk_urb && bpriv) // everything went OK, link with old bulk URB
+ bpriv->next_queued_urb=urb;
+
list_add (&qh->desc_list, &urb_priv->desc_list);
- if (urb->transfer_flags & USB_QUEUE_BULK) {
- qh->hw.qh.element&=~UHCI_PTR_TERM;
+ if (urb->transfer_flags & USB_QUEUE_BULK)
append_qh(s, td, bqh, UHCI_PTR_DEPTH * depth_first);
- }
urb->status = -EINPROGRESS;
queue_urb_unlocked (s, urb);
- qh->hw.qh.element &= ~UHCI_PTR_TERM;
+ if (urb->transfer_flags & USB_QUEUE_BULK)
+ qh->hw.qh.element = virt_to_bus (first_td);
+ else
+ qh->hw.qh.element &= ~UHCI_PTR_TERM; // arm QH
- if (!bulk_urb) {
+ if (!bulk_urb) { // new bulk queue
if (urb->transfer_flags & USB_QUEUE_BULK) {
- spin_lock (&s->td_lock); // both QHs in one go
+ spin_lock (&s->td_lock); // both QHs in one go
insert_qh (s, s->chain_end, qh, 0); // Main QH
insert_qh (s, s->chain_end, nqh, 0); // Helper QH
spin_unlock (&s->td_lock);
@@ -954,83 +968,102 @@ _static void uhci_clean_iso_step2(uhci_t *s, urb_priv_t *urb_priv)
}
}
/*-------------------------------------------------------------------*/
-// mode: 0: unlink + no deletion mark, 1: regular (unlink/delete-mark), 2: don't unlink
+// mode: 0: unlink but no deletion mark (step 1 of async_unlink)
+// 1: regular (unlink/delete-mark)
+// 2: deletion mark for QH (step 2 of async_unlink)
// looks a bit complicated because of all the bulk queueing goodies
_static void uhci_clean_transfer (uhci_t *s, urb_t *urb, uhci_desc_t *qh, int mode)
{
- uhci_desc_t *bqh, *nqh, *prevqh;
+ uhci_desc_t *bqh, *nqh, *prevqh, *prevtd;
int now;
urb_priv_t *priv=(urb_priv_t*)urb->hcpriv;
now=UHCI_GET_CURRENT_FRAME(s);
- dbg("clean transfer urb %p, qh %p, mode %i",urb,qh,mode);
bqh=priv->bottom_qh;
-
+
if (!priv->next_queued_urb) { // no more appended bulk queues
- if (mode != 2)
- unlink_qh (s, qh);
+ queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p",urb, qh, bqh, priv->next_qh);
- if (priv->prev_queued_urb) {
+ if (priv->prev_queued_urb) { // qh not top of the queue
urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
- ppriv->bottom_qh = priv->bottom_qh;
- ppriv->next_queued_urb = NULL;
+ if (mode != 2) {
+ unsigned long flags;
+
+ spin_lock_irqsave (&s->qh_lock, flags);
+ prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
+ prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical);
+ prevtd->hw.td.link = virt_to_bus(priv->bottom_qh) | UHCI_PTR_QH; // skip current qh
+ mb();
+ queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd);
+ spin_unlock_irqrestore (&s->qh_lock, flags);
+
+ ppriv->bottom_qh = priv->bottom_qh;
+ ppriv->next_queued_urb = NULL;
+ }
}
- else if (bqh) { // queue dead
- nqh=priv->next_qh;
+ else { // queue is dead, qh is top of the queue
- if (mode != 2)
- unlink_qh(s, nqh);
-
- if (mode) {
- nqh->last_used = bqh->last_used = now;
- list_add_tail (&nqh->horizontal, &s->free_desc);
- list_add_tail (&bqh->horizontal, &s->free_desc);
- }
+ if (mode!=2)
+ unlink_qh(s, qh); // remove qh from horizontal chain
+
+ if (bqh) { // remove remainings of bulk queue
+ nqh=priv->next_qh;
+
+ if (mode != 2)
+ unlink_qh(s, nqh); // remove nqh from horizontal chain
+
+ if (mode) {
+ nqh->last_used = bqh->last_used = now;
+ list_add_tail (&nqh->horizontal, &s->free_desc);
+ list_add_tail (&bqh->horizontal, &s->free_desc);
+ }
+ }
}
}
else { // there are queued urbs following
- urb_t *nurb;
- unsigned long flags;
-
- nurb=priv->next_queued_urb;
- spin_lock_irqsave (&s->qh_lock, flags);
-
- if (!priv->prev_queued_urb) { // top
- if (mode !=2) {
+
+ queue_dbg("uhci_clean_transfer: urb %p, prevurb %p, nexturb %p, qh %p, bqh %p, nqh %p",
+ urb, priv->prev_queued_urb, priv->next_queued_urb, qh, bqh, priv->next_qh);
+
+ if (mode !=2) { // no work for cleanup at unlink-completion
+ urb_t *nurb;
+ unsigned long flags;
+
+ nurb = priv->next_queued_urb;
+ spin_lock_irqsave (&s->qh_lock, flags);
+
+ if (!priv->prev_queued_urb) { // top QH
+
prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal);
prevqh->hw.qh.head = virt_to_bus(bqh) | UHCI_PTR_QH;
- queue_dbg ("TOP relink of %p to %p-%p",qh,prevqh,bqh);
-
- list_del (&qh->horizontal);
- list_add (&bqh->horizontal, &prevqh->horizontal);
- }
- }
- else { //intermediate
- urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
- uhci_desc_t * bnqh;
-
- bnqh=list_entry (&((urb_priv_t*)(nurb->hcpriv))->desc_list.next, uhci_desc_t, desc_list);
- ppriv->bottom_qh=bnqh;
- ppriv->next_queued_urb=nurb;
-
- if (mode!=2) {
+ list_del (&qh->horizontal); // remove this qh form horizontal chain
+ list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain
+ }
+ else { // intermediate QH
+ urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
+ urb_priv_t* npriv=(urb_priv_t*)nurb->hcpriv;
+ uhci_desc_t * bnqh;
+
+ bnqh = list_entry (npriv->desc_list.next, uhci_desc_t, desc_list);
+ ppriv->bottom_qh = bnqh;
+ ppriv->next_queued_urb = nurb;
prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
prevqh->hw.qh.head = virt_to_bus(bqh) | UHCI_PTR_QH;
- queue_dbg ("IM relink of %p to %p-%p",qh,prevqh,bqh);
}
- }
- mb();
- spin_unlock_irqrestore (&s->qh_lock, flags);
- ((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb;
+
+ mb();
+ spin_unlock_irqrestore (&s->qh_lock, flags);
+ ((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb;
+ }
}
if (mode) {
- qh->last_used = now;
- list_add_tail (&qh->horizontal, &s->free_desc); // mark for later deletion
+ qh->last_used = now;
+ list_add_tail (&qh->horizontal, &s->free_desc); // mark for later deletion/kfree
}
}
/*-------------------------------------------------------------------*/
@@ -1070,13 +1103,14 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb)
uhci_switch_timer_int(s);
s->unlink_urb_done=1;
+ uhci_release_bandwidth(urb);
+ urb->status = -ENOENT; // mark urb as killed
+
if (!in_interrupt())
spin_unlock(&urb->lock);
- uhci_release_bandwidth(urb);
spin_unlock_irqrestore (&s->urb_list_lock, flags);
- urb->status = -ENOENT; // mark urb as killed
urb_priv = urb->hcpriv;
switch (usb_pipetype (urb->pipe)) {
@@ -1092,8 +1126,8 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb)
case PIPE_BULK:
case PIPE_CONTROL:
- qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list);
spin_lock_irqsave (&s->urb_list_lock, flags);
+ qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list);
uhci_clean_transfer(s, urb, qh, 1);
spin_unlock_irqrestore (&s->urb_list_lock, flags);
uhci_wait_ms(1);
@@ -1149,7 +1183,7 @@ _static void uhci_cleanup_unlink(uhci_t *s, int force)
async_dbg("async cleanup %p",urb);
switch (usb_pipetype (urb->pipe)) { // process descriptors
case PIPE_CONTROL:
- process_transfer (s, urb, 2);
+ process_transfer (s, urb, 2); // 2: don't unlink (already done)
break;
case PIPE_BULK:
if (!s->avoid_bulk.counter)
@@ -1201,6 +1235,7 @@ _static void uhci_cleanup_unlink(uhci_t *s, int force)
}
/*-------------------------------------------------------------------*/
+// needs urb_list_lock!
_static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb)
{
uhci_desc_t *qh;
@@ -1570,7 +1605,7 @@ _static int uhci_submit_urb (urb_t *urb)
urb_priv_t *urb_priv;
int ret = 0;
unsigned long flags;
- urb_t *bulk_urb=NULL;
+ urb_t *queued_urb=NULL;
int bustime;
if (!urb->dev || !urb->dev->bus)
@@ -1589,18 +1624,18 @@ _static int uhci_submit_urb (urb_t *urb)
spin_lock_irqsave (&s->urb_list_lock, flags);
- bulk_urb = search_dev_ep (s, urb);
+ queued_urb = search_dev_ep (s, urb); // returns already queued urb for that pipe
- if (bulk_urb) {
+ if (queued_urb) {
- queue_dbg("found bulk urb %p\n",bulk_urb);
+ queue_dbg("found bulk urb %p\n", queued_urb);
if ((usb_pipetype (urb->pipe) != PIPE_BULK) ||
((usb_pipetype (urb->pipe) == PIPE_BULK) &&
- (!(urb->transfer_flags & USB_QUEUE_BULK) || !(bulk_urb->transfer_flags & USB_QUEUE_BULK)))) {
+ (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) {
spin_unlock_irqrestore (&s->urb_list_lock, flags);
usb_dec_dev_use (urb->dev);
- err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb);
+ err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,queued_urb);
return -ENXIO; // urb already queued
}
}
@@ -1627,14 +1662,14 @@ _static int uhci_submit_urb (urb_t *urb)
if (usb_pipetype (urb->pipe) == PIPE_BULK) {
- if (bulk_urb) {
- while (((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb) // find last queued bulk
- bulk_urb=((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb;
+ if (queued_urb) {
+ while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb) // find last queued bulk
+ queued_urb=((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb;
- ((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb=urb;
+ ((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb=urb;
}
atomic_inc (&s->avoid_bulk);
- ret = uhci_submit_bulk_urb (urb, bulk_urb);
+ ret = uhci_submit_bulk_urb (urb, queued_urb);
atomic_dec (&s->avoid_bulk);
spin_unlock_irqrestore (&s->urb_list_lock, flags);
}
@@ -2214,7 +2249,7 @@ struct usb_operations uhci_device_operations =
* have announced. This leads to a queue abort due to the short packet,
* the status stage is not executed. If this happens, the status stage
* is manually re-executed.
- * mode: 0: QHs already unlinked
+ * mode: 1: regular (unlink QH), 2: QHs already unlinked (for async unlink_urb)
*/
_static int process_transfer (uhci_t *s, urb_t *urb, int mode)
@@ -2231,7 +2266,7 @@ _static int process_transfer (uhci_t *s, urb_t *urb, int mode)
int actual_length;
int status = 0;
- //dbg("process_transfer: urb contains bulk/control request");
+ //dbg("process_transfer: urb %p, urb_priv %p, qh %p last_desc %p\n",urb,urb_priv, qh, last_desc);
/* if the status phase has been retriggered and the
queue is empty or the last status-TD is inactive, the retriggered
@@ -2305,7 +2340,7 @@ _static int process_transfer (uhci_t *s, urb_t *urb, int mode)
transfer_finished:
- uhci_clean_transfer(s, urb, qh, (mode==0?2:1));
+ uhci_clean_transfer(s, urb, qh, mode);
urb->status = status;
@@ -2511,7 +2546,6 @@ _static int process_urb (uhci_t *s, struct list_head *p)
}
if (urb->status != -EINPROGRESS) {
- int proceed = 0;
struct usb_device *usb_dev;
usb_dev=urb->dev;
@@ -2533,64 +2567,77 @@ _static int process_urb (uhci_t *s, struct list_head *p)
kfree (urb->hcpriv);
#endif
- if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) {
- urb_t *tmp = urb->next; // pointer to first urb
+ if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) { // process_interrupt does completion on its own
+ urb_t *next_urb = urb->next;
int is_ring = 0;
+ int contains_killed = 0;
+ int loop_count=0;
- if (urb->next) {
- do {
- if (tmp->status != -EINPROGRESS) {
- proceed = 1;
+ if (next_urb) {
+ // Find out if the URBs are linked to a ring
+ while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) {
+ if (next_urb->status == -ENOENT) {// killed URBs break ring structure & resubmission
+ contains_killed = 1;
break;
- }
- tmp = tmp->next;
+ }
+ next_urb = next_urb->next;
+ loop_count++;
}
- while (tmp != NULL && tmp != urb->next);
- if (tmp == urb->next)
- is_ring = 1;
- }
+
+ if (loop_count == MAX_NEXT_COUNT)
+ err("process_urb: Too much linked URBs in ring detection!");
+ if (next_urb == urb)
+ is_ring=1;
+ }
+
spin_lock(&urb->lock);
- spin_unlock(&s->urb_list_lock);
- // In case you need the current URB status for your completion handler (before resubmit)
- if (urb->complete && (!proceed )) {
- dbg("process_transfer: calling early completion");
+ // Submit idle/non-killed URBs linked with urb->next
+ // Stop before the current URB
+
+ next_urb = urb->next;
+ if (next_urb && !contains_killed) {
+ int ret_submit;
+ next_urb = urb->next;
+
+ loop_count=0;
+ while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) {
+ if (next_urb->status != -EINPROGRESS) {
+
+ if (next_urb->status == -ENOENT)
+ break;
+
+ spin_unlock(&s->urb_list_lock);
+
+ ret_submit=uhci_submit_urb(next_urb);
+ spin_lock(&s->urb_list_lock);
+
+ if (ret_submit)
+ break;
+ }
+ loop_count++;
+ next_urb = next_urb->next;
+ }
+ if (loop_count == MAX_NEXT_COUNT)
+ err("process_urb: Too much linked URBs in resubmission!");
+ }
+
+ // Completion
+ if (urb->complete) {
urb->dev = NULL;
+ spin_unlock(&s->urb_list_lock);
urb->complete ((struct urb *) urb);
- if (!proceed && is_ring && (urb->status != -ENOENT)) {
+ // Re-submit the URB if ring-linked
+ if (is_ring && (urb->status != -ENOENT) && !contains_killed) {
urb->dev=usb_dev;
uhci_submit_urb (urb);
}
- }
- else if (!urb->complete)
- urb->dev = NULL;
-
- if (proceed && urb->next) {
- // if there are linked urbs - handle submitting of them right now.
- tmp = urb->next; // pointer to first urb
-
- do {
- if ((tmp->status != -EINPROGRESS) && (tmp->status != -ENOENT) && uhci_submit_urb (tmp) != 0)
- break;
- tmp = tmp->next;
- }
- while (tmp != NULL && tmp != urb->next); // submit until we reach NULL or our own pointer or submit fails
-
- if (urb->complete) {
- dbg("process_transfer: calling completion");
- if (urb->status!=-EINPROGRESS)
- urb->dev=NULL;
- urb->complete ((struct urb *) urb);
- }
- else
- if (urb->status!=-EINPROGRESS)
- urb->dev=NULL;
+ spin_lock(&s->urb_list_lock);
}
usb_dec_dev_use (usb_dev);
spin_unlock(&urb->lock);
- spin_lock(&s->urb_list_lock);
}
}
@@ -2603,7 +2650,8 @@ _static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
unsigned int io_addr = s->io_addr;
unsigned short status;
struct list_head *p, *p2;
-
+ int restarts, work_done;
+
/*
* Read the interrupt status, and write it back to clear the
* interrupt cause
@@ -2631,20 +2679,34 @@ _static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
* may be added at the end.
* also, because process_urb may unlink the current urb,
* we need to advance the list before
+ * New: check for max. workload and restart count
*/
spin_lock (&s->urb_list_lock);
+
+ restarts=0;
+ work_done=0;
+
restart:
s->unlink_urb_done=0;
p = s->urb_list.prev;
- while (p != &s->urb_list) {
+ while (p != &s->urb_list && (work_done < 1024)) {
p2 = p;
p = p->prev;
+
process_urb (s, p2);
+
+ work_done++;
+
if (s->unlink_urb_done) {
s->unlink_urb_done=0;
- goto restart;
+ restarts++;
+
+ if (restarts<16) // avoid endless restarts
+ goto restart;
+ else
+ break;
}
}
if ((jiffies - s->timeout_check) > (HZ/30))
@@ -2706,8 +2768,10 @@ _static void start_hc (uhci_t *s)
s->running = 1;
}
-_static void uhci_cleanup_dev(uhci_t *s)
+_static void __devexit
+uhci_pci_remove (struct pci_dev *dev)
{
+ uhci_t *s = (uhci_t*) dev->driver_data;
struct usb_device *root_hub = s->bus->root_hub;
s->running = 0; // Don't allow submit_urb
@@ -2750,28 +2814,23 @@ _static int __init uhci_start_usb (uhci_t *s)
return 0;
}
-_static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data)
+_static void
+uhci_pci_suspend (struct pci_dev *dev)
{
- uhci_t *s = (uhci_t*) dev->data;
- dbg("handle_apm_event(%d)", rqst);
- if (s) {
- switch (rqst) {
- case PM_SUSPEND:
- reset_hc (s);
- break;
- case PM_RESUME:
- start_hc (s);
- break;
- }
- }
- return 0;
+ reset_hc((uhci_t *) dev->driver_data);
}
-_static int __init alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
+_static void
+uhci_pci_resume (struct pci_dev *dev)
+{
+ start_hc((uhci_t *) dev->driver_data);
+}
+
+
+_static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
{
uhci_t *s;
struct usb_bus *bus;
- struct pm_dev *pmdev;
char buf[8], *bufp = buf;
#ifndef __sparc__
@@ -2798,7 +2857,6 @@ _static int __init alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_add
s->irq = -1;
s->io_addr = io_addr;
s->io_size = io_size;
- s->next = devs; //chain new uhci device into global list
s->timeout_check = 0;
s->uhci_pci=dev;
@@ -2859,53 +2917,90 @@ _static int __init alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_add
return -1;
}
+ /* Enable PIRQ */
+ pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
s->irq = irq;
if(uhci_start_usb (s) < 0) {
- uhci_cleanup_dev(s);
+ uhci_pci_remove(dev);
return -1;
}
//chain new uhci device into global list
- devs = s;
-
- pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(dev), handle_pm_event);
- if (pmdev)
- pmdev->data = s;
+ dev->driver_data = s;
+ devs=s;
return 0;
}
-_static int __init start_uhci (struct pci_dev *dev)
+_static int __devinit
+uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
int i;
+ if (pci_enable_device(dev) < 0)
+ return -ENODEV;
+
/* Search for the IO base address.. */
for (i = 0; i < 6; i++) {
unsigned int io_addr = dev->resource[i].start;
unsigned int io_size =
dev->resource[i].end - dev->resource[i].start + 1;
- if (!(dev->resource[i].flags & 1))
+ if (!(dev->resource[i].flags & IORESOURCE_IO))
continue;
/* Is it already in use? */
if (check_region (io_addr, io_size))
break;
/* disable legacy emulation */
- pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT);
-
+ pci_write_config_word (dev, USBLEGSUP, 0);
+
+ pci_set_master(dev);
return alloc_uhci(dev, dev->irq, io_addr, io_size);
}
- return -1;
+ return -ENODEV;
}
-static int __init uhci_init (void)
+/*-------------------------------------------------------------------------*/
+
+static const struct pci_device_id __devinitdata uhci_pci_ids [] = { {
+
+ /* handle any USB UHCI controller */
+ class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00),
+ class_mask: ~0,
+
+ /* no matter who makes it */
+ vendor: PCI_ANY_ID,
+ device: PCI_ANY_ID,
+ subvendor: PCI_ANY_ID,
+ subdevice: PCI_ANY_ID,
+
+ }, { /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE (pci, uhci_pci_ids);
+
+static struct pci_driver uhci_pci_driver = {
+ name: "usb-uhci",
+ id_table: &uhci_pci_ids [0],
+
+ probe: uhci_pci_probe,
+ remove: uhci_pci_remove,
+
+#ifdef CONFIG_PM
+ suspend: uhci_pci_suspend,
+ resume: uhci_pci_resume,
+#endif /* PM */
+
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init uhci_hcd_init (void)
{
- int retval = -ENODEV;
- struct pci_dev *dev = NULL;
- u8 type;
- int i=0;
+ int retval;
#ifdef DEBUG_SLAB
@@ -2929,31 +3024,8 @@ static int __init uhci_init (void)
#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
info("High bandwidth mode enabled");
#endif
- for (;;) {
- dev = pci_find_class (PCI_CLASS_SERIAL_USB << 8, dev);
- if (!dev)
- break;
- /* Is it UHCI */
- pci_read_config_byte (dev, PCI_CLASS_PROG, &type);
- if (type != 0)
- continue;
-
- if (pci_enable_device (dev) < 0)
- continue;
-
- if(!dev->irq)
- {
- err("Found UHCI device with no IRQ assigned. Check BIOS settings!");
- continue;
- }
-
- /* Ok set it up */
- retval = start_uhci (dev);
-
- if (!retval)
- i++;
- }
+ retval = pci_module_init (&uhci_pci_driver);
#ifdef DEBUG_SLAB
if (retval < 0 ) {
@@ -2967,13 +3039,10 @@ static int __init uhci_init (void)
return retval;
}
-static void __exit uhci_cleanup (void)
-{
- uhci_t *s;
- while ((s = devs)) {
- devs = devs->next;
- uhci_cleanup_dev(s);
- }
+static void __exit uhci_hcd_cleanup (void)
+{
+ pci_unregister_driver (&uhci_pci_driver);
+
#ifdef DEBUG_SLAB
if(kmem_cache_destroy(uhci_desc_kmem))
err("uhci_desc_kmem remained");
@@ -2983,14 +3052,9 @@ static void __exit uhci_cleanup (void)
#endif
}
-static void __exit uhci_exit (void)
-{
- pm_unregister_all (handle_pm_event);
- uhci_cleanup ();
-}
+module_init (uhci_hcd_init);
+module_exit (uhci_hcd_cleanup);
-module_init(uhci_init);
-module_exit(uhci_exit);
MODULE_AUTHOR("Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c
index 5b1b76003..fad7e48f6 100644
--- a/drivers/usb/usb.c
+++ b/drivers/usb/usb.c
@@ -30,7 +30,7 @@
#include <linux/interrupt.h> /* for in_interrupt() */
#include <linux/kmod.h>
#include <linux/init.h>
-
+#include <linux/devfs_fs_kernel.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
@@ -67,6 +67,8 @@ static void usb_check_support(struct usb_device *);
LIST_HEAD(usb_driver_list);
LIST_HEAD(usb_bus_list);
+devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
+
static struct usb_busmap busmap;
static struct usb_driver *usb_minors[16];
@@ -86,7 +88,7 @@ int usb_register(struct usb_driver *new_driver)
init_MUTEX(&new_driver->serialize);
/* Add it to the list of known drivers */
- list_add(&new_driver->driver_list, &usb_driver_list);
+ list_add_tail(&new_driver->driver_list, &usb_driver_list);
usb_scan_devices();
@@ -296,11 +298,13 @@ void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime,
else
dev->bus->bandwidth_int_reqs++;
urb->bandwidth = bustime;
-
+
+#ifdef USB_BANDWIDTH_MESSAGES
dbg("bandwidth alloc increased by %d to %d for %d requesters",
bustime,
dev->bus->bandwidth_allocated,
dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
+#endif
}
/*
@@ -316,10 +320,12 @@ void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, int isoc)
else
dev->bus->bandwidth_int_reqs--;
+#ifdef USB_BANDWIDTH_MESSAGES
dbg("bandwidth alloc reduced by %d to %d for %d requesters",
urb->bandwidth,
dev->bus->bandwidth_allocated,
dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
+#endif
urb->bandwidth = 0;
}
@@ -554,7 +560,7 @@ usb_match_id(struct usb_device *dev, struct usb_interface *interface,
continue;
if (id->bDeviceSubClass &&
- id->bDeviceSubClass!= dev->descriptor.bDeviceClass)
+ id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)
continue;
if (id->bDeviceProtocol &&
@@ -2047,9 +2053,9 @@ int usb_new_device(struct usb_device *dev)
if (err < 0) {
err("unable to get device %d configuration (error=%d)",
dev->devnum, err);
- usb_destroy_configuration(dev);
clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
dev->devnum = -1;
+ usb_free_dev(dev);
return 1;
}
@@ -2119,16 +2125,20 @@ static struct file_operations usb_fops = {
int usb_major_init(void)
{
- if (register_chrdev(USB_MAJOR,"usb",&usb_fops)) {
+ if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
err("unable to get major %d for usb devices", USB_MAJOR);
return -EBUSY;
}
+
+ usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);
+
return 0;
}
void usb_major_cleanup(void)
{
- unregister_chrdev(USB_MAJOR, "usb");
+ devfs_unregister(usb_devfs_handle);
+ devfs_unregister_chrdev(USB_MAJOR, "usb");
}
@@ -2231,3 +2241,5 @@ EXPORT_SYMBOL(usb_unlink_urb);
EXPORT_SYMBOL(usb_control_msg);
EXPORT_SYMBOL(usb_bulk_msg);
+
+EXPORT_SYMBOL(usb_devfs_handle);
diff --git a/drivers/usb/wacom.c b/drivers/usb/wacom.c
index af813ceab..e4ecaeba4 100644
--- a/drivers/usb/wacom.c
+++ b/drivers/usb/wacom.c
@@ -1,11 +1,12 @@
/*
- * $Id: wacom.c,v 1.11 2000/10/18 12:12:26 vojtech Exp $
+ * $Id: wacom.c,v 1.14 2000/11/23 09:34:32 vojtech Exp $
*
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk>
* Copyright (c) 2000 Clifford Wolf <clifford@clifford.at>
* Copyright (c) 2000 Sam Mosel <sam.mosel@computer.org>
* Copyright (c) 2000 James E. Blair <corvus@gnu.org>
+ * Copyright (c) 2000 Daniel Egger <egger@suse.de>
*
* USB Wacom Graphire and Wacom Intuos tablet support
*
@@ -24,6 +25,9 @@
* other cleanups
* v1.11 (vp) - Add URB ->dev setting for new kernels
* v1.11 (jb) - Add support for the 4D Mouse & Lens
+ * v1.12 (de) - Add support for two more inking pen IDs
+ * v1.14 (vp) - Use new USB device id probing scheme.
+ * Fix Wacom Graphire mouse wheel
*/
/*
@@ -129,7 +133,6 @@ MODULE_DESCRIPTION("USB Wacom Graphire and Wacom Intuos tablet driver");
struct wacom_features {
char *name;
- int idProduct;
int pktlen;
int x_max;
int y_max;
@@ -211,6 +214,8 @@ static void wacom_intuos_irq(struct urb *urb)
if (((data[1] >> 5) & 0x3) == 0x2) { /* Enter report */
switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
+ case 0x832:
+ case 0x812:
case 0x012: wacom->tool = BTN_TOOL_PENCIL; break; /* Inking pen */
case 0x822:
case 0x022: wacom->tool = BTN_TOOL_PEN; break; /* Pen */
@@ -279,21 +284,33 @@ static void wacom_intuos_irq(struct urb *urb)
#define WACOM_INTUOS_ABS (BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE))
struct wacom_features wacom_features[] = {
- { "Wacom Graphire", 0x10, 8, 10206, 7422, 511, 32, wacom_graphire_irq,
- BIT(EV_REL), 0, 0, 0 },
- { "Wacom Intuos 4x5", 0x20, 10, 12700, 10360, 1023, 15, wacom_intuos_irq,
+ { "Wacom Graphire", 8, 10206, 7422, 511, 32, wacom_graphire_irq,
+ BIT(EV_REL), 0, REL_WHEEL, 0 },
+ { "Wacom Intuos 4x5", 10, 12700, 10360, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
- { "Wacom Intuos 6x8", 0x21, 10, 20320, 15040, 1023, 15, wacom_intuos_irq,
+ { "Wacom Intuos 6x8", 10, 20320, 15040, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
- { "Wacom Intuos 9x12", 0x22, 10, 30480, 23060, 1023, 15, wacom_intuos_irq,
+ { "Wacom Intuos 9x12", 10, 30480, 23060, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
- { "Wacom Intuos 12x12", 0x23, 10, 30480, 30480, 1023, 15, wacom_intuos_irq,
+ { "Wacom Intuos 12x12", 10, 30480, 30480, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
- { "Wacom Intuos 12x18", 0x24, 10, 47720, 30480, 1023, 15, wacom_intuos_irq,
+ { "Wacom Intuos 12x18", 10, 47720, 30480, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
{ NULL , 0 }
};
+struct usb_device_id wacom_ids[] = {
+ { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x10, driver_info: 0 },
+ { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x20, driver_info: 1 },
+ { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x21, driver_info: 2 },
+ { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x22, driver_info: 3 },
+ { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x23, driver_info: 4 },
+ { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x24, driver_info: 5 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(usb, wacom_ids);
+
static int wacom_open(struct input_dev *dev)
{
struct wacom *wacom = dev->private;
@@ -316,22 +333,15 @@ static void wacom_close(struct input_dev *dev)
usb_unlink_urb(&wacom->irq);
}
-static void *wacom_probe(struct usb_device *dev, unsigned int ifnum)
+static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
{
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
- int i;
-
- if (dev->descriptor.idVendor != USB_VENDOR_ID_WACOM) return NULL;
- for (i = 0; wacom_features[i].idProduct && wacom_features[i].idProduct != dev->descriptor.idProduct; i++);
- if (!wacom_features[i].idProduct) return NULL;
-
- endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
memset(wacom, 0, sizeof(struct wacom));
- wacom->features = wacom_features + i;
+ wacom->features = wacom_features + id->driver_info;
wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | wacom->features->evbit;
wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | wacom->features->absbit;
@@ -366,6 +376,8 @@ static void *wacom_probe(struct usb_device *dev, unsigned int ifnum)
wacom->dev.idversion = dev->descriptor.bcdDevice;
wacom->usbdev = dev;
+ endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
+
FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval);
@@ -389,6 +401,7 @@ static struct usb_driver wacom_driver = {
name: "wacom",
probe: wacom_probe,
disconnect: wacom_disconnect,
+ id_table: wacom_ids,
};
static int __init wacom_init(void)
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 96de87f86..54dd6eca1 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -68,7 +68,7 @@ obj-$(CONFIG_FB_CYBER) += cyberfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
-obj-$(CONFIG_FB_MAC) += macfb.o
+obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o
obj-$(CONFIG_FB_HP300) += hpfb.o
obj-$(CONFIG_FB_OF) += offb.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index e6ad28fcf..44f6fc8c5 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -750,13 +750,6 @@ static struct fb_info fb_info;
/*
- * The minimum period for audio depends on htotal (for OCS/ECS/AGA)
- * (Imported from arch/m68k/amiga/amisound.c)
- */
-
-extern volatile u_short amiga_audio_min_period;
-
- /*
* Since we can't read the palette on OCS/ECS, and since reading one
* single color palette entry requires 5 expensive custom chip bus accesses
* on AGA, we keep a copy of the current palette.
@@ -1206,6 +1199,8 @@ int __init amifb_setup(char *options)
if (!strcmp(this_opt, "inverse")) {
amifb_inverse = 1;
fb_invert_cmaps();
+ } else if (!strcmp(this_opt, "off")) {
+ amifb_video_off();
} else if (!strcmp(this_opt, "ilbm"))
amifb_ilbm = 1;
else if (!strncmp(this_opt, "monitorcap:", 11))
@@ -1771,7 +1766,7 @@ default_chipset:
* access the videomem with writethrough cache
*/
videomemory_phys = (u_long)ZTWO_PADDR(videomemory);
- videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize);
+ //videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize);
if (!videomemory) {
printk("amifb: WARNING! unable to map videomem cached writethrough\n");
videomemory = ZTWO_VADDR(videomemory_phys);
@@ -1792,15 +1787,11 @@ default_chipset:
ami_init_copper();
- if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, 0,
- "fb vertb handler", NULL)) {
+ if (request_irq(IRQ_AMIGA_VERTB, amifb_interrupt, 0,
+ "fb vertb handler", &currentpar)) {
err = -EBUSY;
goto amifb_error;
}
- amiga_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER;
- amiga_intena_vals[IRQ_AMIGA_COPPER] = 0;
- custom.intena = IF_VERTB;
- custom.intena = IF_SETCLR | IF_COPER;
amifb_set_var(&var, -1, &fb_info);
@@ -1895,57 +1886,33 @@ static int flash_cursor(void)
static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
{
- u_short ints = custom.intreqr & custom.intenar;
- static struct irq_server server = {0, 0};
- unsigned long flags;
-
- if (ints & IF_BLIT) {
- custom.intreq = IF_BLIT;
- amiga_do_irq(IRQ_AMIGA_BLIT, fp);
- }
-
- if (ints & IF_COPER) {
- custom.intreq = IF_COPER;
- if (do_vmode_pan || do_vmode_full)
- ami_update_display();
-
- if (do_vmode_full)
- ami_init_display();
-
- if (do_vmode_pan) {
- flash_cursor();
- ami_rebuild_copper();
- do_cursor = do_vmode_pan = 0;
- } else if (do_cursor) {
- flash_cursor();
+ if (do_vmode_pan || do_vmode_full)
+ ami_update_display();
+
+ if (do_vmode_full)
+ ami_init_display();
+
+ if (do_vmode_pan) {
+ flash_cursor();
+ ami_rebuild_copper();
+ do_cursor = do_vmode_pan = 0;
+ } else if (do_cursor) {
+ flash_cursor();
+ ami_set_sprite();
+ do_cursor = 0;
+ } else {
+ if (flash_cursor())
ami_set_sprite();
- do_cursor = 0;
- } else {
- if (flash_cursor())
- ami_set_sprite();
- }
-
- save_flags(flags);
- cli();
- if (get_vbpos() < down2(currentpar.diwstrt_v - 6))
- custom.copjmp2 = 0;
- restore_flags(flags);
-
- if (do_blank) {
- ami_do_blank();
- do_blank = 0;
- }
+ }
- if (do_vmode_full) {
- ami_reinit_copper();
- do_vmode_full = 0;
- }
- amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+ if (do_blank) {
+ ami_do_blank();
+ do_blank = 0;
}
- if (ints & IF_VERTB) {
- printk("%s: Warning: IF_VERTB was enabled\n", __FUNCTION__);
- custom.intena = IF_VERTB;
+ if (do_vmode_full) {
+ ami_reinit_copper();
+ do_vmode_full = 0;
}
}
@@ -3379,5 +3346,6 @@ void cleanup_module(void)
{
unregister_framebuffer(&fb_info);
amifb_deinit();
+ amifb_video_off();
}
#endif /* MODULE */
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index c09a691a8..e305027a7 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2425,6 +2425,21 @@ do_install_cmap(int con, struct fb_info *info)
}
static int
+atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ struct atafb_par par;
+ if (con == -1)
+ atafb_get_par(&par);
+ else {
+ int err;
+ if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
+ return err;
+ }
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ return fbhw->encode_fix(fix, &par);
+}
+
+static int
atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
struct atafb_par par;
@@ -2776,7 +2791,7 @@ int __init atafb_init(void)
#endif /* ATAFB_EXT */
mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
- screen_base = atari_stram_alloc(mem_req, NULL, "atafb");
+ screen_base = atari_stram_alloc(mem_req, "atafb");
if (!screen_base)
panic("Cannot allocate screen memory");
memset(screen_base, 0, mem_req);
diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c
index 05fcfcbe1..626bf3cad 100644
--- a/drivers/video/aty128fb.c
+++ b/drivers/video/aty128fb.c
@@ -283,7 +283,6 @@ struct fb_info_aty128 {
const struct aty128_meminfo *mem; /* onboard mem info */
struct aty128fb_par default_par, current_par;
struct display disp;
- struct display_switch dispsw; /* for cursor and font */
struct { u8 red, green, blue, pad; } palette[256];
union {
#ifdef FBCON_HAS_CFB16
@@ -347,7 +346,7 @@ static void aty128fbcon_blank(int blank, struct fb_info *fb);
static void aty128_encode_fix(struct fb_fix_screeninfo *fix,
struct aty128fb_par *par,
const struct fb_info_aty128 *info);
-static void aty128_set_disp(struct display *disp,
+static void aty128_set_dispsw(struct display *disp,
struct fb_info_aty128 *info, int bpp, int accel);
static int aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
@@ -1392,7 +1391,7 @@ aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
display->inverse = 0;
accel = var->accel_flags & FB_ACCELF_TEXT;
- aty128_set_disp(display, info, par.crtc.bpp, accel);
+ aty128_set_dispsw(display, info, par.crtc.bpp, accel);
if (accel)
display->scrollmode = SCROLL_YNOMOVE;
@@ -1417,35 +1416,31 @@ aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
static void
-aty128_set_disp(struct display *disp,
+aty128_set_dispsw(struct display *disp,
struct fb_info_aty128 *info, int bpp, int accel)
{
switch (bpp) {
#ifdef FBCON_HAS_CFB8
case 8:
- info->dispsw = accel ? fbcon_aty128_8 : fbcon_cfb8;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 15:
case 16:
- info->dispsw = accel ? fbcon_aty128_16 : fbcon_cfb16;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;
disp->dispsw_data = info->fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
- info->dispsw = accel ? fbcon_aty128_24 : fbcon_cfb24;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24;
disp->dispsw_data = info->fbcon_cmap.cfb24;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
- info->dispsw = accel ? fbcon_aty128_32 : fbcon_cfb32;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32;
disp->dispsw_data = info->fbcon_cmap.cfb32;
break;
#endif
@@ -2135,7 +2130,7 @@ aty128fbcon_switch(int con, struct fb_info *fb)
aty128_decode_var(&fb_display[con].var, &par, info);
aty128_set_par(&par, info);
- aty128_set_disp(&fb_display[con], info, par.crtc.bpp,
+ aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp,
par.accel_flags & FB_ACCELF_TEXT);
do_install_cmap(con, fb);
diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c
index 48b3b4ca2..fb3b09bc9 100644
--- a/drivers/video/atyfb.c
+++ b/drivers/video/atyfb.c
@@ -466,8 +466,8 @@ static void set_off_pitch(struct atyfb_par *par,
static int encode_fix(struct fb_fix_screeninfo *fix,
const struct atyfb_par *par,
const struct fb_info_aty *info);
-static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
- int bpp, int accel);
+static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
+ int bpp, int accel);
static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *fb);
static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -2826,8 +2826,8 @@ static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
}
-static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
- int bpp, int accel)
+static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
+ int bpp, int accel)
{
switch (bpp) {
#ifdef FBCON_HAS_CFB8
@@ -2898,6 +2898,7 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
oldbpp = display->var.bits_per_pixel;
oldaccel = display->var.accel_flags;
display->var = *var;
+ accel = var->accel_flags & FB_ACCELF_TEXT;
if (oldxres != var->xres || oldyres != var->yres ||
oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
@@ -2913,8 +2914,6 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
display->line_length = fix.line_length;
display->can_soft_blank = 1;
display->inverse = 0;
- accel = var->accel_flags & FB_ACCELF_TEXT;
- atyfb_set_disp(display, info, par.crtc.bpp, accel);
if (accel)
display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
else
@@ -2923,8 +2922,10 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
(*info->fb_info.changevar)(con);
}
if (!info->fb_info.display_fg ||
- info->fb_info.display_fg->vc_num == con)
+ info->fb_info.display_fg->vc_num == con) {
atyfb_set_par(&par, info);
+ atyfb_set_dispsw(display, info, par.crtc.bpp, accel);
+ }
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
@@ -4241,8 +4242,8 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
atyfb_decode_var(&fb_display[con].var, &par, info);
atyfb_set_par(&par, info);
- atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
- par.accel_flags & FB_ACCELF_TEXT);
+ atyfb_set_dispsw(&fb_display[con], info, par.crtc.bpp,
+ par.accel_flags & FB_ACCELF_TEXT);
/* Install new colormap */
do_install_cmap(con, fb);
diff --git a/drivers/video/dummycon.c b/drivers/video/dummycon.c
index 3e08ebcb2..f7a09a5d0 100644
--- a/drivers/video/dummycon.c
+++ b/drivers/video/dummycon.c
@@ -20,6 +20,9 @@
#if defined(__arm__)
#define DUMMY_COLUMNS ORIG_VIDEO_COLS
#define DUMMY_ROWS ORIG_VIDEO_LINES
+#elif defined(__hppa__)
+#define DUMMY_COLUMNS 80 /* fixme ! (mine uses 160x64 at 1280x1024) */
+#define DUMMY_ROWS 25
#else
#define DUMMY_COLUMNS 80
#define DUMMY_ROWS 25
diff --git a/drivers/video/fbcon-sti.c b/drivers/video/fbcon-sti.c
new file mode 100644
index 000000000..174ad05c4
--- /dev/null
+++ b/drivers/video/fbcon-sti.c
@@ -0,0 +1,330 @@
+/*
+ * linux/drivers/video/fbcon-sti.c -- Low level frame buffer
+ * operations for generic HP video boards using STI (standard
+ * text interface) firmware
+ *
+ * Based on linux/drivers/video/fbcon-artist.c
+ * Created 5 Apr 1997 by Geert Uytterhoeven
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details. */
+
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <asm/delay.h>
+#include <asm/types.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+
+#include "sti.h"
+
+/* Translate an address as it would be found in a 2048x2048x1 bit frame
+ * buffer into a logical address Artist actually expects. Addresses fed
+ * into Artist look like this:
+ * fixed Y X
+ * FFFF FFFF LLLL LLLL LLLC CCCC CCCC CC00
+ *
+ * our "RAM" addresses look like this:
+ *
+ * FFFF FFFF 0000 0LLL LLLL LLLL CCCC CCCC [CCC]
+ *
+ * */
+
+static inline u32
+ram2log(void * addr)
+{
+ u32 a = (unsigned long) addr;
+ u32 r;
+
+#if 0
+ r = a & 0xff000000; /* fixed part */
+ r += ((a & 0x000000ff) << 5);
+ r += ((a & 0x00ffff00) << 3);
+#else
+ r = a & 0xff000000; /* fixed part */
+ r += ((a & 0x000000ff) << 5);
+ r += ((a & 0x0007ff00) << 5);
+#endif
+
+ return r;
+}
+
+/* All those functions need better names. */
+
+static void
+memcpy_fromhp_tohp(void *dest, void *src, int count)
+{
+ unsigned long d = ram2log(dest);
+ unsigned long s = ram2log(src);
+
+ count += 3;
+ count &= ~3; /* XXX */
+
+ while(count) {
+ count --;
+ gsc_writel(~gsc_readl(s), d);
+ d += 32*4;
+ s += 32*4;
+ }
+}
+
+static void
+memcpy_tohp(void *dest, void *src, int count)
+{
+ unsigned long d = (unsigned long) dest;
+ u32 *s = (u32 *)src;
+
+ count += 3;
+ count &= ~3; /* XXX */
+
+ d = ram2log(dest);
+
+ while(count) {
+ count--;
+ gsc_writel(*s++, d);
+ d += 32*4;
+ }
+}
+
+static void
+memcopy_fromhp(void *dest, void *src, int count)
+{
+ /* FIXME */
+ printk("uhm ...\n");
+}
+
+static void
+memset_tohp(void *dest, u32 word, int count)
+{
+ unsigned long d = ram2log(dest);
+
+ count += 3;
+ count &= ~3;
+
+ while(count) {
+ count--;
+ gsc_writel(word, d);
+ d += 32;
+ }
+}
+
+static u8
+readb_hp(void *src)
+{
+ unsigned long s = ram2log(src);
+
+ return ~gsc_readb(s);
+}
+
+static void
+writeb_hp(u8 b, void *dst)
+{
+ unsigned long d = ram2log(dst);
+
+ if((d&0xf0000000) != 0xf0000000) {
+ printk("writeb_hp %02x %p (%08lx) (%p)\n",
+ b, dst, d, __builtin_return_address(0));
+ return;
+ }
+
+ gsc_writeb(b, d);
+}
+
+static void
+fbcon_sti_setup(struct display *p)
+{
+ if (p->line_length)
+ p->next_line = p->line_length;
+ else
+ p->next_line = p->var.xres_virtual>>3;
+ p->next_plane = 0;
+}
+
+static void
+fbcon_sti_bmove(struct display *p, int sy, int sx,
+ int dy, int dx,
+ int height, int width)
+{
+#if 0 /* Unfortunately, still broken */
+ sti_bmove(&default_sti /* FIXME */, sy, sx, dy, dx, height, width);
+#else
+ u8 *src, *dest;
+ u_int rows;
+
+ if (sx == 0 && dx == 0 && width == p->next_line) {
+ src = p->screen_base+sy*fontheight(p)*width;
+ dest = p->screen_base+dy*fontheight(p)*width;
+ memcpy_fromhp_tohp(dest, src, height*fontheight(p)*width);
+ } else if (dy <= sy) {
+ src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+ dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
+ for (rows = height*fontheight(p); rows--;) {
+ memcpy_fromhp_tohp(dest, src, width);
+ src += p->next_line;
+ dest += p->next_line;
+ }
+ } else {
+ src = p->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
+ dest = p->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
+ for (rows = height*fontheight(p); rows--;) {
+ memcpy_fromhp_tohp(dest, src, width);
+ src -= p->next_line;
+ dest -= p->next_line;
+ }
+ }
+#endif
+}
+
+static void
+fbcon_sti_clear(struct vc_data *conp,
+ struct display *p, int sy, int sx,
+ int height, int width)
+{
+ u8 *dest;
+ u_int rows;
+ int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
+
+ dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+
+ if (sx == 0 && width == p->next_line) {
+ if (inverse)
+ memset_tohp(dest, ~0, height*fontheight(p)*width);
+ else
+ memset_tohp(dest, 0, height*fontheight(p)*width);
+ } else
+ for (rows = height*fontheight(p); rows--; dest += p->next_line)
+ if (inverse)
+ memset_tohp(dest, 0xffffffff, width);
+ else
+ memset_tohp(dest, 0x00000000, width);
+}
+
+static void fbcon_sti_putc(struct vc_data *conp,
+ struct display *p, int c,
+ int yy, int xx)
+{
+ u8 *dest, *cdat;
+ u_int rows, bold, revs, underl;
+ u8 d;
+
+ dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+ cdat = p->fontdata+(c&p->charmask)*fontheight(p);
+ bold = attr_bold(p,c);
+ revs = attr_reverse(p,c);
+ underl = attr_underline(p,c);
+
+ for (rows = fontheight(p); rows--; dest += p->next_line) {
+ d = *cdat++;
+ if (underl && !rows)
+ d = 0xff;
+ else if (bold)
+ d |= d>>1;
+ if (revs)
+ d = ~d;
+ writeb_hp (d, dest);
+ }
+}
+
+static void fbcon_sti_putcs(struct vc_data *conp,
+ struct display *p,
+ const unsigned short *s,
+ int count, int yy, int xx)
+{
+ u8 *dest, *dest0, *cdat;
+ u_int rows, bold, revs, underl;
+ u8 d;
+ u16 c;
+
+ if(((unsigned)xx > 200) || ((unsigned) yy > 200)) {
+ printk("refusing to putcs %p %p %p %d %d %d (%p)\n",
+ conp, p, s, count, yy, xx, __builtin_return_address(0));
+ return;
+ }
+
+
+ dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+ if(((u32)dest0&0xf0000000)!=0xf0000000) {
+ printk("refusing to putcs %p %p %p %d %d %d (%p) %p = %p + %d * %d * %ld + %d\n",
+ conp, p, s, count, yy, xx, __builtin_return_address(0),
+ dest0, p->screen_base, yy, fontheight(p), p->next_line,
+ xx);
+ return;
+ }
+
+ bold = attr_bold(p,scr_readw(s));
+ revs = attr_reverse(p,scr_readw(s));
+ underl = attr_underline(p,scr_readw(s));
+
+ while (count--) {
+ c = scr_readw(s++) & p->charmask;
+ dest = dest0++;
+ cdat = p->fontdata+c*fontheight(p);
+ for (rows = fontheight(p); rows--; dest += p->next_line) {
+ d = *cdat++;
+ if (0 && underl && !rows)
+ d = 0xff;
+ else if (0 && bold)
+ d |= d>>1;
+ if (revs)
+ d = ~d;
+ writeb_hp (d, dest);
+ }
+ }
+}
+
+static void fbcon_sti_revc(struct display *p,
+ int xx, int yy)
+{
+ u8 *dest, d;
+ u_int rows;
+
+
+ dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+ for (rows = fontheight(p); rows--; dest += p->next_line) {
+ d = readb_hp(dest);
+ writeb_hp (~d, dest);
+ }
+}
+
+static void
+fbcon_sti_clear_margins(struct vc_data *conp,
+ struct display *p,
+ int bottom_only)
+{
+ u8 *dest;
+ int height, bottom;
+ int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
+
+
+ /* XXX Need to handle right margin? */
+
+ height = p->var.yres - conp->vc_rows * fontheight(p);
+ if (!height)
+ return;
+ bottom = conp->vc_rows + p->yscroll;
+ if (bottom >= p->vrows)
+ bottom -= p->vrows;
+ dest = p->screen_base + bottom * fontheight(p) * p->next_line;
+ if (inverse)
+ memset_tohp(dest, 0xffffffff, height * p->next_line);
+ else
+ memset_tohp(dest, 0x00000000, height * p->next_line);
+}
+
+
+ /*
+ * `switch' for the low level operations
+ */
+
+struct display_switch fbcon_sti = {
+ fbcon_sti_setup, fbcon_sti_bmove, fbcon_sti_clear,
+ fbcon_sti_putc, fbcon_sti_putcs, fbcon_sti_revc,
+ NULL, NULL, fbcon_sti_clear_margins,
+ FONTWIDTH(8)
+};
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index ba6d70289..60b76a447 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -113,6 +113,8 @@ extern int tdfxfb_init(void);
extern int tdfxfb_setup(char*);
extern int sisfb_init(void);
extern int sisfb_setup(char*);
+extern int stifb_init(void);
+extern int stifb_setup(char*);
extern int pmagbafb_init(void);
extern int pmagbafb_setup(char *);
@@ -200,6 +202,9 @@ static struct {
* management!
*/
+#ifdef CONFIG_FB_STI
+ { "stifb", stifb_init, stifb_setup },
+#endif
#ifdef CONFIG_FB_OF
{ "offb", offb_init, NULL },
#endif
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 8f984ae12..d1ff9c8cc 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -17,7 +17,9 @@
#include <linux/fb.h>
#include <linux/string.h>
+#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
+#endif
#include <video/fbcon.h>
#include <video/macmodes.h>
diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c
index d988d9e39..98e58b46c 100644
--- a/drivers/video/mdacon.c
+++ b/drivers/video/mdacon.c
@@ -77,10 +77,8 @@ static int mda_last_vc = 16;
static struct vc_data *mda_display_fg = NULL;
-#ifdef MODULE_PARM
MODULE_PARM(mda_first_vc, "1-255i");
MODULE_PARM(mda_last_vc, "1-255i");
-#endif
/* MDA register values
*/
@@ -200,11 +198,7 @@ void __init mdacon_setup(char *str, int *ints)
}
#endif
-#ifdef MODULE
-static int mda_detect(void)
-#else
static int __init mda_detect(void)
-#endif
{
int count=0;
u16 *p, p_save;
@@ -287,11 +281,7 @@ static int __init mda_detect(void)
return 1;
}
-#ifdef MODULE
-static void mda_initialize(void)
-#else
static void __init mda_initialize(void)
-#endif
{
write_mda_b(97, 0x00); /* horizontal total */
write_mda_b(80, 0x01); /* horizontal displayed */
@@ -316,11 +306,7 @@ static void __init mda_initialize(void)
outb_p(0x00, mda_gfx_port);
}
-#ifdef MODULE
-static const char *mdacon_startup(void)
-#else
static const char __init *mdacon_startup(void)
-#endif
{
mda_num_columns = 80;
mda_num_lines = 25;
@@ -605,11 +591,7 @@ const struct consw mda_con = {
con_invert_region: mdacon_invert_region,
};
-#ifdef MODULE
-void mda_console_init(void)
-#else
void __init mda_console_init(void)
-#endif
{
if (mda_first_vc > mda_last_vc)
return;
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 558b6f44e..20ab5c4e5 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -65,7 +65,6 @@ struct fb_par_platinum {
struct fb_info_platinum {
struct fb_info fb_info;
struct display disp;
- struct display_switch dispsw;
struct fb_par_platinum default_par;
struct fb_par_platinum current_par;
@@ -140,8 +139,9 @@ static int platinum_var_to_par(const struct fb_var_screeninfo *var,
static int platinum_encode_fix(struct fb_fix_screeninfo *fix,
const struct fb_par_platinum *par,
const struct fb_info_platinum *info);
-static void platinum_set_disp(struct display *disp, struct fb_info_platinum *info,
- int cmode, int accel);
+static void platinum_set_dispsw(struct display *disp,
+ struct fb_info_platinum *info, int cmode,
+ int accel);
static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *fb);
static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -193,27 +193,25 @@ static int platinum_get_var(struct fb_var_screeninfo *var, int con,
return 0;
}
-static void platinum_set_disp(struct display *disp, struct fb_info_platinum *info,
- int cmode, int accel)
+static void platinum_set_dispsw(struct display *disp,
+ struct fb_info_platinum *info, int cmode,
+ int accel)
{
switch(cmode) {
#ifdef FBCON_HAS_CFB8
case CMODE_8:
- info->dispsw = fbcon_cfb8;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = &fbcon_cfb8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case CMODE_16:
- info->dispsw = fbcon_cfb16;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = &fbcon_cfb16;
disp->dispsw_data = info->fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB32
case CMODE_32:
- info->dispsw = fbcon_cfb32;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = &fbcon_cfb32;
disp->dispsw_data = info->fbcon_cmap.cfb32;
break;
#endif
@@ -271,7 +269,7 @@ static int platinum_set_var(struct fb_var_screeninfo *var, int con,
display->line_length = fix.line_length;
display->can_soft_blank = 1;
display->inverse = 0;
- platinum_set_disp(display, info, par.cmode, 0);
+ platinum_set_dispsw(display, info, par.cmode, 0);
display->scrollmode = SCROLL_YREDRAW;
if (info->fb_info.changevar)
(*info->fb_info.changevar)(con);
@@ -341,7 +339,7 @@ static int platinum_switch(int con, struct fb_info *fb)
platinum_var_to_par(&fb_display[con].var, &par, info);
platinum_set_par(&par, info);
- platinum_set_disp(&fb_display[con], info, par.cmode, 0);
+ platinum_set_dispsw(&fb_display[con], info, par.cmode, 0);
do_install_cmap(con, fb);
return 1;
diff --git a/drivers/video/sti-bmode.h b/drivers/video/sti-bmode.h
new file mode 100644
index 000000000..4aa38f6d9
--- /dev/null
+++ b/drivers/video/sti-bmode.h
@@ -0,0 +1,287 @@
+#define STI_REGION_MAX 8
+#define STI_DEV_NAME_LENGTH 32
+
+typedef struct {
+ u8 res[3];
+ u8 data;
+} __attribute__((packed)) sti_u8;
+
+typedef struct {
+ sti_u8 data[2];
+} __attribute__((packed)) sti_u16;
+
+typedef struct {
+ sti_u8 data[4];
+} __attribute__((packed)) sti_u32;
+
+#define STI_U8( u8) ((u8).data)
+#define STI_U16(u16) ((STI_U8((u16).data[0])<<8) | STI_U8((u16).data[1]))
+#define STI_U32(u32) ((STI_U8((u32).data[0])<<24) | \
+ (STI_U8((u32).data[1])<<16) | \
+ (STI_U8((u32).data[2])<< 8) | \
+ (STI_U8((u32).data[3])<< 0))
+
+struct sti_rom_region {
+ sti_u32 region;
+};
+
+struct sti_rom_font {
+ sti_u16 first_char;
+ sti_u16 last_char;
+ sti_u8 width;
+ sti_u8 height;
+ sti_u8 font_type;
+ sti_u8 bytes_per_char;
+ sti_u32 next_font;
+ sti_u8 underline_height;
+ sti_u8 underline_pos;
+ sti_u8 res008[2];
+};
+
+struct sti_rom {
+ sti_u8 type;
+ sti_u8 num_mons;
+ sti_u8 revno[2];
+
+ sti_u8 graphics_id[8]; /* 0x010 */
+
+ sti_u32 font_start; /* 0x030 */
+ sti_u32 statesize;
+ sti_u32 last_addr;
+ sti_u32 region_list;
+
+ sti_u16 reentsize; /* 0x070 */
+ sti_u16 maxtime;
+ sti_u32 mon_tbl_addr;
+ sti_u32 user_data_addr;
+ sti_u32 sti_mem_req;
+
+ sti_u32 user_data_size; /* 0x0b0 */
+ sti_u16 power; /* 0x0c0 */
+ sti_u8 bus_support;
+ sti_u8 ext_bus_support;
+ sti_u8 alt_code_type; /* 0x0d0 */
+ sti_u8 ext_dd_struct[3];
+ sti_u32 cfb_addr; /* 0x0e0 */
+
+ sti_u8 res0f0[4];
+
+ sti_u32 init_graph; /* 0x0e0 */
+ sti_u32 state_mgmt;
+ sti_u32 font_unpmv;
+ sti_u32 block_move;
+ sti_u32 self_test;
+ sti_u32 excep_hdlr;
+ sti_u32 inq_conf;
+ sti_u32 set_cm_entry;
+ sti_u32 dma_ctrl;
+ sti_u32 flow_ctrl;
+ sti_u32 user_timing;
+ sti_u32 process_mgr;
+ sti_u32 sti_util;
+ sti_u32 end_addr;
+ sti_u32 res0b8;
+ sti_u32 res0bc;
+
+ sti_u32 init_graph_m68k; /* 0x0e0 */
+ sti_u32 state_mgmt_m68k;
+ sti_u32 font_unpmv_m68k;
+ sti_u32 block_move_m68k;
+ sti_u32 self_test_m68k;
+ sti_u32 excep_hdlr_m68k;
+ sti_u32 inq_conf_m68k;
+ sti_u32 set_cm_entry_m68k;
+ sti_u32 dma_ctrl_m68k;
+ sti_u32 flow_ctrl_m68k;
+ sti_u32 user_timing_m68k;
+ sti_u32 process_mgr_m68k;
+ sti_u32 sti_util_m68k;
+ sti_u32 end_addr_m68k;
+ sti_u32 res0b8_m68k;
+ sti_u32 res0bc_m68k;
+
+ sti_u8 res040[7 * 4];
+};
+
+struct sti_cooked_font {
+ struct sti_rom_font *raw;
+ struct sti_cooked_font *next_font;
+};
+
+struct sti_cooked_rom {
+ struct sti_rom *raw;
+ struct sti_cooked_font *font_start;
+ u32 *region_list;
+};
+
+struct sti_glob_cfg_ext {
+ u8 curr_mon;
+ u8 friendly_boot;
+ s16 power;
+ s32 freq_ref;
+ s32 *sti_mem_addr;
+ s32 *future_ptr;
+};
+
+struct sti_glob_cfg {
+ s32 text_planes;
+ s16 onscreen_x;
+ s16 onscreen_y;
+ s16 offscreen_x;
+ s16 offscreen_y;
+ s16 total_x;
+ s16 total_y;
+ u32 region_ptrs[STI_REGION_MAX];
+ s32 reent_lvl;
+ s32 *save_addr;
+ struct sti_glob_cfg_ext *ext_ptr;
+};
+
+struct sti_init_flags {
+ u32 wait : 1;
+ u32 reset : 1;
+ u32 text : 1;
+ u32 nontext : 1;
+ u32 clear : 1;
+ u32 cmap_blk : 1;
+ u32 enable_be_timer : 1;
+ u32 enable_be_int : 1;
+ u32 no_chg_tx : 1;
+ u32 no_chg_ntx : 1;
+ u32 no_chg_bet : 1;
+ u32 no_chg_bei : 1;
+ u32 init_cmap_tx : 1;
+ u32 cmt_chg : 1;
+ u32 retain_ie : 1;
+ u32 pad : 17;
+
+ s32 *future_ptr;
+};
+
+struct sti_init_inptr_ext {
+ u8 config_mon_type;
+ u8 pad[1];
+ u16 inflight_data;
+ s32 *future_ptr;
+};
+
+struct sti_init_inptr {
+ s32 text_planes;
+ struct sti_init_inptr_ext *ext_ptr;
+};
+
+struct sti_init_outptr {
+ s32 errno;
+ s32 text_planes;
+ s32 *future_ptr;
+};
+
+struct sti_conf_flags {
+ u32 wait : 1;
+ u32 pad : 31;
+ s32 *future_ptr;
+};
+
+struct sti_conf_inptr {
+ s32 *future_ptr;
+};
+
+struct sti_conf_outptr_ext {
+ u32 crt_config[3];
+ u32 crt_hdw[3];
+ s32 *future_ptr;
+};
+
+struct sti_conf_outptr {
+ s32 errno;
+ s16 onscreen_x;
+ s16 onscreen_y;
+ s16 offscreen_x;
+ s16 offscreen_y;
+ s16 total_x;
+ s16 total_y;
+ s32 bits_per_pixel;
+ s32 bits_used;
+ s32 planes;
+ u8 dev_name[STI_DEV_NAME_LENGTH];
+ u32 attributes;
+ struct sti_conf_outptr_ext *ext_ptr;
+};
+
+
+struct sti_font_inptr {
+ u32 font_start_addr;
+ s16 index;
+ u8 fg_color;
+ u8 bg_color;
+ s16 dest_x;
+ s16 dest_y;
+ s32 *future_ptr;
+};
+
+struct sti_font_flags {
+ u32 wait : 1;
+ u32 non_text : 1;
+ u32 pad : 30;
+
+ s32 *future_ptr;
+};
+
+struct sti_font_outptr {
+ s32 errno;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_flags {
+ u32 wait : 1;
+ u32 color : 1;
+ u32 clear : 1;
+ u32 non_text : 1;
+ u32 pad : 28;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_inptr {
+ u8 fg_color;
+ u8 bg_color;
+ s16 src_x;
+ s16 src_y;
+ s16 dest_x;
+ s16 dest_y;
+ s16 width;
+ s16 height;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_outptr {
+ s32 errno;
+ s32 *future_ptr;
+};
+
+struct sti_struct {
+ spinlock_t lock;
+
+ struct sti_cooked_rom *rom;
+
+ unsigned long font_unpmv;
+ unsigned long block_move;
+ unsigned long init_graph;
+ unsigned long inq_conf;
+
+ struct sti_glob_cfg *glob_cfg;
+ struct sti_rom_font *font;
+
+ s32 text_planes;
+
+ char **mon_strings;
+ u32 *regions;
+ u8 *pci_regions;
+};
+
+#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
+ ({ \
+ real32_call( func, (unsigned long)STI_PTR(flags), \
+ STI_PTR(inptr), STI_PTR(outptr), \
+ glob_cfg); \
+ })
+
diff --git a/drivers/video/sti.h b/drivers/video/sti.h
new file mode 100644
index 000000000..feea4fb92
--- /dev/null
+++ b/drivers/video/sti.h
@@ -0,0 +1,289 @@
+#define STI_REGION_MAX 8
+#define STI_DEV_NAME_LENGTH 32
+
+struct sti_rom_font {
+ u16 first_char;
+ u16 last_char;
+ u8 width;
+ u8 height;
+ u8 font_type;
+ u8 bytes_per_char;
+ u32 next_font;
+ u8 underline_height;
+ u8 underline_pos;
+ u8 res008[2];
+};
+
+struct sti_rom {
+ u8 type[4];
+ u8 res004;
+ u8 num_mons;
+ u8 revno[2];
+ u8 graphics_id[8];
+
+ u32 font_start;
+ u32 statesize;
+ u32 last_addr;
+ u32 region_list;
+
+ u16 reentsize;
+ u16 maxtime;
+ u32 mon_tbl_addr;
+ u32 user_data_addr;
+ u32 sti_mem_req;
+
+ u32 user_data_size;
+ u16 power;
+ u8 bus_support;
+ u8 ext_bus_support;
+ u8 alt_code_type;
+ u8 ext_dd_struct[3];
+ u32 cfb_addr;
+
+ u32 init_graph;
+ u32 state_mgmt;
+ u32 font_unpmv;
+ u32 block_move;
+ u32 self_test;
+ u32 excep_hdlr;
+ u32 inq_conf;
+ u32 set_cm_entry;
+ u32 dma_ctrl;
+ u8 res040[7 * 4];
+
+ u32 init_graph_m68k;
+ u32 flow_ctrl;
+ u32 user_timing;
+ u32 process_mgr;
+ u32 sti_util;
+ u32 end_addr;
+ u32 res0b8;
+ u32 res0bc;
+};
+
+struct sti_cooked_font {
+ struct sti_rom_font *raw;
+ struct sti_cooked_font *next_font;
+};
+
+struct sti_cooked_rom {
+ struct sti_rom *raw;
+ struct sti_cooked_font *font_start;
+ u32 *region_list;
+};
+
+struct sti_glob_cfg_ext {
+ u8 curr_mon;
+ u8 friendly_boot;
+ s16 power;
+ s32 freq_ref;
+ s32 *sti_mem_addr;
+ s32 *future_ptr;
+};
+
+struct sti_glob_cfg {
+ s32 text_planes;
+ s16 onscreen_x;
+ s16 onscreen_y;
+ s16 offscreen_x;
+ s16 offscreen_y;
+ s16 total_x;
+ s16 total_y;
+ u32 region_ptrs[STI_REGION_MAX];
+ s32 reent_lvl;
+ s32 *save_addr;
+ struct sti_glob_cfg_ext *ext_ptr;
+};
+
+struct sti_init_flags {
+ u32 wait : 1;
+ u32 reset : 1;
+ u32 text : 1;
+ u32 nontext : 1;
+ u32 clear : 1;
+ u32 cmap_blk : 1;
+ u32 enable_be_timer : 1;
+ u32 enable_be_int : 1;
+ u32 no_chg_tx : 1;
+ u32 no_chg_ntx : 1;
+ u32 no_chg_bet : 1;
+ u32 no_chg_bei : 1;
+ u32 init_cmap_tx : 1;
+ u32 cmt_chg : 1;
+ u32 retain_ie : 1;
+ u32 pad : 17;
+
+ s32 *future_ptr;
+};
+
+struct sti_init_inptr_ext {
+ u8 config_mon_type;
+ u8 pad[1];
+ u16 inflight_data;
+ s32 *future_ptr;
+};
+
+struct sti_init_inptr {
+ s32 text_planes;
+ struct sti_init_inptr_ext *ext_ptr;
+};
+
+struct sti_init_outptr {
+ s32 errno;
+ s32 text_planes;
+ s32 *future_ptr;
+};
+
+struct sti_conf_flags {
+ u32 wait : 1;
+ u32 pad : 31;
+ s32 *future_ptr;
+};
+
+struct sti_conf_inptr {
+ s32 *future_ptr;
+};
+
+struct sti_conf_outptr_ext {
+ u32 crt_config[3];
+ u32 crt_hdw[3];
+ s32 *future_ptr;
+};
+
+struct sti_conf_outptr {
+ s32 errno;
+ s16 onscreen_x;
+ s16 onscreen_y;
+ s16 offscreen_x;
+ s16 offscreen_y;
+ s16 total_x;
+ s16 total_y;
+ s32 bits_per_pixel;
+ s32 bits_used;
+ s32 planes;
+ u8 dev_name[STI_DEV_NAME_LENGTH];
+ u32 attributes;
+ struct sti_conf_outptr_ext *ext_ptr;
+};
+
+
+struct sti_font_inptr {
+ u32 font_start_addr;
+ s16 index;
+ u8 fg_color;
+ u8 bg_color;
+ s16 dest_x;
+ s16 dest_y;
+ s32 *future_ptr;
+};
+
+struct sti_font_flags {
+ u32 wait : 1;
+ u32 non_text : 1;
+ u32 pad : 30;
+
+ s32 *future_ptr;
+};
+
+struct sti_font_outptr {
+ s32 errno;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_flags {
+ u32 wait : 1;
+ u32 color : 1;
+ u32 clear : 1;
+ u32 non_text : 1;
+ u32 pad : 28;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_inptr {
+ u8 fg_color;
+ u8 bg_color;
+ s16 src_x;
+ s16 src_y;
+ s16 dest_x;
+ s16 dest_y;
+ s16 width;
+ s16 height;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_outptr {
+ s32 errno;
+ s32 *future_ptr;
+};
+
+struct sti_struct {
+ spinlock_t lock;
+
+ struct sti_cooked_rom *rom;
+
+ unsigned long font_unpmv;
+ unsigned long block_move;
+ unsigned long init_graph;
+ unsigned long inq_conf;
+
+ struct sti_glob_cfg *glob_cfg;
+ struct sti_rom_font *font;
+
+ s32 text_planes;
+
+ char **mon_strings;
+ u32 *regions;
+ u8 *pci_regions;
+};
+
+#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
+ ({ \
+ real32_call( func, (unsigned long)STI_PTR(flags), \
+ STI_PTR(inptr), STI_PTR(outptr), \
+ glob_cfg); \
+ })
+
+/* The latency of the STI functions cannot really be reduced by setting
+ * this to 0; STI doesn't seem to be designed to allow calling a different
+ * function (or the same function with different arguments) after a
+ * function exited with 1 as return value.
+ *
+ * As all of the functions below could be called from interrupt context,
+ * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
+ * block. Really bad latency there.
+ *
+ * Probably the best solution to all this is have the generic code manage
+ * the screen buffer and a kernel thread to call STI occasionally.
+ *
+ * Luckily, the frame buffer guys have the same problem so we can just wait
+ * for them to fix it and steal their solution. prumpf
+ *
+ * Actually, another long-term viable solution is to completely do STI
+ * support in userspace - that way we avoid the potential license issues
+ * of using proprietary fonts, too. */
+
+#define STI_WAIT 1
+#define STI_PTR(p) ( (typeof(p)) virt_to_phys(p))
+#define PTR_STI(p) ( (typeof(p)) phys_to_virt((unsigned long)p) )
+
+#define sti_onscreen_x(sti) (PTR_STI(sti->glob_cfg)->onscreen_x)
+#define sti_onscreen_y(sti) (PTR_STI(sti->glob_cfg)->onscreen_y)
+#define sti_font_x(sti) (PTR_STI(sti->font)->width)
+#define sti_font_y(sti) (PTR_STI(sti->font)->height)
+
+extern struct sti_struct * sti_init_roms(void);
+
+void sti_init_graph(struct sti_struct *sti);
+void sti_inq_conf(struct sti_struct *sti);
+void sti_putc(struct sti_struct *sti, int c, int y, int x);
+void sti_set(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width, u8 color);
+void sti_clear(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width);
+void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
+ int dst_y, int dst_x, int height, int width);
+
+/* XXX: this probably should not be here, but we rely on STI being
+ initialized early and independently of stifb at the moment, so
+ there's no other way for stifb to find it. */
+extern struct sti_struct default_sti;
diff --git a/drivers/video/sticon-bmode.c b/drivers/video/sticon-bmode.c
new file mode 100644
index 000000000..e401cbfcd
--- /dev/null
+++ b/drivers/video/sticon-bmode.c
@@ -0,0 +1,906 @@
+/*
+TPG CVS users: please don't commit changes to this file directly, send
+them to prumpf@tux.org and wait for a new version instead. Otherwise,
+your changes will get lost when prumpf releases the next version, as
+this file *will* be replaced with it. You have been warned.
+
+2000-05-30, <deller@gmx.de>
+*/
+#if 1
+#define DPRINTK(x) printk x
+#else
+#define DPRINTK(x)
+#endif
+
+/*
+ * linux/drivers/video/sticon.c - console driver using HP's STI firmware
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
+ * which were
+ *
+ * Created 28 Sep 1997 by Geert Uytterhoeven
+ * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1995 Jay Estabrook
+ * Copyright (C) 1995 Geert Uytterhoeven
+ * Copyright (C) 1993 Bjoern Brauel
+ * Roman Hodek
+ * Copyright (C) 1993 Hamish Macdonald
+ * Greg Harp
+ * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
+ *
+ * with work by William Rucklidge (wjr@cs.cornell.edu)
+ * Geert Uytterhoeven
+ * Jes Sorensen (jds@kom.auc.dk)
+ * Martin Apel
+ * with work by Guenther Kelleter
+ * Martin Schaller
+ * Andreas Schwab
+ * Emmanuel Marty (core@ggi-project.org)
+ * Jakub Jelinek (jj@ultra.linux.cz)
+ * Martin Mares <mj@ucw.cz>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+/*
+ * TODO:
+ * - call STI in virtual mode rather than in real mode
+ * - support for PCI-only STI ROMs (which don't have a traditional region
+ * list)
+ * - safe detection (i.e. verify there is a graphics device at a given
+ * address first, not just read a random device's io space)
+ * - support for multiple STI devices in one machine
+ * - support for byte-mode STI ROMs
+ * - support for just using STI to switch to a colour fb (stifb ?)
+ * - try to make it work on m68k hp workstations ;)
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/malloc.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/real.h>
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/smp.h>
+
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon.h>
+#include <video/font.h>
+
+#include "sti-bmode.h"
+
+/* The latency of the STI functions cannot really be reduced by setting
+ * this to 0; STI doesn't seem to be designed to allow calling a different
+ * function (or the same function with different arguments) after a
+ * function exited with 1 as return value.
+ *
+ * As all of the functions below could be called from interrupt context,
+ * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
+ * block. Really bad latency there.
+ *
+ * Probably the best solution to all this is have the generic code manage
+ * the screen buffer and a kernel thread to call STI occasionally.
+ *
+ * Luckily, the frame buffer guys have the same problem so we can just wait
+ * for them to fix it and steal their solution. prumpf
+ *
+ * Actually, another long-term viable solution is to completely do STI
+ * support in userspace - that way we avoid the potential license issues
+ * of using proprietary fonts, too. */
+
+#define STI_WAIT 1
+#define STI_PTR(p) ( (typeof(p)) virt_to_phys(p))
+#define PTR_STI(p) ( (typeof(p)) phys_to_virt((unsigned long)p) )
+
+static struct sti_struct default_sti = {
+ SPIN_LOCK_UNLOCKED,
+};
+
+static struct sti_font_flags default_font_flags = {
+ STI_WAIT, 0, 0, NULL
+};
+
+/* The colour indices used by STI are
+ * 0 - Black
+ * 1 - White
+ * 2 - Red
+ * 3 - Yellow/Brown
+ * 4 - Green
+ * 5 - Cyan
+ * 6 - Blue
+ * 7 - Magenta
+ *
+ * So we have the same colours as VGA (basically one bit each for R, G, B),
+ * but have to translate them, anyway. */
+
+static u8 col_trans[8] = {
+ 0, 6, 4, 5,
+ 2, 7, 3, 1
+};
+
+#define c_fg(sti, c) col_trans[((c>> 8) & 7)]
+#define c_bg(sti, c) col_trans[((c>>11) & 7)]
+#define c_index(sti, c) (c&0xff)
+
+#define sti_onscreen_x(sti) (PTR_STI(sti->glob_cfg)->onscreen_x)
+#define sti_onscreen_y(sti) (PTR_STI(sti->glob_cfg)->onscreen_y)
+#define sti_font_x(sti) (STI_U8(PTR_STI(sti->font)->width))
+#define sti_font_y(sti) (STI_U8(PTR_STI(sti->font)->height))
+
+static struct sti_init_flags default_init_flags = {
+ STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
+};
+
+static void sti_init_graph(struct sti_struct *sti)
+{
+ struct sti_init_inptr_ext inptr_ext = {
+ 0, { 0 }, 0, NULL
+ };
+ struct sti_init_inptr inptr = {
+ 3, STI_PTR(&inptr_ext)
+ };
+ struct sti_init_outptr outptr = { 0 };
+ unsigned long flags;
+ s32 ret;
+
+ spin_lock_irqsave(&sti->lock, flags);
+
+ ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,
+ &outptr, sti->glob_cfg);
+
+ spin_unlock_irqrestore(&sti->lock, flags);
+
+ sti->text_planes = outptr.text_planes;
+}
+
+#if 0
+static struct sti_conf_flags default_conf_flags = {
+ STI_WAIT, 0, NULL
+};
+
+static void sti_inq_conf(struct sti_struct *sti)
+{
+ struct sti_conf_inptr inptr = { NULL };
+ struct sti_conf_outptr_ext outptr_ext = { future_ptr: NULL };
+ struct sti_conf_outptr outptr = {
+ ext_ptr: STI_PTR(&outptr_ext)
+ };
+ unsigned long flags;
+ s32 ret;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->inq_conf, &default_conf_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+#endif
+
+static void sti_putc(struct sti_struct *sti, int c, int y, int x)
+{
+ struct sti_font_inptr inptr = {
+ (u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c),
+ x * sti_font_x(sti), y * sti_font_y(sti), NULL
+ };
+ struct sti_font_outptr outptr = {
+ 0, NULL
+ };
+ s32 ret;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->font_unpmv, &default_font_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static struct sti_blkmv_flags clear_blkmv_flags = {
+ STI_WAIT, 1, 1, 0, 0, NULL
+};
+
+static void sti_set(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width, u8 color)
+{
+ struct sti_blkmv_inptr inptr = {
+ color, color,
+ src_x, src_y ,
+ src_x, src_y ,
+ width, height,
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static void sti_clear(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width)
+{
+ struct sti_blkmv_inptr inptr = {
+ 0, 0,
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ width * sti_font_x(sti), height* sti_font_y(sti),
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static struct sti_blkmv_flags default_blkmv_flags = {
+ STI_WAIT, 0, 0, 0, 0, NULL
+};
+
+static void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
+ int dst_y, int dst_x, int height, int width)
+{
+ struct sti_blkmv_inptr inptr = {
+ 0, 0,
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ dst_x * sti_font_x(sti), dst_y * sti_font_y(sti),
+ width * sti_font_x(sti), height* sti_font_y(sti),
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &default_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+
+/* STICON */
+
+static const char __init *sticon_startup(void)
+{
+ return "STI console";
+}
+
+static int sticon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ return -EINVAL;
+}
+static int sticon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+ return -ENOSYS;
+}
+
+static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
+{
+ sti_putc(&default_sti, c, ypos, xpos);
+}
+
+static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
+ int count, int ypos, int xpos)
+{
+ while(count--) {
+ sti_putc(&default_sti, *s++, ypos, xpos++);
+ }
+}
+
+static void sticon_cursor(struct vc_data *conp, int mode)
+{
+}
+
+static int sticon_scroll(struct vc_data *conp, int t, int b, int dir,
+ int count)
+{
+ struct sti_struct *sti = &default_sti;
+
+ if(console_blanked)
+ return 0;
+
+ sticon_cursor(conp, CM_ERASE);
+
+ switch(dir) {
+ case SM_UP:
+ sti_bmove(sti, t+count, 0, t, 0, b-t-count, conp->vc_cols);
+ sti_clear(sti, b-count, 0, count, conp->vc_cols);
+
+ break;
+
+ case SM_DOWN:
+ sti_bmove(sti, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+ sti_clear(sti, t, 0, count, conp->vc_cols);
+
+ break;
+ }
+
+ return 0;
+}
+
+static void sticon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ sti_bmove(&default_sti, sy, sx, dy, dx, height, width);
+}
+
+static void sticon_init(struct vc_data *c, int init)
+{
+ struct sti_struct *sti = &default_sti;
+ int vc_cols, vc_rows;
+
+ sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
+ c->vc_can_do_color = 1;
+ vc_cols = PTR_STI(sti->glob_cfg)->onscreen_x / sti_font_x(sti);
+ vc_rows = PTR_STI(sti->glob_cfg)->onscreen_y / sti_font_y(sti);
+
+ vc_resize_con(vc_rows, vc_cols, c->vc_num);
+}
+
+static void sticon_deinit(struct vc_data *c)
+{
+}
+
+static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
+ int width)
+{
+ sti_clear(&default_sti, sy, sx, height, width);
+}
+
+static int sticon_switch(struct vc_data *conp)
+{
+ return 0;
+}
+
+static int sticon_blank(struct vc_data *conp, int blank)
+{
+ return 0;
+}
+
+static int sticon_scrolldelta(struct vc_data *conp, int lines)
+{
+ return 0;
+}
+
+static int sticon_set_origin(struct vc_data *conp)
+{
+ return 0;
+}
+
+static u16 *sticon_screen_pos(struct vc_data *conp, int offset)
+{
+ return NULL;
+}
+
+static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py)
+{
+ return 0;
+}
+
+static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, u8 blink, u8 underline, u8 reverse)
+{
+ u8 attr = ((color & 0x70) >> 1) | ((color & 7));
+
+ if(reverse) {
+ color = ((color>>3)&0x7) | ((color &0x7)<<3);
+ }
+
+
+ return attr;
+}
+
+static struct consw sti_con = {
+ con_startup: sticon_startup,
+ con_init: sticon_init,
+ con_deinit: sticon_deinit,
+ con_clear: sticon_clear,
+ con_putc: sticon_putc,
+ con_putcs: sticon_putcs,
+ con_cursor: sticon_cursor,
+ con_scroll: sticon_scroll,
+ con_bmove: sticon_bmove,
+ con_switch: sticon_switch,
+ con_blank: sticon_blank,
+ con_font_op: sticon_font_op,
+ con_set_palette: sticon_set_palette,
+ con_scrolldelta: sticon_scrolldelta,
+ con_set_origin: sticon_set_origin,
+ con_save_screen: NULL,
+ con_build_attr: sticon_build_attr,
+ con_invert_region: NULL,
+ con_screen_pos: sticon_screen_pos,
+ con_getxy: sticon_getxy,
+};
+
+#include <asm/pgalloc.h> /* need cache flush routines */
+static void __init sti_rom_copy(unsigned long base, unsigned long offset,
+ unsigned long count, void *dest)
+{
+ void *savedest = dest;
+ int savecount = count;
+
+ while(count >= 4) {
+ count -= 4;
+ *(u32 *)dest = gsc_readl(base + offset);
+#if 0
+ DPRINTK(("%08x\n", *(u32 *)dest));
+ if(*(u32 *)dest == 0x64646464) {
+ DPRINTK(("!!!!\n"));
+ { u32 foo = 0; while(foo += 0x100); }
+ }
+#endif
+ offset += 4;
+ dest += 4;
+ }
+ while(count) {
+ count--;
+ *(u8 *)dest = gsc_readb(base + offset);
+ offset++;
+ dest++;
+ }
+ __flush_dcache_range(dest, count);
+ __flush_icache_range(dest, count);
+}
+
+static void dump_sti_rom(struct sti_rom *rom)
+{
+ printk("STI byte mode ROM type %d\n", STI_U8(rom->type));
+ printk(" supports %d monitors\n", STI_U8(rom->num_mons));
+ printk(" conforms to STI ROM spec revision %d.%02x\n",
+ STI_U8(rom->revno[0]) >> 4, STI_U8(rom->revno[0]) & 0x0f);
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ (unsigned int) STI_U8(rom->graphics_id[0]),
+ (unsigned int) STI_U8(rom->graphics_id[1]),
+ (unsigned int) STI_U8(rom->graphics_id[2]),
+ (unsigned int) STI_U8(rom->graphics_id[3]),
+ (unsigned int) STI_U8(rom->graphics_id[4]),
+ (unsigned int) STI_U8(rom->graphics_id[5]),
+ (unsigned int) STI_U8(rom->graphics_id[6]),
+ (unsigned int) STI_U8(rom->graphics_id[7]));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" font start %08x\n", STI_U32(rom->font_start));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" region list %08x\n", STI_U32(rom->region_list));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" init_graph %08x\n", STI_U32(rom->init_graph));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" alternate code type %d\n", STI_U8(rom->alt_code_type));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+}
+
+static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
+ struct sti_rom *raw_rom)
+{
+ struct sti_rom_font *raw_font;
+ struct sti_cooked_font *cooked_font;
+ struct sti_rom_font *font_start;
+
+ cooked_font =
+ kmalloc(sizeof *cooked_font, GFP_KERNEL);
+ if(!cooked_font)
+ return;
+
+ cooked_rom->font_start = cooked_font;
+
+#if 0
+ DPRINTK(("%p = %p + %08x\n",
+ ((void *)raw_rom) + (STI_U32(raw_rom->font_start)),
+ ((void *)raw_rom), (STI_U32(raw_rom->font_start))));
+#endif
+ raw_font = ((void *)raw_rom) + STI_U32(raw_rom->font_start) - 3;
+
+ font_start = raw_font;
+ cooked_font->raw = raw_font;
+
+ DPRINTK(("next font %08x\n", STI_U32(raw_font->next_font)));
+
+ while(0 && STI_U32(raw_font->next_font)) {
+ raw_font = ((void *)font_start) + STI_U32(raw_font->next_font);
+
+ cooked_font->next_font =
+ kmalloc(sizeof *cooked_font, GFP_KERNEL);
+ if(!cooked_font->next_font)
+ return;
+
+ cooked_font = cooked_font->next_font;
+
+// cooked_font->raw = raw_font;
+
+ DPRINTK(("raw_font %p\n",
+ raw_font));
+ DPRINTK(("next_font %08x %p\n",
+ STI_U32(raw_font->next_font),
+ ((void *)font_start) + STI_U32(raw_font->next_font)));
+ }
+
+ cooked_font->next_font = NULL;
+}
+
+static unsigned long __init sti_cook_function(void *function,
+ u32 size)
+{
+ sti_u32 *func = (sti_u32 *)function;
+ u32 *ret;
+ int i;
+
+ ret = kmalloc(size, GFP_KERNEL);
+ if(!ret) {
+ printk(KERN_ERR __FILE__ ": could not get memory.\n");
+ return 0;
+ }
+
+ for(i=0; i<(size/4); i++)
+ ret[i] = STI_U32(func[i]);
+
+ flush_all_caches();
+
+ return virt_to_phys(ret);
+}
+
+static int font_index, font_height, font_width;
+
+static int __init sti_search_font(struct sti_cooked_rom *rom,
+ int height, int width)
+{
+ struct sti_cooked_font *font;
+ int i = 0;
+
+ for(font = rom->font_start; font; font = font->next_font, i++) {
+ if((STI_U8(font->raw->width) == width) &&
+ (STI_U8(font->raw->height) == height))
+ return i;
+ }
+
+ return 0;
+}
+
+static struct sti_cooked_font * __init
+sti_select_font(struct sti_cooked_rom *rom)
+{
+ struct sti_cooked_font *font;
+ int i;
+
+ if(font_width && font_height)
+ font_index = sti_search_font(rom, font_height, font_width);
+
+ for(font = rom->font_start, i = font_index;
+ font && (i > 0);
+ font = font->next_font, i--);
+
+ if(font)
+ return font;
+ else
+ return rom->font_start;
+}
+
+/* address is a pointer to a word mode or pci rom */
+static struct sti_struct * __init sti_read_rom(unsigned long address)
+{
+ struct sti_struct *ret = NULL;
+ struct sti_cooked_rom *cooked = NULL;
+ struct sti_rom *raw = NULL;
+ unsigned long size;
+
+ ret = &default_sti;
+
+ if(!ret)
+ goto out_err;
+
+ cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
+ raw = kmalloc(sizeof *raw, GFP_KERNEL);
+
+ if(!(raw && cooked))
+ goto out_err;
+
+ /* reallocate raw */
+ sti_rom_copy(address, 0, sizeof *raw, raw);
+
+ dump_sti_rom(raw);
+
+ size = STI_U32(raw->last_addr) + 1;
+ size = 128*1024;
+// DPRINTK(("size %08lx\n", size));
+// DPRINTK(("font_start %08x\n", STI_U32(raw->font_start)));
+// kfree(raw);
+ raw = kmalloc(size, GFP_KERNEL);
+ if(!raw)
+ goto out_err;
+ sti_rom_copy(address, 0, size-1, raw);
+
+ sti_cook_fonts(cooked, raw);
+// sti_cook_regions(cooked, raw);
+// sti_cook_functions(cooked, raw);
+
+ if(STI_U32(raw->region_list)) {
+ struct sti_rom_region *region =
+ ((void *)raw) + STI_U32(raw->region_list) - 3;
+
+// DPRINTK(("region_list %08x\n", STI_U32(raw->region_list)));
+
+ ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME!! */
+
+ ret->regions[0] = STI_U32(region[0].region);
+ ret->regions[1] = STI_U32(region[1].region);
+ ret->regions[2] = STI_U32(region[2].region);
+ ret->regions[3] = STI_U32(region[3].region);
+ ret->regions[4] = STI_U32(region[4].region);
+ ret->regions[5] = STI_U32(region[5].region);
+ ret->regions[6] = STI_U32(region[6].region);
+ ret->regions[7] = STI_U32(region[7].region);
+ }
+
+ address = virt_to_phys(raw);
+
+#if 0
+ DPRINTK(("init_graph %08x %08x\n"
+ "state_mgmt %08x %08x\n"
+ "font_unpmv %08x %08x\n"
+ "block_move %08x %08x\n"
+ "self_test %08x %08x\n"
+ "excep_hdlr %08x %08x\n"
+ "irq_conf %08x %08x\n"
+ "set_cm_e %08x %08x\n"
+ "dma_ctrl %08x %08x\n"
+ "flow_ctrl %08x %08x\n"
+ "user_timin %08x %08x\n"
+ "process_m %08x %08x\n"
+ "sti_util %08x %08x\n"
+ "end_addr %08x %08x\n",
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->state_mgmt), STI_U32(raw->state_mgmt_m68k),
+ STI_U32(raw->font_unpmv), STI_U32(raw->font_unpmv_m68k),
+ STI_U32(raw->block_move), STI_U32(raw->block_move_m68k),
+ STI_U32(raw->self_test), STI_U32(raw->self_test_m68k),
+ STI_U32(raw->excep_hdlr), STI_U32(raw->excep_hdlr_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->end_addr), STI_U32(raw->end_addr_m68k) ) );
+#endif
+
+ ret->init_graph = sti_cook_function(((void *)raw)+STI_U32(raw->init_graph)-3,
+ (STI_U32(raw->state_mgmt) -
+ STI_U32(raw->init_graph))/4);
+
+
+ ret->font_unpmv = sti_cook_function(((void *)raw)+STI_U32(raw->font_unpmv)-3,
+ (STI_U32(raw->block_move) -
+ STI_U32(raw->font_unpmv))/4);
+
+ ret->block_move = sti_cook_function(((void *)raw)+STI_U32(raw->block_move)-3,
+ (STI_U32(raw->self_test) -
+ STI_U32(raw->block_move))/4);
+
+ ret->inq_conf = sti_cook_function(((void *)raw)+STI_U32(raw->inq_conf),
+ STI_U32(raw->set_cm_entry) -
+ STI_U32(raw->inq_conf));
+
+ ret->rom = cooked;
+ ret->rom->raw = raw;
+
+ ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);
+
+ return ret;
+
+out_err:
+ if(raw)
+ kfree(raw);
+ if(cooked)
+ kfree(cooked);
+
+ return NULL;
+}
+
+#if 0
+static void dump_globcfg_ext(struct sti_glob_cfg_ext *cfg)
+{
+ DPRINTK(("monitor %d\n"
+ "in friendly mode: %d\n"
+ "power consumption %d watts\n"
+ "freq ref %d\n"
+ "sti_mem_addr %p\n",
+ cfg->curr_mon,
+ cfg->friendly_boot,
+ cfg->power,
+ cfg->freq_ref,
+ cfg->sti_mem_addr));
+}
+
+static void dump_globcfg(struct sti_glob_cfg *glob_cfg)
+{
+ DPRINTK(("%d text planes\n"
+ "%4d x %4d screen resolution\n"
+ "%4d x %4d offscreen\n"
+ "%4d x %4d layout\n"
+ "regions at %08x %08x %08x %08x\n"
+ "regions at %08x %08x %08x %08x\n"
+ "reent_lvl %d\n"
+ "save_addr %p\n",
+ glob_cfg->text_planes,
+ glob_cfg->onscreen_x, glob_cfg->onscreen_y,
+ glob_cfg->offscreen_x, glob_cfg->offscreen_y,
+ glob_cfg->total_x, glob_cfg->total_y,
+ glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
+ glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
+ glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
+ glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
+ glob_cfg->reent_lvl,
+ glob_cfg->save_addr));
+ dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));
+}
+#endif
+
+static void __init sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,
+ unsigned long rom_address)
+{
+ struct sti_glob_cfg *glob_cfg;
+ struct sti_glob_cfg_ext *glob_cfg_ext;
+ void *save_addr;
+ void *sti_mem_addr;
+
+ glob_cfg = kmalloc(sizeof *sti->glob_cfg, GFP_KERNEL);
+ glob_cfg_ext = kmalloc(sizeof *glob_cfg_ext, GFP_KERNEL);
+ save_addr = kmalloc(1024 /*XXX*/, GFP_KERNEL);
+ sti_mem_addr = kmalloc(1024, GFP_KERNEL);
+
+ if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))
+ return;
+
+ memset(glob_cfg, 0, sizeof *glob_cfg);
+ memset(glob_cfg_ext, 0, sizeof *glob_cfg_ext);
+ memset(save_addr, 0, 1024);
+ memset(sti_mem_addr, 0, 1024);
+
+ glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
+ glob_cfg->save_addr = STI_PTR(save_addr);
+ glob_cfg->region_ptrs[0] = ((sti->regions[0]>>18)<<12) + rom_address;
+ glob_cfg->region_ptrs[1] = ((sti->regions[1]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[2] = ((sti->regions[2]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[3] = ((sti->regions[3]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[4] = ((sti->regions[4]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[5] = ((sti->regions[5]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[6] = ((sti->regions[6]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[7] = ((sti->regions[7]>>18)<<12) + hpa;
+
+ glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
+
+ sti->glob_cfg = STI_PTR(glob_cfg);
+}
+
+static void __init sti_try_rom(unsigned long address, unsigned long hpa)
+{
+ struct sti_struct *sti = NULL;
+ u16 sig;
+
+ /* if we can't read the ROM, bail out early. Not being able
+ * to read the hpa is okay, for romless sti */
+ if(pdc_add_valid((void*)address))
+ return;
+
+ printk("found potential STI ROM at %08lx\n", address);
+
+ sig = le16_to_cpu(gsc_readw(address));
+
+ if((sig&0xff) == 0x01) {
+ sti = sti_read_rom(address);
+ }
+
+ if(sig == 0x0303) {
+ printk("STI word mode ROM at %08lx, ignored\n",
+ address);
+
+ sti = NULL;
+ }
+
+ if(!sti)
+ return;
+
+ /* this is hacked. We need a better way to find out the HPA for
+ * romless STI (eg search for the graphics devices we know about
+ * by sversion) */
+ if (!pdc_add_valid((void *)0xf5000000)) DPRINTK(("f4000000 b\n"));
+ if (!pdc_add_valid((void *)0xf7000000)) DPRINTK(("f6000000 b\n"));
+ if (!pdc_add_valid((void *)0xf9000000)) DPRINTK(("f8000000 b\n"));
+ if (!pdc_add_valid((void *)0xfb000000)) DPRINTK(("fa000000 b\n"));
+ sti_init_glob_cfg(sti, hpa, address);
+
+ sti_init_graph(sti);
+
+ //sti_inq_conf(sti);
+#if !defined(SERIAL_CONSOLE)
+ {
+ extern void pdc_console_die(void);
+ pdc_console_die();
+ }
+#endif
+
+ take_over_console(&sti_con, 0, MAX_NR_CONSOLES-1, 1);
+
+ /* sti_inq_conf(sti); */
+}
+
+static unsigned long sti_address;
+static unsigned long sti_hpa;
+
+static void __init sti_init_roms(void)
+{
+ /* handle the command line */
+ if(sti_address && sti_hpa) {
+ sti_try_rom(sti_address, sti_hpa);
+
+ return;
+ }
+
+ /* 712, 715, some other boxes don't have a separate STI ROM,
+ * but use part of the regular flash */
+ if(PAGE0->proc_sti) {
+ printk("STI ROM from PDC at %08x\n", PAGE0->proc_sti);
+ if(!pdc_add_valid((void *)0xf9000000))
+ sti_try_rom(PAGE0->proc_sti, 0xf8000000);
+ else if(!pdc_add_valid((void *)0xf5000000))
+ sti_try_rom(PAGE0->proc_sti, 0xf4000000);
+ else if(!pdc_add_valid((void *)0xf7000000))
+ sti_try_rom(PAGE0->proc_sti, 0xf6000000);
+ else if(!pdc_add_valid((void *)0xfb000000))
+ sti_try_rom(PAGE0->proc_sti, 0xfa000000);
+ }
+
+ /* standard locations for GSC graphic devices */
+ if(!pdc_add_valid((void *)0xf4000000))
+ sti_try_rom(0xf4000000, 0xf4000000);
+ if(!pdc_add_valid((void *)0xf6000000))
+ sti_try_rom(0xf6000000, 0xf6000000);
+ if(!pdc_add_valid((void *)0xf8000000))
+ sti_try_rom(0xf8000000, 0xf8000000);
+ if(!pdc_add_valid((void *)0xfa000000))
+ sti_try_rom(0xfa000000, 0xfa000000);
+}
+
+static int __init sti_init(void)
+{
+ printk("searching for byte mode STI ROMs\n");
+ sti_init_roms();
+ return 0;
+}
+
+module_init(sti_init)
diff --git a/drivers/video/sticon.c b/drivers/video/sticon.c
new file mode 100644
index 000000000..ba3f1167d
--- /dev/null
+++ b/drivers/video/sticon.c
@@ -0,0 +1,229 @@
+/*
+ * linux/drivers/video/sticon.c - console driver using HP's STI firmware
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
+ * which were
+ *
+ * Created 28 Sep 1997 by Geert Uytterhoeven
+ * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1995 Jay Estabrook
+ * Copyright (C) 1995 Geert Uytterhoeven
+ * Copyright (C) 1993 Bjoern Brauel
+ * Roman Hodek
+ * Copyright (C) 1993 Hamish Macdonald
+ * Greg Harp
+ * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
+ *
+ * with work by William Rucklidge (wjr@cs.cornell.edu)
+ * Geert Uytterhoeven
+ * Jes Sorensen (jds@kom.auc.dk)
+ * Martin Apel
+ * with work by Guenther Kelleter
+ * Martin Schaller
+ * Andreas Schwab
+ * Emmanuel Marty (core@ggi-project.org)
+ * Jakub Jelinek (jj@ultra.linux.cz)
+ * Martin Mares <mj@ucw.cz>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+/*
+ * TODO:
+ * - call STI in virtual mode rather than in real mode
+ * - support for PCI-only STI ROMs (which don't have a traditional region
+ * list)
+ * - safe detection (i.e. verify there is a graphics device at a given
+ * address first, not just read a random device's io space)
+ * - support for multiple STI devices in one machine
+ * - support for byte-mode STI ROMs
+ * - support for just using STI to switch to a colour fb (stifb ?)
+ * - try to make it work on m68k hp workstations ;)
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/errno.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+
+#include <asm/io.h>
+
+#include "sti.h"
+
+/* STICON */
+
+static const char * __init
+sticon_startup(void)
+{
+ return "STI console";
+}
+
+static int
+sticon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ return -EINVAL;
+}
+static int
+sticon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+ return -ENOSYS;
+}
+
+static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
+{
+ sti_putc(&default_sti, c, ypos, xpos);
+}
+
+static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
+ int count, int ypos, int xpos)
+{
+ while(count--) {
+ sti_putc(&default_sti, *s++, ypos, xpos++);
+ }
+}
+
+static void sticon_cursor(struct vc_data *conp, int mode)
+{
+}
+
+static int sticon_scroll(struct vc_data *conp, int t, int b, int dir,
+ int count)
+{
+ struct sti_struct *sti = &default_sti;
+
+ if(console_blanked)
+ return 0;
+
+ sticon_cursor(conp, CM_ERASE);
+
+ switch(dir) {
+ case SM_UP:
+ sti_bmove(sti, t+count, 0, t, 0, b-t-count, conp->vc_cols);
+ sti_clear(sti, b-count, 0, count, conp->vc_cols);
+
+ break;
+
+ case SM_DOWN:
+ sti_bmove(sti, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+ sti_clear(sti, t, 0, count, conp->vc_cols);
+
+ break;
+ }
+
+ return 0;
+}
+
+static void sticon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ sti_bmove(&default_sti, sy, sx, dy, dx, height, width);
+}
+
+static void sticon_init(struct vc_data *c, int init)
+{
+ struct sti_struct *sti = &default_sti;
+ int vc_cols, vc_rows;
+
+ sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
+ c->vc_can_do_color = 1;
+ vc_cols = PTR_STI(sti->glob_cfg)->onscreen_x / sti_font_x(sti);
+ vc_rows = PTR_STI(sti->glob_cfg)->onscreen_y / sti_font_y(sti);
+
+ vc_resize_con(vc_rows, vc_cols, c->vc_num);
+}
+
+static void sticon_deinit(struct vc_data *c)
+{
+}
+
+static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
+ int width)
+{
+ sti_clear(&default_sti, sy, sx, height, width);
+}
+
+static int sticon_switch(struct vc_data *conp)
+{
+ return 0;
+}
+
+static int sticon_blank(struct vc_data *conp, int blank)
+{
+ return 0;
+}
+
+static int sticon_scrolldelta(struct vc_data *conp, int lines)
+{
+ return 0;
+}
+
+static int sticon_set_origin(struct vc_data *conp)
+{
+ return 0;
+}
+
+static u16 *sticon_screen_pos(struct vc_data *conp, int offset)
+{
+ return NULL;
+}
+
+static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py)
+{
+ return 0;
+}
+
+static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, u8 blink, u8 underline, u8 reverse)
+{
+ u8 attr = ((color & 0x70) >> 1) | ((color & 7));
+
+ if(reverse) {
+ color = ((color>>3)&0x7) | ((color &0x7)<<3);
+ }
+
+
+ return attr;
+}
+
+struct consw sti_con = {
+ con_startup: sticon_startup,
+ con_init: sticon_init,
+ con_deinit: sticon_deinit,
+ con_clear: sticon_clear,
+ con_putc: sticon_putc,
+ con_putcs: sticon_putcs,
+ con_cursor: sticon_cursor,
+ con_scroll: sticon_scroll,
+ con_bmove: sticon_bmove,
+ con_switch: sticon_switch,
+ con_blank: sticon_blank,
+ con_font_op: sticon_font_op,
+ con_set_palette: sticon_set_palette,
+ con_scrolldelta: sticon_scrolldelta,
+ con_set_origin: sticon_set_origin,
+ con_save_screen: NULL,
+ con_build_attr: sticon_build_attr,
+ con_invert_region: NULL,
+ con_screen_pos: sticon_screen_pos,
+ con_getxy: sticon_getxy,
+};
+
+static int __init sti_init(void)
+{
+ printk("searching for word mode STI ROMs\n");
+ if (sti_init_roms()) {
+ pdc_console_die();
+ take_over_console(&sti_con, 0, MAX_NR_CONSOLES-1, 1);
+ return 0;
+ } else
+ return -ENODEV;
+}
+
+module_init(sti_init)
diff --git a/drivers/video/sticore.c b/drivers/video/sticore.c
new file mode 100644
index 000000000..56e7f43ce
--- /dev/null
+++ b/drivers/video/sticore.c
@@ -0,0 +1,598 @@
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/io.h>
+
+#include "sti.h"
+
+struct sti_struct default_sti = {
+ SPIN_LOCK_UNLOCKED,
+};
+
+static struct sti_font_flags default_font_flags = {
+ STI_WAIT, 0, 0, NULL
+};
+
+/* The colour indices used by STI are
+ * 0 - Black
+ * 1 - White
+ * 2 - Red
+ * 3 - Yellow/Brown
+ * 4 - Green
+ * 5 - Cyan
+ * 6 - Blue
+ * 7 - Magenta
+ *
+ * So we have the same colours as VGA (basically one bit each for R, G, B),
+ * but have to translate them, anyway. */
+
+static u8 col_trans[8] = {
+ 0, 6, 4, 5,
+ 2, 7, 3, 1
+};
+
+#define c_fg(sti, c) col_trans[((c>> 8) & 7)]
+#define c_bg(sti, c) col_trans[((c>>11) & 7)]
+#define c_index(sti, c) (c&0xff)
+
+static struct sti_init_flags default_init_flags = {
+ STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
+};
+
+void
+sti_init_graph(struct sti_struct *sti)
+{
+ struct sti_init_inptr_ext inptr_ext = {
+ 0, { 0 }, 0, NULL
+ };
+ struct sti_init_inptr inptr = {
+ 3, STI_PTR(&inptr_ext)
+ };
+ struct sti_init_outptr outptr = { 0 };
+ unsigned long flags;
+ s32 ret;
+
+ spin_lock_irqsave(&sti->lock, flags);
+
+ ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,
+ &outptr, sti->glob_cfg);
+
+ spin_unlock_irqrestore(&sti->lock, flags);
+
+ sti->text_planes = outptr.text_planes;
+}
+
+static struct sti_conf_flags default_conf_flags = {
+ STI_WAIT, 0, NULL
+};
+
+void
+sti_inq_conf(struct sti_struct *sti)
+{
+ struct sti_conf_inptr inptr = { NULL };
+ struct sti_conf_outptr_ext outptr_ext = { future_ptr: NULL };
+ struct sti_conf_outptr outptr = {
+ ext_ptr: STI_PTR(&outptr_ext)
+ };
+ unsigned long flags;
+ s32 ret;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->inq_conf, &default_conf_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+void
+sti_putc(struct sti_struct *sti, int c, int y, int x)
+{
+ struct sti_font_inptr inptr = {
+ (u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c),
+ x * sti_font_x(sti), y * sti_font_y(sti), NULL
+ };
+ struct sti_font_outptr outptr = {
+ 0, NULL
+ };
+ s32 ret;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->font_unpmv, &default_font_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static struct sti_blkmv_flags clear_blkmv_flags = {
+ STI_WAIT, 1, 1, 0, 0, NULL
+};
+
+void
+sti_set(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width, u8 color)
+{
+ struct sti_blkmv_inptr inptr = {
+ color, color,
+ src_x, src_y ,
+ src_x, src_y ,
+ width, height,
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+void
+sti_clear(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width)
+{
+ struct sti_blkmv_inptr inptr = {
+ 0, 0,
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ width * sti_font_x(sti), height* sti_font_y(sti),
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static struct sti_blkmv_flags default_blkmv_flags = {
+ STI_WAIT, 0, 0, 0, 0, NULL
+};
+
+void
+sti_bmove(struct sti_struct *sti, int src_y, int src_x,
+ int dst_y, int dst_x, int height, int width)
+{
+ struct sti_blkmv_inptr inptr = {
+ 0, 0,
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ dst_x * sti_font_x(sti), dst_y * sti_font_y(sti),
+ width * sti_font_x(sti), height* sti_font_y(sti),
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &default_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+
+static void __init
+sti_rom_copy(unsigned long base, unsigned long offset,
+ unsigned long count, void *dest)
+{
+ void *savedest = dest;
+ int savecount = count;
+
+ while(count >= 4) {
+ count -= 4;
+ *(u32 *)dest = gsc_readl(base + offset);
+ offset += 4;
+ dest += 4;
+ }
+ while(count) {
+ count--;
+ *(u8 *)dest = gsc_readb(base + offset);
+ offset++;
+ dest++;
+ }
+ __flush_dcache_range((unsigned long) dest, count);
+ __flush_icache_range((unsigned long) dest, count);
+}
+
+static void dump_sti_rom(struct sti_rom *rom)
+{
+ printk("STI word mode ROM type %d\n", rom->type[3]);
+ printk(" supports %d monitors\n", rom->num_mons);
+ printk(" conforms to STI ROM spec revision %d.%02x\n",
+ rom->revno[0] >> 4, rom->revno[0] & 0x0f);
+ printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ rom->graphics_id[0],
+ rom->graphics_id[1],
+ rom->graphics_id[2],
+ rom->graphics_id[3],
+ rom->graphics_id[4],
+ rom->graphics_id[5],
+ rom->graphics_id[6],
+ rom->graphics_id[7]);
+ printk(" font start %08x\n", rom->font_start);
+ printk(" region list %08x\n", rom->region_list);
+ printk(" init_graph %08x\n", rom->init_graph);
+ printk(" alternate code type %d\n", rom->alt_code_type);
+}
+
+static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
+ struct sti_rom *raw_rom)
+{
+ struct sti_rom_font *raw_font;
+ struct sti_cooked_font *cooked_font;
+ struct sti_rom_font *font_start;
+
+ cooked_font =
+ kmalloc(sizeof *cooked_font, GFP_KERNEL);
+ if(!cooked_font)
+ return;
+
+ cooked_rom->font_start = cooked_font;
+
+ raw_font = ((void *)raw_rom) + (raw_rom->font_start);
+
+ font_start = raw_font;
+ cooked_font->raw = raw_font;
+
+ while(raw_font->next_font) {
+ raw_font = ((void *)font_start) + (raw_font->next_font);
+
+ cooked_font->next_font =
+ kmalloc(sizeof *cooked_font, GFP_KERNEL);
+ if(!cooked_font->next_font)
+ return;
+
+ cooked_font = cooked_font->next_font;
+
+ cooked_font->raw = raw_font;
+ }
+
+ cooked_font->next_font = NULL;
+}
+
+static int font_index, font_height, font_width;
+
+static int __init sti_font_setup(char *str)
+{
+ char *x;
+
+ /* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style
+ * command lines. */
+
+ if((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
+ font_height = simple_strtoul(str, NULL, 0);
+ font_width = simple_strtoul(x+1, NULL, 0);
+ } else {
+ font_index = simple_strtoul(str, NULL, 0);
+ }
+
+ return 0;
+}
+
+__setup("sti_font=", sti_font_setup);
+
+static int __init sti_search_font(struct sti_cooked_rom *rom,
+ int height, int width)
+{
+ struct sti_cooked_font *font;
+ int i = 0;
+
+ for(font = rom->font_start; font; font = font->next_font, i++) {
+ if((font->raw->width == width) && (font->raw->height == height))
+ return i;
+ }
+
+ return 0;
+}
+
+static struct sti_cooked_font * __init
+sti_select_font(struct sti_cooked_rom *rom)
+{
+ struct sti_cooked_font *font;
+ int i;
+
+ if(font_width && font_height)
+ font_index = sti_search_font(rom, font_height, font_width);
+
+ for(font = rom->font_start, i = font_index;
+ font && (i > 0);
+ font = font->next_font, i--);
+
+ if(font)
+ return font;
+ else
+ return rom->font_start;
+}
+
+static void __init
+sti_dump_globcfg_ext(struct sti_glob_cfg_ext *cfg)
+{
+ printk( "monitor %d\n"
+ "in friendly mode: %d\n"
+ "power consumption %d watts\n"
+ "freq ref %d\n"
+ "sti_mem_addr %p\n",
+ cfg->curr_mon,
+ cfg->friendly_boot,
+ cfg->power,
+ cfg->freq_ref,
+ cfg->sti_mem_addr);
+}
+
+void __init
+sti_dump_globcfg(struct sti_glob_cfg *glob_cfg)
+{
+ printk( "%d text planes\n"
+ "%4d x %4d screen resolution\n"
+ "%4d x %4d offscreen\n"
+ "%4d x %4d layout\n"
+ "regions at %08x %08x %08x %08x\n"
+ "regions at %08x %08x %08x %08x\n"
+ "reent_lvl %d\n"
+ "save_addr %p\n",
+ glob_cfg->text_planes,
+ glob_cfg->onscreen_x, glob_cfg->onscreen_y,
+ glob_cfg->offscreen_x, glob_cfg->offscreen_y,
+ glob_cfg->total_x, glob_cfg->total_y,
+ glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
+ glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
+ glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
+ glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
+ glob_cfg->reent_lvl,
+ glob_cfg->save_addr);
+ sti_dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));
+}
+
+static void __init
+sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,
+ unsigned long rom_address)
+{
+ struct sti_glob_cfg *glob_cfg;
+ struct sti_glob_cfg_ext *glob_cfg_ext;
+ void *save_addr;
+ void *sti_mem_addr;
+
+ glob_cfg = kmalloc(sizeof *sti->glob_cfg, GFP_KERNEL);
+ glob_cfg_ext = kmalloc(sizeof *glob_cfg_ext, GFP_KERNEL);
+ save_addr = kmalloc(1024 /*XXX*/, GFP_KERNEL);
+ sti_mem_addr = kmalloc(1024, GFP_KERNEL);
+
+ if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))
+ return;
+
+ memset(glob_cfg, 0, sizeof *glob_cfg);
+ memset(glob_cfg_ext, 0, sizeof *glob_cfg_ext);
+ memset(save_addr, 0, 1024);
+ memset(sti_mem_addr, 0, 1024);
+
+ glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
+ glob_cfg->save_addr = STI_PTR(save_addr);
+ glob_cfg->region_ptrs[0] = ((sti->regions[0]>>18)<<12) + rom_address;
+ glob_cfg->region_ptrs[1] = ((sti->regions[1]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[2] = ((sti->regions[2]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[3] = ((sti->regions[3]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[4] = ((sti->regions[4]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[5] = ((sti->regions[5]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[6] = ((sti->regions[6]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[7] = ((sti->regions[7]>>18)<<12) + hpa;
+
+ glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
+
+ sti->glob_cfg = STI_PTR(glob_cfg);
+}
+
+/* address is a pointer to a word mode or pci rom */
+static struct sti_struct * __init
+sti_read_rom(unsigned long address)
+{
+ struct sti_struct *ret = NULL;
+ struct sti_cooked_rom *cooked = NULL;
+ struct sti_rom *raw = NULL;
+ unsigned long size;
+
+ ret = &default_sti;
+
+ if(!ret)
+ goto out_err;
+
+ cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
+ raw = kmalloc(sizeof *raw, GFP_KERNEL);
+
+ if(!(raw && cooked))
+ goto out_err;
+
+ /* reallocate raw */
+ sti_rom_copy(address, 0, sizeof *raw, raw);
+
+ dump_sti_rom(raw);
+
+ size = raw->last_addr;
+ /* kfree(raw); */
+ raw = kmalloc(size, GFP_KERNEL);
+ if(!raw)
+ goto out_err;
+ sti_rom_copy(address, 0, size, raw);
+
+ sti_cook_fonts(cooked, raw);
+#if 0
+ sti_cook_regions(cooked, raw);
+ sti_cook_functions(cooked, raw);
+#endif
+
+ if(raw->region_list) {
+ ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME */
+
+ memcpy(ret->regions, ((void *)raw)+raw->region_list, 32);
+ }
+
+ address = virt_to_phys(raw);
+
+ ret->font_unpmv = address+(raw->font_unpmv & 0x03ffffff);
+ ret->block_move = address+(raw->block_move & 0x03ffffff);
+ ret->init_graph = address+(raw->init_graph & 0x03ffffff);
+ ret->inq_conf = address+(raw->inq_conf & 0x03ffffff);
+
+ ret->rom = cooked;
+ ret->rom->raw = raw;
+
+ ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);
+
+ return ret;
+
+out_err:
+ if(raw)
+ kfree(raw);
+ if(cooked)
+ kfree(cooked);
+
+ return NULL;
+}
+
+static struct sti_struct * __init
+sti_try_rom(unsigned long address, unsigned long hpa)
+{
+ struct sti_struct *sti = NULL;
+ u16 sig;
+
+test_rom:
+ /* if we can't read the ROM, bail out early. Not being able
+ * to read the hpa is okay, for romless sti */
+ if(pdc_add_valid((void*)address))
+ return NULL;
+
+ printk("found potential STI ROM at %08lx\n", address);
+
+ sig = le16_to_cpu(gsc_readw(address));
+
+ if((sig==0x55aa) || (sig==0xaa55)) {
+ address += le32_to_cpu(gsc_readl(address+8));
+ printk("sig %04x, PCI STI ROM at %08lx\n",
+ sig, address);
+
+ goto test_rom;
+ }
+
+ if((sig&0xff) == 0x01) {
+ printk("STI byte mode ROM at %08lx, ignored\n",
+ address);
+
+ sti = NULL;
+ }
+
+ if(sig == 0x0303) {
+ printk("STI word mode ROM at %08lx\n",
+ address);
+
+ sti = sti_read_rom(address);
+ }
+
+ if (!sti)
+ return NULL;
+
+ /* this is hacked. We need a better way to find out the HPA for
+ * romless STI (eg search for the graphics devices we know about
+ * by sversion) */
+ if (!pdc_add_valid((void *)0xf5000000)) printk("f4000000 g\n");
+ if (!pdc_add_valid((void *)0xf7000000)) printk("f6000000 g\n");
+ if (!pdc_add_valid((void *)0xf9000000)) printk("f8000000 g\n");
+ if (!pdc_add_valid((void *)0xfb000000)) printk("fa000000 g\n");
+ sti_init_glob_cfg(sti, hpa, address);
+
+ sti_init_graph(sti);
+
+ sti_inq_conf(sti);
+ sti_dump_globcfg(PTR_STI(sti->glob_cfg));
+
+ return sti;
+}
+
+static unsigned long sti_address;
+static unsigned long sti_hpa;
+
+/* XXX: should build a list of STI ROMs */
+struct sti_struct * __init
+sti_init_roms(void)
+{
+ struct sti_struct *tmp = NULL, *sti = NULL;
+
+ /* handle the command line */
+ if (sti_address && sti_hpa) {
+ return sti_try_rom(sti_address, sti_hpa);
+ }
+
+ /* 712, 715, some other boxes don't have a separate STI ROM,
+ * but use part of the regular flash */
+ if (PAGE0->proc_sti) {
+ printk("STI ROM from PDC at %08x\n", PAGE0->proc_sti);
+ if (!pdc_add_valid((void *)0xf9000000))
+ sti = sti_try_rom(PAGE0->proc_sti, 0xf8000000);
+ else if (!pdc_add_valid((void *)0xf5000000))
+ sti = sti_try_rom(PAGE0->proc_sti, 0xf4000000);
+ else if (!pdc_add_valid((void *)0xf7000000))
+ sti = sti_try_rom(PAGE0->proc_sti, 0xf6000000);
+ else if (!pdc_add_valid((void *)0xfb000000))
+ sti = sti_try_rom(PAGE0->proc_sti, 0xfa000000);
+
+ }
+
+ /* standard locations for GSC graphic devices */
+ if (!pdc_add_valid((void *)0xf4000000))
+ tmp = sti_try_rom(0xf4000000, 0xf4000000);
+ sti = tmp ? tmp : sti;
+ if (!pdc_add_valid((void *)0xf6000000))
+ tmp = sti_try_rom(0xf6000000, 0xf6000000);
+ sti = tmp ? tmp : sti;
+ if (!pdc_add_valid((void *)0xf8000000))
+ tmp = sti_try_rom(0xf8000000, 0xf8000000);
+ sti = tmp ? tmp : sti;
+ if (!pdc_add_valid((void *)0xfa000000))
+ tmp = sti_try_rom(0xfa000000, 0xfa000000);
+ sti = tmp ? tmp : sti;
+
+ return sti;
+}
+
+static int __init
+sti_setup(char *str)
+{
+ char *end;
+
+ if(strcmp(str, "pdc") == 0) {
+ sti_address = PAGE0->proc_sti;
+
+ return 1;
+ } else {
+ sti_address = simple_strtoul(str, &end, 16);
+
+ if((end == str) || (sti_address < 0xf0000000)) {
+ sti_address = 0;
+ return 0;
+ }
+
+ sti_hpa = sti_address;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+__setup("sti=", sti_setup);
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
new file mode 100644
index 000000000..661ff29c5
--- /dev/null
+++ b/drivers/video/stifb.c
@@ -0,0 +1,230 @@
+/*
+ * linux/drivers/video/stifb.c - Generic frame buffer driver for HP
+ * workstations with STI (standard text interface) video firmware.
+ *
+ * Based on:
+ * linux/drivers/video/artistfb.c -- Artist frame buffer driver
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * based on skeletonfb, which was
+ * Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details. */
+
+/*
+ * Notes:
+ *
+ * This driver assumes that the video has been set up in 1bpp mode by
+ * the firmware. Since HP video tends to be planar rather than
+ * packed-pixel this will probably work anyway even if it isn't.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#include <video/fbcon.h>
+
+#include "sti.h"
+
+static struct fb_ops stifb_ops;
+
+struct stifb_info {
+ struct fb_info_gen gen;
+ struct sti_struct *sti;
+};
+
+struct stifb_par {
+};
+
+static struct stifb_info fb_info;
+static struct display disp;
+
+int stifb_init(void);
+int stifb_setup(char*);
+
+extern struct display_switch fbcon_sti;
+
+/* ------------------- chipset specific functions -------------------------- */
+
+static int
+sti_encode_fix(struct fb_fix_screeninfo *fix,
+ const void *par, struct fb_info_gen *info)
+{
+ /* XXX: what about smem_len? */
+ fix->smem_start = PTR_STI(fb_info.sti->glob_cfg)->region_ptrs[1];
+ fix->type = FB_TYPE_PLANES; /* well, sort of */
+
+ return 0;
+}
+
+static int
+sti_decode_var(const struct fb_var_screeninfo *var,
+ void *par, struct fb_info_gen *info)
+{
+ return 0;
+}
+
+static int
+sti_encode_var(struct fb_var_screeninfo *var,
+ const void *par, struct fb_info_gen *info)
+{
+ var->xres = PTR_STI(fb_info.sti->glob_cfg)->onscreen_x;
+ var->yres = PTR_STI(fb_info.sti->glob_cfg)->onscreen_y;
+ var->xres_virtual = PTR_STI(fb_info.sti->glob_cfg)->total_x;
+ var->yres_virtual = PTR_STI(fb_info.sti->glob_cfg)->total_y;
+ var->xoffset = var->yoffset = 0;
+
+ var->bits_per_pixel = 1;
+ var->grayscale = 0;
+
+ return 0;
+}
+
+static void
+sti_get_par(void *par, struct fb_info_gen *info)
+{
+}
+
+static void
+sti_set_par(const void *par, struct fb_info_gen *info)
+{
+}
+
+static int
+sti_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp, struct fb_info *info)
+{
+ return 0;
+}
+
+static int
+sti_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info)
+{
+ return 0;
+}
+
+static void
+sti_set_disp(const void *par, struct display *disp,
+ struct fb_info_gen *info)
+{
+ disp->screen_base =
+ (void *) PTR_STI(fb_info.sti->glob_cfg)->region_ptrs[1];
+ disp->dispsw = &fbcon_sti;
+}
+
+static void
+sti_detect(void)
+{
+}
+
+static int
+sti_blank(int blank_mode, const struct fb_info *info)
+{
+ return 0;
+}
+
+/* ------------ Interfaces to hardware functions ------------ */
+
+struct fbgen_hwswitch sti_switch = {
+ detect: sti_detect,
+ encode_fix: sti_encode_fix,
+ decode_var: sti_decode_var,
+ encode_var: sti_encode_var,
+ get_par: sti_get_par,
+ set_par: sti_set_par,
+ getcolreg: sti_getcolreg,
+ setcolreg: sti_setcolreg,
+ pan_display: NULL,
+ blank: sti_blank,
+ set_disp: sti_set_disp
+};
+
+
+/* ------------ Hardware Independent Functions ------------ */
+
+ /*
+ * Initialization
+ */
+
+int __init
+stifb_init(void)
+{
+ printk("searching for word mode STI ROMs\n");
+ /* XXX: in the future this will return a list of ROMs */
+ if ((fb_info.sti = sti_init_roms()) == NULL)
+ return -ENXIO;
+
+ fb_info.gen.info.node = -1;
+ fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+ fb_info.gen.info.fbops = &stifb_ops;
+ fb_info.gen.info.disp = &disp;
+ fb_info.gen.info.changevar = NULL;
+ fb_info.gen.info.switch_con = &fbgen_switch;
+ fb_info.gen.info.updatevar = &fbgen_update_var;
+ fb_info.gen.info.blank = &fbgen_blank;
+ strcpy(fb_info.gen.info.modename, "STI Generic");
+ fb_info.gen.fbhw = &sti_switch;
+ fb_info.gen.fbhw->detect();
+
+ /* This should give a reasonable default video mode */
+ fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+ fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+ fbgen_set_disp(-1, &fb_info.gen);
+ fbgen_install_cmap(0, &fb_info.gen);
+ pdc_console_die();
+ if (register_framebuffer(&fb_info.gen.info) < 0)
+ return -EINVAL;
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
+
+ return 0;
+}
+
+
+ /*
+ * Cleanup
+ */
+
+void
+stifb_cleanup(struct fb_info *info)
+{
+ printk("stifb_cleanup: you're on crack\n");
+}
+
+
+int __init
+stifb_setup(char *options)
+{
+ /* XXX: we should take the resolution, bpp as command line arguments. */
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static struct fb_ops stifb_ops = {
+ owner: THIS_MODULE,
+ fb_open: NULL,
+ fb_release: NULL,
+ fb_get_fix: fbgen_get_fix,
+ fb_get_var: fbgen_get_var,
+ fb_set_var: fbgen_set_var,
+ fb_get_cmap: fbgen_get_cmap,
+ fb_set_cmap: fbgen_set_cmap,
+ fb_pan_display: fbgen_pan_display,
+ fb_ioctl: NULL
+};
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 4128c313e..d954dc02e 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -327,7 +327,6 @@ struct fb_info_tdfx {
struct tdfxfb_par default_par;
struct tdfxfb_par current_par;
struct display disp;
- struct display_switch dispsw;
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
union {
#ifdef FBCON_HAS_CFB16
@@ -412,10 +411,10 @@ static int tdfxfb_encode_var(struct fb_var_screeninfo* var,
static int tdfxfb_encode_fix(struct fb_fix_screeninfo* fix,
const struct tdfxfb_par* par,
const struct fb_info_tdfx* info);
-static void tdfxfb_set_disp(struct display* disp,
- struct fb_info_tdfx* info,
- int bpp,
- int accel);
+static void tdfxfb_set_dispsw(struct display* disp,
+ struct fb_info_tdfx* info,
+ int bpp,
+ int accel);
static int tdfxfb_getcolreg(u_int regno,
u_int* red,
u_int* green,
@@ -1640,48 +1639,43 @@ static int tdfxfb_get_var(struct fb_var_screeninfo *var,
return 0;
}
-static void tdfxfb_set_disp(struct display *disp,
- struct fb_info_tdfx *info,
- int bpp,
- int accel) {
+static void tdfxfb_set_dispsw(struct display *disp,
+ struct fb_info_tdfx *info,
+ int bpp,
+ int accel) {
if (disp->dispsw && disp->conp)
fb_con.con_cursor(disp->conp, CM_ERASE);
switch(bpp) {
#ifdef FBCON_HAS_CFB8
case 8:
- info->dispsw = noaccel ? fbcon_cfb8 : fbcon_banshee8;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = noaccel ? &fbcon_cfb8 : &fbcon_banshee8;
if (nohwcursor) fbcon_banshee8.cursor = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
- info->dispsw = noaccel ? fbcon_cfb16 : fbcon_banshee16;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = noaccel ? &fbcon_cfb16 : &fbcon_banshee16;
disp->dispsw_data = info->fbcon_cmap.cfb16;
if (nohwcursor) fbcon_banshee16.cursor = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
- info->dispsw = noaccel ? fbcon_cfb24 : fbcon_banshee24;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = noaccel ? &fbcon_cfb24 : &fbcon_banshee24;
disp->dispsw_data = info->fbcon_cmap.cfb24;
if (nohwcursor) fbcon_banshee24.cursor = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
- info->dispsw = noaccel ? fbcon_cfb32 : fbcon_banshee32;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = noaccel ? &fbcon_cfb32 : &fbcon_banshee32;
disp->dispsw_data = info->fbcon_cmap.cfb32;
if (nohwcursor) fbcon_banshee32.cursor = NULL;
break;
#endif
default:
- info->dispsw = fbcon_dummy;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = &fbcon_dummy;
}
}
@@ -1735,7 +1729,7 @@ static int tdfxfb_set_var(struct fb_var_screeninfo *var,
display->can_soft_blank = 1;
display->inverse = inverse;
accel = var->accel_flags & FB_ACCELF_TEXT;
- tdfxfb_set_disp(display, info, par.bpp, accel);
+ tdfxfb_set_dispsw(display, info, par.bpp, accel);
if(nopan) display->scrollmode = SCROLL_YREDRAW;
@@ -2083,10 +2077,10 @@ static int tdfxfb_switch_con(int con,
info->cursor.redraw=1;
- tdfxfb_set_disp(&fb_display[con],
- info,
- par.bpp,
- par.accel_flags & FB_ACCELF_TEXT);
+ tdfxfb_set_dispsw(&fb_display[con],
+ info,
+ par.bpp,
+ par.accel_flags & FB_ACCELF_TEXT);
tdfxfb_install_cmap(&fb_display[con], fb);
tdfxfb_updatevar(con, fb);
diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c
index e48c0f458..6268b1766 100644
--- a/drivers/video/vgacon.c
+++ b/drivers/video/vgacon.c
@@ -11,7 +11,7 @@
* 1995 Jay Estabrook
*
* User definable mapping table and font loading by Eugene G. Crosser,
- * <crosser@pccross.msk.su>
+ * <crosser@average.org>
*
* Improved loadable font/UTF-8 support by H. Peter Anvin
* Feb-Sep 1995 <peter.anvin@linux.org>
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 42f19e292..161122650 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -53,7 +53,7 @@ abort_toobig:
return 0;
}
-static int adfs_writepage(struct file *file, struct page *page)
+static int adfs_writepage(struct page *page)
{
return block_write_full_page(page, adfs_get_block);
}
diff --git a/fs/affs/file.c b/fs/affs/file.c
index de0808b9e..341660c4b 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -338,7 +338,7 @@ abort_negative:
}
-static int affs_writepage(struct file *file, struct page *page)
+static int affs_writepage(struct page *page)
{
return block_write_full_page(page,affs_get_block);
}
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index f0ee10a15..de63fb2de 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -135,7 +135,7 @@ out:
return err;
}
-static int bfs_writepage(struct file *file, struct page *page)
+static int bfs_writepage(struct page *page)
{
return block_write_full_page(page, bfs_get_block);
}
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index b3827a7ae..8e33b4ab2 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -77,7 +77,6 @@ static void bfs_read_inode(struct inode * inode)
inode->i_atime = di->i_atime;
inode->i_mtime = di->i_mtime;
inode->i_ctime = di->i_ctime;
- inode->i_rdev = 0; /* BFS doesn't have special nodes */
inode->iu_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
inode->iu_sblock = di->i_sblock;
inode->iu_eblock = di->i_eblock;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 861ede356..c84164fc4 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -247,7 +247,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
goto out;
if (!elf_check_arch(interp_elf_ex))
goto out;
- if (!interpreter->f_op->mmap)
+ if (!interpreter->f_op || !interpreter->f_op->mmap)
goto out;
/*
@@ -364,7 +364,7 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
do_brk(0, text_data);
retval = -ENOEXEC;
- if (!interpreter->f_op->read)
+ if (!interpreter->f_op || !interpreter->f_op->read)
goto out;
retval = interpreter->f_op->read(interpreter, addr, text_data, &offset);
if (retval < 0)
@@ -789,7 +789,7 @@ static int load_elf_library(struct file *file)
/* First of all, some simple consistency checks */
if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
- !elf_check_arch(&elf_ex) || !file->f_op->mmap)
+ !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
goto out;
/* Now read in all of the header information */
diff --git a/fs/buffer.c b/fs/buffer.c
index 9f9fbbfbd..8e2a382c3 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -69,6 +69,8 @@ static char buffersize_index[65] =
* lru_list_lock > hash_table_lock > free_list_lock > unused_list_lock
*/
+#define BH_ENTRY(list) list_entry((list), struct buffer_head, b_inode_buffers)
+
/*
* Hash table gook..
*/
@@ -567,6 +569,42 @@ unsigned int get_hardblocksize(kdev_t dev)
return 0;
}
+void buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode)
+{
+ spin_lock(&lru_list_lock);
+ if (bh->b_inode)
+ list_del(&bh->b_inode_buffers);
+ bh->b_inode = inode;
+ list_add(&bh->b_inode_buffers, &inode->i_dirty_buffers);
+ spin_unlock(&lru_list_lock);
+}
+
+/* The caller must have the lru_list lock before calling the
+ remove_inode_queue functions. */
+static void __remove_inode_queue(struct buffer_head *bh)
+{
+ bh->b_inode = NULL;
+ list_del(&bh->b_inode_buffers);
+}
+
+static inline void remove_inode_queue(struct buffer_head *bh)
+{
+ if (bh->b_inode)
+ __remove_inode_queue(bh);
+}
+
+int inode_has_buffers(struct inode *inode)
+{
+ int ret;
+
+ spin_lock(&lru_list_lock);
+ ret = !list_empty(&inode->i_dirty_buffers);
+ spin_unlock(&lru_list_lock);
+
+ return ret;
+}
+
+
/* If invalidate_buffers() will trash dirty buffers, it means some kind
of fs corruption is going on. Trashing dirty data always imply losing
information that was supposed to be just stored on the physical layer
@@ -615,6 +653,7 @@ void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
write_lock(&hash_table_lock);
if (!atomic_read(&bh->b_count) &&
(destroy_dirty_buffers || !buffer_dirty(bh))) {
+ remove_inode_queue(bh);
__remove_from_queues(bh);
put_last_free(bh);
}
@@ -679,6 +718,7 @@ void set_blocksize(kdev_t dev, int size)
printk(KERN_WARNING
"set_blocksize: dev %s buffer_dirty %lu size %hu\n",
kdevname(dev), bh->b_blocknr, bh->b_size);
+ remove_inode_queue(bh);
__remove_from_queues(bh);
put_last_free(bh);
} else {
@@ -718,12 +758,6 @@ void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private)
bh->b_private = private;
}
-static void end_buffer_io_sync(struct buffer_head *bh, int uptodate)
-{
- mark_buffer_uptodate(bh, uptodate);
- unlock_buffer(bh);
-}
-
static void end_buffer_io_bad(struct buffer_head *bh, int uptodate)
{
mark_buffer_uptodate(bh, uptodate);
@@ -794,6 +828,137 @@ still_busy:
}
/*
+ * Synchronise all the inode's dirty buffers to the disk.
+ *
+ * We have conflicting pressures: we want to make sure that all
+ * initially dirty buffers get waited on, but that any subsequently
+ * dirtied buffers don't. After all, we don't want fsync to last
+ * forever if somebody is actively writing to the file.
+ *
+ * Do this in two main stages: first we copy dirty buffers to a
+ * temporary inode list, queueing the writes as we go. Then we clean
+ * up, waiting for those writes to complete.
+ *
+ * During this second stage, any subsequent updates to the file may end
+ * up refiling the buffer on the original inode's dirty list again, so
+ * there is a chance we will end up with a buffer queued for write but
+ * not yet completed on that list. So, as a final cleanup we go through
+ * the osync code to catch these locked, dirty buffers without requeuing
+ * any newly dirty buffers for write.
+ */
+
+int fsync_inode_buffers(struct inode *inode)
+{
+ struct buffer_head *bh;
+ struct inode tmp;
+ int err = 0, err2;
+
+ INIT_LIST_HEAD(&tmp.i_dirty_buffers);
+
+ spin_lock(&lru_list_lock);
+
+ while (!list_empty(&inode->i_dirty_buffers)) {
+ bh = BH_ENTRY(inode->i_dirty_buffers.next);
+ list_del(&bh->b_inode_buffers);
+ if (!buffer_dirty(bh) && !buffer_locked(bh))
+ bh->b_inode = NULL;
+ else {
+ bh->b_inode = &tmp;
+ list_add(&bh->b_inode_buffers, &tmp.i_dirty_buffers);
+ if (buffer_dirty(bh)) {
+ atomic_inc(&bh->b_count);
+ spin_unlock(&lru_list_lock);
+ ll_rw_block(WRITE, 1, &bh);
+ brelse(bh);
+ spin_lock(&lru_list_lock);
+ }
+ }
+ }
+
+ while (!list_empty(&tmp.i_dirty_buffers)) {
+ bh = BH_ENTRY(tmp.i_dirty_buffers.prev);
+ remove_inode_queue(bh);
+ atomic_inc(&bh->b_count);
+ spin_unlock(&lru_list_lock);
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh))
+ err = -EIO;
+ brelse(bh);
+ spin_lock(&lru_list_lock);
+ }
+
+ spin_unlock(&lru_list_lock);
+ err2 = osync_inode_buffers(inode);
+
+ if (err)
+ return err;
+ else
+ return err2;
+}
+
+
+/*
+ * osync is designed to support O_SYNC io. It waits synchronously for
+ * all already-submitted IO to complete, but does not queue any new
+ * writes to the disk.
+ *
+ * To do O_SYNC writes, just queue the buffer writes with ll_rw_block as
+ * you dirty the buffers, and then use osync_inode_buffers to wait for
+ * completion. Any other dirty buffers which are not yet queued for
+ * write will not be flushed to disk by the osync.
+ */
+
+int osync_inode_buffers(struct inode *inode)
+{
+ struct buffer_head *bh;
+ struct list_head *list;
+ int err = 0;
+
+ spin_lock(&lru_list_lock);
+
+ repeat:
+
+ for (list = inode->i_dirty_buffers.prev;
+ bh = BH_ENTRY(list), list != &inode->i_dirty_buffers;
+ list = bh->b_inode_buffers.prev) {
+ if (buffer_locked(bh)) {
+ atomic_inc(&bh->b_count);
+ spin_unlock(&lru_list_lock);
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh))
+ err = -EIO;
+ brelse(bh);
+ spin_lock(&lru_list_lock);
+ goto repeat;
+ }
+ }
+
+ spin_unlock(&lru_list_lock);
+ return err;
+}
+
+
+/*
+ * Invalidate any and all dirty buffers on a given inode. We are
+ * probably unmounting the fs, but that doesn't mean we have already
+ * done a sync(). Just drop the buffers from the inode list.
+ */
+void invalidate_inode_buffers(struct inode *inode)
+{
+ struct list_head *list, *next;
+
+ spin_lock(&lru_list_lock);
+ list = inode->i_dirty_buffers.next;
+ while (list != &inode->i_dirty_buffers) {
+ next = list->next;
+ remove_inode_queue(BH_ENTRY(list));
+ list = next;
+ }
+ spin_unlock(&lru_list_lock);
+}
+
+
+/*
* Ok, this is getblk, and it isn't very clear, again to hinder
* race-conditions. Most of the code is seldom used, (ie repeating),
* so it should be much more efficient than it looks.
@@ -830,7 +995,7 @@ repeat:
* and it is clean.
*/
if (bh) {
- init_buffer(bh, end_buffer_io_sync, NULL);
+ init_buffer(bh, end_buffer_io_bad, NULL);
bh->b_dev = dev;
bh->b_blocknr = block;
bh->b_state = 1 << BH_Mapped;
@@ -941,6 +1106,8 @@ static void __refile_buffer(struct buffer_head *bh)
if (dispose != bh->b_list) {
__remove_from_lru_list(bh, bh->b_list);
bh->b_list = dispose;
+ if (dispose == BUF_CLEAN)
+ remove_inode_queue(bh);
__insert_into_lru_list(bh, dispose);
}
}
@@ -978,6 +1145,7 @@ void __bforget(struct buffer_head * buf)
if (!atomic_dec_and_test(&buf->b_count) || buffer_locked(buf))
goto in_use;
__hash_unlink(buf);
+ remove_inode_queue(buf);
write_unlock(&hash_table_lock);
__remove_from_lru_list(buf, buf->b_list);
spin_unlock(&lru_list_lock);
@@ -1009,71 +1177,12 @@ struct buffer_head * bread(kdev_t dev, int block, int size)
}
/*
- * Ok, breada can be used as bread, but additionally to mark other
- * blocks for reading as well. End the argument list with a negative
- * number.
- */
-
-#define NBUF 16
-
-struct buffer_head * breada(kdev_t dev, int block, int bufsize,
- unsigned int pos, unsigned int filesize)
-{
- struct buffer_head * bhlist[NBUF];
- unsigned int blocks;
- struct buffer_head * bh;
- int index;
- int i, j;
-
- if (pos >= filesize)
- return NULL;
-
- if (block < 0)
- return NULL;
-
- bh = getblk(dev, block, bufsize);
- index = BUFSIZE_INDEX(bh->b_size);
-
- if (buffer_uptodate(bh))
- return(bh);
- else ll_rw_block(READ, 1, &bh);
-
- blocks = (filesize - pos) >> (9+index);
-
- if (blocks > NBUF)
- blocks = NBUF;
-
- bhlist[0] = bh;
- j = 1;
- for(i=1; i<blocks; i++) {
- bh = getblk(dev,block+i,bufsize);
- if (buffer_uptodate(bh)) {
- brelse(bh);
- break;
- }
- else bhlist[j++] = bh;
- }
-
- /* Request the read for these buffers, and then release them. */
- if (j>1)
- ll_rw_block(READA, (j-1), bhlist+1);
- for(i=1; i<j; i++)
- brelse(bhlist[i]);
-
- /* Wait for this buffer, and then continue on. */
- bh = bhlist[0];
- wait_on_buffer(bh);
- if (buffer_uptodate(bh))
- return bh;
- brelse(bh);
- return NULL;
-}
-
-/*
* Note: the caller should wake up the buffer_wait list if needed.
*/
static __inline__ void __put_unused_buffer_head(struct buffer_head * bh)
{
+ if (bh->b_inode)
+ BUG();
if (nr_unused_buffer_heads >= MAX_UNUSED_BUFFERS) {
kmem_cache_free(bh_cachep, bh);
} else {
@@ -1241,40 +1350,6 @@ no_grow:
goto try_again;
}
-static int create_page_buffers(int rw, struct page *page, kdev_t dev, int b[], int size)
-{
- struct buffer_head *head, *bh, *tail;
- int block;
-
- if (!PageLocked(page))
- BUG();
- /*
- * Allocate async buffer heads pointing to this page, just for I/O.
- * They don't show up in the buffer hash table, but they *are*
- * registered in page->buffers.
- */
- head = create_buffers(page, size, 1);
- if (page->buffers)
- BUG();
- if (!head)
- BUG();
- tail = head;
- for (bh = head; bh; bh = bh->b_this_page) {
- block = *(b++);
-
- tail = bh;
- init_buffer(bh, end_buffer_io_async, NULL);
- bh->b_dev = dev;
- bh->b_blocknr = block;
-
- set_bit(BH_Mapped, &bh->b_state);
- }
- tail->b_this_page = head;
- page_cache_get(page);
- page->buffers = head;
- return 0;
-}
-
static void unmap_buffer(struct buffer_head * bh)
{
if (buffer_mapped(bh)) {
@@ -1339,7 +1414,7 @@ int block_flushpage(struct page *page, unsigned long offset)
return 1;
}
-static void create_empty_buffers(struct page *page, struct inode *inode, unsigned long blocksize)
+static void create_empty_buffers(struct page *page, kdev_t dev, unsigned long blocksize)
{
struct buffer_head *bh, *head, *tail;
@@ -1349,7 +1424,7 @@ static void create_empty_buffers(struct page *page, struct inode *inode, unsigne
bh = head;
do {
- bh->b_dev = inode->i_dev;
+ bh->b_dev = dev;
bh->b_blocknr = 0;
bh->b_end_io = end_buffer_io_bad;
tail = bh;
@@ -1407,7 +1482,7 @@ static void unmap_underlying_metadata(struct buffer_head * bh)
*/
static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block)
{
- int err, i, need_balance_dirty = 0;
+ int err, i;
unsigned long block;
struct buffer_head *bh, *head;
@@ -1415,13 +1490,15 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
BUG();
if (!page->buffers)
- create_empty_buffers(page, inode, inode->i_sb->s_blocksize);
+ create_empty_buffers(page, inode->i_dev, inode->i_sb->s_blocksize);
head = page->buffers;
block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
bh = head;
i = 0;
+
+ /* Stage 1: make sure we have all the buffers mapped! */
do {
/*
* If the buffer isn't up-to-date, we can't be sure
@@ -1431,7 +1508,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
* Leave it to the low-level FS to make all those
* decisions (block #0 may actually be a valid block)
*/
- bh->b_end_io = end_buffer_io_sync;
if (!buffer_mapped(bh)) {
err = get_block(inode, block, bh, 1);
if (err)
@@ -1439,23 +1515,33 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
if (buffer_new(bh))
unmap_underlying_metadata(bh);
}
- set_bit(BH_Uptodate, &bh->b_state);
- if (!atomic_set_buffer_dirty(bh)) {
- __mark_dirty(bh);
- need_balance_dirty = 1;
- }
-
bh = bh->b_this_page;
block++;
} while (bh != head);
- if (need_balance_dirty)
- balance_dirty(bh->b_dev);
+ /* Stage 2: lock the buffers, mark them dirty */
+ do {
+ lock_buffer(bh);
+ bh->b_end_io = end_buffer_io_async;
+ atomic_inc(&bh->b_count);
+ set_bit(BH_Uptodate, &bh->b_state);
+ set_bit(BH_Dirty, &bh->b_state);
+ bh = bh->b_this_page;
+ } while (bh != head);
+ /* Stage 3: submit the IO */
+ do {
+ submit_bh(WRITE, bh);
+ bh = bh->b_this_page;
+ } while (bh != head);
+
+ /* Done - end_buffer_io_async will unlock */
SetPageUptodate(page);
return 0;
+
out:
ClearPageUptodate(page);
+ UnlockPage(page);
return err;
}
@@ -1471,7 +1557,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
blocksize = inode->i_sb->s_blocksize;
if (!page->buffers)
- create_empty_buffers(page, inode, blocksize);
+ create_empty_buffers(page, inode->i_dev, blocksize);
head = page->buffers;
bbits = inode->i_sb->s_blocksize_bits;
@@ -1486,7 +1572,6 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
continue;
if (block_start >= to)
break;
- bh->b_end_io = end_buffer_io_sync;
if (!buffer_mapped(bh)) {
err = get_block(inode, block, bh, 1);
if (err)
@@ -1551,6 +1636,7 @@ static int __block_commit_write(struct inode *inode, struct page *page,
set_bit(BH_Uptodate, &bh->b_state);
if (!atomic_set_buffer_dirty(bh)) {
__mark_dirty(bh);
+ buffer_insert_inode_queue(bh, inode);
need_balance_dirty = 1;
}
}
@@ -1582,14 +1668,13 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
unsigned long iblock, lblock;
struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
unsigned int blocksize, blocks;
- char *kaddr = NULL;
int nr, i;
if (!PageLocked(page))
PAGE_BUG(page);
blocksize = inode->i_sb->s_blocksize;
if (!page->buffers)
- create_empty_buffers(page, inode, blocksize);
+ create_empty_buffers(page, inode->i_dev, blocksize);
head = page->buffers;
blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits;
@@ -1609,35 +1694,40 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
continue;
}
if (!buffer_mapped(bh)) {
- if (!kaddr)
- kaddr = kmap(page);
- memset(kaddr + i*blocksize, 0, blocksize);
+ memset(kmap(page) + i*blocksize, 0, blocksize);
flush_dcache_page(page);
+ kunmap(page);
set_bit(BH_Uptodate, &bh->b_state);
continue;
}
}
- init_buffer(bh, end_buffer_io_async, NULL);
- atomic_inc(&bh->b_count);
arr[nr] = bh;
nr++;
} while (i++, iblock++, (bh = bh->b_this_page) != head);
- if (nr) {
- if (Page_Uptodate(page))
- BUG();
- ll_rw_block(READ, nr, arr);
- } else {
+ if (!nr) {
/*
* all buffers are uptodate - we can set the page
* uptodate as well.
*/
SetPageUptodate(page);
UnlockPage(page);
+ return 0;
}
- if (kaddr)
- kunmap(page);
+
+ /* Stage two: lock the buffers */
+ for (i = 0; i < nr; i++) {
+ struct buffer_head * bh = arr[i];
+ lock_buffer(bh);
+ bh->b_end_io = end_buffer_io_async;
+ atomic_inc(&bh->b_count);
+ }
+
+ /* Stage 3: start the IO */
+ for (i = 0; i < nr; i++)
+ submit_bh(READ, arr[i]);
+
return 0;
}
@@ -1779,7 +1869,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, blocksize);
+ create_empty_buffers(page, inode->i_dev, blocksize);
/* Find the buffer that contains "offset" */
bh = page->buffers;
@@ -1805,7 +1895,6 @@ int block_truncate_page(struct address_space *mapping, loff_t from, get_block_t
if (Page_Uptodate(page))
set_bit(BH_Uptodate, &bh->b_state);
- bh->b_end_io = end_buffer_io_sync;
if (!buffer_uptodate(bh)) {
err = -EIO;
ll_rw_block(READ, 1, &bh);
@@ -1843,8 +1932,11 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
/* things got complicated... */
offset = inode->i_size & (PAGE_CACHE_SIZE-1);
/* OK, are we completely out? */
- if (page->index >= end_index+1 || !offset)
+ if (page->index >= end_index+1 || !offset) {
+ UnlockPage(page);
return -EIO;
+ }
+
/* Sigh... will have to work, then... */
err = __block_prepare_write(inode, page, 0, offset, get_block);
if (!err) {
@@ -1853,6 +1945,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
__block_commit_write(inode,page,0,offset);
done:
kunmap(page);
+ UnlockPage(page);
return err;
}
ClearPageUptodate(page);
@@ -1947,7 +2040,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
int pageind;
int bhind;
int offset;
- int sectors = size>>9;
unsigned long blocknr;
struct kiobuf * iobuf = NULL;
struct page * map;
@@ -1999,9 +2091,8 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
tmp->b_this_page = tmp;
init_buffer(tmp, end_buffer_io_kiobuf, iobuf);
- tmp->b_rdev = tmp->b_dev = dev;
+ tmp->b_dev = dev;
tmp->b_blocknr = blocknr;
- tmp->b_rsector = blocknr*sectors;
tmp->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | (1 << BH_Req);
if (rw == WRITE) {
@@ -2015,7 +2106,7 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
atomic_inc(&iobuf->io_count);
- generic_make_request(rw, tmp);
+ submit_bh(rw, tmp);
/*
* Wait for IO if we have got too much
*/
@@ -2075,67 +2166,30 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
*/
int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size)
{
- struct buffer_head *head, *bh, *arr[MAX_BUF_PER_PAGE];
- int nr, fresh /* temporary debugging flag */, block;
+ struct buffer_head *head, *bh;
if (!PageLocked(page))
panic("brw_page: page not locked for I/O");
-// ClearPageError(page);
- /*
- * We pretty much rely on the page lock for this, because
- * create_page_buffers() might sleep.
- */
- fresh = 0;
- if (!page->buffers) {
- create_page_buffers(rw, page, dev, b, size);
- fresh = 1;
- }
+
if (!page->buffers)
- BUG();
+ create_empty_buffers(page, dev, size);
+ head = bh = page->buffers;
- head = page->buffers;
- bh = head;
- nr = 0;
+ /* Stage 1: lock all the buffers */
do {
- block = *(b++);
+ lock_buffer(bh);
+ bh->b_blocknr = *(b++);
+ set_bit(BH_Mapped, &bh->b_state);
+ bh->b_end_io = end_buffer_io_async;
+ atomic_inc(&bh->b_count);
+ bh = bh->b_this_page;
+ } while (bh != head);
- if (fresh && (atomic_read(&bh->b_count) != 0))
- BUG();
- if (rw == READ) {
- if (!fresh)
- BUG();
- if (!buffer_uptodate(bh)) {
- arr[nr++] = bh;
- atomic_inc(&bh->b_count);
- }
- } else { /* WRITE */
- if (!bh->b_blocknr) {
- if (!block)
- BUG();
- bh->b_blocknr = block;
- } else {
- if (!block)
- BUG();
- }
- set_bit(BH_Uptodate, &bh->b_state);
- set_bit(BH_Dirty, &bh->b_state);
- arr[nr++] = bh;
- atomic_inc(&bh->b_count);
- }
+ /* Stage 2: start the IO */
+ do {
+ submit_bh(rw, bh);
bh = bh->b_this_page;
} while (bh != head);
- if ((rw == READ) && nr) {
- if (Page_Uptodate(page))
- BUG();
- ll_rw_block(rw, nr, arr);
- } else {
- if (!nr && rw == READ) {
- SetPageUptodate(page);
- UnlockPage(page);
- }
- if (nr && (rw == WRITE))
- ll_rw_block(rw, nr, arr);
- }
return 0;
}
@@ -2313,9 +2367,10 @@ cleaned_buffers_try_again:
/* The buffer can be either on the regular
* queues or on the free list..
*/
- if (p->b_dev != B_FREE)
+ if (p->b_dev != B_FREE) {
+ remove_inode_queue(p);
__remove_from_queues(p);
- else
+ } else
__remove_from_free_list(p, index);
__put_unused_buffer_head(p);
} while (tmp != bh);
@@ -2481,9 +2536,9 @@ void wakeup_bdflush(int block)
return;
}
- /* kflushd can wakeup us before we have a chance to
+ /* bdflush can wakeup us before we have a chance to
go to sleep so we must be smart in handling
- this wakeup event from kflushd to avoid deadlocking in SMP
+ this wakeup event from bdflush to avoid deadlocking in SMP
(we are not holding any lock anymore in these two paths). */
__set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&bdflush_done, &wait);
@@ -2646,7 +2701,7 @@ int bdflush(void *sem)
tsk->session = 1;
tsk->pgrp = 1;
- strcpy(tsk->comm, "kflushd");
+ strcpy(tsk->comm, "bdflush");
bdflush_tsk = tsk;
/* avoid getting signals */
diff --git a/fs/dquot.c b/fs/dquot.c
index 1bcd12ceb..a63685d34 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -522,7 +522,7 @@ static inline struct dquot *find_best_free(void)
struct dquot *get_empty_dquot(void)
{
struct dquot *dquot;
- int shrink = 1; /* Number of times we should try to shrink dcache and icache */
+ int shrink = 8; /* Number of times we should try to shrink dcache and icache */
repeat:
dquot = find_best_free();
@@ -1474,7 +1474,7 @@ static int quota_on(struct super_block *sb, short type, char *path)
if (IS_ERR(f))
goto out_lock;
error = -EIO;
- if (!f->f_op->read && !f->f_op->write)
+ if (!f->f_op || (!f->f_op->read && !f->f_op->write))
goto out_f;
inode = f->f_dentry->d_inode;
error = -EACCES;
diff --git a/fs/exec.c b/fs/exec.c
index 1e24a4ace..f04fab7e3 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -604,6 +604,8 @@ int prepare_binprm(struct linux_binprm *bprm)
/* Huh? We had already checked for MAY_EXEC, WTF do we check this? */
if (!(mode & 0111)) /* with at least _one_ execute bit set */
return -EACCES;
+ if (bprm->file->f_op == NULL)
+ return -EACCES;
bprm->e_uid = current->euid;
bprm->e_gid = current->egid;
diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c
index 42ce44c65..8b2ecab41 100644
--- a/fs/ext2/fsync.c
+++ b/fs/ext2/fsync.c
@@ -28,98 +28,6 @@
#include <linux/smp_lock.h>
-#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
-#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
-
-static int sync_indirect(struct inode * inode, u32 * block, int wait)
-{
- struct buffer_head * bh;
-
- if (!*block)
- return 0;
- bh = get_hash_table(inode->i_dev, le32_to_cpu(*block), blocksize);
- if (!bh)
- return 0;
- if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- /* There can be a parallell read(2) that started read-I/O
- on the buffer so we can't assume that there's been
- an I/O error without first waiting I/O completation. */
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- {
- brelse (bh);
- return -1;
- }
- }
- if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
- if (wait)
- /* when we return from fsync all the blocks
- must be _just_ stored on disk */
- wait_on_buffer(bh);
- brelse(bh);
- return 0;
- }
- ll_rw_block(WRITE, 1, &bh);
- atomic_dec(&bh->b_count);
- return 0;
-}
-
-static int sync_iblock(struct inode * inode, u32 * iblock,
- struct buffer_head ** bh, int wait)
-{
- int rc, tmp;
-
- *bh = NULL;
- tmp = le32_to_cpu(*iblock);
- if (!tmp)
- return 0;
- rc = sync_indirect(inode, iblock, wait);
- if (rc)
- return rc;
- *bh = bread(inode->i_dev, tmp, blocksize);
- if (!*bh)
- return -1;
- return 0;
-}
-
-static int sync_dindirect(struct inode * inode, u32 * diblock, int wait)
-{
- int i;
- struct buffer_head * dind_bh;
- int rc, err = 0;
-
- rc = sync_iblock(inode, diblock, &dind_bh, wait);
- if (rc || !dind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_indirect(inode, ((u32 *) dind_bh->b_data) + i, wait);
- if (rc)
- err = rc;
- }
- brelse(dind_bh);
- return err;
-}
-
-static int sync_tindirect(struct inode * inode, u32 * tiblock, int wait)
-{
- int i;
- struct buffer_head * tind_bh;
- int rc, err = 0;
-
- rc = sync_iblock(inode, tiblock, &tind_bh, wait);
- if (rc || !tind_bh)
- return rc;
-
- for (i = 0; i < addr_per_block; i++) {
- rc = sync_dindirect(inode, ((u32 *) tind_bh->b_data) + i, wait);
- if (rc)
- err = rc;
- }
- brelse(tind_bh);
- return err;
-}
-
/*
* File may be NULL when we are called. Perhaps we shouldn't
* even pass file to fsync ?
@@ -127,32 +35,20 @@ static int sync_tindirect(struct inode * inode, u32 * tiblock, int wait)
int ext2_sync_file(struct file * file, struct dentry *dentry, int datasync)
{
- int wait, err = 0;
struct inode *inode = dentry->d_inode;
+ return ext2_fsync_inode(inode, datasync);
+}
- lock_kernel();
- if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
- /*
- * Don't sync fast links!
- */
- goto skip;
-
- err = generic_buffer_fdatasync(inode, 0, ~0UL);
-
- for (wait=0; wait<=1; wait++)
- {
- err |= sync_indirect(inode,
- inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
- wait);
- err |= sync_dindirect(inode,
- inode->u.ext2_i.i_data+EXT2_DIND_BLOCK,
- wait);
- err |= sync_tindirect(inode,
- inode->u.ext2_i.i_data+EXT2_TIND_BLOCK,
- wait);
- }
-skip:
- err |= ext2_sync_inode (inode);
- unlock_kernel();
+int ext2_fsync_inode(struct inode *inode, int datasync)
+{
+ int err;
+
+ err = fsync_inode_buffers(inode);
+ if (!(inode->i_state & I_DIRTY))
+ return err;
+ if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+ return err;
+
+ err |= ext2_sync_inode(inode);
return err ? -EIO : 0;
}
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index cf8fa5154..9e4a9b6b0 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -256,7 +256,7 @@ error_return:
* For other inodes, search forward from the parent directory\'s block
* group to find a free inode.
*/
-struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
+struct inode * ext2_new_inode (const struct inode * dir, int mode)
{
struct super_block * sb;
struct buffer_head * bh;
@@ -267,26 +267,22 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
struct ext2_group_desc * gdp;
struct ext2_group_desc * tmp;
struct ext2_super_block * es;
+ int err;
/* Cannot create files in a deleted directory */
- if (!dir || !dir->i_nlink) {
- *err = -EPERM;
- return NULL;
- }
+ if (!dir || !dir->i_nlink)
+ return ERR_PTR(-EPERM);
sb = dir->i_sb;
inode = new_inode(sb);
- if (!inode) {
- *err = -ENOMEM;
- return NULL;
- }
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
lock_super (sb);
es = sb->u.ext2_sb.s_es;
repeat:
gdp = NULL; i=0;
- *err = -ENOSPC;
if (S_ISDIR(mode)) {
avefreei = le32_to_cpu(es->s_free_inodes_count) /
sb->u.ext2_sb.s_groups_count;
@@ -365,18 +361,14 @@ repeat:
}
}
- if (!gdp) {
- unlock_super (sb);
- iput(inode);
- return NULL;
- }
+ err = -ENOSPC;
+ if (!gdp)
+ goto fail;
+
+ err = -EIO;
bitmap_nr = load_inode_bitmap (sb, i);
- if (bitmap_nr < 0) {
- unlock_super (sb);
- iput(inode);
- *err = -EIO;
- return NULL;
- }
+ if (bitmap_nr < 0)
+ goto fail;
bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
@@ -397,11 +389,11 @@ repeat:
ext2_error (sb, "ext2_new_inode",
"Free inodes count corrupted in group %d",
i);
- if (sb->s_flags & MS_RDONLY) {
- unlock_super (sb);
- iput (inode);
- return NULL;
- }
+ /* Is it really ENOSPC? */
+ err = -ENOSPC;
+ if (sb->s_flags & MS_RDONLY)
+ goto fail;
+
gdp->bg_free_inodes_count = 0;
mark_buffer_dirty(bh2);
}
@@ -412,10 +404,8 @@ repeat:
ext2_error (sb, "ext2_new_inode",
"reserved inode or inode > inodes count - "
"block_group = %d,inode=%d", i, j);
- unlock_super (sb);
- iput (inode);
- *err = -EIO;
- return NULL;
+ err = -EIO;
+ goto fail;
}
gdp->bg_free_inodes_count =
cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
@@ -464,13 +454,15 @@ repeat:
sb->dq_op->drop(inode);
inode->i_nlink = 0;
iput(inode);
- *err = -EDQUOT;
- return NULL;
+ return ERR_PTR(-EDQUOT);
}
ext2_debug ("allocating inode %lu\n", inode->i_ino);
-
- *err = 0;
return inode;
+
+fail:
+ unlock_super(sb);
+ iput(inode);
+ return ERR_PTR(err);
}
unsigned long ext2_count_free_inodes (struct super_block * sb)
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 5852cef4c..658a06416 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -404,7 +404,7 @@ static int ext2_alloc_branch(struct inode *inode,
branch[n].p = (u32*) bh->b_data + offsets[n];
*branch[n].p = branch[n].key;
mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh);
+ mark_buffer_dirty_inode(bh, inode);
if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -469,7 +469,7 @@ static inline int ext2_splice_branch(struct inode *inode,
/* had we spliced it onto indirect block? */
if (where->bh) {
- mark_buffer_dirty(where->bh);
+ mark_buffer_dirty_inode(where->bh, inode);
if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {
ll_rw_block (WRITE, 1, &where->bh);
wait_on_buffer(where->bh);
@@ -591,7 +591,7 @@ struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, i
wait_on_buffer(bh);
memset(bh->b_data, 0, inode->i_sb->s_blocksize);
mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh);
+ mark_buffer_dirty_inode(bh, inode);
}
return bh;
}
@@ -650,7 +650,7 @@ struct buffer_head * ext2_bread (struct inode * inode, int block,
return NULL;
}
-static int ext2_writepage(struct file *file, struct page *page)
+static int ext2_writepage(struct page *page)
{
return block_write_full_page(page,ext2_get_block);
}
@@ -907,7 +907,7 @@ void ext2_truncate (struct inode * inode)
if (partial == chain)
mark_inode_dirty(inode);
else
- mark_buffer_dirty(partial->bh);
+ mark_buffer_dirty_inode(partial->bh, inode);
ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);
}
/* Clear the ends of indirect blocks on the shared branch */
@@ -916,7 +916,7 @@ void ext2_truncate (struct inode * inode)
partial->p + 1,
(u32*)partial->bh->b_data + addr_per_block,
(chain+n-1) - partial);
- mark_buffer_dirty(partial->bh);
+ mark_buffer_dirty_inode(partial->bh, inode);
if (IS_SYNC(inode)) {
ll_rw_block (WRITE, 1, &partial->bh);
wait_on_buffer (partial->bh);
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 3c981f75c..59d3ef492 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -296,7 +296,7 @@ int ext2_add_entry (struct inode * dir, const char * name, int namelen,
dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(dir);
dir->i_version = ++event;
- mark_buffer_dirty(bh);
+ mark_buffer_dirty_inode(bh, dir);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -337,7 +337,7 @@ static int ext2_delete_entry (struct inode * dir,
else
de->inode = 0;
dir->i_version = ++event;
- mark_buffer_dirty(bh);
+ mark_buffer_dirty_inode(bh, dir);
if (IS_SYNC(dir)) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
@@ -361,11 +361,9 @@ static int ext2_delete_entry (struct inode * dir,
*/
static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
{
- struct inode * inode;
- int err;
-
- inode = ext2_new_inode (dir, mode, &err);
- if (!inode)
+ struct inode * inode = ext2_new_inode (dir, mode);
+ int err = PTR_ERR(inode);
+ if (IS_ERR(inode))
return err;
inode->i_op = &ext2_file_inode_operations;
@@ -387,11 +385,10 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
{
- struct inode * inode;
- int err;
+ struct inode * inode = ext2_new_inode (dir, mode);
+ int err = PTR_ERR(inode);
- inode = ext2_new_inode (dir, mode, &err);
- if (!inode)
+ if (IS_ERR(inode))
return err;
inode->i_uid = current->fsuid;
@@ -421,8 +418,9 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
if (dir->i_nlink >= EXT2_LINK_MAX)
return -EMLINK;
- inode = ext2_new_inode (dir, S_IFDIR, &err);
- if (!inode)
+ inode = ext2_new_inode (dir, S_IFDIR);
+ err = PTR_ERR(inode);
+ if (IS_ERR(inode))
return err;
inode->i_op = &ext2_dir_inode_operations;
@@ -449,7 +447,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
strcpy (de->name, "..");
ext2_set_de_type(dir->i_sb, de, S_IFDIR);
inode->i_nlink = 2;
- mark_buffer_dirty(dir_block);
+ mark_buffer_dirty_inode(dir_block, dir);
brelse (dir_block);
inode->i_mode = S_IFDIR | mode;
if (dir->i_mode & S_ISGID)
@@ -628,7 +626,9 @@ static int ext2_symlink (struct inode * dir, struct dentry *dentry, const char *
if (l > dir->i_sb->s_blocksize)
return -ENAMETOOLONG;
- if (!(inode = ext2_new_inode (dir, S_IFLNK, &err)))
+ inode = ext2_new_inode (dir, S_IFLNK);
+ err = PTR_ERR(inode);
+ if (IS_ERR(inode))
return err;
inode->i_mode = S_IFLNK | S_IRWXUGO;
@@ -755,7 +755,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
EXT2_FEATURE_INCOMPAT_FILETYPE))
new_de->file_type = old_de->file_type;
new_dir->i_version = ++event;
- mark_buffer_dirty(new_bh);
+ mark_buffer_dirty_inode(new_bh, new_dir);
if (IS_SYNC(new_dir)) {
ll_rw_block (WRITE, 1, &new_bh);
wait_on_buffer (new_bh);
@@ -786,7 +786,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
mark_inode_dirty(old_dir);
if (dir_bh) {
PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
- mark_buffer_dirty(dir_bh);
+ mark_buffer_dirty_inode(dir_bh, old_inode);
old_dir->i_nlink--;
mark_inode_dirty(old_dir);
if (new_inode) {
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 7537ee569..82f58826d 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -735,7 +735,7 @@ static int is_exec(char *extension)
return 0;
}
-static int fat_writepage(struct file *file, struct page *page)
+static int fat_writepage(struct page *page)
{
return block_write_full_page(page,fat_get_block);
}
diff --git a/fs/file.c b/fs/file.c
index 2f8ea1918..84d0275cd 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -16,7 +16,7 @@
/*
- * Allocate an fd array, using __get_free_page() if possible.
+ * Allocate an fd array, using kmalloc or vmalloc.
* Note: the array isn't cleared at allocation time.
*/
struct file ** alloc_fd_array(int num)
@@ -125,7 +125,7 @@ out:
}
/*
- * Allocate an fdset array, using __get_free_page() if possible.
+ * Allocate an fdset array, using kmalloc or vmalloc.
* Note: the array isn't cleared at allocation time.
*/
fd_set * alloc_fdset(int num)
diff --git a/fs/file_table.c b/fs/file_table.c
index 09b28574d..7a935a739 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -40,13 +40,11 @@ struct file * get_empty_filp(void)
list_del(&f->f_list);
files_stat.nr_free_files--;
new_one:
- file_list_unlock();
memset(f, 0, sizeof(*f));
atomic_set(&f->f_count,1);
f->f_version = ++event;
f->f_uid = current->fsuid;
f->f_gid = current->fsgid;
- file_list_lock();
list_add(&f->f_list, &anon_list);
file_list_unlock();
return f;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 56d1547e7..7414a4c29 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -220,7 +220,7 @@ int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
return __hfs_notify_change(dentry, attr, HFS_HDR);
}
-static int hfs_writepage(struct file *file, struct page *page)
+static int hfs_writepage(struct page *page)
{
return block_write_full_page(page,hfs_get_block);
}
diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c
index 5f5ec196f..c7b63f358 100644
--- a/fs/hpfs/buffer.c
+++ b/fs/hpfs/buffer.c
@@ -127,7 +127,7 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head
if (!ahead || secno + ahead >= s->s_hpfs_fs_size)
*bhp = bh = bread(dev, secno, 512);
- else *bhp = bh = breada(dev, secno, 512, 0, (ahead + 1) << 9);
+ else *bhp = bh = bread(dev, secno, 512);
if (bh != NULL)
return bh->b_data;
else {
@@ -175,7 +175,7 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
if (!ahead || secno + 4 + ahead > s->s_hpfs_fs_size)
qbh->bh[0] = bh = bread(dev, secno, 512);
- else qbh->bh[0] = bh = breada(dev, secno, 512, 0, (ahead + 4) << 9);
+ else qbh->bh[0] = bh = bread(dev, secno, 512);
if (!bh)
goto bail0;
memcpy(data, bh->b_data, 512);
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index fb5f566e7..a9675ef54 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -93,7 +93,7 @@ int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resu
return 0;
}
-static int hpfs_writepage(struct file *file, struct page *page)
+static int hpfs_writepage(struct page *page)
{
return block_write_full_page(page,hpfs_get_block);
}
diff --git a/fs/inode.c b/fs/inode.c
index 96e3664e5..abbc04f1c 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -77,7 +77,13 @@ static kmem_cache_t * inode_cachep;
#define alloc_inode() \
((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL))
-#define destroy_inode(inode) kmem_cache_free(inode_cachep, (inode))
+static void destroy_inode(struct inode *inode)
+{
+ if (!list_empty(&inode->i_dirty_buffers))
+ BUG();
+ kmem_cache_free(inode_cachep, (inode));
+}
+
/*
* These are initializations that only need to be done
@@ -96,6 +102,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
INIT_LIST_HEAD(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_data.pages);
INIT_LIST_HEAD(&inode->i_dentry);
+ INIT_LIST_HEAD(&inode->i_dirty_buffers);
sema_init(&inode->i_sem, 1);
sema_init(&inode->i_zombie, 1);
spin_lock_init(&inode->i_data.i_shared_lock);
@@ -122,14 +129,14 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
* Mark an inode as dirty. Callers should use mark_inode_dirty.
*/
-void __mark_inode_dirty(struct inode *inode)
+void __mark_inode_dirty(struct inode *inode, int flags)
{
struct super_block * sb = inode->i_sb;
if (sb) {
spin_lock(&inode_lock);
- if (!(inode->i_state & I_DIRTY)) {
- inode->i_state |= I_DIRTY;
+ if ((inode->i_state & flags) != flags) {
+ inode->i_state |= flags;
/* Only add valid (ie hashed) inodes to the dirty list */
if (!list_empty(&inode->i_hash)) {
list_del(&inode->i_list);
@@ -196,7 +203,8 @@ static inline void sync_one(struct inode *inode, int sync)
? &inode_in_use
: &inode_unused);
/* Set I_LOCK, reset I_DIRTY */
- inode->i_state ^= I_DIRTY | I_LOCK;
+ inode->i_state |= I_LOCK;
+ inode->i_state &= ~I_DIRTY;
spin_unlock(&inode_lock);
write_inode(inode, sync);
@@ -282,6 +290,60 @@ void write_inode_now(struct inode *inode, int sync)
}
/**
+ * generic_osync_inode - flush all dirty data for a given inode to disk
+ * @inode: inode to write
+ * @datasync: if set, don't bother flushing timestamps
+ *
+ * This can be called by file_write functions for files which have the
+ * O_SYNC flag set, to flush dirty writes to disk.
+ */
+
+int generic_osync_inode(struct inode *inode, int datasync)
+{
+ int err;
+
+ /*
+ * WARNING
+ *
+ * Currently, the filesystem write path does not pass the
+ * filp down to the low-level write functions. Therefore it
+ * is impossible for (say) __block_commit_write to know if
+ * the operation is O_SYNC or not.
+ *
+ * Ideally, O_SYNC writes would have the filesystem call
+ * ll_rw_block as it went to kick-start the writes, and we
+ * could call osync_inode_buffers() here to wait only for
+ * those IOs which have already been submitted to the device
+ * driver layer. As it stands, if we did this we'd not write
+ * anything to disk since our writes have not been queued by
+ * this point: they are still on the dirty LRU.
+ *
+ * So, currently we will call fsync_inode_buffers() instead,
+ * to flush _all_ dirty buffers for this inode to disk on
+ * every O_SYNC write, not just the synchronous I/Os. --sct
+ */
+
+#ifdef WRITERS_QUEUE_IO
+ err = osync_inode_buffers(inode);
+#else
+ err = fsync_inode_buffers(inode);
+#endif
+
+ spin_lock(&inode_lock);
+ if (!(inode->i_state & I_DIRTY))
+ goto out;
+ if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+ goto out;
+ spin_unlock(&inode_lock);
+ write_inode_now(inode, 1);
+ return err;
+
+ out:
+ spin_unlock(&inode_lock);
+ return err;
+}
+
+/**
* clear_inode - clear an inode
* @inode: inode to clear
*
@@ -292,6 +354,9 @@ void write_inode_now(struct inode *inode, int sync)
void clear_inode(struct inode *inode)
{
+ if (!list_empty(&inode->i_dirty_buffers))
+ invalidate_inode_buffers(inode);
+
if (inode->i_data.nrpages)
BUG();
if (!(inode->i_state & I_FREEING))
@@ -351,6 +416,7 @@ static int invalidate_list(struct list_head *head, struct super_block * sb, stru
inode = list_entry(tmp, struct inode, i_list);
if (inode->i_sb != sb)
continue;
+ invalidate_inode_buffers(inode);
if (!atomic_read(&inode->i_count)) {
list_del(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_hash);
@@ -412,7 +478,8 @@ int invalidate_inodes(struct super_block * sb)
* dispose_list.
*/
#define CAN_UNUSE(inode) \
- (((inode)->i_state | (inode)->i_data.nrpages) == 0)
+ ((((inode)->i_state | (inode)->i_data.nrpages) == 0) && \
+ !inode_has_buffers(inode))
#define INODE(entry) (list_entry(entry, struct inode, i_list))
void prune_icache(int goal)
@@ -911,7 +978,7 @@ void update_atime (struct inode *inode)
if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return;
if ( IS_RDONLY (inode) ) return;
inode->i_atime = CURRENT_TIME;
- mark_inode_dirty (inode);
+ mark_inode_dirty_sync (inode);
} /* End Function update_atime */
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index c9915cf80..6f0957dce 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -115,9 +115,6 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
char *p = NULL; /* Quiet GCC */
struct iso_directory_record *de;
- if (filp->f_pos >= inode->i_size)
- return 0;
-
offset = filp->f_pos & (bufsize - 1);
block = filp->f_pos >> bufbits;
high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
@@ -132,7 +129,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
}
de = (struct iso_directory_record *) (bh->b_data + offset);
- if (first_de) inode_number = (bh->b_blocknr << bufbits) + offset;
+ if (first_de)
+ inode_number = (bh->b_blocknr << bufbits) + offset;
de_len = *(unsigned char *) de;
@@ -165,7 +163,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
return 0;
memcpy((void *) tmpde + slop, bh->b_data, offset);
}
- de = tmpde;
+ de = tmpde;
}
if (de->flags[-high_sierra] & 0x80) {
@@ -207,7 +205,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
map = 1;
if (inode->i_sb->u.isofs_sb.s_rock) {
len = get_rock_ridge_filename(de, tmpname, inode);
- if (len != 0) {
+ if (len != 0) { /* may be -1 */
p = tmpname;
map = 0;
}
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 453e4a456..5d50c37a6 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -45,14 +45,14 @@ static int check_bread = 0;
static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
static int isofs_hash(struct dentry *parent, struct qstr *qstr);
-static int isofs_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
-static int isofs_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
+static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
+static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
#ifdef CONFIG_JOLIET
static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);
static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);
-static int isofs_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
-static int isofs_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
+static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
+static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
#endif
static void isofs_put_super(struct super_block *sb)
@@ -84,20 +84,20 @@ static struct super_operations isofs_sops = {
static struct dentry_operations isofs_dentry_ops[] = {
{
d_hash: isofs_hash,
- d_compare: isofs_cmp,
+ d_compare: isofs_dentry_cmp,
},
{
d_hash: isofs_hashi,
- d_compare: isofs_cmpi,
+ d_compare: isofs_dentry_cmpi,
},
#ifdef CONFIG_JOLIET
{
d_hash: isofs_hash_ms,
- d_compare: isofs_cmp_ms,
+ d_compare: isofs_dentry_cmp_ms,
},
{
d_hash: isofs_hashi_ms,
- d_compare: isofs_cmpi_ms,
+ d_compare: isofs_dentry_cmpi_ms,
}
#endif
};
@@ -173,7 +173,7 @@ isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
* Case insensitive compare of two isofs names.
*/
static int
-isofs_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
+isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
{
int alen, blen;
@@ -197,7 +197,7 @@ isofs_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
* Case sensitive compare of two isofs names.
*/
static int
-isofs_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
+isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
{
int alen, blen;
@@ -230,15 +230,15 @@ isofs_hashi(struct dentry *dentry, struct qstr *qstr)
}
static int
-isofs_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b)
+isofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b)
{
- return isofs_cmp_common(dentry, a, b, 0);
+ return isofs_dentry_cmp_common(dentry, a, b, 0);
}
static int
-isofs_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b)
+isofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b)
{
- return isofs_cmpi_common(dentry, a, b, 0);
+ return isofs_dentry_cmpi_common(dentry, a, b, 0);
}
#ifdef CONFIG_JOLIET
@@ -255,15 +255,15 @@ isofs_hashi_ms(struct dentry *dentry, struct qstr *qstr)
}
static int
-isofs_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
+isofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
{
- return isofs_cmp_common(dentry, a, b, 1);
+ return isofs_dentry_cmp_common(dentry, a, b, 1);
}
static int
-isofs_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
+isofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
{
- return isofs_cmpi_common(dentry, a, b, 1);
+ return isofs_dentry_cmpi_common(dentry, a, b, 1);
}
#endif
@@ -500,15 +500,13 @@ static struct super_block *isofs_read_super(struct super_block *s, void *data,
* that value.
*/
blocksize = get_hardblocksize(dev);
- if( (blocksize != 0)
- && (blocksize > opt.blocksize) )
- {
+ if(blocksize > opt.blocksize) {
/*
* Force the blocksize we are going to use to be the
* hardware blocksize.
*/
opt.blocksize = blocksize;
- }
+ }
blocksize_bits = 0;
{
@@ -605,9 +603,8 @@ static struct super_block *isofs_read_super(struct super_block *s, void *data,
pri_bh = NULL;
root_found:
- brelse(pri_bh);
- if (joliet_level && opt.rock == 'n') {
+ if (joliet_level && (pri == NULL || opt.rock == 'n')) {
/* This is the case of Joliet with the norock mount flag.
* A disc with both Joliet and Rock Ridge is handled later
*/
@@ -704,6 +701,7 @@ root_found:
* We're all done using the volume descriptor, and may need
* to change the device blocksize, so release the buffer now.
*/
+ brelse(pri_bh);
brelse(bh);
/*
@@ -756,8 +754,9 @@ root_found:
s->u.isofs_sb.s_gid = opt.gid;
s->u.isofs_sb.s_utf8 = opt.utf8;
/*
- * It would be incredibly stupid to allow people to mark every file on the disk
- * as suid, so we merely allow them to set the default permissions.
+ * It would be incredibly stupid to allow people to mark every file
+ * on the disk as suid, so we merely allow them to set the default
+ * permissions.
*/
s->u.isofs_sb.s_mode = opt.mode & 0777;
@@ -873,7 +872,7 @@ static int isofs_statfs (struct super_block *sb, struct statfs *buf)
/* Life is simpler than for other filesystem since we never
* have to create a new block, only find an existing one.
*/
-int isofs_get_block(struct inode *inode, long iblock,
+static int isofs_get_block(struct inode *inode, long iblock,
struct buffer_head *bh_result, int create)
{
unsigned long b_off;
@@ -940,26 +939,26 @@ abort:
return err;
abort_create_attempted:
- printk("_isofs_bmap: Kernel tries to allocate a block\n");
+ printk("isofs_get_block: Kernel tries to allocate a block\n");
goto abort;
abort_negative:
- printk("_isofs_bmap: block < 0\n");
+ printk("isofs_get_block: block < 0\n");
goto abort;
abort_beyond_end:
- printk("_isofs_bmap: block >= EOF (%ld, %ld)\n",
+ printk("isofs_get_block: block >= EOF (%ld, %ld)\n",
iblock, (unsigned long) inode->i_size);
goto abort;
abort_too_many_sections:
- printk("isofs_bmap: More than 100 file sections ?!?, aborting...\n");
- printk("isofs_bmap: ino=%lu block=%ld firstext=%u sect_size=%u nextino=%lu\n",
+ printk("isofs_get_block: More than 100 file sections ?!?, aborting...\n");
+ printk("isofs_get_block: ino=%lu block=%ld firstext=%u sect_size=%u nextino=%lu\n",
inode->i_ino, iblock, firstext, (unsigned) sect_size, nextino);
goto abort;
}
-int isofs_bmap(struct inode *inode, int block)
+static int isofs_bmap(struct inode *inode, int block)
{
struct buffer_head dummy;
int error;
@@ -1019,10 +1018,7 @@ static int isofs_read_level3_size(struct inode * inode)
unsigned long block, offset;
int i = 0;
int more_entries = 0;
- struct iso_directory_record * tmpde = kmalloc(256, GFP_KERNEL);
-
- if (!tmpde)
- return -ENOMEM;
+ struct iso_directory_record * tmpde = NULL;
inode->i_size = 0;
inode->u.isofs_i.i_next_section_ino = 0;
@@ -1056,6 +1052,11 @@ static int isofs_read_level3_size(struct inode * inode)
/* Make sure we have a full directory entry */
if (offset >= bufsize) {
int slop = bufsize - offset + de_len;
+ if (!tmpde) {
+ tmpde = kmalloc(256, GFP_KERNEL);
+ if (!tmpde)
+ goto out_nomem;
+ }
memcpy(tmpde, de, slop);
offset &= bufsize - 1;
block++;
@@ -1082,14 +1083,23 @@ static int isofs_read_level3_size(struct inode * inode)
goto out_toomany;
} while(more_entries);
out:
- kfree(tmpde);
- if (bh) brelse(bh);
+ if (tmpde)
+ kfree(tmpde);
+ if (bh)
+ brelse(bh);
return 0;
+out_nomem:
+ if (bh)
+ brelse(bh);
+ return -ENOMEM;
+
out_noread:
printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block);
- kfree(tmpde);
- return 1;
+ if (tmpde)
+ kfree(tmpde);
+ return -EIO;
+
out_toomany:
printk(KERN_INFO "isofs_read_level3_size: "
"More than 100 file sections ?!?, aborting...\n"
@@ -1104,22 +1114,39 @@ static void isofs_read_inode(struct inode * inode)
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
int high_sierra = sb->u.isofs_sb.s_high_sierra;
- struct buffer_head * bh;
- struct iso_directory_record * raw_inode;
- unsigned char *pnt;
+ struct buffer_head * bh = NULL;
+ struct iso_directory_record * de;
+ struct iso_directory_record * tmpde = NULL;
+ unsigned int de_len;
+ unsigned long offset;
int volume_seq_no, i;
bh = bread(inode->i_dev, block, bufsize);
- if (!bh) {
- printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
- goto fail;
- }
+ if (!bh)
+ goto out_badread;
+
+ offset = (inode->i_ino & (bufsize - 1));
+ de = (struct iso_directory_record *) (bh->b_data + offset);
+ de_len = *(unsigned char *) de;
+
+ if (offset + de_len > bufsize) {
+ int frag1 = bufsize - offset;
- pnt = ((unsigned char *) bh->b_data
- + (inode->i_ino & (bufsize - 1)));
- raw_inode = ((struct iso_directory_record *) pnt);
+ tmpde = kmalloc(de_len, GFP_KERNEL);
+ if (tmpde == NULL) {
+ printk(KERN_INFO "isofs_read_inode: out of memory\n");
+ goto fail;
+ }
+ memcpy(tmpde, bh->b_data + offset, frag1);
+ brelse(bh);
+ bh = bread(inode->i_dev, ++block, bufsize);
+ if (!bh)
+ goto out_badread;
+ memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1);
+ de = tmpde;
+ }
- if (raw_inode->flags[-high_sierra] & 2) {
+ if (de->flags[-high_sierra] & 2) {
inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
inode->i_nlink = 1; /* Set to 1. We know there are 2, but
the find utility tries to optimize
@@ -1134,10 +1161,10 @@ static void isofs_read_inode(struct inode * inode)
/* If there are no periods in the name,
* then set the execute permission bit
*/
- for(i=0; i< raw_inode->name_len[0]; i++)
- if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
+ for(i=0; i< de->name_len[0]; i++)
+ if(de->name[i]=='.' || de->name[i]==';')
break;
- if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
+ if(i == de->name_len[0] || de->name[i] == ';')
inode->i_mode |= S_IXUGO; /* execute permission */
}
inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
@@ -1145,84 +1172,77 @@ static void isofs_read_inode(struct inode * inode)
inode->i_blocks = inode->i_blksize = 0;
- inode->u.isofs_i.i_section_size = isonum_733 (raw_inode->size);
- if(raw_inode->flags[-high_sierra] & 0x80) {
+ inode->u.isofs_i.i_section_size = isonum_733 (de->size);
+ if(de->flags[-high_sierra] & 0x80) {
if(isofs_read_level3_size(inode)) goto fail;
} else {
- inode->i_size = isonum_733 (raw_inode->size);
+ inode->i_size = isonum_733 (de->size);
}
/* There are defective discs out there - we do this to protect
ourselves. A cdrom will never contain more than 800Mb
.. but a DVD may be up to 1Gig (Ulrich Habel) */
- if((inode->i_size < 0 || inode->i_size > 1073741824) &&
+
+ if ((inode->i_size < 0 || inode->i_size > 1073741824) &&
inode->i_sb->u.isofs_sb.s_cruft == 'n') {
- printk(KERN_WARNING "Warning: defective CD-ROM. Enabling \"cruft\" mount option.\n");
- inode->i_sb->u.isofs_sb.s_cruft = 'y';
+ printk(KERN_WARNING "Warning: defective CD-ROM. "
+ "Enabling \"cruft\" mount option.\n");
+ inode->i_sb->u.isofs_sb.s_cruft = 'y';
}
-/* Some dipshit decided to store some other bit of information in the high
- byte of the file length. Catch this and holler. WARNING: this will make
- it impossible for a file to be > 16Mb on the CDROM!!!*/
+ /*
+ * Some dipshit decided to store some other bit of information
+ * in the high byte of the file length. Catch this and holler.
+ * WARNING: this will make it impossible for a file to be > 16MB
+ * on the CDROM.
+ */
- if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
- inode->i_size & 0xff000000){
-/* printk("Illegal format on cdrom. Pester manufacturer.\n"); */
- inode->i_size &= 0x00ffffff;
+ if (inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
+ inode->i_size & 0xff000000) {
+ inode->i_size &= 0x00ffffff;
}
- if (raw_inode->interleave[0]) {
+ if (de->interleave[0]) {
printk("Interleaved files not (yet) supported.\n");
inode->i_size = 0;
}
/* I have no idea what file_unit_size is used for, so
we will flag it for now */
- if(raw_inode->file_unit_size[0] != 0){
- printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
+ if (de->file_unit_size[0] != 0) {
+ printk("File unit size != 0 for ISO file (%ld).\n",
+ inode->i_ino);
}
/* I have no idea what other flag bits are used for, so
we will flag it for now */
#ifdef DEBUG
- if((raw_inode->flags[-high_sierra] & ~2)!= 0){
+ if((de->flags[-high_sierra] & ~2)!= 0){
printk("Unusual flag settings for ISO file (%ld %x).\n",
- inode->i_ino, raw_inode->flags[-high_sierra]);
+ inode->i_ino, de->flags[-high_sierra]);
}
#endif
-#ifdef DEBUG
- printk("Get inode %x: %d %d: %d\n",inode->i_ino, block,
- ((int)pnt) & 0x3ff, inode->i_size);
-#endif
-
inode->i_mtime = inode->i_atime = inode->i_ctime =
- iso_date(raw_inode->date, high_sierra);
+ iso_date(de->date, high_sierra);
- inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) +
- isonum_711 (raw_inode->ext_attr_length));
+ inode->u.isofs_i.i_first_extent = (isonum_733 (de->extent) +
+ isonum_711 (de->ext_attr_length));
-/* Now test for possible Rock Ridge extensions which will override some of
- these numbers in the inode structure. */
+ /*
+ * Now test for possible Rock Ridge extensions which will override
+ * some of these numbers in the inode structure.
+ */
if (!high_sierra) {
- parse_rock_ridge_inode(raw_inode, inode);
- /* hmm..if we want uid or gid set, override the rock ridge setting */
- test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
- test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid);
+ parse_rock_ridge_inode(de, inode);
+ /* if we want uid/gid set, override the rock ridge setting */
+ test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
+ test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid);
}
-#ifdef DEBUG
- printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
-#endif
-
/* get the volume sequence number */
- volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
-
- /*
- * All done with buffer ... no more references to buffer memory!
- */
- brelse(bh);
+ volume_seq_no = isonum_723 (de->volume_sequence_number) ;
/*
* Disable checking if we see any volume number other than 0 or 1.
@@ -1232,8 +1252,10 @@ static void isofs_read_inode(struct inode * inode)
*/
if (inode->i_sb->u.isofs_sb.s_cruft == 'n' &&
(volume_seq_no != 0) && (volume_seq_no != 1)) {
- printk(KERN_WARNING "Warning: defective CD-ROM (volume sequence number). Enabling \"cruft\" mount option.\n");
- inode->i_sb->u.isofs_sb.s_cruft = 'y';
+ printk(KERN_WARNING "Warning: defective CD-ROM "
+ "(volume sequence number %d). "
+ "Enabling \"cruft\" mount option.\n", volume_seq_no);
+ inode->i_sb->u.isofs_sb.s_cruft = 'y';
}
/* Install the inode operations vector */
@@ -1244,25 +1266,32 @@ static void isofs_read_inode(struct inode * inode)
} else
#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
{
- if (S_ISREG(inode->i_mode)) {
- inode->i_fop = &generic_ro_fops;
- inode->i_data.a_ops = &isofs_aops;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &isofs_dir_inode_operations;
- inode->i_fop = &isofs_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &page_symlink_inode_operations;
- inode->i_data.a_ops = &isofs_symlink_aops;
- } else
- /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
- init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev));
+ if (S_ISREG(inode->i_mode)) {
+ inode->i_fop = &generic_ro_fops;
+ inode->i_data.a_ops = &isofs_aops;
+ } else if (S_ISDIR(inode->i_mode)) {
+ inode->i_op = &isofs_dir_inode_operations;
+ inode->i_fop = &isofs_dir_operations;
+ } else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &isofs_symlink_aops;
+ } else
+ /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
+ init_special_inode(inode, inode->i_mode,
+ kdev_t_to_nr(inode->i_rdev));
}
+ out:
+ if (tmpde)
+ kfree(tmpde);
+ if (bh)
+ brelse(bh);
return;
- fail:
- /* With a data error we return this information */
+ out_badread:
+ printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
+ fail:
make_bad_inode(inode);
- return;
+ goto out;
}
#ifdef LEAK_CHECK
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 4473f7c0d..3f44d9033 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -53,9 +53,7 @@ isofs_cmp(struct dentry * dentry, const char * compare, int dlen)
* isofs_find_entry()
*
* finds an entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as an inode number). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
+ * returns the inode number of the found entry, or 0 on error.
*/
static unsigned long
isofs_find_entry(struct inode *dir, struct dentry *dentry,
@@ -123,7 +121,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
if (dir->i_sb->u.isofs_sb.s_rock &&
((i = get_rock_ridge_filename(de, tmpname, dir)))) {
- dlen = i;
+ dlen = i; /* possibly -1 */
dpnt = tmpname;
#ifdef CONFIG_JOLIET
} else if (dir->i_sb->u.isofs_sb.s_joliet_level) {
@@ -142,8 +140,9 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
* Skip hidden or associated files unless unhide is set
*/
match = 0;
- if ((!(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5)
- || dir->i_sb->u.isofs_sb.s_unhide == 'y') && dlen)
+ if (dlen > 0 &&
+ (!(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5)
+ || dir->i_sb->u.isofs_sb.s_unhide == 'y'))
{
match = (isofs_cmp(dentry,dpnt,dlen) == 0);
}
@@ -162,13 +161,14 @@ struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry)
struct inode *inode;
struct page *page;
-#ifdef DEBUG
- printk("lookup: %x %s\n",dir->i_ino, dentry->d_name.name);
-#endif
dentry->d_op = dir->i_sb->s_root->d_op;
page = alloc_page(GFP_USER);
- ino = isofs_find_entry(dir, dentry, page_address(page), 1024 + page_address(page));
+ if (!page)
+ return ERR_PTR(-ENOMEM);
+
+ ino = isofs_find_entry(dir, dentry, page_address(page),
+ 1024 + page_address(page));
__free_page(page);
inode = NULL;
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index b2eff877f..4ac4bc0ce 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -72,7 +72,7 @@
cont_size = 0; \
cont_offset = 0; \
goto LABEL; \
- }; \
+ } \
printk("Unable to read rock-ridge attributes\n"); \
}}
@@ -120,22 +120,16 @@ int find_rock_ridge_relocation(struct iso_directory_record * de,
CHECK_SP(goto out);
break;
case SIG('C','L'):
-#ifdef DEBUG
- printk("RR: CL\n");
-#endif
if (flag == 0) {
retval = isonum_733(rr->u.CL.location);
goto out;
- };
+ }
break;
case SIG('P','L'):
-#ifdef DEBUG
- printk("RR: PL\n");
-#endif
if (flag != 0) {
retval = isonum_733(rr->u.PL.location);
goto out;
- };
+ }
break;
case SIG('C','E'):
CHECK_CE; /* This tells is if there is a continuation record */
@@ -143,8 +137,8 @@ int find_rock_ridge_relocation(struct iso_directory_record * de,
default:
break;
}
- };
- };
+ }
+ }
MAYBE_CONTINUE(repeat, inode);
return retval;
out:
@@ -152,6 +146,7 @@ int find_rock_ridge_relocation(struct iso_directory_record * de,
return retval;
}
+/* return length of name field; 0: not found, -1: to be ignored */
int get_rock_ridge_filename(struct iso_directory_record * de,
char * retname, struct inode * inode)
{
@@ -202,24 +197,21 @@ int get_rock_ridge_filename(struct iso_directory_record * de,
if (rr->u.NM.flags & ~1) {
printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
break;
- };
+ }
if((strlen(retname) + rr->len - 5) >= 254) {
truncate = 1;
break;
- };
+ }
strncat(retname, rr->u.NM.name, rr->len - 5);
retnamlen += rr->len - 5;
break;
case SIG('R','E'):
-#ifdef DEBUG
- printk("RR: RE (%x)\n", inode->i_ino);
-#endif
if (buffer) kfree(buffer);
- return 0;
+ return -1;
default:
break;
}
- };
+ }
}
MAYBE_CONTINUE(repeat,inode);
return retnamlen; /* If 0, this file did not have a NM field */
@@ -265,10 +257,10 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
break;
case SIG('E','R'):
inode->i_sb->u.isofs_sb.s_rock = 1;
- printk(KERN_DEBUG"ISO 9660 Extensions: ");
+ printk(KERN_DEBUG "ISO 9660 Extensions: ");
{ int p;
for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
- };
+ }
printk("\n");
break;
case SIG('P','X'):
@@ -293,7 +285,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
} else {
inode->i_rdev = MKDEV(high, low);
}
- };
+ }
break;
case SIG('T','F'):
/* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
@@ -333,7 +325,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
break;
default:
printk("Symlink component flag not implemented\n");
- };
+ }
slen -= slp->len + 2;
oldslp = slp;
slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
@@ -347,19 +339,16 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
/*
* If this component record isn't continued, then append a '/'.
*/
- if( (!rootflag)
- && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
+ if (!rootflag && (oldslp->flags & 1) == 0)
+ inode->i_size += 1;
}
}
symlink_len = inode->i_size;
break;
case SIG('R','E'):
- printk("Attempt to read inode for relocated directory\n");
+ printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
goto out;
case SIG('C','L'):
-#ifdef DEBUG
- printk("RR CL (%x)\n",inode->i_ino);
-#endif
inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
reloc = iget(inode->i_sb,
(inode->u.isofs_i.i_first_extent <<
@@ -380,7 +369,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
default:
break;
}
- };
+ }
}
MAYBE_CONTINUE(repeat,inode);
return 0;
diff --git a/fs/isofs/util.c b/fs/isofs/util.c
index 12cd2d304..b966c512b 100644
--- a/fs/isofs/util.c
+++ b/fs/isofs/util.c
@@ -98,7 +98,7 @@ isonum_733 (char * p)
int iso_date(char * p, int flag)
{
- int year, month, day, hour ,minute, second, tz;
+ int year, month, day, hour, minute, second, tz;
int crtime, days, i;
year = p[0] - 70;
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 211b01530..592851be6 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -50,7 +50,7 @@ nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
nlmclnt_next_cookie(&argp->cookie);
argp->state = nsm_local_state;
- memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry), sizeof(struct nfs_fh));
+ memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh));
lock->caller = system_utsname.nodename;
lock->oh.data = req->a_owner;
lock->oh.len = sprintf(req->a_owner, "%d@%s",
diff --git a/fs/locks.c b/fs/locks.c
index 7da293a31..e65b59394 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -511,7 +511,8 @@ static inline void locks_unlock_delete(struct file_lock **thisfl_p)
struct file_lock *fl = *thisfl_p;
int (*lock)(struct file *, int, struct file_lock *);
- if ((lock = fl->fl_file->f_op->lock) != NULL) {
+ if (fl->fl_file->f_op &&
+ (lock = fl->fl_file->f_op->lock) != NULL) {
fl->fl_type = F_UNLCK;
lock(fl->fl_file, F_SETLK, fl);
}
@@ -1355,7 +1356,7 @@ int fcntl_getlk(unsigned int fd, struct flock *l)
if (!flock_to_posix_lock(filp, &file_lock, &flock))
goto out_putf;
- if (filp->f_op->lock) {
+ if (filp->f_op && filp->f_op->lock) {
error = filp->f_op->lock(filp, F_GETLK, &file_lock);
if (error < 0)
goto out_putf;
@@ -1479,7 +1480,7 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
goto out_putf;
}
- if (filp->f_op->lock != NULL) {
+ if (filp->f_op && filp->f_op->lock != NULL) {
error = filp->f_op->lock(filp, cmd, file_lock);
if (error < 0)
goto out_putf;
@@ -1520,7 +1521,7 @@ int fcntl_getlk64(unsigned int fd, struct flock64 *l)
if (!flock64_to_posix_lock(filp, &file_lock, &flock))
goto out_putf;
- if (filp->f_op->lock) {
+ if (filp->f_op && filp->f_op->lock) {
error = filp->f_op->lock(filp, F_GETLK, &file_lock);
if (error < 0)
goto out_putf;
@@ -1617,12 +1618,12 @@ int fcntl_setlk64(unsigned int fd, unsigned int cmd, struct flock64 *l)
goto out_putf;
}
- if (filp->f_op->lock != NULL) {
+ if (filp->f_op && filp->f_op->lock != NULL) {
error = filp->f_op->lock(filp, cmd, file_lock);
if (error < 0)
goto out_putf;
}
- error = posix_lock_file(filp, file_lock, cmd == F_SETLKW);
+ error = posix_lock_file(filp, file_lock, cmd == F_SETLKW64);
out_putf:
fput(filp);
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 38bb52cfd..7ff0b7bd9 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -396,7 +396,7 @@ struct buffer_head * minix_bread(struct inode * inode, int block, int create)
return NULL;
}
-static int minix_writepage(struct file *file, struct page *page)
+static int minix_writepage(struct page *page)
{
return block_write_full_page(page,minix_get_block);
}
diff --git a/fs/namei.c b/fs/namei.c
index c0d1abc36..37644f4a1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -152,18 +152,10 @@ char * getname(const char * filename)
* for filesystem access without changing the "normal" uids which
* are used for other things..
*/
-int permission(struct inode * inode,int mask)
+int vfs_permission(struct inode * inode,int mask)
{
int mode = inode->i_mode;
- if (inode->i_op && inode->i_op->permission) {
- int retval;
- lock_kernel();
- retval = inode->i_op->permission(inode, mask);
- unlock_kernel();
- return retval;
- }
-
if ((mask & S_IWOTH) && IS_RDONLY(inode) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS; /* Nobody gets write access to a read-only fs */
@@ -188,6 +180,18 @@ int permission(struct inode * inode,int mask)
return -EACCES;
}
+int permission(struct inode * inode,int mask)
+{
+ if (inode->i_op && inode->i_op->permission) {
+ int retval;
+ lock_kernel();
+ retval = inode->i_op->permission(inode, mask);
+ unlock_kernel();
+ return retval;
+ }
+ return vfs_permission(inode, mask);
+}
+
/*
* get_write_access() gets write permission for a file.
* put_write_access() releases this write permission.
diff --git a/fs/ncpfs/Config.in b/fs/ncpfs/Config.in
index 104f5a3c7..1f1eb1278 100644
--- a/fs/ncpfs/Config.in
+++ b/fs/ncpfs/Config.in
@@ -7,7 +7,5 @@ dep_mbool ' Clear remove/delete inhibit when needed' CONFIG_NCPFS_STRONG $CONFI
dep_mbool ' Use NFS namespace if available' CONFIG_NCPFS_NFS_NS $CONFIG_NCP_FS
dep_mbool ' Use LONG (OS/2) namespace if available' CONFIG_NCPFS_OS2_NS $CONFIG_NCP_FS
dep_mbool ' Lowercase DOS filenames' CONFIG_NCPFS_SMALLDOS $CONFIG_NCP_FS
-dep_mbool ' Allow mounting of volume subdirectories' CONFIG_NCPFS_MOUNT_SUBDIR $CONFIG_NCP_FS
-dep_mbool ' NDS authentication support' CONFIG_NCPFS_NDS_DOMAINS $CONFIG_NCP_FS
dep_mbool ' Use Native Language Support' CONFIG_NCPFS_NLS $CONFIG_NCP_FS
dep_mbool ' Enable symbolic links and execute flags' CONFIG_NCPFS_EXTRAS $CONFIG_NCP_FS
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 4b6afe2e9..37c87f8b2 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -165,7 +165,6 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
return 0;
}
-#ifdef CONFIG_NCPFS_MOUNT_SUBDIR
case NCP_IOC_GETROOT:
{
struct ncp_setroot_ioctl sr;
@@ -241,7 +240,6 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
return 0;
}
-#endif /* CONFIG_NCPFS_MOUNT_SUBDIR */
#ifdef CONFIG_NCPFS_PACKET_SIGNING
case NCP_IOC_SIGN_INIT:
@@ -374,7 +372,6 @@ outrel:
}
#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
-#ifdef CONFIG_NCPFS_NDS_DOMAINS
case NCP_IOC_GETOBJECTNAME:
if (current->uid != server->m.mounted_uid) {
return -EACCES;
@@ -503,7 +500,6 @@ outrel:
if (old) ncp_kfree_s(old, oldlen);
return 0;
}
-#endif /* CONFIG_NCPFS_NDS_DOMAINS */
#ifdef CONFIG_NCPFS_NLS
/* Here we are select the iocharset and the codepage for NLS.
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 6d07ead73..162c89b4b 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -96,16 +96,14 @@ ncp_ClearPhysicalRecord(struct ncp_server *server,
__u32 offset, __u32 length);
#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
-#ifdef CONFIG_NCPFS_MOUNT_SUBDIR
int
ncp_mount_subdir(struct ncp_server *, struct nw_info_struct *,
__u8, __u8, __u32);
-#endif /* CONFIG_NCPFS_MOUNT_SUBDIR */
#ifdef CONFIG_NCPFS_NLS
-inline unsigned char ncp__tolower(struct nls_table *, unsigned char);
-inline unsigned char ncp__toupper(struct nls_table *, unsigned char);
+unsigned char ncp__tolower(struct nls_table *, unsigned char);
+unsigned char ncp__toupper(struct nls_table *, unsigned char);
int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *,
const unsigned char *, unsigned int, int);
int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *,
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index c66d870d9..564a47b32 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -63,6 +63,7 @@ struct inode_operations nfs_dir_inode_operations = {
rmdir: nfs_rmdir,
mknod: nfs_mknod,
rename: nfs_rename,
+ permission: nfs_permission,
revalidate: nfs_revalidate,
setattr: nfs_notify_change,
};
@@ -97,6 +98,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
{
struct file *file = desc->file;
struct inode *inode = file->f_dentry->d_inode;
+ struct rpc_cred *cred = nfs_file_cred(file);
void *buffer = kmap(page);
int plus = NFS_USE_READDIRPLUS(inode);
int error;
@@ -104,7 +106,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index);
again:
- error = NFS_PROTO(inode)->readdir(file, desc->entry->cookie, buffer,
+ error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, buffer,
NFS_SERVER(inode)->dtsize, plus);
/* We requested READDIRPLUS, but the server doesn't grok it */
if (desc->plus && error == -ENOTSUPP) {
@@ -308,6 +310,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
{
struct file *file = desc->file;
struct inode *inode = file->f_dentry->d_inode;
+ struct rpc_cred *cred = nfs_file_cred(file);
struct page *page = NULL;
u32 *p;
int status = -EIO;
@@ -324,7 +327,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
goto out;
}
p = kmap(page);
- status = NFS_PROTO(inode)->readdir(file, desc->target, p,
+ status = NFS_PROTO(inode)->readdir(inode, cred, desc->target, p,
NFS_SERVER(inode)->dtsize, 0);
if (status >= 0) {
p = desc->decode(p, desc->entry, 0);
@@ -483,16 +486,15 @@ static inline int nfs_neg_need_reval(struct dentry *dentry)
*/
static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
{
- struct dentry *dir = dentry->d_parent;
- struct inode *dir_i = dir->d_inode;
- struct inode * inode = dentry->d_inode;
+ struct inode *dir;
+ struct inode *inode;
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
lock_kernel();
- dir = dentry->d_parent;
- dir_i = dir->d_inode;
+ dir = dentry->d_parent->d_inode;
+ inode = dentry->d_inode;
/*
* If we don't have an inode, let's look at the parent
* directory mtime to get a hint about how often we
@@ -506,7 +508,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
if (is_bad_inode(inode)) {
dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n",
- dir->d_name.name, dentry->d_name.name);
+ dentry->d_parent->d_name.name, dentry->d_name.name);
goto out_bad;
}
@@ -514,15 +516,14 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
goto out_valid;
if (IS_ROOT(dentry)) {
- __nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+ __nfs_revalidate_inode(NFS_SERVER(inode), inode);
goto out_valid_renew;
}
/*
* Do a new lookup and check the dentry attributes.
*/
- error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name, &fhandle,
- &fattr);
+ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
if (error)
goto out_bad;
@@ -532,13 +533,12 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
NFS_FILEID(inode) != fattr.fileid)
goto out_bad;
- /* Filehandle matches? */
- if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh)))
- goto out_bad;
-
- /* Ok, remeber that we successfully checked it.. */
+ /* Ok, remember that we successfully checked it.. */
nfs_refresh_inode(inode, &fattr);
+ if (nfs_inode_is_stale(inode, &fhandle, &fattr))
+ goto out_bad;
+
out_valid_renew:
nfs_renew_times(dentry);
out_valid:
@@ -551,7 +551,7 @@ out_bad:
goto out_valid;
d_drop(dentry);
/* Purge readdir caches. */
- nfs_zap_caches(dir_i);
+ nfs_zap_caches(dir);
if (inode && S_ISDIR(inode->i_mode))
nfs_zap_caches(inode);
unlock_kernel();
@@ -575,30 +575,6 @@ static int nfs_dentry_delete(struct dentry *dentry)
}
-static kmem_cache_t *nfs_fh_cachep;
-
-__inline__ struct nfs_fh *nfs_fh_alloc(void)
-{
- return kmem_cache_alloc(nfs_fh_cachep, SLAB_KERNEL);
-}
-
-__inline__ void nfs_fh_free(struct nfs_fh *p)
-{
- kmem_cache_free(nfs_fh_cachep, p);
-}
-
-/*
- * Called when the dentry is being freed to release private memory.
- */
-static void nfs_dentry_release(struct dentry *dentry)
-{
- if (dentry->d_fsdata) {
- lock_kernel();
- nfs_fh_free(dentry->d_fsdata);
- unlock_kernel();
- }
-}
-
/*
* Called when the dentry loses inode.
* We use it to clean up silly-renamed files.
@@ -616,35 +592,27 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
struct dentry_operations nfs_dentry_operations = {
d_revalidate: nfs_lookup_revalidate,
d_delete: nfs_dentry_delete,
- d_release: nfs_dentry_release,
d_iput: nfs_dentry_iput,
};
-static struct dentry *nfs_lookup(struct inode *dir_i, struct dentry * dentry)
+static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
{
- struct dentry *dir = dentry->d_parent;
struct inode *inode;
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
- dir->d_name.name, dentry->d_name.name);
+ dentry->d_parent->d_name.name, dentry->d_name.name);
error = -ENAMETOOLONG;
- if (dentry->d_name.len > NFS_SERVER(dir_i)->namelen)
+ if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
goto out;
error = -ENOMEM;
- if (!dentry->d_fsdata) {
- dentry->d_fsdata = nfs_fh_alloc();
- if (!dentry->d_fsdata)
- goto out;
- }
dentry->d_op = &nfs_dentry_operations;
- error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name, &fhandle,
- &fattr);
+ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
inode = NULL;
if (error == -ENOENT)
goto no_entry;
@@ -686,16 +654,15 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
* that the operation succeeded on the server, but an error in the
* reply path made it appear to have failed.
*/
-static int nfs_create(struct inode *dir_i, struct dentry *dentry, int mode)
+static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
{
- struct dentry *dir = dentry->d_parent;
struct iattr attr;
struct nfs_fattr fattr;
struct nfs_fh fhandle;
int error;
dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
- dir_i->i_dev, dir_i->i_ino, dentry->d_name.name);
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
@@ -706,8 +673,8 @@ static int nfs_create(struct inode *dir_i, struct dentry *dentry, int mode)
* select the appropriate create strategy. Currently open_namei
* does not pass the create flags.
*/
- nfs_zap_caches(dir_i);
- error = NFS_PROTO(dir_i)->create(dir, &dentry->d_name,
+ nfs_zap_caches(dir);
+ error = NFS_PROTO(dir)->create(dir, &dentry->d_name,
&attr, 0, &fhandle, &fattr);
if (!error && fhandle.size != 0)
error = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -719,22 +686,21 @@ static int nfs_create(struct inode *dir_i, struct dentry *dentry, int mode)
/*
* See comments for nfs_proc_create regarding failed operations.
*/
-static int nfs_mknod(struct inode *dir_i, struct dentry *dentry, int mode, int rdev)
+static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
{
- struct dentry *dir = dentry->d_parent;
struct iattr attr;
struct nfs_fattr fattr;
struct nfs_fh fhandle;
int error;
dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
- dir_i->i_dev, dir_i->i_ino, dentry->d_name.name);
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
- nfs_zap_caches(dir_i);
- error = NFS_PROTO(dir_i)->mknod(dir, &dentry->d_name, &attr, rdev,
+ nfs_zap_caches(dir);
+ error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,
&fhandle, &fattr);
if (!error && fhandle.size != 0)
error = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -746,16 +712,15 @@ static int nfs_mknod(struct inode *dir_i, struct dentry *dentry, int mode, int r
/*
* See comments for nfs_proc_create regarding failed operations.
*/
-static int nfs_mkdir(struct inode *dir_i, struct dentry *dentry, int mode)
+static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
- struct dentry *dir = dentry->d_parent;
struct iattr attr;
struct nfs_fattr fattr;
struct nfs_fh fhandle;
int error;
dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
- dir_i->i_dev, dir_i->i_ino, dentry->d_name.name);
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
attr.ia_valid = ATTR_MODE;
attr.ia_mode = mode | S_IFDIR;
@@ -769,8 +734,8 @@ static int nfs_mkdir(struct inode *dir_i, struct dentry *dentry, int mode)
*/
d_drop(dentry);
#endif
- nfs_zap_caches(dir_i);
- error = NFS_PROTO(dir_i)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
+ nfs_zap_caches(dir);
+ error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
&fattr);
if (!error && fhandle.size != 0)
error = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -779,25 +744,23 @@ static int nfs_mkdir(struct inode *dir_i, struct dentry *dentry, int mode)
return error;
}
-static int nfs_rmdir(struct inode *dir_i, struct dentry *dentry)
+static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
- struct dentry *dir = dentry->d_parent;
int error;
dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
- dir_i->i_dev, dir_i->i_ino, dentry->d_name.name);
+ dir->i_dev, dir->i_ino, dentry->d_name.name);
- nfs_zap_caches(dir_i);
- error = NFS_PROTO(dir_i)->rmdir(dir, &dentry->d_name);
+ nfs_zap_caches(dir);
+ error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
return error;
}
-static int nfs_sillyrename(struct inode *dir_i, struct dentry *dentry)
+static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
{
- struct dentry *dir = dentry->d_parent;
static unsigned int sillycounter;
- const int i_inosize = sizeof(dir_i->i_ino)*2;
+ const int i_inosize = sizeof(dir->i_ino)*2;
const int countersize = sizeof(sillycounter)*2;
const int slen = strlen(".nfs") + i_inosize + countersize;
char silly[slen+1];
@@ -848,10 +811,10 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
goto out;
} while(sdentry->d_inode != NULL); /* need negative lookup */
- nfs_zap_caches(dir_i);
+ nfs_zap_caches(dir);
qsilly.name = silly;
qsilly.len = strlen(silly);
- error = NFS_PROTO(dir_i)->rename(dir, &dentry->d_name, dir, &qsilly);
+ error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, dir, &qsilly);
if (!error) {
nfs_renew_times(dentry);
d_move(dentry, sdentry);
@@ -872,8 +835,7 @@ out:
*/
static int nfs_safe_remove(struct dentry *dentry)
{
- struct dentry *dir = dentry->d_parent;
- struct inode *dir_i = dir->d_inode;
+ struct inode *dir = dentry->d_parent->d_inode;
struct inode *inode = dentry->d_inode;
int error = -EBUSY, rehash = 0;
@@ -902,10 +864,10 @@ static int nfs_safe_remove(struct dentry *dentry)
goto out_delete;
}
- nfs_zap_caches(dir_i);
+ nfs_zap_caches(dir);
if (inode)
NFS_CACHEINV(inode);
- error = NFS_PROTO(dir_i)->remove(dir, &dentry->d_name);
+ error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
if (error < 0)
goto out;
@@ -943,9 +905,8 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
}
static int
-nfs_symlink(struct inode *dir_i, struct dentry *dentry, const char *symname)
+nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
- struct dentry *dir = dentry->d_parent;
struct iattr attr;
struct nfs_fattr sym_attr;
struct nfs_fh sym_fh;
@@ -954,10 +915,10 @@ nfs_symlink(struct inode *dir_i, struct dentry *dentry, const char *symname)
int error;
dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",
- dir_i->i_dev, dir_i->i_ino, dentry->d_name.name, symname);
+ dir->i_dev, dir->i_ino, dentry->d_name.name, symname);
error = -ENAMETOOLONG;
- maxlen = (NFS_PROTO(dir_i)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN;
+ maxlen = (NFS_PROTO(dir)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN;
if (strlen(symname) > maxlen)
goto out;
@@ -976,15 +937,15 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
qsymname.name = symname;
qsymname.len = strlen(symname);
- nfs_zap_caches(dir_i);
- error = NFS_PROTO(dir_i)->symlink(dir, &dentry->d_name, &qsymname,
+ nfs_zap_caches(dir);
+ error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,
&attr, &sym_fh, &sym_attr);
if (!error && sym_fh.size != 0 && (sym_attr.valid & NFS_ATTR_FATTR)) {
error = nfs_instantiate(dentry, &sym_fh, &sym_attr);
} else {
if (error == -EEXIST)
printk("nfs_proc_symlink: %s/%s already exists??\n",
- dir->d_name.name, dentry->d_name.name);
+ dentry->d_parent->d_name.name, dentry->d_name.name);
d_drop(dentry);
}
@@ -993,9 +954,8 @@ out:
}
static int
-nfs_link(struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
+nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
- struct dentry *dir = dentry->d_parent;
struct inode *inode = old_dentry->d_inode;
int error;
@@ -1009,9 +969,9 @@ nfs_link(struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
* we can't use the existing dentry.
*/
d_drop(dentry);
- nfs_zap_caches(dir_i);
+ nfs_zap_caches(dir);
NFS_CACHEINV(inode);
- error = NFS_PROTO(dir_i)->link(old_dentry, dir, &dentry->d_name);
+ error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
return error;
}
@@ -1116,10 +1076,8 @@ go_ahead:
nfs_zap_caches(new_dir);
nfs_zap_caches(old_dir);
- error = NFS_PROTO(old_dir)->rename(old_dentry->d_parent,
- &old_dentry->d_name,
- new_dentry->d_parent,
- &new_dentry->d_name);
+ error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
+ new_dir, &new_dentry->d_name);
out:
if (rehash)
d_rehash(rehash);
@@ -1132,22 +1090,33 @@ out:
return error;
}
-int nfs_init_fhcache(void)
+int
+nfs_permission(struct inode *inode, int mask)
{
- nfs_fh_cachep = kmem_cache_create("nfs_fh",
- sizeof(struct nfs_fh),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (nfs_fh_cachep == NULL)
- return -ENOMEM;
+ int error = vfs_permission(inode, mask);
- return 0;
-}
+ if (!NFS_PROTO(inode)->access)
+ goto out;
+ /*
+ * Trust UNIX mode bits except:
+ *
+ * 1) When override capabilities may have been invoked
+ * 2) When root squashing may be involved
+ * 3) When ACLs may overturn a negative answer */
+ if (!capable(CAP_DAC_OVERRIDE) && !capable(CAP_DAC_READ_SEARCH)
+ && (current->fsuid != 0) && (current->fsgid != 0)
+ && error != -EACCES)
+ goto out;
-void nfs_destroy_fhcache(void)
-{
- if (kmem_cache_destroy(nfs_fh_cachep))
- printk(KERN_INFO "nfs_fh: not all structures were freed\n");
+ error = NFS_PROTO(inode)->access(inode, mask, 0);
+
+ if (error == -EACCES && NFS_CLIENT(inode)->cl_droppriv &&
+ current->uid != 0 && current->gid != 0 &&
+ (current->fsuid != current->uid || current->fsgid != current->gid))
+ error = NFS_PROTO(inode)->access(inode, mask, 1);
+
+ out:
+ return error;
}
/*
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index c30fc5062..d5c92ba3b 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -52,6 +52,7 @@ struct file_operations nfs_file_operations = {
};
struct inode_operations nfs_file_inode_operations = {
+ permission: nfs_permission,
revalidate: nfs_revalidate,
setattr: nfs_notify_change,
};
@@ -90,13 +91,14 @@ static ssize_t
nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
{
struct dentry * dentry = file->f_dentry;
+ struct inode * inode = dentry->d_inode;
ssize_t result;
dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long) *ppos);
- result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+ result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
if (!result)
result = generic_file_read(file, buf, count, ppos);
return result;
@@ -106,12 +108,13 @@ static int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
struct dentry *dentry = file->f_dentry;
+ struct inode *inode = dentry->d_inode;
int status;
dfprintk(VFS, "nfs: mmap(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
- status = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+ status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
if (!status)
status = generic_file_mmap(file, vma);
return status;
@@ -179,7 +182,7 @@ static int nfs_sync_page(struct page *page)
struct address_space *mapping;
struct inode *inode;
unsigned long index = page_index(page);
- unsigned int rpages, wpages;
+ unsigned int rpages;
int result;
mapping = page->mapping;
@@ -192,14 +195,8 @@ static int nfs_sync_page(struct page *page)
rpages = NFS_SERVER(inode)->rpages;
result = nfs_pagein_inode(inode, index, rpages);
if (result < 0)
- goto out_bad;
- wpages = NFS_SERVER(inode)->wpages;
- result = nfs_sync_file(inode, NULL, index, wpages, FLUSH_STABLE);
- if (result < 0)
- goto out_bad;
+ return result;
return 0;
- out_bad:
- return result;
}
struct address_space_operations nfs_file_aops = {
@@ -227,7 +224,7 @@ nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
result = -EBUSY;
if (IS_SWAPFILE(inode))
goto out_swapfile;
- result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+ result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
if (result)
goto out;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5b582024e..f741cb6dd 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -39,7 +39,7 @@
#define NFSDBG_FACILITY NFSDBG_VFS
#define NFS_PARANOIA 1
-static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *);
+static struct inode * __nfs_fhget(struct super_block *, struct nfs_fh *, struct nfs_fattr *);
void nfs_zap_caches(struct inode *);
static void nfs_invalidate_inode(struct inode *);
@@ -222,13 +222,10 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh)
return NULL;
}
- inode = __nfs_fhget(sb, &fattr);
+ inode = __nfs_fhget(sb, rootfh, &fattr);
return inode;
}
-extern struct nfs_fh *nfs_fh_alloc(void);
-extern void nfs_fh_free(struct nfs_fh *p);
-
/*
* The way this works is that the mount process passes a structure
* in the data argument which contains the server's IP address
@@ -242,7 +239,7 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
struct nfs_server *server;
struct rpc_xprt *xprt = NULL;
struct rpc_clnt *clnt = NULL;
- struct nfs_fh *root = &data->root, *root_fh, fh;
+ struct nfs_fh *root = &data->root, fh;
struct inode *root_inode = NULL;
unsigned int authflavor;
struct sockaddr_in srvaddr;
@@ -365,16 +362,10 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
* Keep the super block locked while we try to get
* the root fh attributes.
*/
- root_fh = nfs_fh_alloc();
- if (!root_fh)
- goto out_no_fh;
- memcpy((u8*)root_fh, (u8*)root, sizeof(*root));
-
/* Did getting the root inode fail? */
if (!(root_inode = nfs_get_root(sb, root))
&& (data->flags & NFS_MOUNT_VER3)) {
data->flags &= ~NFS_MOUNT_VER3;
- nfs_fh_free(root_fh);
rpciod_down();
rpc_shutdown_client(server->client);
goto nfsv3_try_again;
@@ -387,7 +378,6 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
goto out_no_root;
sb->s_root->d_op = &nfs_dentry_operations;
- sb->s_root->d_fsdata = root_fh;
/* Get some general file system info */
if (server->rpc_ops->statfs(server, root, &fsinfo) >= 0) {
@@ -462,8 +452,6 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
out_no_root:
printk("nfs_read_super: get root inode failed\n");
iput(root_inode);
- nfs_fh_free(root_fh);
-out_no_fh:
rpciod_down();
goto out_shutdown;
@@ -507,7 +495,7 @@ nfs_statfs(struct super_block *sb, struct statfs *buf)
struct nfs_fsinfo res;
int error;
- error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root), &res);
+ error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root->d_inode), &res);
buf->f_type = NFS_SUPER_MAGIC;
if (error < 0)
goto out_err;
@@ -532,43 +520,6 @@ nfs_statfs(struct super_block *sb, struct statfs *buf)
}
/*
- * Free all unused dentries in an inode's alias list.
- *
- * Subtle note: we have to be very careful not to cause
- * any IO operations with the stale dentries, as this
- * could cause file corruption. But since the dentry
- * count is 0 and all pending IO for a dentry has been
- * flushed when the count went to 0, we're safe here.
- * Also returns the number of unhashed dentries
- */
-static int
-nfs_free_dentries(struct inode *inode)
-{
- struct list_head *tmp, *head;
- int unhashed;
-
- if (S_ISDIR(inode->i_mode)) {
- struct dentry *dentry = d_find_alias(inode);
- if (dentry) {
- shrink_dcache_parent(dentry);
- dput(dentry);
- }
- }
- d_prune_aliases(inode);
- spin_lock(&dcache_lock);
- head = &inode->i_dentry;
- tmp = head;
- unhashed = 0;
- while ((tmp = tmp->next) != head) {
- struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
- if (list_empty(&dentry->d_hash))
- unhashed++;
- }
- spin_unlock(&dcache_lock);
- return unhashed;
-}
-
-/*
* Invalidate the local caches
*/
void
@@ -600,7 +551,7 @@ nfs_invalidate_inode(struct inode *inode)
* Fill in inode information from the fattr.
*/
static void
-nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
+nfs_fill_inode(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr)
{
/*
* Check whether the mode has been set, as we only want to
@@ -638,10 +589,16 @@ nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
NFS_CACHE_ISIZE(inode) = fattr->size;
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
+ memcpy(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh));
}
nfs_refresh_inode(inode, fattr);
}
+struct nfs_find_desc {
+ struct nfs_fh *fh;
+ struct nfs_fattr *fattr;
+};
+
/*
* In NFSv3 we can have 64bit inode numbers. In order to support
* this, and re-exported directories (also seen in NFSv2)
@@ -651,43 +608,38 @@ nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
static int
nfs_find_actor(struct inode *inode, unsigned long ino, void *opaque)
{
- struct nfs_fattr *fattr = (struct nfs_fattr *)opaque;
+ struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque;
+ struct nfs_fh *fh = desc->fh;
+ struct nfs_fattr *fattr = desc->fattr;
+
if (NFS_FSID(inode) != fattr->fsid)
return 0;
if (NFS_FILEID(inode) != fattr->fileid)
return 0;
+ if (memcmp(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh)) != 0)
+ return 0;
return 1;
}
-static int
-nfs_inode_is_stale(struct inode *inode, struct nfs_fattr *fattr)
+int
+nfs_inode_is_stale(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr)
{
- int unhashed;
- int is_stale = 0;
+ /* Empty inodes are not stale */
+ if (!inode->i_mode)
+ return 0;
- if (inode->i_mode &&
- (fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))
- is_stale = 1;
+ if ((fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))
+ return 1;
if (is_bad_inode(inode))
- is_stale = 1;
+ return 1;
- /*
- * If the inode seems stale, free up cached dentries.
- */
- unhashed = nfs_free_dentries(inode);
-
- /* Assume we're holding an i_count
- *
- * NB: sockets sometimes have volatile file handles
- * don't invalidate their inodes even if all dentries are
- * unhashed.
- */
- if (unhashed && atomic_read(&inode->i_count) == unhashed + 1
- && !S_ISSOCK(inode->i_mode) && !S_ISFIFO(inode->i_mode))
- is_stale = 1;
+ /* Has the filehandle changed? If so is the old one stale? */
+ if (memcmp(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh)) != 0 &&
+ __nfs_revalidate_inode(NFS_SERVER(inode),inode) == -ESTALE)
+ return 1;
- return is_stale;
+ return 0;
}
/*
@@ -696,8 +648,6 @@ nfs_inode_is_stale(struct inode *inode, struct nfs_fattr *fattr)
* the vfs read_inode function because there is no way to pass the
* file handle or current attributes into the read_inode function.
*
- * We provide a special check for NetApp .snapshot directories to avoid
- * inode aliasing problems. All snapshot inodes are anonymous (unhashed).
*/
struct inode *
nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
@@ -708,44 +658,16 @@ nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
dprintk("NFS: nfs_fhget(%s/%s fileid=%Ld)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
(long long)fattr->fileid);
-
- /* Install the file handle in the dentry */
- memcpy(dentry->d_fsdata, fhandle, sizeof(struct nfs_fh));
-
-#ifdef CONFIG_NFS_SNAPSHOT
- /*
- * Check for NetApp snapshot dentries, and get an
- * unhashed inode to avoid aliasing problems.
- */
- if ((dentry->d_parent->d_inode->u.nfs_i.flags & NFS_IS_SNAPSHOT) ||
- (dentry->d_name.len == 9 &&
- memcmp(dentry->d_name.name, ".snapshot", 9) == 0)) {
- struct inode *inode = new_inode(sb);
- if (!inode)
- goto out;
- inode->i_ino = nfs_fattr_to_ino_t(fattr);
- nfs_read_inode(inode);
- nfs_fill_inode(inode, fattr);
- inode->u.nfs_i.flags |= NFS_IS_SNAPSHOT;
- dprintk("NFS: nfs_fhget(snapshot ino=%ld)\n", inode->i_ino);
- out:
- return inode;
- }
-#endif
- return __nfs_fhget(sb, fattr);
+ return __nfs_fhget(sb, fhandle, fattr);
}
/*
* Look up the inode by super block and fattr->fileid.
- *
- * Note carefully the special handling of busy inodes (i_count > 1).
- * With the kernel 2.1.xx dcache all inodes except hard links must
- * have i_count == 1 after iget(). Otherwise, it indicates that the
- * server has reused a fileid (i_ino) and we have a stale inode.
*/
static struct inode *
-__nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
+__nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
{
+ struct nfs_find_desc desc = { fh, fattr };
struct inode *inode = NULL;
unsigned long ino;
@@ -759,33 +681,13 @@ __nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
ino = nfs_fattr_to_ino_t(fattr);
- while((inode = iget4(sb, ino, nfs_find_actor, fattr)) != NULL) {
-
- /*
- * Check for busy inodes, and attempt to get rid of any
- * unused local references. If successful, we release the
- * inode and try again.
- *
- * Note that the busy test uses the values in the fattr,
- * as the inode may have become a different object.
- * (We can probably handle modes changes here, too.)
- */
- if (!nfs_inode_is_stale(inode,fattr))
- break;
-
- dprintk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
- inode->i_ino, atomic_read(&inode->i_count));
- nfs_zap_caches(inode);
- remove_inode_hash(inode);
- iput(inode);
- }
-
- if (!inode)
+ if (!(inode = iget4(sb, ino, nfs_find_actor, &desc)))
goto out_no_inode;
- nfs_fill_inode(inode, fattr);
- dprintk("NFS: __nfs_fhget(%x/%ld ct=%d)\n",
- inode->i_dev, inode->i_ino, atomic_read(&inode->i_count));
+ nfs_fill_inode(inode, fh, fattr);
+ dprintk("NFS: __nfs_fhget(%x/%Ld ct=%d)\n",
+ inode->i_dev, (long long)NFS_FILEID(inode),
+ atomic_read(&inode->i_count));
out:
return inode;
@@ -820,7 +722,7 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error);
if (error)
goto out;
- error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
+ error = NFS_PROTO(inode)->setattr(inode, &fattr, attr);
if (error)
goto out;
/*
@@ -872,7 +774,8 @@ nfs_wait_on_inode(struct inode *inode, int flag)
int
nfs_revalidate(struct dentry *dentry)
{
- return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+ struct inode *inode = dentry->d_inode;
+ return nfs_revalidate_inode(NFS_SERVER(inode), inode);
}
/*
@@ -913,18 +816,16 @@ int nfs_release(struct inode *inode, struct file *filp)
* the cached attributes have to be refreshed.
*/
int
-__nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
+__nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
{
- struct inode *inode = dentry->d_inode;
int status = 0;
struct nfs_fattr fattr;
- dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- inode->i_ino);
+ dfprintk(PAGECACHE, "NFS: revalidating (%x/%Ld)\n",
+ inode->i_dev, (long long)NFS_FILEID(inode));
lock_kernel();
- if (!inode || is_bad_inode(inode)) {
+ if (!inode || is_bad_inode(inode) || NFS_STALE(inode)) {
unlock_kernel();
return -ESTALE;
}
@@ -936,55 +837,35 @@ __nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
return status;
}
if (time_before(jiffies,NFS_READTIME(inode)+NFS_ATTRTIMEO(inode))) {
- unlock_kernel();
- return 0;
+ status = NFS_STALE(inode) ? -ESTALE : 0;
+ goto out_nowait;
}
}
NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;
- status = NFS_PROTO(inode)->getattr(dentry, &fattr);
+ status = NFS_PROTO(inode)->getattr(inode, &fattr);
if (status) {
- struct dentry *dir = dentry->d_parent;
- struct inode *dir_i = dir->d_inode;
- int error;
- u32 *fh;
- struct nfs_fh fhandle;
- dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n",
- dir->d_name.name, dentry->d_name.name,
- inode->i_ino, status);
- if (status != -ESTALE)
- goto out;
- /*
- * A "stale filehandle" error ... show the current fh
- * and find out what the filehandle should be.
- */
- fh = (u32 *) NFS_FH(dentry)->data;
- dfprintk(PAGECACHE, "NFS: bad fh %08x%08x%08x%08x%08x%08x%08x%08x\n",
- fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]);
- error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name,
- &fhandle, &fattr);
- if (error) {
- dfprintk(PAGECACHE, "NFS: lookup failed, error=%d\n", error);
- goto out;
+ dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) getattr failed, error=%d\n",
+ inode->i_dev, (long long)NFS_FILEID(inode), status);
+ if (status == -ESTALE) {
+ NFS_FLAGS(inode) |= NFS_INO_STALE;
+ remove_inode_hash(inode);
}
- fh = (u32 *) fhandle.data;
- dfprintk(PAGECACHE, " %08x%08x%08x%08x%08x%08x%08x%08x\n",
- fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]);
goto out;
}
status = nfs_refresh_inode(inode, &fattr);
if (status) {
- dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s refresh failed, ino=%ld, error=%d\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name, inode->i_ino, status);
+ dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) refresh failed, error=%d\n",
+ inode->i_dev, (long long)NFS_FILEID(inode), status);
goto out;
}
- dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ dfprintk(PAGECACHE, "NFS: (%x/%Ld) revalidation complete\n",
+ inode->i_dev, (long long)NFS_FILEID(inode));
out:
NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;
wake_up(&inode->i_wait);
+ out_nowait:
unlock_kernel();
return status;
}
@@ -1165,8 +1046,6 @@ out_changed:
*/
static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, FS_ODD_RENAME);
-extern int nfs_init_fhcache(void);
-extern void nfs_destroy_fhcache(void);
extern int nfs_init_nfspagecache(void);
extern void nfs_destroy_nfspagecache(void);
extern int nfs_init_readpagecache(void);
@@ -1180,10 +1059,6 @@ init_nfs_fs(void)
{
int err;
- err = nfs_init_fhcache();
- if (err)
- return err;
-
err = nfs_init_nfspagecache();
if (err)
return err;
@@ -1218,7 +1093,6 @@ cleanup_module(void)
{
nfs_destroy_readpagecache();
nfs_destroy_nfspagecache();
- nfs_destroy_fhcache();
#ifdef CONFIG_PROC_FS
rpc_proc_unregister("nfs");
#endif
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index d75e9eda0..86cfd1b81 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -37,34 +37,34 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* One function for each procedure in the NFS protocol.
*/
static int
-nfs3_proc_getattr(struct dentry *dentry, struct nfs_fattr *fattr)
+nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
{
int status;
dprintk("NFS call getattr\n");
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_GETATTR,
- NFS_FH(dentry), fattr, 0);
+ status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
+ NFS_FH(inode), fattr, 0);
dprintk("NFS reply getattr\n");
return status;
}
static int
-nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
+nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
struct iattr *sattr)
{
- struct nfs3_sattrargs arg = { NFS_FH(dentry), sattr, 0, 0 };
+ struct nfs3_sattrargs arg = { NFS_FH(inode), sattr, 0, 0 };
int status;
dprintk("NFS call setattr\n");
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_SETATTR, &arg, fattr, 0);
+ status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
dprintk("NFS reply setattr\n");
return status;
}
static int
-nfs3_proc_lookup(struct dentry *dir, struct qstr *name,
+nfs3_proc_lookup(struct inode *dir, struct qstr *name,
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs_fattr dir_attr;
@@ -75,20 +75,20 @@ nfs3_proc_lookup(struct dentry *dir, struct qstr *name,
dprintk("NFS call lookup %s\n", name->name);
dir_attr.valid = 0;
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_LOOKUP, &arg, &res, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_GETATTR,
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
fhandle, fattr, 0);
dprintk("NFS reply lookup: %d\n", status);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
+ nfs_refresh_inode(dir, &dir_attr);
return status;
}
static int
-nfs3_proc_access(struct dentry *dentry, int mode, int ruid)
+nfs3_proc_access(struct inode *inode, int mode, int ruid)
{
struct nfs_fattr fattr;
- struct nfs3_accessargs arg = { NFS_FH(dentry), 0 };
+ struct nfs3_accessargs arg = { NFS_FH(inode), 0 };
struct nfs3_accessres res = { &fattr, 0 };
int status, flags;
@@ -97,7 +97,7 @@ nfs3_proc_access(struct dentry *dentry, int mode, int ruid)
if (mode & MAY_READ)
arg.access |= NFS3_ACCESS_READ;
- if (S_ISDIR(dentry->d_inode->i_mode)) {
+ if (S_ISDIR(inode->i_mode)) {
if (mode & MAY_WRITE)
arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;
if (mode & MAY_EXEC)
@@ -109,8 +109,8 @@ nfs3_proc_access(struct dentry *dentry, int mode, int ruid)
arg.access |= NFS3_ACCESS_EXECUTE;
}
flags = (ruid) ? RPC_CALL_REALUID : 0;
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_ACCESS, &arg, &res, flags);
- nfs_refresh_inode(dentry->d_inode, &fattr);
+ status = rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, &arg, &res, flags);
+ nfs_refresh_inode(inode, &fattr);
dprintk("NFS reply access\n");
if (status == 0 && (arg.access & res.access) != arg.access)
@@ -119,29 +119,28 @@ nfs3_proc_access(struct dentry *dentry, int mode, int ruid)
}
static int
-nfs3_proc_readlink(struct dentry *dentry, void *buffer, unsigned int buflen)
+nfs3_proc_readlink(struct inode *inode, void *buffer, unsigned int buflen)
{
struct nfs_fattr fattr;
- struct nfs3_readlinkargs args = { NFS_FH(dentry), buffer, buflen };
+ struct nfs3_readlinkargs args = { NFS_FH(inode), buffer, buflen };
struct nfs3_readlinkres res = { &fattr, buffer, buflen };
int status;
dprintk("NFS call readlink\n");
fattr.valid = 0;
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_READLINK,
+ status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
&args, &res, 0);
- nfs_refresh_inode(dentry->d_inode, &fattr);
+ nfs_refresh_inode(inode, &fattr);
dprintk("NFS reply readlink: %d\n", status);
return status;
}
static int
-nfs3_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
+nfs3_proc_read(struct inode *inode, struct rpc_cred *cred,
+ struct nfs_fattr *fattr, int flags,
loff_t offset, unsigned int count, void *buffer, int *eofp)
{
- struct dentry *dentry = file->f_dentry;
- struct rpc_cred *cred = nfs_file_cred(file);
- struct nfs_readargs arg = { NFS_FH(dentry), offset, count, 1,
+ struct nfs_readargs arg = { NFS_FH(inode), offset, count, 1,
{{buffer, count}, {0,0}, {0,0}, {0,0},
{0,0}, {0,0}, {0,0}, {0,0}} };
struct nfs_readres res = { fattr, count, 0 };
@@ -150,20 +149,19 @@ nfs3_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
dprintk("NFS call read %d @ %Ld\n", count, (long long)offset);
fattr->valid = 0;
- status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
dprintk("NFS reply read: %d\n", status);
*eofp = res.eof;
return status;
}
static int
-nfs3_proc_write(struct file *file, struct nfs_fattr *fattr, int flags,
+nfs3_proc_write(struct inode *inode, struct rpc_cred *cred,
+ struct nfs_fattr *fattr, int flags,
loff_t offset, unsigned int count,
void *buffer, struct nfs_writeverf *verf)
{
- struct dentry *dentry = file->f_dentry;
- struct rpc_cred *cred = nfs_file_cred(file);
- struct nfs_writeargs arg = { NFS_FH(dentry), offset, count,
+ struct nfs_writeargs arg = { NFS_FH(inode), offset, count,
NFS_FILE_SYNC, 1,
{{buffer, count}, {0,0}, {0,0}, {0,0},
{0,0}, {0,0}, {0,0}, {0,0}} };
@@ -177,7 +175,7 @@ nfs3_proc_write(struct file *file, struct nfs_fattr *fattr, int flags,
rpcflags |= NFS_RPC_SWAPFLAGS;
arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE;
- status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, rpcflags);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
dprintk("NFS reply read: %d\n", status);
return status < 0? status : res.count;
@@ -188,7 +186,7 @@ nfs3_proc_write(struct file *file, struct nfs_fattr *fattr, int flags,
* For now, we don't implement O_EXCL.
*/
static int
-nfs3_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs3_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs_fattr dir_attr;
@@ -208,8 +206,8 @@ nfs3_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
again:
dir_attr.valid = 0;
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_CREATE, &arg, &res, 0);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
+ nfs_refresh_inode(dir, &dir_attr);
/* If the server doesn't support the exclusive creation semantics,
* try again with simple 'guarded' mode. */
@@ -242,7 +240,7 @@ exit:
* not sure this buys us anything (and I'd have
* to revamp the NFSv3 XDR code) */
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_SETATTR,
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,
&arg, fattr, 0);
dprintk("NFS reply setattr (post-create): %d\n", status);
}
@@ -251,7 +249,7 @@ exit:
}
static int
-nfs3_proc_remove(struct dentry *dir, struct qstr *name)
+nfs3_proc_remove(struct inode *dir, struct qstr *name)
{
struct nfs_fattr dir_attr;
struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len };
@@ -260,8 +258,8 @@ nfs3_proc_remove(struct dentry *dir, struct qstr *name)
dprintk("NFS call remove %s\n", name->name);
dir_attr.valid = 0;
- status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ nfs_refresh_inode(dir, &dir_attr);
dprintk("NFS reply remove: %d\n", status);
return status;
}
@@ -276,7 +274,7 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr
if (!arg)
return -ENOMEM;
res = (struct nfs_fattr*)(arg + 1);
- arg->fh = NFS_FH(dir);
+ arg->fh = NFS_FH(dir->d_inode);
arg->name = name->name;
arg->len = name->len;
res->valid = 0;
@@ -299,8 +297,8 @@ nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
}
static int
-nfs3_proc_rename(struct dentry *old_dir, struct qstr *old_name,
- struct dentry *new_dir, struct qstr *new_name)
+nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
+ struct inode *new_dir, struct qstr *new_name)
{
struct nfs_fattr old_dir_attr, new_dir_attr;
struct nfs3_renameargs arg = { NFS_FH(old_dir),
@@ -313,18 +311,18 @@ nfs3_proc_rename(struct dentry *old_dir, struct qstr *old_name,
dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name);
old_dir_attr.valid = 0;
new_dir_attr.valid = 0;
- status = rpc_call(NFS_CLIENT(old_dir->d_inode), NFS3PROC_RENAME, &arg, &res, 0);
- nfs_refresh_inode(old_dir->d_inode, &old_dir_attr);
- nfs_refresh_inode(new_dir->d_inode, &new_dir_attr);
+ status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
+ nfs_refresh_inode(old_dir, &old_dir_attr);
+ nfs_refresh_inode(new_dir, &new_dir_attr);
dprintk("NFS reply rename: %d\n", status);
return status;
}
static int
-nfs3_proc_link(struct dentry *dentry, struct dentry *dir, struct qstr *name)
+nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
struct nfs_fattr dir_attr, fattr;
- struct nfs3_linkargs arg = { NFS_FH(dentry), NFS_FH(dir),
+ struct nfs3_linkargs arg = { NFS_FH(inode), NFS_FH(dir),
name->name, name->len };
struct nfs3_linkres res = { &dir_attr, &fattr };
int status;
@@ -332,15 +330,15 @@ nfs3_proc_link(struct dentry *dentry, struct dentry *dir, struct qstr *name)
dprintk("NFS call link %s\n", name->name);
dir_attr.valid = 0;
fattr.valid = 0;
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_LINK, &arg, &res, 0);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
- nfs_refresh_inode(dentry->d_inode, &fattr);
+ status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
+ nfs_refresh_inode(dir, &dir_attr);
+ nfs_refresh_inode(inode, &fattr);
dprintk("NFS reply link: %d\n", status);
return status;
}
static int
-nfs3_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path,
+nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
struct iattr *sattr, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
@@ -353,14 +351,14 @@ nfs3_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path,
dprintk("NFS call symlink %s -> %s\n", name->name, path->name);
dir_attr.valid = 0;
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_SYMLINK, &arg, &res, 0);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
+ nfs_refresh_inode(dir, &dir_attr);
dprintk("NFS reply symlink: %d\n", status);
return status;
}
static int
-nfs3_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs_fattr dir_attr;
@@ -372,14 +370,14 @@ nfs3_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr,
dprintk("NFS call mkdir %s\n", name->name);
dir_attr.valid = 0;
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_MKDIR, &arg, &res, 0);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
+ nfs_refresh_inode(dir, &dir_attr);
dprintk("NFS reply mkdir: %d\n", status);
return status;
}
static int
-nfs3_proc_rmdir(struct dentry *dir, struct qstr *name)
+nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
{
struct nfs_fattr dir_attr;
struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len };
@@ -387,8 +385,8 @@ nfs3_proc_rmdir(struct dentry *dir, struct qstr *name)
dprintk("NFS call rmdir %s\n", name->name);
dir_attr.valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
+ nfs_refresh_inode(dir, &dir_attr);
dprintk("NFS reply rmdir: %d\n", status);
return status;
}
@@ -403,16 +401,15 @@ nfs3_proc_rmdir(struct dentry *dir, struct qstr *name)
* readdirplus.
*/
static int
-nfs3_proc_readdir(struct file *file, u64 cookie, void *entry,
+nfs3_proc_readdir(struct inode *dir, struct rpc_cred *cred,
+ u64 cookie, void *entry,
unsigned int size, int plus)
{
- struct dentry *dir = file->f_dentry;
- struct rpc_cred *cred = nfs_file_cred(file);
struct nfs_fattr dir_attr;
struct nfs3_readdirargs arg = { NFS_FH(dir), cookie, {0, 0}, 0, 0, 0 };
struct nfs3_readdirres res = { &dir_attr, 0, 0, 0, 0 };
struct rpc_message msg = { NFS3PROC_READDIR, &arg, &res, cred };
- u32 *verf = NFS_COOKIEVERF(dir->d_inode);
+ u32 *verf = NFS_COOKIEVERF(dir);
int status;
arg.buffer = entry;
@@ -432,14 +429,14 @@ nfs3_proc_readdir(struct file *file, u64 cookie, void *entry,
plus? "plus" : "", (unsigned int) cookie);
dir_attr.valid = 0;
- status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ nfs_refresh_inode(dir, &dir_attr);
dprintk("NFS reply readdir: %d\n", status);
return status;
}
static int
-nfs3_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
{
struct nfs_fattr dir_attr;
@@ -459,8 +456,8 @@ nfs3_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr,
dprintk("NFS call mknod %s %x\n", name->name, rdev);
dir_attr.valid = 0;
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_MKNOD, &arg, &res, 0);
- nfs_refresh_inode(dir->d_inode, &dir_attr);
+ status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
+ nfs_refresh_inode(dir, &dir_attr);
dprintk("NFS reply mknod: %d\n", status);
return status;
}
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index be935c083..17bb39f36 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -64,34 +64,34 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* One function for each procedure in the NFS protocol.
*/
static int
-nfs_proc_getattr(struct dentry *dentry, struct nfs_fattr *fattr)
+nfs_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
{
int status;
dprintk("NFS call getattr\n");
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_GETATTR,
- NFS_FH(dentry), fattr, 0);
+ status = rpc_call(NFS_CLIENT(inode), NFSPROC_GETATTR,
+ NFS_FH(inode), fattr, 0);
dprintk("NFS reply getattr\n");
return status;
}
static int
-nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
+nfs_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
struct iattr *sattr)
{
- struct nfs_sattrargs arg = { NFS_FH(dentry), sattr };
+ struct nfs_sattrargs arg = { NFS_FH(inode), sattr };
int status;
dprintk("NFS call setattr\n");
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_SETATTR, &arg, fattr, 0);
+ status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0);
dprintk("NFS reply setattr\n");
return status;
}
static int
-nfs_proc_lookup(struct dentry *dir, struct qstr *name,
+nfs_proc_lookup(struct inode *dir, struct qstr *name,
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs_diropargs arg = { NFS_FH(dir), name->name, name->len };
@@ -100,32 +100,31 @@ nfs_proc_lookup(struct dentry *dir, struct qstr *name,
dprintk("NFS call lookup %s\n", name->name);
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_LOOKUP, &arg, &res, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0);
dprintk("NFS reply lookup: %d\n", status);
return status;
}
static int
-nfs_proc_readlink(struct dentry *dentry, void *buffer, unsigned int bufsiz)
+nfs_proc_readlink(struct inode *inode, void *buffer, unsigned int bufsiz)
{
- struct nfs_readlinkargs args = { NFS_FH(dentry), buffer, bufsiz };
+ struct nfs_readlinkargs args = { NFS_FH(inode), buffer, bufsiz };
struct nfs_readlinkres res = { buffer, bufsiz };
int status;
dprintk("NFS call readlink\n");
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_READLINK,
+ status = rpc_call(NFS_CLIENT(inode), NFSPROC_READLINK,
&args, &res, 0);
dprintk("NFS reply readlink: %d\n", status);
return status;
}
static int
-nfs_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
+nfs_proc_read(struct inode *inode, struct rpc_cred *cred,
+ struct nfs_fattr *fattr, int flags,
loff_t offset, unsigned int count, void *buffer, int *eofp)
{
- struct dentry *dentry = file->f_dentry;
- struct rpc_cred *cred = nfs_file_cred(file);
- struct nfs_readargs arg = { NFS_FH(dentry), offset, count, 1,
+ struct nfs_readargs arg = { NFS_FH(inode), offset, count, 1,
{{ buffer, count }, {0,0}, {0,0}, {0,0},
{0,0}, {0,0}, {0,0}, {0,0}} };
struct nfs_readres res = { fattr, count, 0};
@@ -134,7 +133,7 @@ nfs_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
dprintk("NFS call read %d @ %Ld\n", count, (long long)offset);
fattr->valid = 0;
- status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
dprintk("NFS reply read: %d\n", status);
*eofp = res.eof;
@@ -142,13 +141,12 @@ nfs_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
}
static int
-nfs_proc_write(struct file *file, struct nfs_fattr *fattr, int how,
+nfs_proc_write(struct inode *inode, struct rpc_cred *cred,
+ struct nfs_fattr *fattr, int how,
loff_t offset, unsigned int count,
void *buffer, struct nfs_writeverf *verf)
{
- struct dentry *dentry = file->f_dentry;
- struct rpc_cred *cred = nfs_file_cred(file);
- struct nfs_writeargs arg = {NFS_FH(dentry), offset, count,
+ struct nfs_writeargs arg = {NFS_FH(inode), offset, count,
NFS_FILE_SYNC, 1,
{{buffer, count}, {0,0}, {0,0}, {0,0},
{0,0}, {0,0}, {0,0}, {0,0}}};
@@ -160,7 +158,7 @@ nfs_proc_write(struct file *file, struct nfs_fattr *fattr, int how,
fattr->valid = 0;
if (how & NFS_RW_SWAP)
flags |= NFS_RPC_SWAPFLAGS;
- status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
dprintk("NFS reply write: %d\n", status);
verf->committed = NFS_FILE_SYNC; /* NFSv2 always syncs data */
@@ -168,7 +166,7 @@ nfs_proc_write(struct file *file, struct nfs_fattr *fattr, int how,
}
static int
-nfs_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs_createargs arg = { NFS_FH(dir), name->name,
@@ -178,7 +176,7 @@ nfs_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
fattr->valid = 0;
dprintk("NFS call create %s\n", name->name);
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
dprintk("NFS reply create: %d\n", status);
return status;
}
@@ -187,7 +185,7 @@ nfs_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
* In NFSv2, mknod is grafted onto the create call.
*/
static int
-nfs_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs_createargs arg = { NFS_FH(dir), name->name,
@@ -207,26 +205,26 @@ nfs_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr,
}
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
if (status == -EINVAL && S_ISFIFO(mode)) {
sattr->ia_mode = mode;
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
}
dprintk("NFS reply mknod: %d\n", status);
return status;
}
static int
-nfs_proc_remove(struct dentry *dir, struct qstr *name)
+nfs_proc_remove(struct inode *dir, struct qstr *name)
{
struct nfs_diropargs arg = { NFS_FH(dir), name->name, name->len };
struct rpc_message msg = { NFSPROC_REMOVE, &arg, NULL, NULL };
int status;
dprintk("NFS call remove %s\n", name->name);
- status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
dprintk("NFS reply remove: %d\n", status);
return status;
@@ -240,7 +238,7 @@ nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *
arg = (struct nfs_diropargs *)kmalloc(sizeof(*arg), GFP_KERNEL);
if (!arg)
return -ENOMEM;
- arg->fh = NFS_FH(dir);
+ arg->fh = NFS_FH(dir->d_inode);
arg->name = name->name;
arg->len = name->len;
msg->rpc_proc = NFSPROC_REMOVE;
@@ -258,8 +256,8 @@ nfs_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
}
static int
-nfs_proc_rename(struct dentry *old_dir, struct qstr *old_name,
- struct dentry *new_dir, struct qstr *new_name)
+nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
+ struct inode *new_dir, struct qstr *new_name)
{
struct nfs_renameargs arg = { NFS_FH(old_dir), old_name->name,
old_name->len,
@@ -268,26 +266,26 @@ nfs_proc_rename(struct dentry *old_dir, struct qstr *old_name,
int status;
dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name);
- status = rpc_call(NFS_CLIENT(old_dir->d_inode), NFSPROC_RENAME, &arg, NULL, 0);
+ status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0);
dprintk("NFS reply rename: %d\n", status);
return status;
}
static int
-nfs_proc_link(struct dentry *dentry, struct dentry *dir, struct qstr *name)
+nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
- struct nfs_linkargs arg = { NFS_FH(dentry), NFS_FH(dir),
+ struct nfs_linkargs arg = { NFS_FH(inode), NFS_FH(dir),
name->name, name->len };
int status;
dprintk("NFS call link %s\n", name->name);
- status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_LINK, &arg, NULL, 0);
+ status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0);
dprintk("NFS reply link: %d\n", status);
return status;
}
static int
-nfs_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path,
+nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
struct iattr *sattr, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
@@ -297,13 +295,13 @@ nfs_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path,
dprintk("NFS call symlink %s -> %s\n", name->name, path->name);
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_SYMLINK, &arg, NULL, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0);
dprintk("NFS reply symlink: %d\n", status);
return status;
}
static int
-nfs_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs_createargs arg = { NFS_FH(dir), name->name, name->len,
@@ -313,19 +311,19 @@ nfs_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr,
dprintk("NFS call mkdir %s\n", name->name);
fattr->valid = 0;
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_MKDIR, &arg, &res, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0);
dprintk("NFS reply mkdir: %d\n", status);
return status;
}
static int
-nfs_proc_rmdir(struct dentry *dir, struct qstr *name)
+nfs_proc_rmdir(struct inode *dir, struct qstr *name)
{
struct nfs_diropargs arg = { NFS_FH(dir), name->name, name->len };
int status;
dprintk("NFS call rmdir %s\n", name->name);
- status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_RMDIR, &arg, NULL, 0);
+ status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0);
dprintk("NFS reply rmdir: %d\n", status);
return status;
}
@@ -338,11 +336,10 @@ nfs_proc_rmdir(struct dentry *dir, struct qstr *name)
* from nfs_readdir by calling the decode_entry function directly.
*/
static int
-nfs_proc_readdir(struct file *file, __u64 cookie, void *entry,
+nfs_proc_readdir(struct inode *dir, struct rpc_cred *cred,
+ __u64 cookie, void *entry,
unsigned int size, int plus)
{
- struct dentry *dir = file->f_dentry;
- struct rpc_cred *cred = nfs_file_cred(file);
struct nfs_readdirargs arg;
struct nfs_readdirres res;
struct rpc_message msg = { NFSPROC_READDIR, &arg, &res, cred };
@@ -356,7 +353,7 @@ nfs_proc_readdir(struct file *file, __u64 cookie, void *entry,
res.bufsiz = size;
dprintk("NFS call readdir %d\n", (unsigned int)cookie);
- status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
dprintk("NFS reply readdir: %d\n", status);
return status;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 76fc2f437..e0f7313be 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -36,7 +36,7 @@
struct nfs_read_data {
struct rpc_task task;
- struct dentry *dentry;
+ struct inode *inode;
struct rpc_cred *cred;
struct nfs_readargs args; /* XDR argument struct */
struct nfs_readres res; /* ... and result struct */
@@ -82,10 +82,9 @@ static void nfs_readdata_release(struct rpc_task *task)
* Read a page synchronously.
*/
static int
-nfs_readpage_sync(struct file *file, struct page *page)
+nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
+ struct rpc_cred *cred = NULL;
struct nfs_fattr fattr;
loff_t offset = page_offset(page);
char *buffer;
@@ -97,6 +96,9 @@ nfs_readpage_sync(struct file *file, struct page *page)
dprintk("NFS: nfs_readpage_sync(%p)\n", page);
+ if (file)
+ cred = nfs_file_cred(file);
+
/*
* This works now because the socket layer never tries to DMA
* into this buffer directly.
@@ -106,16 +108,16 @@ nfs_readpage_sync(struct file *file, struct page *page)
if (count < rsize)
rsize = count;
- dprintk("NFS: nfs_proc_read(%s, (%s/%s), %Ld, %d, %p)\n",
+ dprintk("NFS: nfs_proc_read(%s, (%x/%Ld), %Ld, %d, %p)\n",
NFS_SERVER(inode)->hostname,
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ inode->i_dev, (long long)NFS_FILEID(inode),
(long long)offset, rsize, buffer);
lock_kernel();
- result = NFS_PROTO(inode)->read(file, &fattr, flags, offset,
- rsize, buffer, &eof);
- unlock_kernel();
+ result = NFS_PROTO(inode)->read(inode, cred, &fattr, flags,
+ offset, rsize, buffer, &eof);
nfs_refresh_inode(inode, &fattr);
+ unlock_kernel();
/*
* Even if we had a partial success we can't mark the page
@@ -180,7 +182,7 @@ nfs_find_read(struct inode *inode, struct page *page)
static inline void
nfs_mark_request_read(struct nfs_page *req)
{
- struct inode *inode = req->wb_dentry->d_inode;
+ struct inode *inode = req->wb_inode;
spin_lock(&nfs_wreq_lock);
if (list_empty(&req->wb_list)) {
@@ -196,9 +198,8 @@ nfs_mark_request_read(struct nfs_page *req)
}
static int
-nfs_readpage_async(struct file *file, struct page *page)
+nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
{
- struct inode *inode = file->f_dentry->d_inode;
struct nfs_page *req, *new = NULL;
int result;
@@ -228,7 +229,7 @@ nfs_readpage_async(struct file *file, struct page *page)
}
result = -ENOMEM;
- new = nfs_create_request(file, page, 0, PAGE_CACHE_SIZE);
+ new = nfs_create_request(file, inode, page, 0, PAGE_CACHE_SIZE);
if (!new)
break;
}
@@ -264,9 +265,9 @@ nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data)
data->args.nriov++;
}
req = nfs_list_entry(data->pages.next);
- data->dentry = req->wb_dentry;
+ data->inode = req->wb_inode;
data->cred = req->wb_cred;
- data->args.fh = NFS_FH(req->wb_dentry);
+ data->args.fh = NFS_FH(req->wb_inode);
data->args.offset = page_offset(req->wb_page) + req->wb_offset;
data->args.count = count;
data->res.fattr = &data->fattr;
@@ -292,9 +293,8 @@ nfs_async_read_error(struct list_head *head)
}
static int
-nfs_pagein_one(struct list_head *head, struct dentry *dentry)
+nfs_pagein_one(struct list_head *head, struct inode *inode)
{
- struct inode *inode = dentry->d_inode;
struct rpc_task *task;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
struct nfs_read_data *data;
@@ -328,9 +328,9 @@ nfs_pagein_one(struct list_head *head, struct dentry *dentry)
msg.rpc_cred = data->cred;
/* Start the async call */
- dprintk("NFS: %4d initiated read call (req %s/%s count %d nriov %d.\n",
+ dprintk("NFS: %4d initiated read call (req %x/%Ld count %d nriov %d.\n",
task->tk_pid,
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ inode->i_dev, (long long)NFS_FILEID(inode),
data->args.count, data->args.nriov);
rpc_clnt_sigmask(clnt, &oldset);
@@ -355,7 +355,7 @@ nfs_pagein_list(struct inode *inode, struct list_head *head)
while (!list_empty(head)) {
pages += nfs_coalesce_requests(head, &one_request, rpages);
req = nfs_list_entry(one_request.next);
- error = nfs_pagein_one(&one_request, req->wb_dentry);
+ error = nfs_pagein_one(&one_request, req->wb_inode);
if (error < 0)
break;
}
@@ -429,8 +429,7 @@ static void
nfs_readpage_result(struct rpc_task *task)
{
struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
- struct dentry *dentry = data->dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = data->inode;
int count = data->res.count;
dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
@@ -451,9 +450,9 @@ nfs_readpage_result(struct rpc_task *task)
kunmap(page);
UnlockPage(page);
- dprintk("NFS: read (%s/%s %d@%Ld)\n",
- req->wb_dentry->d_parent->d_name.name,
- req->wb_dentry->d_name.name,
+ dprintk("NFS: read (%x/%Ld %d@%Ld)\n",
+ req->wb_inode->i_dev,
+ (long long)NFS_FILEID(req->wb_inode),
req->wb_bytes,
(long long)(page_offset(page) + req->wb_offset));
nfs_unlock_request(req);
@@ -473,9 +472,19 @@ nfs_readpage_result(struct rpc_task *task)
int
nfs_readpage(struct file *file, struct page *page)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode;
int error;
+ if (!file) {
+ struct address_space *mapping = page->mapping;
+ if (!mapping)
+ BUG();
+ inode = (struct inode *)mapping->host;
+ } else
+ inode = file->f_dentry->d_inode;
+ if (!inode)
+ BUG();
+
dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
page, PAGE_CACHE_SIZE, page->index);
/*
@@ -491,11 +500,11 @@ nfs_readpage(struct file *file, struct page *page)
error = -1;
if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE)
- error = nfs_readpage_async(file, page);
+ error = nfs_readpage_async(file, inode, page);
if (error >= 0)
goto out;
- error = nfs_readpage_sync(file, page);
+ error = nfs_readpage_sync(file, inode, page);
if (error < 0 && IS_SWAPFILE(inode))
printk("Aiee.. nfs swap-in of page failed!\n");
out:
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 4960526b4..eba7a859a 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -27,9 +27,8 @@
/* Symlink caching in the page cache is even more simplistic
* and straight-forward than readdir caching.
*/
-static int nfs_symlink_filler(struct dentry *dentry, struct page *page)
+static int nfs_symlink_filler(struct inode *inode, struct page *page)
{
- struct inode *inode = dentry->d_inode;
void *buffer = kmap(page);
int error;
@@ -38,7 +37,7 @@ static int nfs_symlink_filler(struct dentry *dentry, struct page *page)
* XDR response verification will NULL terminate it.
*/
lock_kernel();
- error = NFS_PROTO(inode)->readlink(dentry, buffer,
+ error = NFS_PROTO(inode)->readlink(inode, buffer,
PAGE_CACHE_SIZE - sizeof(u32)-4);
unlock_kernel();
if (error < 0)
@@ -55,15 +54,14 @@ error:
return -EIO;
}
-static char *nfs_getlink(struct dentry *dentry, struct page **ppage)
+static char *nfs_getlink(struct inode *inode, struct page **ppage)
{
- struct inode *inode = dentry->d_inode;
struct page *page;
u32 *p;
/* Caller revalidated the directory inode already. */
page = read_cache_page(&inode->i_data, 0,
- (filler_t *)nfs_symlink_filler, dentry);
+ (filler_t *)nfs_symlink_filler, inode);
if (IS_ERR(page))
goto read_failed;
if (!Page_Uptodate(page))
@@ -81,8 +79,9 @@ read_failed:
static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
+ struct inode *inode = dentry->d_inode;
struct page *page = NULL;
- int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(dentry,&page));
+ int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(inode,&page));
if (page) {
kunmap(page);
page_cache_release(page);
@@ -92,8 +91,9 @@ static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
+ struct inode *inode = dentry->d_inode;
struct page *page = NULL;
- int res = vfs_follow_link(nd, nfs_getlink(dentry,&page));
+ int res = vfs_follow_link(nd, nfs_getlink(inode,&page));
if (page) {
kunmap(page);
page_cache_release(page);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 230954993..f75190be5 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -77,7 +77,7 @@ static atomic_t nfs_nr_requests = ATOMIC_INIT(0);
*/
struct nfs_write_data {
struct rpc_task task;
- struct dentry *dentry;
+ struct inode *inode;
struct rpc_cred *cred;
struct nfs_writeargs args; /* argument struct */
struct nfs_writeres res; /* result struct */
@@ -89,7 +89,8 @@ struct nfs_write_data {
/*
* Local function declarations
*/
-static struct nfs_page * nfs_update_request(struct file*, struct page *page,
+static struct nfs_page * nfs_update_request(struct file*, struct inode *,
+ struct page *,
unsigned int, unsigned int);
static void nfs_strategy(struct inode *inode);
static void nfs_writeback_done(struct rpc_task *);
@@ -167,11 +168,10 @@ nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr)
* Offset is the data offset within the page.
*/
static int
-nfs_writepage_sync(struct file *file, struct page *page,
+nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page,
unsigned int offset, unsigned int count)
{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
+ struct rpc_cred *cred = NULL;
loff_t base;
unsigned int wsize = NFS_SERVER(inode)->wsize;
int result, refresh = 0, written = 0, flags;
@@ -179,9 +179,13 @@ nfs_writepage_sync(struct file *file, struct page *page,
struct nfs_fattr fattr;
struct nfs_writeverf verf;
+
+ if (file)
+ cred = nfs_file_cred(file);
+
lock_kernel();
- dprintk("NFS: nfs_writepage_sync(%s/%s %d@%Ld)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ dprintk("NFS: nfs_writepage_sync(%x/%Ld %d@%Ld)\n",
+ inode->i_dev, (long long)NFS_FILEID(inode),
count, (long long)(page_offset(page) + offset));
buffer = kmap(page) + offset;
@@ -193,7 +197,7 @@ nfs_writepage_sync(struct file *file, struct page *page,
if (count < wsize && !IS_SWAPFILE(inode))
wsize = count;
- result = NFS_PROTO(inode)->write(file, &fattr, flags,
+ result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags,
base, wsize, buffer, &verf);
nfs_write_attributes(inode, &fattr);
@@ -229,18 +233,18 @@ io_error:
}
static int
-nfs_writepage_async(struct file *file, struct page *page,
+nfs_writepage_async(struct file *file, struct inode *inode, struct page *page,
unsigned int offset, unsigned int count)
{
struct nfs_page *req;
int status;
- req = nfs_update_request(file, page, offset, count);
+ req = nfs_update_request(file, inode, page, offset, count);
status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
if (status < 0)
goto out;
nfs_release_request(req);
- nfs_strategy(file->f_dentry->d_inode);
+ nfs_strategy(inode);
out:
return status;
}
@@ -249,33 +253,48 @@ nfs_writepage_async(struct file *file, struct page *page,
* Write an mmapped page to the server.
*/
int
-nfs_writepage(struct file *file, struct page *page)
+nfs_writepage(struct page *page)
{
- struct inode *inode = file->f_dentry->d_inode;
- unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ struct inode *inode;
+ unsigned long end_index;
unsigned offset = PAGE_CACHE_SIZE;
int err;
+ struct address_space *mapping = page->mapping;
+
+ if (!mapping)
+ BUG();
+ inode = (struct inode *)mapping->host;
+ if (!inode)
+ BUG();
+ end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+
+ /* Ensure we've flushed out any previous writes */
+ nfs_wb_page(inode,page);
/* easy case */
if (page->index < end_index)
goto do_it;
/* things got complicated... */
offset = inode->i_size & (PAGE_CACHE_SIZE-1);
+
/* OK, are we completely out? */
+ err = -EIO;
if (page->index >= end_index+1 || !offset)
- return -EIO;
+ goto out;
do_it:
if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) {
- err = nfs_writepage_async(file, page, 0, offset);
+ err = nfs_writepage_async(NULL, inode, page, 0, offset);
if (err >= 0)
goto out_ok;
}
- err = nfs_writepage_sync(file, page, 0, offset);
- if ( err == offset)
- goto out_ok;
+ err = nfs_writepage_sync(NULL, inode, page, 0, offset);
+ if ( err == offset) {
+out_ok:
+ err = 0;
+ }
+out:
+ UnlockPage(page);
return err;
- out_ok:
- return 0;
}
/*
@@ -315,6 +334,8 @@ nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
return;
if (!NFS_WBACK_BUSY(req))
printk(KERN_ERR "NFS: unlocked request attempted hashed!\n");
+ if (list_empty(&inode->u.nfs_i.writeback))
+ atomic_inc(&inode->i_count);
inode->u.nfs_i.npages++;
list_add(&req->wb_hash, &inode->u.nfs_i.writeback);
req->wb_count++;
@@ -334,12 +355,14 @@ nfs_inode_remove_request(struct nfs_page *req)
}
if (!NFS_WBACK_BUSY(req))
printk(KERN_ERR "NFS: unlocked request attempted unhashed!\n");
- inode = req->wb_dentry->d_inode;
+ inode = req->wb_inode;
list_del(&req->wb_hash);
INIT_LIST_HEAD(&req->wb_hash);
inode->u.nfs_i.npages--;
if ((inode->u.nfs_i.npages == 0) != list_empty(&inode->u.nfs_i.writeback))
printk(KERN_ERR "NFS: desynchronized value of nfs_i.npages.\n");
+ if (list_empty(&inode->u.nfs_i.writeback))
+ iput(inode);
if (!nfs_have_writebacks(inode) && !nfs_have_read(inode))
inode_remove_flushd(inode);
spin_unlock(&nfs_wreq_lock);
@@ -422,7 +445,7 @@ void nfs_list_remove_request(struct nfs_page *req)
static inline void
nfs_mark_request_dirty(struct nfs_page *req)
{
- struct inode *inode = req->wb_dentry->d_inode;
+ struct inode *inode = req->wb_inode;
spin_lock(&nfs_wreq_lock);
if (list_empty(&req->wb_list)) {
@@ -443,7 +466,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
static inline int
nfs_dirty_request(struct nfs_page *req)
{
- struct inode *inode = req->wb_dentry->d_inode;
+ struct inode *inode = req->wb_inode;
return !list_empty(&req->wb_list) && req->wb_list_head == &inode->u.nfs_i.dirty;
}
@@ -454,7 +477,7 @@ nfs_dirty_request(struct nfs_page *req)
static inline void
nfs_mark_request_commit(struct nfs_page *req)
{
- struct inode *inode = req->wb_dentry->d_inode;
+ struct inode *inode = req->wb_inode;
spin_lock(&nfs_wreq_lock);
if (list_empty(&req->wb_list)) {
@@ -477,11 +500,10 @@ nfs_mark_request_commit(struct nfs_page *req)
* when we reach the hard limit on the number of dirty pages.
* It should be safe to sleep here.
*/
-struct nfs_page *nfs_create_request(struct file *file, struct page *page,
+struct nfs_page *nfs_create_request(struct file *file, struct inode *inode,
+ struct page *page,
unsigned int offset, unsigned int count)
{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
struct nfs_page *req = NULL;
long timeout;
@@ -533,9 +555,15 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page,
req->wb_offset = offset;
req->wb_bytes = count;
req->wb_file = file;
- get_file(file);
- req->wb_dentry = dentry;
- req->wb_cred = nfs_file_cred(file);
+
+ /* If we have a struct file, use its cached credentials
+ * else cache the current process' credentials. */
+ if (file) {
+ get_file(file);
+ req->wb_cred = nfs_file_cred(file);
+ } else
+ req->wb_cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+ req->wb_inode = inode;
req->wb_count = 1;
/* register request's existence */
@@ -554,7 +582,7 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page,
void
nfs_release_request(struct nfs_page *req)
{
- struct inode *inode = req->wb_dentry->d_inode;
+ struct inode *inode = req->wb_inode;
struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
struct page *page = req->wb_page;
@@ -576,7 +604,11 @@ nfs_release_request(struct nfs_page *req)
if (NFS_WBACK_BUSY(req))
printk(KERN_ERR "NFS: Request released while still locked!\n");
- fput(req->wb_file);
+ /* Release struct file or cached credential */
+ if (req->wb_file)
+ fput(req->wb_file);
+ else
+ rpcauth_releasecred(NFS_CLIENT(inode)->cl_auth, req->wb_cred);
page_cache_release(page);
nfs_page_free(req);
/* wake up anyone waiting to allocate a request */
@@ -599,7 +631,7 @@ nfs_release_request(struct nfs_page *req)
static int
nfs_wait_on_request(struct nfs_page *req)
{
- struct inode *inode = req->wb_dentry->d_inode;
+ struct inode *inode = req->wb_inode;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
if (!NFS_WBACK_BUSY(req))
@@ -814,10 +846,9 @@ int nfs_coalesce_requests(struct list_head *src, struct list_head *dst, unsigned
* Note: Should always be called with the Page Lock held!
*/
static struct nfs_page *
-nfs_update_request(struct file* file, struct page *page,
+nfs_update_request(struct file* file, struct inode *inode, struct page *page,
unsigned int offset, unsigned int bytes)
{
- struct inode *inode = file->f_dentry->d_inode;
struct nfs_page *req, *new = NULL;
unsigned long rqend, end;
@@ -857,7 +888,7 @@ nfs_update_request(struct file* file, struct page *page,
*/
if (inode->u.nfs_i.npages >= MAX_REQUEST_SOFT)
nfs_wb_file(inode, file);
- new = nfs_create_request(file, page, offset, bytes);
+ new = nfs_create_request(file, inode, page, offset, bytes);
if (!new)
return ERR_PTR(-ENOMEM);
/* If the region is locked, adjust the timeout */
@@ -995,7 +1026,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign
* page synchronously.
*/
if (NFS_SERVER(inode)->wsize < PAGE_SIZE)
- return nfs_writepage_sync(file, page, offset, count);
+ return nfs_writepage_sync(file, inode, page, offset, count);
/*
* Try to find an NFS request corresponding to this page
@@ -1004,7 +1035,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign
* it out now.
*/
do {
- req = nfs_update_request(file, page, offset, count);
+ req = nfs_update_request(file, inode, page, offset, count);
status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
if (status != -EBUSY)
break;
@@ -1068,9 +1099,9 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data)
data->args.nriov++;
}
req = nfs_list_entry(data->pages.next);
- data->dentry = req->wb_dentry;
+ data->inode = req->wb_inode;
data->cred = req->wb_cred;
- data->args.fh = NFS_FH(req->wb_dentry);
+ data->args.fh = NFS_FH(req->wb_inode);
data->args.offset = page_offset(req->wb_page) + req->wb_offset;
data->args.count = count;
data->res.fattr = &data->fattr;
@@ -1088,9 +1119,8 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data)
* that has been written but not committed.
*/
static int
-nfs_flush_one(struct list_head *head, struct dentry *dentry, int how)
+nfs_flush_one(struct list_head *head, struct inode *inode, int how)
{
- struct inode *inode = dentry->d_inode;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
struct nfs_write_data *data;
struct rpc_task *task;
@@ -1134,10 +1164,10 @@ nfs_flush_one(struct list_head *head, struct dentry *dentry, int how)
msg.rpc_resp = &data->res;
msg.rpc_cred = data->cred;
- dprintk("NFS: %4d initiated write call (req %s/%s count %d nriov %d)\n",
+ dprintk("NFS: %4d initiated write call (req %x/%Ld count %d nriov %d)\n",
task->tk_pid,
- dentry->d_parent->d_name.name,
- dentry->d_name.name,
+ inode->i_dev,
+ (long long)NFS_FILEID(inode),
data->args.count, data->args.nriov);
rpc_clnt_sigmask(clnt, &oldset);
@@ -1167,7 +1197,7 @@ nfs_flush_list(struct inode *inode, struct list_head *head, int how)
while (!list_empty(head)) {
pages += nfs_coalesce_requests(head, &one_request, wpages);
req = nfs_list_entry(one_request.next);
- error = nfs_flush_one(&one_request, req->wb_dentry, how);
+ error = nfs_flush_one(&one_request, req->wb_inode, how);
if (error < 0)
break;
}
@@ -1193,8 +1223,7 @@ nfs_writeback_done(struct rpc_task *task)
struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
struct nfs_writeargs *argp = &data->args;
struct nfs_writeres *resp = &data->res;
- struct dentry *dentry = data->dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = data->inode;
struct nfs_page *req;
struct page *page;
@@ -1249,9 +1278,9 @@ nfs_writeback_done(struct rpc_task *task)
kunmap(page);
- dprintk("NFS: write (%s/%s %d@%Ld)",
- req->wb_dentry->d_parent->d_name.name,
- req->wb_dentry->d_name.name,
+ dprintk("NFS: write (%x/%Ld %d@%Ld)",
+ req->wb_inode->i_dev,
+ (long long)NFS_FILEID(req->wb_inode),
req->wb_bytes,
(long long)(page_offset(page) + req->wb_offset));
@@ -1292,7 +1321,6 @@ static void
nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data)
{
struct nfs_page *first, *last;
- struct dentry *dentry;
struct inode *inode;
loff_t start, end, len;
@@ -1303,8 +1331,7 @@ nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data)
INIT_LIST_HEAD(head);
first = nfs_list_entry(data->pages.next);
last = nfs_list_entry(data->pages.prev);
- dentry = first->wb_dentry;
- inode = dentry->d_inode;
+ inode = first->wb_inode;
/*
* Determine the offset range of requests in the COMMIT call.
@@ -1317,9 +1344,9 @@ nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data)
if (end >= inode->i_size || len < 0 || len > (~((u32)0) >> 1))
len = 0;
- data->dentry = dentry;
+ data->inode = inode;
data->cred = first->wb_cred;
- data->args.fh = NFS_FH(dentry);
+ data->args.fh = NFS_FH(inode);
data->args.offset = start;
data->res.count = data->args.count = (u32)len;
data->res.fattr = &data->fattr;
@@ -1352,7 +1379,7 @@ nfs_commit_list(struct list_head *head, int how)
/* Set up the argument struct */
nfs_commit_rpcsetup(head, data);
req = nfs_list_entry(data->pages.next);
- clnt = NFS_CLIENT(req->wb_dentry->d_inode);
+ clnt = NFS_CLIENT(req->wb_inode);
rpc_init_task(task, clnt, nfs_commit_done, flags);
task->tk_calldata = data;
@@ -1389,8 +1416,7 @@ nfs_commit_done(struct rpc_task *task)
struct nfs_write_data *data = (struct nfs_write_data *)task->tk_calldata;
struct nfs_writeres *resp = &data->res;
struct nfs_page *req;
- struct dentry *dentry = data->dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = data->inode;
dprintk("NFS: %4d nfs_commit_done (status %d)\n",
task->tk_pid, task->tk_status);
@@ -1400,9 +1426,9 @@ nfs_commit_done(struct rpc_task *task)
req = nfs_list_entry(data->pages.next);
nfs_list_remove_request(req);
- dprintk("NFS: commit (%s/%s %d@%Ld)",
- req->wb_dentry->d_parent->d_name.name,
- req->wb_dentry->d_name.name,
+ dprintk("NFS: commit (%x/%Ld %d@%Ld)",
+ req->wb_inode->i_dev,
+ (long long)NFS_FILEID(req->wb_inode),
req->wb_bytes,
(long long)(page_offset(req->wb_page) + req->wb_offset));
if (task->tk_status < 0) {
diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c
index 49d2160a6..ad99eb13b 100644
--- a/fs/ntfs/fs.c
+++ b/fs/ntfs/fs.c
@@ -557,7 +557,8 @@ ntfs_bmap(struct inode *ino,int block)
#endif
/* It's fscking broken. */
-
+/* FIXME: [bm]map code is disabled until ntfs_get_block gets sorted! */
+/*
static int ntfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create)
{
BUG();
@@ -573,6 +574,7 @@ static struct file_operations ntfs_file_operations = {
};
static struct inode_operations ntfs_inode_operations;
+*/
static struct file_operations ntfs_dir_operations = {
read: generic_read_dir,
@@ -587,7 +589,8 @@ static struct inode_operations ntfs_dir_inode_operations = {
#endif
};
-static int ntfs_writepage(struct file *file, struct page *page)
+/*
+static int ntfs_writepage(struct page *page)
{
return block_write_full_page(page,ntfs_get_block);
}
@@ -612,6 +615,8 @@ struct address_space_operations ntfs_aops = {
commit_write: generic_commit_write,
bmap: _ntfs_bmap
};
+*/
+
/* ntfs_read_inode is called by the Virtual File System (the kernel layer that
* deals with filesystems) when iget is called requesting an inode not already
* present in the inode table. Typically filesystems have separate
@@ -664,7 +669,10 @@ static void ntfs_read_inode(struct inode* inode)
else
{
inode->i_size=data->size;
- can_mmap=!data->resident && !data->compressed;
+ /* FIXME: once ntfs_get_block is implemented, uncomment the
+ * next line and remove the can_mmap = 0; */
+ /* can_mmap=!data->resident && !data->compressed;*/
+ can_mmap = 0;
}
/* get the file modification times from the standard information */
si=ntfs_find_attr(ino,vol->at_standard_information,NULL);
@@ -687,12 +695,17 @@ static void ntfs_read_inode(struct inode* inode)
}
else
{
- if (can_mmap) {
+ /* As long as ntfs_get_block() is just a call to BUG() do not
+ * define any [bm]map ops or we get the BUG() whenever someone
+ * runs mc or mpg123 on an ntfs partition!
+ * FIXME: Uncomment the below code when ntfs_get_block is
+ * implemented. */
+ /* if (can_mmap) {
inode->i_op = &ntfs_inode_operations;
inode->i_fop = &ntfs_file_operations;
inode->i_mapping->a_ops = &ntfs_aops;
inode->u.ntfs_i.mmu_private = inode->i_size;
- } else {
+ } else */ {
inode->i_op=&ntfs_inode_operations_nobmap;
inode->i_fop=&ntfs_file_operations_nommap;
}
@@ -931,8 +944,7 @@ static int __init init_ntfs_fs(void)
/* Comment this if you trust klogd. There are reasons not to trust it
*/
#if defined(DEBUG) && !defined(MODULE)
- extern int console_loglevel;
- console_loglevel=15;
+ console_verbose();
#endif
printk(KERN_NOTICE "NTFS version " NTFS_VERSION "\n");
SYSCTL(1);
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index e58b04e02..e46ef0b25 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -43,7 +43,7 @@ static struct file_operations proc_file_operations = {
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
-/* 4K page size but our output routines use some slack for overruns */
+/* buffer size is one page but our output routines use some slack for overruns */
#define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
static ssize_t
@@ -336,6 +336,7 @@ int proc_readdir(struct file * filp,
* the /proc directory.
*/
static struct file_operations proc_dir_operations = {
+ read: generic_read_dir,
readdir: proc_readdir,
};
diff --git a/fs/proc/root.c b/fs/proc/root.c
index cae861960..c54369a32 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -82,6 +82,7 @@ static int proc_root_readdir(struct file * filp,
* directory handling functions for that..
*/
static struct file_operations proc_root_operations = {
+ read: generic_read_dir,
readdir: proc_root_readdir,
};
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 78dbc34f0..45a945209 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -415,7 +415,7 @@ static void qnx4_put_super(struct super_block *sb)
return;
}
-static int qnx4_writepage(struct file *file, struct page *page)
+static int qnx4_writepage(struct page *page)
{
return block_write_full_page(page,qnx4_get_block);
}
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 31461669c..36fa933a4 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -78,7 +78,7 @@ static int ramfs_readpage(struct file *file, struct page * page)
* Writing: just make sure the page gets marked dirty, so that
* the page stealer won't grab it.
*/
-static int ramfs_writepage(struct file *file, struct page *page)
+static int ramfs_writepage(struct page *page)
{
SetPageDirty(page);
return 0;
diff --git a/fs/readdir.c b/fs/readdir.c
index cd8f7ad3d..16eba6383 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -325,4 +325,3 @@ out_putf:
out:
return error;
}
-
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index b2d5c4099..7b62899c1 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -124,7 +124,7 @@ smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
qname.len = entry->len;
entry->ino = find_inode_number(dentry, &qname);
if (!entry->ino)
- entry->ino = smb_invent_inos(1);
+ entry->ino = iunique(dentry->d_sb, 2);
}
if (filldir(dirent, entry->name, entry->len,
@@ -325,7 +325,7 @@ smb_lookup(struct inode *dir, struct dentry *dentry)
goto add_entry;
if (!error) {
error = -EACCES;
- finfo.f_ino = smb_invent_inos(1);
+ finfo.f_ino = iunique(dentry->d_sb, 2);
inode = smb_iget(dir->i_sb, &finfo);
if (inode) {
add_entry:
@@ -362,7 +362,7 @@ smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
goto out_close;
smb_renew_times(dentry);
- fattr.f_ino = smb_invent_inos(1);
+ fattr.f_ino = iunique(dentry->d_sb, 2);
inode = smb_iget(dentry->d_sb, &fattr);
if (!inode)
goto out_no_inode;
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 135e8707c..79627f880 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -48,8 +48,7 @@ smb_readpage_sync(struct dentry *dentry, struct page *page)
DENTRY_PATH(dentry), count, offset, rsize);
result = smb_open(dentry, SMB_O_RDONLY);
- if (result < 0)
- {
+ if (result < 0) {
PARANOIA("%s/%s open failed, error=%d\n",
DENTRY_PATH(dentry), result);
goto io_error;
@@ -59,7 +58,7 @@ smb_readpage_sync(struct dentry *dentry, struct page *page)
if (count < rsize)
rsize = count;
- result = smb_proc_read(dentry, offset, rsize, buffer);
+ result = smb_proc_read(dentry->d_inode, offset, rsize, buffer);
if (result < 0)
goto io_error;
@@ -82,7 +81,7 @@ io_error:
}
/*
- * We are called with the page locked and the caller unlocks.
+ * We are called with the page locked and we unlock it when done.
*/
static int
smb_readpage(struct file *file, struct page *page)
@@ -103,25 +102,27 @@ smb_readpage(struct file *file, struct page *page)
* Offset is the data offset within the page.
*/
static int
-smb_writepage_sync(struct dentry *dentry, struct page *page,
+smb_writepage_sync(struct inode *inode, struct page *page,
unsigned long offset, unsigned int count)
{
- struct inode *inode = dentry->d_inode;
u8 *buffer = page_address(page) + offset;
- int wsize = smb_get_wsize(server_from_dentry(dentry));
+ int wsize = smb_get_wsize(server_from_inode(inode));
int result, written = 0;
offset += page->index << PAGE_CACHE_SHIFT;
- VERBOSE("file %s/%s, count=%d@%ld, wsize=%d\n",
- DENTRY_PATH(dentry), count, offset, wsize);
+ VERBOSE("file ino=%ld, fileid=%d, count=%d@%ld, wsize=%d\n",
+ inode->i_ino, inode->u.smbfs_i.fileid, count, offset, wsize);
do {
if (count < wsize)
wsize = count;
- result = smb_proc_write(dentry, offset, wsize, buffer);
- if (result < 0)
+ result = smb_proc_write(inode, offset, wsize, buffer);
+ if (result < 0) {
+ PARANOIA("failed write, wsize=%d, result=%d\n",
+ wsize, result);
break;
+ }
/* N.B. what if result < wsize?? */
#ifdef SMBFS_PARANOIA
if (result < wsize)
@@ -147,17 +148,25 @@ smb_writepage_sync(struct dentry *dentry, struct page *page,
* Write a page to the server. This will be used for NFS swapping only
* (for now), and we currently do this synchronously only.
*
- * We are called with the page locked and the caller unlocks.
+ * We are called with the page locked and we unlock it when done.
*/
static int
-smb_writepage(struct file *file, struct page *page)
+smb_writepage(struct page *page)
{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
- unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ struct address_space *mapping = page->mapping;
+ struct inode *inode;
+ unsigned long end_index;
unsigned offset = PAGE_CACHE_SIZE;
int err;
+ if (!mapping)
+ BUG();
+ inode = (struct inode *)mapping->host;
+ if (!inode)
+ BUG();
+
+ end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+
/* easy case */
if (page->index < end_index)
goto do_it;
@@ -168,8 +177,9 @@ smb_writepage(struct file *file, struct page *page)
return -EIO;
do_it:
get_page(page);
- err = smb_writepage_sync(dentry, page, 0, offset);
+ err = smb_writepage_sync(inode, page, 0, offset);
SetPageUptodate(page);
+ UnlockPage(page);
put_page(page);
return err;
}
@@ -183,7 +193,7 @@ smb_updatepage(struct file *file, struct page *page, unsigned long offset,
DEBUG1("(%s/%s %d@%ld)\n", DENTRY_PATH(dentry),
count, (page->index << PAGE_CACHE_SHIFT)+offset);
- return smb_writepage_sync(dentry, page, offset, count);
+ return smb_writepage_sync(dentry->d_inode, page, offset, count);
}
static ssize_t
@@ -308,8 +318,16 @@ out:
static int
smb_file_open(struct inode *inode, struct file * file)
{
+ int result;
+ struct dentry *dentry = file->f_dentry;
+ int smb_mode = (file->f_mode & O_ACCMODE) - 1;
+
lock_kernel();
+ result = smb_open(dentry, smb_mode);
+ if (result)
+ goto out;
inode->u.smbfs_i.openers++;
+out:
unlock_kernel();
return 0;
}
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index bcc900626..e502fb60b 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -53,22 +53,6 @@ static struct super_operations smb_sops =
statfs: smb_statfs,
};
-/* FIXME: Look at all inodes whether so that we do not get duplicate
- * inode numbers. */
-
-unsigned long
-smb_invent_inos(unsigned long n)
-{
- static unsigned long ino = 2;
-
- if (ino + 2*n < ino)
- {
- /* wrap around */
- ino = 2;
- }
- ino += n;
- return ino;
-}
/* We are always generating a new inode here */
struct inode *
@@ -282,7 +266,7 @@ out:
static void
smb_delete_inode(struct inode *ino)
{
- DEBUG1("\n");
+ DEBUG1("ino=%ld\n", ino->i_ino);
lock_kernel();
if (smb_close(ino))
PARANOIA("could not close inode %ld\n", ino->i_ino);
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index 7863cd2da..f0444f97d 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -1072,9 +1072,9 @@ smb_close_fileid(struct dentry *dentry, __u16 fileid)
file-id would not be valid after a reconnection. */
int
-smb_proc_read(struct dentry *dentry, off_t offset, int count, char *data)
+smb_proc_read(struct inode *inode, off_t offset, int count, char *data)
{
- struct smb_sb_info *server = server_from_dentry(dentry);
+ struct smb_sb_info *server = server_from_inode(inode);
__u16 returned_count, data_len;
unsigned char *buf;
int result;
@@ -1082,7 +1082,7 @@ smb_proc_read(struct dentry *dentry, off_t offset, int count, char *data)
smb_lock_server(server);
smb_setup_header(server, SMBread, 5, 0);
buf = server->packet;
- WSET(buf, smb_vwv0, dentry->d_inode->u.smbfs_i.fileid);
+ WSET(buf, smb_vwv0, inode->u.smbfs_i.fileid);
WSET(buf, smb_vwv1, count);
DSET(buf, smb_vwv2, offset);
WSET(buf, smb_vwv4, 0);
@@ -1114,25 +1114,26 @@ smb_proc_read(struct dentry *dentry, off_t offset, int count, char *data)
result = data_len;
out:
- VERBOSE("file %s/%s, count=%d, result=%d\n",
- DENTRY_PATH(dentry), count, result);
+ VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
+ inode->ino, inode->u.smbfs_i.fileid, count, result);
smb_unlock_server(server);
return result;
}
int
-smb_proc_write(struct dentry *dentry, off_t offset, int count, const char *data)
+smb_proc_write(struct inode *inode, off_t offset, int count, const char *data)
{
- struct smb_sb_info *server = server_from_dentry(dentry);
+ struct smb_sb_info *server = server_from_inode(inode);
int result;
__u8 *p;
- VERBOSE("file %s/%s, count=%d@%ld, packet_size=%d\n",
- DENTRY_PATH(dentry), count, offset, server->packet_size);
+ VERBOSE("ino=%ld, fileid=%d, count=%d@%ld, packet_size=%d\n",
+ inode->ino, inode->u.smbfs_i.fileid, count, offset,
+ server->packet_size);
smb_lock_server(server);
p = smb_setup_header(server, SMBwrite, 5, count + 3);
- WSET(server->packet, smb_vwv0, dentry->d_inode->u.smbfs_i.fileid);
+ WSET(server->packet, smb_vwv0, inode->u.smbfs_i.fileid);
WSET(server->packet, smb_vwv1, count);
DSET(server->packet, smb_vwv2, offset);
WSET(server->packet, smb_vwv4, 0);
diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c
index 66dbd9efb..cb1e697fc 100644
--- a/fs/smbfs/sock.c
+++ b/fs/smbfs/sock.c
@@ -163,12 +163,12 @@ smb_data_ready(struct sock *sk, int len)
found_data(sk);
return;
}
- job->cb.next = NULL;
+ INIT_LIST_HEAD(&job->cb.list);
job->cb.sync = 0;
job->cb.routine = smb_data_callback;
job->cb.data = job;
job->sk = sk;
- queue_task(&job->cb, &tq_scheduler);
+ schedule_task(&job->cb);
}
int
diff --git a/fs/stat.c b/fs/stat.c
index e07b237e4..3d7efa0ad 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -25,7 +25,7 @@ do_revalidate(struct dentry *dentry)
}
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__) && !defined(__hppa__)
/*
* For backward compatibility? Maybe this should be moved
@@ -126,7 +126,7 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf)
}
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__) && !defined(__hppa__)
/*
* For backward compatibility? Maybe this should be moved
* into arch/i386 instead?
@@ -162,7 +162,7 @@ asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
return error;
}
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__) && !defined(__hppa__)
/*
* For backward compatibility? Maybe this should be moved
@@ -200,7 +200,7 @@ asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
return error;
}
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__) && !defined(__hppa__)
/*
* For backward compatibility? Maybe this should be moved
diff --git a/fs/super.c b/fs/super.c
index 4f2e3908a..1c0b48c11 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1037,13 +1037,13 @@ static int do_umount(struct vfsmount *mnt, int umount_root, int flags)
}
spin_lock(&dcache_lock);
- if (atomic_read(&mnt->mnt_count) > 2) {
- spin_unlock(&dcache_lock);
- mntput(mnt);
- return -EBUSY;
- }
if (mnt->mnt_instances.next != mnt->mnt_instances.prev) {
+ if (atomic_read(&mnt->mnt_count) > 2) {
+ spin_unlock(&dcache_lock);
+ mntput(mnt);
+ return -EBUSY;
+ }
if (sb->s_type->fs_flags & FS_SINGLE)
put_filesystem(sb->s_type);
/* We hold two references, so mntput() is safe */
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 7e5f6c54a..1fb7beaa8 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -916,7 +916,7 @@ struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create)
return NULL;
}
-static int sysv_writepage(struct file *file, struct page *page)
+static int sysv_writepage(struct page *page)
{
return block_write_full_page(page,sysv_get_block);
}
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 7e8ac9b7d..3895d769b 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -67,7 +67,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page)
return 0;
}
-static int udf_adinicb_writepage(struct file *file, struct page *page)
+static int udf_adinicb_writepage(struct page *page)
{
struct inode *inode = (struct inode *)page->mapping->host;
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 83a34f258..3783b43fd 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -125,7 +125,7 @@ void udf_discard_prealloc(struct inode * inode)
udf_trunc(inode);
}
-static int udf_writepage(struct file *file, struct page *page)
+static int udf_writepage(struct page *page)
{
return block_write_full_page(page, udf_get_block);
}
@@ -202,7 +202,7 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
mark_buffer_dirty(bh);
udf_release_data(bh);
- inode->i_data.a_ops->writepage(NULL, page);
+ inode->i_data.a_ops->writepage(page);
UnlockPage(page);
page_cache_release(page);
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 10a9d9be4..55830ac19 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -518,7 +518,7 @@ struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
return NULL;
}
-static int ufs_writepage(struct file *file, struct page *page)
+static int ufs_writepage(struct page *page)
{
return block_write_full_page(page,ufs_getfrag_block);
}
diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
index 649abd02d..78e0f58c3 100644
--- a/include/asm-alpha/bitops.h
+++ b/include/asm-alpha/bitops.h
@@ -20,31 +20,12 @@
* bit 0 is the LSB of addr; bit 64 is the LSB of (addr+1).
*/
-#define BITOPS_NO_BRANCH
-
-extern __inline__ void set_bit(unsigned long nr, volatile void * addr)
+extern __inline__ void
+set_bit(unsigned long nr, volatile void * addr)
{
-#ifndef BITOPS_NO_BRANCH
- unsigned long oldbit;
-#endif
unsigned long temp;
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+ int *m = ((int *) addr) + (nr >> 5);
-#ifndef BITOPS_NO_BRANCH
- __asm__ __volatile__(
- "1: ldl_l %0,%4\n"
- " and %0,%3,%2\n"
- " bne %2,2f\n"
- " xor %0,%3,%0\n"
- " stl_c %0,%1\n"
- " beq %0,3f\n"
- "2:\n"
- ".subsection 2\n"
- "3: br 1b\n"
- ".previous"
- :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
- :"Ir" (1UL << (nr & 31)), "m" (*m));
-#else
__asm__ __volatile__(
"1: ldl_l %0,%3\n"
" bis %0,%2,%0\n"
@@ -55,58 +36,28 @@ extern __inline__ void set_bit(unsigned long nr, volatile void * addr)
".previous"
:"=&r" (temp), "=m" (*m)
:"Ir" (1UL << (nr & 31)), "m" (*m));
-#endif
}
/*
* WARNING: non atomic version.
*/
-extern __inline__ void __set_bit(unsigned long nr, volatile void * addr)
+extern __inline__ void
+__set_bit(unsigned long nr, volatile void * addr)
{
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
- /*
- * Asm and C produces the same thing so let
- * the compiler to do its good work.
- */
-#if 0
- int tmp;
+ int *m = ((int *) addr) + (nr >> 5);
- __asm__ __volatile__(
- "ldl %0,%3\n\t"
- "bis %0,%2,%0\n\t"
- "stl %0,%1"
- : "=&r" (tmp), "=m" (*m)
- : "Ir" (1UL << (nr & 31)), "m" (*m));
-#else
*m |= 1UL << (nr & 31);
-#endif
}
#define smp_mb__before_clear_bit() smp_mb()
#define smp_mb__after_clear_bit() smp_mb()
-extern __inline__ void clear_bit(unsigned long nr, volatile void * addr)
+
+extern __inline__ void
+clear_bit(unsigned long nr, volatile void * addr)
{
-#ifndef BITOPS_NO_BRANCH
- unsigned long oldbit;
-#endif
unsigned long temp;
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+ int *m = ((int *) addr) + (nr >> 5);
-#ifndef BITOPS_NO_BRANCH
- __asm__ __volatile__(
- "1: ldl_l %0,%4\n"
- " and %0,%3,%2\n"
- " beq %2,2f\n"
- " xor %0,%3,%0\n"
- " stl_c %0,%1\n"
- " beq %0,3f\n"
- "2:\n"
- ".subsection 2\n"
- "3: br 1b\n"
- ".previous"
- :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
- :"Ir" (1UL << (nr & 31)), "m" (*m));
-#else
__asm__ __volatile__(
"1: ldl_l %0,%3\n"
" and %0,%2,%0\n"
@@ -117,13 +68,13 @@ extern __inline__ void clear_bit(unsigned long nr, volatile void * addr)
".previous"
:"=&r" (temp), "=m" (*m)
:"Ir" (~(1UL << (nr & 31))), "m" (*m));
-#endif
}
-extern __inline__ void change_bit(unsigned long nr, volatile void * addr)
+extern __inline__ void
+change_bit(unsigned long nr, volatile void * addr)
{
unsigned long temp;
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+ int *m = ((int *) addr) + (nr >> 5);
__asm__ __volatile__(
"1: ldl_l %0,%3\n"
@@ -137,12 +88,12 @@ extern __inline__ void change_bit(unsigned long nr, volatile void * addr)
:"Ir" (1UL << (nr & 31)), "m" (*m));
}
-extern __inline__ int test_and_set_bit(unsigned long nr,
- volatile void * addr)
+extern __inline__ int
+test_and_set_bit(unsigned long nr, volatile void *addr)
{
unsigned long oldbit;
unsigned long temp;
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+ int *m = ((int *) addr) + (nr >> 5);
__asm__ __volatile__(
"1: ldl_l %0,%4\n"
@@ -151,10 +102,10 @@ extern __inline__ int test_and_set_bit(unsigned long nr,
" xor %0,%3,%0\n"
" stl_c %0,%1\n"
" beq %0,3f\n"
+ "2:\n"
#ifdef CONFIG_SMP
" mb\n"
#endif
- "2:\n"
".subsection 2\n"
"3: br 1b\n"
".previous"
@@ -167,32 +118,23 @@ extern __inline__ int test_and_set_bit(unsigned long nr,
/*
* WARNING: non atomic version.
*/
-extern __inline__ int __test_and_set_bit(unsigned long nr,
- volatile void * addr)
+extern __inline__ int
+__test_and_set_bit(unsigned long nr, volatile void * addr)
{
- unsigned long oldbit;
- unsigned long temp;
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
-
- __asm__ __volatile__(
- " ldl %0,%4\n"
- " and %0,%3,%2\n"
- " bne %2,1f\n"
- " xor %0,%3,%0\n"
- " stl %0,%1\n"
- "1:\n"
- :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
- :"Ir" (1UL << (nr & 31)), "m" (*m));
+ unsigned long mask = 1 << (nr & 0x1f);
+ int *m = ((int *) addr) + (nr >> 5);
+ int old = *m;
- return oldbit != 0;
+ *m = old | mask;
+ return (old & mask) != 0;
}
-extern __inline__ int test_and_clear_bit(unsigned long nr,
- volatile void * addr)
+extern __inline__ int
+test_and_clear_bit(unsigned long nr, volatile void * addr)
{
unsigned long oldbit;
unsigned long temp;
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+ int *m = ((int *) addr) + (nr >> 5);
__asm__ __volatile__(
"1: ldl_l %0,%4\n"
@@ -201,10 +143,10 @@ extern __inline__ int test_and_clear_bit(unsigned long nr,
" xor %0,%3,%0\n"
" stl_c %0,%1\n"
" beq %0,3f\n"
+ "2:\n"
#ifdef CONFIG_SMP
" mb\n"
#endif
- "2:\n"
".subsection 2\n"
"3: br 1b\n"
".previous"
@@ -217,32 +159,23 @@ extern __inline__ int test_and_clear_bit(unsigned long nr,
/*
* WARNING: non atomic version.
*/
-extern __inline__ int __test_and_clear_bit(unsigned long nr,
- volatile void * addr)
+extern __inline__ int
+__test_and_clear_bit(unsigned long nr, volatile void * addr)
{
- unsigned long oldbit;
- unsigned long temp;
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+ unsigned long mask = 1 << (nr & 0x1f);
+ int *m = ((int *) addr) + (nr >> 5);
+ int old = *m;
- __asm__ __volatile__(
- " ldl %0,%4\n"
- " and %0,%3,%2\n"
- " beq %2,1f\n"
- " xor %0,%3,%0\n"
- " stl %0,%1\n"
- "1:\n"
- :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
- :"Ir" (1UL << (nr & 31)), "m" (*m));
-
- return oldbit != 0;
+ *m = old & ~mask;
+ return (old & mask) != 0;
}
-extern __inline__ int test_and_change_bit(unsigned long nr,
- volatile void * addr)
+extern __inline__ int
+test_and_change_bit(unsigned long nr, volatile void * addr)
{
unsigned long oldbit;
unsigned long temp;
- unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+ int *m = ((int *) addr) + (nr >> 5);
__asm__ __volatile__(
"1: ldl_l %0,%4\n"
@@ -262,7 +195,8 @@ extern __inline__ int test_and_change_bit(unsigned long nr,
return oldbit != 0;
}
-extern __inline__ int test_bit(int nr, volatile void * addr)
+extern __inline__ int
+test_bit(int nr, volatile void * addr)
{
return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
}
@@ -289,7 +223,7 @@ extern inline unsigned long ffz_b(unsigned long x)
extern inline unsigned long ffz(unsigned long word)
{
#if defined(__alpha_cix__) && defined(__alpha_fix__)
- /* Whee. EV6 can calculate it directly. */
+ /* Whee. EV67 can calculate it directly. */
unsigned long result;
__asm__("cttz %1,%0" : "=r"(result) : "r"(~word));
return result;
@@ -325,7 +259,7 @@ extern inline int ffs(int word)
*/
#if defined(__alpha_cix__) && defined(__alpha_fix__)
-/* Whee. EV6 can calculate it directly. */
+/* Whee. EV67 can calculate it directly. */
extern __inline__ unsigned long hweight64(unsigned long w)
{
unsigned long result;
@@ -347,7 +281,8 @@ extern __inline__ unsigned long hweight64(unsigned long w)
/*
* Find next zero bit in a bitmap reasonably efficiently..
*/
-extern inline unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
+extern inline unsigned long
+find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
unsigned long result = offset & ~63UL;
diff --git a/include/asm-alpha/byteorder.h b/include/asm-alpha/byteorder.h
index edc376a04..91b55ea3e 100644
--- a/include/asm-alpha/byteorder.h
+++ b/include/asm-alpha/byteorder.h
@@ -3,6 +3,44 @@
#include <asm/types.h>
+#ifdef __GNUC__
+
+static __inline __u32 __attribute__((__const)) __arch__swab32(__u32 x)
+{
+ /*
+ * Unfortunately, we can't use the 6 instruction sequence
+ * on ev6 since the latency of the UNPKBW is 3, which is
+ * pretty hard to hide. Just in case a future implementation
+ * has a lower latency, here's the sequence (also by Mike Burrows)
+ *
+ * UNPKBW a0, v0 v0: 00AA00BB00CC00DD
+ * SLL v0, 24, a0 a0: BB00CC00DD000000
+ * BIS v0, a0, a0 a0: BBAACCBBDDCC00DD
+ * EXTWL a0, 6, v0 v0: 000000000000BBAA
+ * ZAP a0, 0xf3, a0 a0: 00000000DDCC0000
+ * ADDL a0, v0, v0 v0: ssssssssDDCCBBAA
+ */
+
+ __u64 t0, t1, t2, t3;
+
+ __asm__("inslh %1, 7, %0" /* t0 : 0000000000AABBCC */
+ : "=r"(t0) : "r"(x));
+ __asm__("inswl %1, 3, %0" /* t1 : 000000CCDD000000 */
+ : "=r"(t1) : "r"(x));
+
+ t1 |= t0; /* t1 : 000000CCDDAABBCC */
+ t2 = t1 >> 16; /* t2 : 0000000000CCDDAA */
+ t0 = t1 & 0xFF00FF00; /* t0 : 00000000DD00BB00 */
+ t3 = t2 & 0x00FF00FF; /* t3 : 0000000000CC00AA */
+ t1 = t0 + t3; /* t1 : ssssssssDDCCBBAA */
+
+ return t1;
+}
+
+#define __arch__swab32 __arch__swab32
+
+#endif /* __GNUC__ */
+
#define __BYTEORDER_HAS_U64__
#include <linux/byteorder/little_endian.h>
diff --git a/include/asm-alpha/fpu.h b/include/asm-alpha/fpu.h
index b02a78594..acd1b9a03 100644
--- a/include/asm-alpha/fpu.h
+++ b/include/asm-alpha/fpu.h
@@ -131,17 +131,19 @@ rdfpcr(void)
unsigned long tmp, ret;
#if defined(__alpha_cix__) || defined(__alpha_fix__)
- __asm__ ("ftoit $f0,%0\n\t"
- "mf_fpcr $f0\n\t"
- "ftoit $f0,%1\n\t"
- "itoft %0,$f0"
- : "=r"(tmp), "=r"(ret));
+ __asm__ __volatile__ (
+ "ftoit $f0,%0\n\t"
+ "mf_fpcr $f0\n\t"
+ "ftoit $f0,%1\n\t"
+ "itoft %0,$f0"
+ : "=r"(tmp), "=r"(ret));
#else
- __asm__ ("stt $f0,%0\n\t"
- "mf_fpcr $f0\n\t"
- "stt $f0,%1\n\t"
- "ldt $f0,%0"
- : "=m"(tmp), "=m"(ret));
+ __asm__ __volatile__ (
+ "stt $f0,%0\n\t"
+ "mf_fpcr $f0\n\t"
+ "stt $f0,%1\n\t"
+ "ldt $f0,%0"
+ : "=m"(tmp), "=m"(ret));
#endif
return ret;
@@ -153,11 +155,12 @@ wrfpcr(unsigned long val)
unsigned long tmp;
#if defined(__alpha_cix__) || defined(__alpha_fix__)
- __asm__ __volatile__ ("ftoit $f0,%0\n\t"
- "itoft %1,$f0\n\t"
- "mt_fpcr $f0\n\t"
- "itoft %0,$f0"
- : "=&r"(tmp) : "r"(val));
+ __asm__ __volatile__ (
+ "ftoit $f0,%0\n\t"
+ "itoft %1,$f0\n\t"
+ "mt_fpcr $f0\n\t"
+ "itoft %0,$f0"
+ : "=&r"(tmp) : "r"(val));
#else
__asm__ __volatile__ (
"stt $f0,%0\n\t"
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 54341fff1..b3f6e8141 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -59,6 +59,11 @@
#define _PAGE_FOW 0x0004 /* used for page protection (fault on write) */
#define _PAGE_FOE 0x0008 /* used for page protection (fault on exec) */
#define _PAGE_ASM 0x0010
+#if defined(CONFIG_ALPHA_EV6) && !defined(CONFIG_SMP)
+#define _PAGE_MBE 0x0080 /* MB disable bit for EV6. */
+#else
+#define _PAGE_MBE 0x0000
+#endif
#define _PAGE_KRE 0x0100 /* xxx - see below on the "accessed" bit */
#define _PAGE_URE 0x0200 /* xxx */
#define _PAGE_KWE 0x1000 /* used to do the dirty bit in software */
@@ -85,19 +90,20 @@
#define _PFN_MASK 0xFFFFFFFF00000000
#define _PAGE_TABLE (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS)
-#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS)
+#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS | _PAGE_MBE)
/*
- * All the normal masks have the "page accessed" bits on, as any time they are used,
- * the page is accessed. They are cleared only by the page-out routines
+ * All the normal masks have the "page accessed" bits on, as any time they
+ * are used, the page is accessed. They are cleared only by the page-out
+ * routines.
*/
#define PAGE_NONE __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE)
#define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS)
#define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
#define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
-#define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
+#define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE | _PAGE_MBE)
-#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
+#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_MBE | (x))
#define _PAGE_P(x) _PAGE_NORMAL((x) | (((x) & _PAGE_FOW)?0:_PAGE_FOW))
#define _PAGE_S(x) _PAGE_NORMAL(x)
@@ -189,6 +195,7 @@ extern unsigned long __zero_page(void);
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
+
#define mk_pte(page, pgprot) \
({ \
pte_t pte; \
@@ -199,7 +206,7 @@ extern unsigned long __zero_page(void);
})
extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; }
+{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | (pgprot_val(pgprot) & ~_PAGE_MBE); return pte; }
extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
diff --git a/include/asm-arm/arch-arc/memory.h b/include/asm-arm/arch-arc/memory.h
index fb4d819f4..3c21224b5 100644
--- a/include/asm-arm/arch-arc/memory.h
+++ b/include/asm-arm/arch-arc/memory.h
@@ -22,6 +22,12 @@
#define TASK_SIZE_26 (0x01a00000UL)
/*
+ * 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: 32MB
*/
#define PAGE_OFFSET (0x02000000UL)
diff --git a/include/asm-arm/arch-arc/processor.h b/include/asm-arm/arch-arc/processor.h
deleted file mode 100644
index 7eea170e3..000000000
--- a/include/asm-arm/arch-arc/processor.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * linux/include/asm-arm/arch-arc/processor.h
- *
- * Copyright (c) 1996-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.
- *
- * Changelog:
- * 10-Sep-1996 RMK Created
- * 21-Mar-1999 RMK Added asm/arch/memory.h
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff --git a/include/asm-arm/arch-cl7500/memory.h b/include/asm-arm/arch-cl7500/memory.h
index a1811df0c..56e1d3bfc 100644
--- a/include/asm-arm/arch-cl7500/memory.h
+++ b/include/asm-arm/arch-cl7500/memory.h
@@ -21,6 +21,12 @@
#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)
diff --git a/include/asm-arm/arch-cl7500/processor.h b/include/asm-arm/arch-cl7500/processor.h
deleted file mode 100644
index 3f75f16bc..000000000
--- a/include/asm-arm/arch-cl7500/processor.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * linux/include/asm-arm/arch-cl7500/processor.h
- *
- * Copyright (c) 1996-1999 Russell King.
- *
- * Changelog:
- * 10-Sep-1996 RMK Created
- * 21-Mar-1999 RMK Added asm/arch/memory.h
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff --git a/include/asm-arm/arch-ebsa285/hardware.h b/include/asm-arm/arch-ebsa285/hardware.h
index 44747379c..21157a5c3 100644
--- a/include/asm-arm/arch-ebsa285/hardware.h
+++ b/include/asm-arm/arch-ebsa285/hardware.h
@@ -94,8 +94,6 @@
#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
-#define PARAMS_OFFSET 0x0100
-
#define FLUSH_BASE_PHYS 0x50000000
#define UNCACHEABLE_ADDR (ARMCSR_BASE + 0x108)
@@ -133,4 +131,9 @@ extern int gpio_read(void);
extern void cpld_modify(int mask, int set);
#endif
+#define pcibios_assign_all_busses() 1
+
+#define PCIBIOS_MIN_IO 0x6000
+#define PCIBIOS_MIN_MEM 0x40000000
+
#endif
diff --git a/include/asm-arm/arch-ebsa285/memory.h b/include/asm-arm/arch-ebsa285/memory.h
index 98172671f..41e730cea 100644
--- a/include/asm-arm/arch-ebsa285/memory.h
+++ b/include/asm-arm/arch-ebsa285/memory.h
@@ -67,6 +67,12 @@ extern unsigned long __bus_to_virt(unsigned long);
#define PHYS_OFFSET (0x00000000UL)
/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+/*
* The DRAM is always contiguous.
*/
#define __virt_to_phys__is_a_macro
diff --git a/include/asm-arm/arch-ebsa285/processor.h b/include/asm-arm/arch-ebsa285/processor.h
deleted file mode 100644
index 1c0561018..000000000
--- a/include/asm-arm/arch-ebsa285/processor.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/processor.h
- *
- * Copyright (C) 1996-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.
- *
- * Changelog:
- * 21-Mar-1999 RMK Added asm/arch/memory.h
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff --git a/include/asm-arm/arch-l7200/hardware.h b/include/asm-arm/arch-l7200/hardware.h
index a9209af7b..506192bc8 100644
--- a/include/asm-arm/arch-l7200/hardware.h
+++ b/include/asm-arm/arch-l7200/hardware.h
@@ -41,9 +41,6 @@
#define FLUSH_BASE_PHYS 0x40000000 /* ROM */
#define FLUSH_BASE 0xdf000000
-#define PARAMS_OFFSET (0x0100)
-#define Z_PARAMS_BASE (RAM_START + PARAMS_OFFSET)
-
#define PCIO_BASE IO_BASE
#endif
diff --git a/include/asm-arm/arch-l7200/memory.h b/include/asm-arm/arch-l7200/memory.h
index d07a1ddc1..a34a0f9a4 100644
--- a/include/asm-arm/arch-l7200/memory.h
+++ b/include/asm-arm/arch-l7200/memory.h
@@ -19,6 +19,12 @@
#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)
diff --git a/include/asm-arm/arch-l7200/processor.h b/include/asm-arm/arch-l7200/processor.h
deleted file mode 100644
index ee4b4b2ca..000000000
--- a/include/asm-arm/arch-l7200/processor.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * linux/include/asm-arm/arch-l7200/processor.h
- *
- * Copyright (c) 2000 Steven Hill (sjhill@cotw.com)
- *
- * Changelog:
- * 03-21-2000 SJH Created
- * 05-03-2000 SJH Comment cleaning
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff --git a/include/asm-arm/arch-nexuspci/memory.h b/include/asm-arm/arch-nexuspci/memory.h
index de0429b6b..a7e644257 100644
--- a/include/asm-arm/arch-nexuspci/memory.h
+++ b/include/asm-arm/arch-nexuspci/memory.h
@@ -15,6 +15,12 @@
#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)
diff --git a/include/asm-arm/arch-nexuspci/processor.h b/include/asm-arm/arch-nexuspci/processor.h
deleted file mode 100644
index 542dd9106..000000000
--- a/include/asm-arm/arch-nexuspci/processor.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/processor.h
- * from linux/include/asm-arm/arch-ebsa110/processor.h
- *
- * Copyright (C) 1996-1999 Russell King
- *
- * Changelog:
- * 21-Mar-1999 RMK Added asm/arch/memory.h
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff --git a/include/asm-arm/arch-rpc/memory.h b/include/asm-arm/arch-rpc/memory.h
index 2b3899173..cf562f87f 100644
--- a/include/asm-arm/arch-rpc/memory.h
+++ b/include/asm-arm/arch-rpc/memory.h
@@ -25,6 +25,12 @@
#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)
diff --git a/include/asm-arm/arch-rpc/processor.h b/include/asm-arm/arch-rpc/processor.h
deleted file mode 100644
index b64eaebfc..000000000
--- a/include/asm-arm/arch-rpc/processor.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * linux/include/asm-arm/arch-rpc/processor.h
- *
- * Copyright (C) 1996-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.
- *
- * Changelog:
- * 10-Sep-1996 RMK Created
- * 21-Mar-1999 RMK Added asm/arch/memory.h
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff --git a/include/asm-arm/arch-rpc/uncompress.h b/include/asm-arm/arch-rpc/uncompress.h
index 0834d287e..dde1bfc7a 100644
--- a/include/asm-arm/arch-rpc/uncompress.h
+++ b/include/asm-arm/arch-rpc/uncompress.h
@@ -56,7 +56,7 @@ static const unsigned long palette_4[16] = {
#define palette_setpixel(p) *(unsigned long *)(IO_START+0x00400000) = 0x10000000|((p) & 255)
#define palette_write(v) *(unsigned long *)(IO_START+0x00400000) = 0x00000000|((v) & 0x00ffffff)
-static struct param_struct * const params = (struct param_struct *)Z_PARAMS_BASE;
+extern struct param_struct params;
#ifndef STANDALONE_DEBUG
/*
@@ -69,8 +69,8 @@ static void puts(const char *s)
unsigned char c;
char *ptr;
- x = params->video_x;
- y = params->video_y;
+ x = params.video_x;
+ y = params.video_y;
while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
if ( c == '\n' ) {
@@ -79,7 +79,7 @@ static void puts(const char *s)
y--;
}
} else {
- ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
+ ptr = VIDMEM + ((y*video_num_columns*params.bytes_per_char_v+x)*bytes_per_char_h);
ll_write_char(ptr, c|(white<<16));
if ( ++x >= video_num_columns ) {
x = 0;
@@ -90,8 +90,8 @@ static void puts(const char *s)
}
}
- params->video_x = x;
- params->video_y = y;
+ params.video_x = x;
+ params.video_y = y;
}
static void error(char *x);
@@ -103,9 +103,9 @@ static void arch_decomp_setup(void)
{
int i;
- video_num_lines = params->video_num_rows;
- video_num_columns = params->video_num_cols;
- bytes_per_char_h = params->bytes_per_char_h;
+ video_num_lines = params.video_num_rows;
+ video_num_columns = params.video_num_cols;
+ bytes_per_char_h = params.bytes_per_char_h;
video_size_row = video_num_columns * bytes_per_char_h;
if (bytes_per_char_h == 4)
for (i = 0; i < 256; i++)
@@ -140,7 +140,7 @@ static void arch_decomp_setup(void)
white = 7;
}
- if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n");
+ if (params.nr_pages * params.page_size < 4096*1024) error("<4M of mem\n");
}
#endif
diff --git a/include/asm-arm/arch-shark/memory.h b/include/asm-arm/arch-shark/memory.h
index d3ede01ec..96b24052a 100644
--- a/include/asm-arm/arch-shark/memory.h
+++ b/include/asm-arm/arch-shark/memory.h
@@ -17,6 +17,12 @@
#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)
diff --git a/include/asm-arm/arch-shark/processor.h b/include/asm-arm/arch-shark/processor.h
deleted file mode 100644
index bd99869af..000000000
--- a/include/asm-arm/arch-shark/processor.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/processor.h
- *
- * Copyright (C) 1996-1999 Russell King
- *
- * Changelog:
- * 21-Mar-1999 RMK Added asm/arch/memory.h
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-#include <asm/arch/memory.h>
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff --git a/include/asm-arm/arch-tbox/memory.h b/include/asm-arm/arch-tbox/memory.h
index e066821f2..e93d0afb1 100644
--- a/include/asm-arm/arch-tbox/memory.h
+++ b/include/asm-arm/arch-tbox/memory.h
@@ -14,6 +14,12 @@
#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)
diff --git a/include/asm-arm/arch-tbox/processor.h b/include/asm-arm/arch-tbox/processor.h
deleted file mode 100644
index 0f8e7129b..000000000
--- a/include/asm-arm/arch-tbox/processor.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/include/asm-arm/arch-tbox/processor.h
- * from linux/include/asm-arm/arch-ebsa110/processor.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index 9773f6749..9bfe93269 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -17,6 +17,9 @@
#ifdef __KERNEL__
+#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.
*/
diff --git a/include/asm-arm/hardware.h b/include/asm-arm/hardware.h
index 4ded5b8f0..1fd1a5b65 100644
--- a/include/asm-arm/hardware.h
+++ b/include/asm-arm/hardware.h
@@ -15,10 +15,4 @@
#include <asm/arch/hardware.h>
-#ifdef PARAMS_OFFSET
-#define PARAMS_BASE ((PAGE_OFFSET) + (PARAMS_OFFSET))
-#else
-#define PARAMS_BASE 0
-#endif
-
#endif
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index 63c1ee9cf..c32ddbc3c 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -3,10 +3,7 @@
#ifdef __KERNEL__
-#define pcibios_assign_all_busses() 0
-
-#define PCIBIOS_MIN_IO 0x8000
-#define PCIBIOS_MIN_MEM 0x40000000
+#include <asm/arch/hardware.h>
extern inline void pcibios_set_master(struct pci_dev *dev)
{
diff --git a/include/asm-arm/proc-armo/processor.h b/include/asm-arm/proc-armo/processor.h
index 581236378..43cbb221e 100644
--- a/include/asm-arm/proc-armo/processor.h
+++ b/include/asm-arm/proc-armo/processor.h
@@ -57,7 +57,7 @@ extern uaccess_t uaccess_user, uaccess_kernel;
uaccess_t *uaccess; /* User access functions*/
#define EXTRA_THREAD_STRUCT_INIT \
- ,&uaccess_kernel
+ uaccess: &uaccess_kernel,
#define start_thread(regs,pc,sp) \
({ \
diff --git a/include/asm-arm/proc-armv/processor.h b/include/asm-arm/proc-armv/processor.h
index ab7f31d65..775ebfc55 100644
--- a/include/asm-arm/proc-armv/processor.h
+++ b/include/asm-arm/proc-armv/processor.h
@@ -41,9 +41,9 @@ struct context_save_struct {
unsigned int domain;
#define EXTRA_THREAD_STRUCT_INIT \
- , domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \
- domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
- domain_val(DOMAIN_IO, DOMAIN_CLIENT)
+ domain: domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \
+ domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
+ domain_val(DOMAIN_IO, DOMAIN_CLIENT)
#define start_thread(regs,pc,sp) \
({ \
diff --git a/include/asm-arm/proc-armv/ptrace.h b/include/asm-arm/proc-armv/ptrace.h
index d15d5a6ec..190caa193 100644
--- a/include/asm-arm/proc-armv/ptrace.h
+++ b/include/asm-arm/proc-armv/ptrace.h
@@ -10,6 +10,8 @@
#ifndef __ASM_PROC_PTRACE_H
#define __ASM_PROC_PTRACE_H
+#include <linux/config.h>
+
#define USR26_MODE 0x00
#define FIQ26_MODE 0x01
#define IRQ26_MODE 0x02
@@ -64,8 +66,12 @@ struct pt_regs {
#define user_mode(regs) \
(((regs)->ARM_cpsr & 0xf) == 0)
+#ifdef CONFIG_ARM_THUMB
#define thumb_mode(regs) \
(((regs)->ARM_cpsr & T_BIT))
+#else
+#define thumb_mode(regs) (0)
+#endif
#define processor_mode(regs) \
((regs)->ARM_cpsr & MODE_MASK)
diff --git a/include/asm-arm/proc-armv/system.h b/include/asm-arm/proc-armv/system.h
index 247ed3e2b..becb31c2d 100644
--- a/include/asm-arm/proc-armv/system.h
+++ b/include/asm-arm/proc-armv/system.h
@@ -10,19 +10,7 @@
#ifndef __ASM_PROC_SYSTEM_H
#define __ASM_PROC_SYSTEM_H
-extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
- extern void __bad_xchg(volatile void *, int);
-
- switch (size) {
- case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]" : "=r" (x) : "r" (x), "r" (ptr) : "memory");
- break;
- case 4: __asm__ __volatile__ ("swp %0, %1, [%2]" : "=r" (x) : "r" (x), "r" (ptr) : "memory");
- break;
- default: __bad_xchg(ptr, size);
- }
- return x;
-}
+#include <linux/config.h>
#define set_cr(x) \
__asm__ __volatile__( \
@@ -131,4 +119,61 @@ extern unsigned long cr_alignment; /* defined in entry-armv.S */
: "r" (x) \
: "memory")
+#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
+/*
+ * On the StrongARM, "swp" is terminally broken since it bypasses the
+ * cache totally. This means that the cache becomes inconsistent, and,
+ * since we use normal loads/stores as well, this is really bad.
+ * Typically, this causes oopsen in filp_close, but could have other,
+ * more disasterous effects. There are two work-arounds:
+ * 1. Disable interrupts and emulate the atomic swap
+ * 2. Clean the cache, perform atomic swap, flush the cache
+ *
+ * We choose (1) since its the "easiest" to achieve here and is not
+ * dependent on the processor type.
+ */
+#define swp_is_buggy
+#endif
+
+extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+ extern void __bad_xchg(volatile void *, int);
+ unsigned long ret;
+#ifdef swp_is_buggy
+ unsigned long flags;
+#endif
+
+ switch (size) {
+#ifdef swp_is_buggy
+ case 1:
+ __save_flags_cli(flags);
+ ret = *(volatile unsigned char *)ptr;
+ *(volatile unsigned char *)ptr = x;
+ __restore_flags(flags);
+ break;
+
+ case 4:
+ __save_flags_cli(flags);
+ ret = *(volatile unsigned long *)ptr;
+ *(volatile unsigned long *)ptr = x;
+ __restore_flags(flags);
+ break;
+#else
+ case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]"
+ : "=r" (ret)
+ : "r" (x), "r" (ptr)
+ : "memory");
+ break;
+ case 4: __asm__ __volatile__ ("swp %0, %1, [%2]"
+ : "=r" (ret)
+ : "r" (x), "r" (ptr)
+ : "memory");
+ break;
+#endif
+ default: __bad_xchg(ptr, size);
+ }
+
+ return ret;
+}
+
#endif
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index cf21f2c1b..f84c5d2d3 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -36,12 +36,12 @@ typedef unsigned long mm_segment_t; /* domain register */
#ifdef __KERNEL__
-#define NR_DEBUGS 5
+#define EISA_bus 0
+#define MCA_bus 0
#include <asm/atomic.h>
#include <asm/ptrace.h>
#include <asm/arch/memory.h>
-#include <asm/arch/processor.h>
#include <asm/proc/processor.h>
struct debug_info {
@@ -67,18 +67,16 @@ struct thread_struct {
EXTRA_THREAD_STRUCT
};
-#define INIT_MMAP \
-{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
-
-#define INIT_THREAD { \
- ATOMIC_INIT(1), \
- 0, \
- 0, \
- 0, \
- { { { 0, }, }, }, \
- { 0, }, \
- (struct context_save_struct *)0 \
- EXTRA_THREAD_STRUCT_INIT \
+#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 \
}
/*
@@ -104,7 +102,6 @@ extern __inline__ void init_thread_css(struct context_save_struct *save)
/* Forward declaration, a strange C thing */
struct task_struct;
-struct mm_struct;
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index a1142be1a..f19eaed13 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -4,7 +4,7 @@
#ifdef __KERNEL__
#include <linux/config.h>
-#include <linux/linkage.h>
+#include <linux/kernel.h>
/* information about the system we're running on */
extern unsigned int system_rev;
@@ -64,8 +64,17 @@ extern struct task_struct *__switch_to(struct task_struct *prev, struct task_str
#ifdef CONFIG_SMP
#error SMP not supported
+
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+
#else
+#define smp_mb() barrier()
+#define smp_rmb() barrier()
+#define smp_wmb() barrier()
+
#define cli() __cli()
#define sti() __sti()
#define clf() __clf()
diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
index 0ae108653..1428fd95b 100644
--- a/include/asm-generic/bitops.h
+++ b/include/asm-generic/bitops.h
@@ -9,14 +9,14 @@
* disable interrupts while they operate. (You have to provide inline
* routines to cli() and sti().)
*
- * Also note, these routines assume that you have 32 bit integers.
+ * Also note, these routines assume that you have 32 bit longs.
* You will have to change this if you are trying to port Linux to the
* Alpha architecture or to a Cray. :-)
*
* C language equivalents written by Theodore Ts'o, 9/26/92
*/
-extern __inline__ int set_bit(int nr,int * addr)
+extern __inline__ int set_bit(int nr,long * addr)
{
int mask, retval;
@@ -29,7 +29,7 @@ extern __inline__ int set_bit(int nr,int * addr)
return retval;
}
-extern __inline__ int clear_bit(int nr, int * addr)
+extern __inline__ int clear_bit(int nr, long * addr)
{
int mask, retval;
@@ -42,7 +42,7 @@ extern __inline__ int clear_bit(int nr, int * addr)
return retval;
}
-extern __inline__ int test_bit(int nr, int * addr)
+extern __inline__ int test_bit(int nr, long * addr)
{
int mask;
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index a65546820..b98102522 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -26,7 +26,7 @@ static inline pte_t ptep_get_and_clear(pte_t *ptep)
return pte;
}
-static inline void ptep_clear_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(pte_t *ptep)
{
pte_t old_pte = *ptep;
set_pte(ptep, pte_wrprotect(old_pte));
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 733ec4cc0..abb627a41 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -10,7 +10,7 @@
#ifdef CONFIG_X86_LOCAL_APIC
#if APIC_DEBUG
-#define Dprintk(x...) printk(##x)
+#define Dprintk(x...) printk(x)
#else
#define Dprintk(x...)
#endif
diff --git a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
index 3860288ad..9ccc2821c 100644
--- a/include/asm-i386/hardirq.h
+++ b/include/asm-i386/hardirq.h
@@ -42,7 +42,7 @@ typedef struct {
#include <asm/smp.h>
extern unsigned char global_irq_holder;
-extern unsigned volatile int global_irq_lock;
+extern unsigned volatile long global_irq_lock; /* long for set_bit -RR */
static inline int irqs_running (void)
{
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h
index 515a8dc5c..72bf155e9 100644
--- a/include/asm-i386/msr.h
+++ b/include/asm-i386/msr.h
@@ -30,3 +30,7 @@
: "=a" (low), "=d" (high) \
: "c" (counter))
+/* symbolic names for some interesting MSRs */
+#define MSR_IA32_PLATFORM_ID 0x17
+#define MSR_IA32_UCODE_WRITE 0x79
+#define MSR_IA32_UCODE_REV 0x8B
diff --git a/include/asm-i386/mtrr.h b/include/asm-i386/mtrr.h
index cc28a42c7..488208e70 100644
--- a/include/asm-i386/mtrr.h
+++ b/include/asm-i386/mtrr.h
@@ -49,6 +49,11 @@ struct mtrr_gentry
#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry)
#define MTRRIOC_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry)
#define MTRRIOC_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry)
+#define MTRRIOC_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry)
+#define MTRRIOC_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry)
+#define MTRRIOC_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry)
+#define MTRRIOC_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry)
+#define MTRRIOC_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry)
/* These are the region types */
#define MTRR_TYPE_UNCACHABLE 0
@@ -79,18 +84,31 @@ static char *mtrr_strings[MTRR_NUM_TYPES] =
# ifdef CONFIG_MTRR
extern int mtrr_add (unsigned long base, unsigned long size,
unsigned int type, char increment);
+extern int mtrr_add_page (unsigned long base, unsigned long size,
+ unsigned int type, char increment);
extern int mtrr_del (int reg, unsigned long base, unsigned long size);
+extern int mtrr_del_page (int reg, unsigned long base, unsigned long size);
# else
static __inline__ int mtrr_add (unsigned long base, unsigned long size,
unsigned int type, char increment)
{
return -ENODEV;
}
+static __inline__ int mtrr_add_page (unsigned long base, unsigned long size,
+ unsigned int type, char increment)
+{
+ return -ENODEV;
+}
static __inline__ int mtrr_del (int reg, unsigned long base,
unsigned long size)
{
return -ENODEV;
}
+static __inline__ int mtrr_del_page (int reg, unsigned long base,
+ unsigned long size)
+{
+ return -ENODEV;
+}
# endif
/* The following functions are for initialisation: don't use them! */
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 8272b8f29..8bf9bd75c 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -82,8 +82,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#ifndef __ASSEMBLY__
-extern int console_loglevel;
-
/*
* Tell the user there is some problem. Beep too, so we can
* see^H^H^Hhear bugs in early bootup as well!
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 1fc0a0b9a..5d7d5717a 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -283,7 +283,7 @@ static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return p
static inline int ptep_test_and_clear_dirty(pte_t *ptep) { return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep); }
static inline int ptep_test_and_clear_young(pte_t *ptep) { return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); }
-static inline void ptep_clear_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, ptep); }
+static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, ptep); }
static inline void ptep_mkdirty(pte_t *ptep) { set_bit(_PAGE_BIT_RW, ptep); }
/*
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 9e8e8c5ef..a03dd0027 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -464,7 +464,8 @@ struct microcode {
unsigned int bits[500];
};
-#define MICROCODE_IOCFREE _IO('6',0) /* because it is for P6 */
+/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
+#define MICROCODE_IOCFREE _IO('6',0)
/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
extern inline void rep_nop(void)
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
index 4a92bb2a2..2d6eb04bf 100644
--- a/include/asm-i386/spinlock.h
+++ b/include/asm-i386/spinlock.h
@@ -141,7 +141,7 @@ typedef struct {
* Changed to use the same technique as rw semaphores. See
* semaphore.h for details. -ben
*/
-/* the spinlock helpers are in arch/i386/kernel/semaphore.S */
+/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
static inline void read_lock(rwlock_t *rw)
{
diff --git a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
index 7c1a4d109..1dabc1bdf 100644
--- a/include/asm-ia64/hardirq.h
+++ b/include/asm-ia64/hardirq.h
@@ -49,7 +49,7 @@ typedef struct {
#include <asm/smp.h>
extern unsigned int global_irq_holder;
-extern volatile unsigned int global_irq_lock;
+extern volatile unsigned long global_irq_lock;
static inline int irqs_running (void)
{
diff --git a/include/asm-m68k/amigahw.h b/include/asm-m68k/amigahw.h
index d63ceca32..3e5a2770c 100644
--- a/include/asm-m68k/amigahw.h
+++ b/include/asm-m68k/amigahw.h
@@ -16,6 +16,8 @@
#ifndef _M68K_AMIGAHW_H
#define _M68K_AMIGAHW_H
+#include <linux/ioport.h>
+
/*
* Different Amiga models
*/
@@ -279,11 +281,27 @@ struct CIA {
#define ciab ((*(volatile struct CIA *)(zTwoBase + CIAB_PHYSADDR)))
#define CHIP_PHYSADDR (0x000000)
-#define chipaddr ((unsigned long)(zTwoBase + CHIP_PHYSADDR))
+
void amiga_chip_init (void);
-void *amiga_chip_alloc (long size, const char *name);
-void amiga_chip_free (void *);
+void *amiga_chip_alloc(unsigned long size, const char *name);
+void *amiga_chip_alloc_res(unsigned long size, struct resource *res);
+void amiga_chip_free(void *ptr);
unsigned long amiga_chip_avail( void ); /*MILAN*/
+extern volatile unsigned short amiga_audio_min_period;
+
+static inline void amifb_video_off(void)
+{
+ if (amiga_chipset == CS_ECS || amiga_chipset == CS_AGA) {
+ /* program Denise/Lisa for a higher maximum play rate */
+ custom.htotal = 113; /* 31 kHz */
+ custom.vtotal = 223; /* 70 Hz */
+ custom.beamcon0 = 0x4390; /* HARDDIS, VAR{BEAM,VSY,HSY,CSY}EN */
+ /* suspend the monitor */
+ custom.hsstrt = custom.hsstop = 116;
+ custom.vsstrt = custom.vsstop = 226;
+ amiga_audio_min_period = 57;
+ }
+}
struct tod3000 {
unsigned int :28, second2:4; /* lower digit */
diff --git a/include/asm-m68k/amigaints.h b/include/asm-m68k/amigaints.h
index 35bc3e18e..2aff4cfbf 100644
--- a/include/asm-m68k/amigaints.h
+++ b/include/asm-m68k/amigaints.h
@@ -106,12 +106,8 @@
#define IF_DSKBLK 0x0002 /* diskblock DMA finished */
#define IF_TBE 0x0001 /* serial transmit buffer empty interrupt */
-struct irq_server {
- unsigned short count, reentrance;
-};
-
extern void amiga_do_irq(int irq, struct pt_regs *fp);
-extern void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server);
+extern void amiga_do_irq_list(int irq, struct pt_regs *fp);
extern unsigned short amiga_intena_vals[];
diff --git a/include/asm-m68k/amipcmcia.h b/include/asm-m68k/amipcmcia.h
index 78ffce6aa..6f1ec1887 100644
--- a/include/asm-m68k/amipcmcia.h
+++ b/include/asm-m68k/amipcmcia.h
@@ -36,17 +36,17 @@ static inline u_char pcmcia_get_intreq(void)
static inline void pcmcia_ack_int(u_char intreq)
{
- gayle.intreq = ((intreq & 0x2c) ^ 0x2c) | 0xc0;
+ gayle.intreq = 0xf8;
}
static inline void pcmcia_enable_irq(void)
{
- gayle.inten = GAYLE_IRQ_IDE|GAYLE_IRQ_IRQ;
+ gayle.inten |= GAYLE_IRQ_IRQ;
}
static inline void pcmcia_disable_irq(void)
{
- gayle.inten = GAYLE_IRQ_IDE;
+ gayle.inten &= ~GAYLE_IRQ_IRQ;
}
#define PCMCIA_INSERTED (gayle.cardstatus & GAYLE_CS_CCDET)
diff --git a/include/asm-m68k/atari_stram.h b/include/asm-m68k/atari_stram.h
index 31d620b67..7546d1396 100644
--- a/include/asm-m68k/atari_stram.h
+++ b/include/asm-m68k/atari_stram.h
@@ -6,12 +6,12 @@
*/
/* public interface */
-void *atari_stram_alloc( long size, unsigned long *start_mem,
- const char *owner );
-void atari_stram_free( void *);
+void *atari_stram_alloc(long size, const char *owner);
+void atari_stram_free(void *);
/* functions called internally by other parts of the kernel */
-void atari_stram_init( void);
-void atari_stram_reserve_pages( unsigned long start_mem );
+void atari_stram_init(void);
+void atari_stram_reserve_pages(void *start_mem);
+void atari_stram_mem_init_hook (void);
#endif /*_M68K_ATARI_STRAM_H */
diff --git a/include/asm-m68k/atarihw.h b/include/asm-m68k/atarihw.h
index 8937fc2d1..e27147ae8 100644
--- a/include/asm-m68k/atarihw.h
+++ b/include/asm-m68k/atarihw.h
@@ -123,7 +123,7 @@ extern struct atari_hw_present atari_hw_present;
*/
#include <linux/mm.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
static inline void dma_cache_maintenance( unsigned long paddr,
unsigned long len,
diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h
index ff1c8b9fa..7d91887d7 100644
--- a/include/asm-m68k/bitops.h
+++ b/include/asm-m68k/bitops.h
@@ -83,6 +83,12 @@ extern __inline__ int __generic_test_and_clear_bit(int nr, void * vaddr)
return retval;
}
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+#define smp_mb__before_clear_bit() barrier()
+#define smp_mb__after_clear_bit() barrier()
+
#define clear_bit(nr,vaddr) \
(__builtin_constant_p(nr) ? \
__constant_clear_bit(nr, vaddr) : \
diff --git a/include/asm-m68k/entry.h b/include/asm-m68k/entry.h
index 444d5ba35..d5eae1ee1 100644
--- a/include/asm-m68k/entry.h
+++ b/include/asm-m68k/entry.h
@@ -49,13 +49,13 @@
LFLUSH_I_AND_D = 0x00000808
LSIGTRAP = 5
-/* process bits for task_struct.flags */
-PF_TRACESYS_OFF = 3
-PF_TRACESYS_BIT = 5
-PF_PTRACED_OFF = 3
-PF_PTRACED_BIT = 4
-PF_DTRACE_OFF = 1
-PF_DTRACE_BIT = 5
+/* process bits for task_struct.ptrace */
+PT_TRACESYS_OFF = 3
+PT_TRACESYS_BIT = 1
+PT_PTRACED_OFF = 3
+PT_PTRACED_BIT = 0
+PT_DTRACE_OFF = 3
+PT_DTRACE_BIT = 2
#define SAVE_ALL_INT save_all_int
#define SAVE_ALL_SYS save_all_sys
diff --git a/include/asm-m68k/fcntl.h b/include/asm-m68k/fcntl.h
index 9738061b7..c0b273f68 100644
--- a/include/asm-m68k/fcntl.h
+++ b/include/asm-m68k/fcntl.h
@@ -35,6 +35,10 @@
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */
+#define F_GETLK64 12 /* using 'struct flock64' */
+#define F_SETLK64 13
+#define F_SETLKW64 14
+
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
@@ -70,5 +74,13 @@ struct flock {
pid_t l_pid;
};
+struct flock64 {
+ short l_type;
+ short l_whence;
+ loff_t l_start;
+ loff_t l_len;
+ pid_t l_pid;
+};
+
#define F_LINUX_SPECIFIC_BASE 1024
#endif /* _M68K_FCNTL_H */
diff --git a/include/asm-m68k/keyboard.h b/include/asm-m68k/keyboard.h
index 555ef68ec..4129be701 100644
--- a/include/asm-m68k/keyboard.h
+++ b/include/asm-m68k/keyboard.h
@@ -8,12 +8,12 @@
* This file contains the m68k architecture specific keyboard definitions
*/
-#include <linux/config.h> /* CONFIG_MAGIC_SYSRQ */
#ifndef __M68K_KEYBOARD_H
#define __M68K_KEYBOARD_H
#ifdef __KERNEL__
+#include <linux/config.h>
#include <asm/machdep.h>
#ifdef CONFIG_Q40
@@ -39,17 +39,6 @@ static __inline__ int kbd_getkeycode(unsigned int scancode)
return scancode > 127 ? -EINVAL : scancode;
}
-static __inline__ int kbd_translate(unsigned char scancode,
- unsigned char *keycode, char raw_mode)
-{
-#ifdef CONFIG_Q40
- if (MACH_IS_Q40)
- return q40kbd_translate(scancode,keycode,raw_mode);
-#endif
- *keycode = scancode;
- return 1;
-}
-
static __inline__ char kbd_unexpected_up(unsigned char keycode)
{
#ifdef CONFIG_Q40
@@ -65,15 +54,16 @@ static __inline__ void kbd_leds(unsigned char leds)
mach_kbd_leds(leds);
}
-#ifdef CONFIG_MAGIC_SYSRQ
-#define kbd_is_sysrq(keycode) ((keycode) == mach_sysrq_key && \
- (up_flag || \
- (shift_state & mach_sysrq_shift_mask) == \
- mach_sysrq_shift_state))
-#define kbd_sysrq_xlate mach_sysrq_xlate
-#endif
+#define kbd_init_hw mach_keyb_init
+#define kbd_translate mach_kbd_translate
+
+#define kbd_sysrq_xlate mach_sysrq_xlate
+
+/* resource allocation */
+#define kbd_request_region()
+#define kbd_request_irq(handler)
-#define kbd_init_hw mach_keyb_init
+extern unsigned int SYSRQ_KEY;
#endif /* __KERNEL__ */
diff --git a/include/asm-m68k/machdep.h b/include/asm-m68k/machdep.h
index 864f09ecd..269d90b9d 100644
--- a/include/asm-m68k/machdep.h
+++ b/include/asm-m68k/machdep.h
@@ -13,6 +13,7 @@ extern void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *));
extern int (*mach_keyb_init) (void);
extern int (*mach_kbdrate) (struct kbd_repeat *);
extern void (*mach_kbd_leds) (unsigned int);
+extern int (*mach_kbd_translate)(unsigned char scancode, unsigned char *keycode, char raw_mode);
/* machine dependent irq functions */
extern void (*mach_init_IRQ) (void);
extern void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
diff --git a/include/asm-m68k/mman.h b/include/asm-m68k/mman.h
index cbee6c998..8255e9d60 100644
--- a/include/asm-m68k/mman.h
+++ b/include/asm-m68k/mman.h
@@ -25,6 +25,12 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* discard these pages */
+
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
diff --git a/include/asm-m68k/motorola_pgalloc.h b/include/asm-m68k/motorola_pgalloc.h
new file mode 100644
index 000000000..9257aeb43
--- /dev/null
+++ b/include/asm-m68k/motorola_pgalloc.h
@@ -0,0 +1,260 @@
+#ifndef _MOTOROLA_PGALLOC_H
+#define _MOTOROLA_PGALLOC_H
+
+extern struct pgtable_cache_struct {
+ unsigned long *pmd_cache;
+ unsigned long *pte_cache;
+/* This counts in units of pointer tables, of which can be eight per page. */
+ unsigned long pgtable_cache_sz;
+} quicklists;
+
+#define pgd_quicklist ((unsigned long *)0)
+#define pmd_quicklist (quicklists.pmd_cache)
+#define pte_quicklist (quicklists.pte_cache)
+/* This isn't accurate because of fragmentation of allocated pages for
+ pointer tables, but that should not be a problem. */
+#define pgtable_cache_size ((quicklists.pgtable_cache_sz+7)/8)
+
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset);
+extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset);
+
+extern pmd_t *get_pointer_table(void);
+extern int free_pointer_table(pmd_t *);
+
+extern inline pte_t *get_pte_fast(void)
+{
+ unsigned long *ret;
+
+ ret = pte_quicklist;
+ if (ret) {
+ pte_quicklist = (unsigned long *)*ret;
+ ret[0] = 0;
+ quicklists.pgtable_cache_sz -= 8;
+ }
+ return (pte_t *)ret;
+}
+
+extern inline void free_pte_fast(pte_t *pte)
+{
+ *(unsigned long *)pte = (unsigned long)pte_quicklist;
+ pte_quicklist = (unsigned long *)pte;
+ quicklists.pgtable_cache_sz += 8;
+}
+
+extern inline void free_pte_slow(pte_t *pte)
+{
+ cache_page((unsigned long)pte);
+ free_page((unsigned long) pte);
+}
+
+extern inline pmd_t *get_pmd_fast(void)
+{
+ unsigned long *ret;
+
+ ret = pmd_quicklist;
+ if (ret) {
+ pmd_quicklist = (unsigned long *)*ret;
+ ret[0] = 0;
+ quicklists.pgtable_cache_sz--;
+ }
+ return (pmd_t *)ret;
+}
+
+extern inline void free_pmd_fast(pmd_t *pmd)
+{
+ *(unsigned long *)pmd = (unsigned long)pmd_quicklist;
+ pmd_quicklist = (unsigned long *) pmd;
+ quicklists.pgtable_cache_sz++;
+}
+
+extern inline int free_pmd_slow(pmd_t *pmd)
+{
+ return free_pointer_table(pmd);
+}
+
+/* The pgd cache is folded into the pmd cache, so these are dummy routines. */
+extern inline pgd_t *get_pgd_fast(void)
+{
+ return (pgd_t *)0;
+}
+
+extern inline void free_pgd_fast(pgd_t *pgd)
+{
+}
+
+extern inline void free_pgd_slow(pgd_t *pgd)
+{
+}
+
+extern void __bad_pte(pmd_t *pmd);
+extern void __bad_pmd(pgd_t *pgd);
+
+extern inline void pte_free(pte_t *pte)
+{
+ free_pte_fast(pte);
+}
+
+extern inline pte_t *pte_alloc(pmd_t *pmd, unsigned long address)
+{
+ address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+ if (pmd_none(*pmd)) {
+ pte_t *page = get_pte_fast();
+
+ if (!page)
+ return get_pte_slow(pmd, address);
+ pmd_set(pmd,page);
+ return page + address;
+ }
+ if (pmd_bad(*pmd)) {
+ __bad_pte(pmd);
+ return NULL;
+ }
+ return (pte_t *)__pmd_page(*pmd) + address;
+}
+
+extern inline void pmd_free(pmd_t *pmd)
+{
+ free_pmd_fast(pmd);
+}
+
+extern inline pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
+{
+ address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
+ if (pgd_none(*pgd)) {
+ pmd_t *page = get_pmd_fast();
+
+ if (!page)
+ return get_pmd_slow(pgd, address);
+ pgd_set(pgd, page);
+ return page + address;
+ }
+ if (pgd_bad(*pgd)) {
+ __bad_pmd(pgd);
+ return NULL;
+ }
+ return (pmd_t *)__pgd_page(*pgd) + address;
+}
+
+extern inline void pte_free_kernel(pte_t *pte)
+{
+ free_pte_fast(pte);
+}
+
+extern inline pte_t *pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+{
+ return pte_alloc(pmd, address);
+}
+
+extern inline void pmd_free_kernel(pmd_t *pmd)
+{
+ free_pmd_fast(pmd);
+}
+
+extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
+{
+ return pmd_alloc(pgd, address);
+}
+
+extern inline void pgd_free(pgd_t *pgd)
+{
+ free_pmd_fast((pmd_t *)pgd);
+}
+
+extern inline pgd_t *pgd_alloc(void)
+{
+ pgd_t *pgd = (pgd_t *)get_pmd_fast();
+ if (!pgd)
+ pgd = (pgd_t *)get_pointer_table();
+ return pgd;
+}
+
+extern int do_check_pgt_cache(int, int);
+
+extern inline void set_pgdir(unsigned long address, pgd_t entry)
+{
+}
+
+
+/*
+ * flush all user-space atc entries.
+ */
+static inline void __flush_tlb(void)
+{
+ if (CPU_IS_040_OR_060)
+ __asm__ __volatile__(".chip 68040\n\t"
+ "pflushan\n\t"
+ ".chip 68k");
+ else
+ __asm__ __volatile__("pflush #0,#4");
+}
+
+static inline void __flush_tlb040_one(unsigned long addr)
+{
+ __asm__ __volatile__(".chip 68040\n\t"
+ "pflush (%0)\n\t"
+ ".chip 68k"
+ : : "a" (addr));
+}
+
+static inline void __flush_tlb_one(unsigned long addr)
+{
+ if (CPU_IS_040_OR_060)
+ __flush_tlb040_one(addr);
+ else
+ __asm__ __volatile__("pflush #0,#4,(%0)" : : "a" (addr));
+}
+
+#define flush_tlb() __flush_tlb()
+
+/*
+ * flush all atc entries (both kernel and user-space entries).
+ */
+static inline void flush_tlb_all(void)
+{
+ if (CPU_IS_040_OR_060)
+ __asm__ __volatile__(".chip 68040\n\t"
+ "pflusha\n\t"
+ ".chip 68k");
+ else
+ __asm__ __volatile__("pflusha");
+}
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+ if (mm == current->mm)
+ __flush_tlb();
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+ if (vma->vm_mm == current->mm)
+ __flush_tlb_one(addr);
+}
+
+static inline void flush_tlb_range(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+ if (mm == current->mm)
+ __flush_tlb();
+}
+
+extern inline void flush_tlb_kernel_page(unsigned long addr)
+{
+ if (CPU_IS_040_OR_060) {
+ mm_segment_t old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ __asm__ __volatile__(".chip 68040\n\t"
+ "pflush (%0)\n\t"
+ ".chip 68k"
+ : : "a" (addr));
+ set_fs(old_fs);
+ } else
+ __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr));
+}
+
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+}
+
+#endif /* _MOTOROLA_PGALLOC_H */
diff --git a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
new file mode 100644
index 000000000..7fea2e4ff
--- /dev/null
+++ b/include/asm-m68k/motorola_pgtable.h
@@ -0,0 +1,266 @@
+#ifndef _MOTOROLA_PGTABLE_H
+#define _MOTOROLA_PGTABLE_H
+
+#include <linux/config.h>
+
+/*
+ * Definitions for MMU descriptors
+ */
+#define _PAGE_PRESENT 0x001
+#define _PAGE_SHORT 0x002
+#define _PAGE_RONLY 0x004
+#define _PAGE_ACCESSED 0x008
+#define _PAGE_DIRTY 0x010
+#define _PAGE_SUPER 0x080 /* 68040 supervisor only */
+#define _PAGE_FAKE_SUPER 0x200 /* fake supervisor only on 680[23]0 */
+#define _PAGE_GLOBAL040 0x400 /* 68040 global bit, used for kva descs */
+#define _PAGE_COW 0x800 /* implemented in software */
+#define _PAGE_NOCACHE030 0x040 /* 68030 no-cache mode */
+#define _PAGE_NOCACHE 0x060 /* 68040 cache mode, non-serialized */
+#define _PAGE_NOCACHE_S 0x040 /* 68040 no-cache mode, serialized */
+#define _PAGE_CACHE040 0x020 /* 68040 cache mode, cachable, copyback */
+#define _PAGE_CACHE040W 0x000 /* 68040 cache mode, cachable, write-through */
+
+#define _DESCTYPE_MASK 0x003
+
+#define _CACHEMASK040 (~0x060)
+#define _TABLE_MASK (0xfffffe00)
+
+#define _PAGE_TABLE (_PAGE_SHORT)
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NOCACHE)
+
+#ifndef __ASSEMBLY__
+
+/* This is the cache mode to be used for pages containing page descriptors for
+ * processors >= '040. It is in pte_mknocache(), and the variable is defined
+ * and initialized in head.S */
+extern int m68k_pgtable_cachemode;
+
+/* This is the cache mode for normal pages, for supervisor access on
+ * processors >= '040. It is used in pte_mkcache(), and the variable is
+ * defined and initialized in head.S */
+
+#if defined(CONFIG_060_WRITETHROUGH)
+extern int m68k_supervisor_cachemode;
+#else
+#define m68k_supervisor_cachemode _PAGE_CACHE040
+#endif
+
+#if defined(CPU_M68040_OR_M68060_ONLY)
+#define mm_cachebits _PAGE_CACHE040
+#elif defined(CPU_M68020_OR_M68030_ONLY)
+#define mm_cachebits 0
+#else
+extern unsigned long mm_cachebits;
+#endif
+
+#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | mm_cachebits)
+#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED | mm_cachebits)
+
+/* Alternate definitions that are compile time constants, for
+ initializing protection_map. The cachebits are fixed later. */
+#define PAGE_NONE_C __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
+#define PAGE_SHARED_C __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_COPY_C __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
+#define PAGE_READONLY_C __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
+
+/*
+ * The m68k can't do page protection for execute, and considers that the same are read.
+ * Also, write permissions imply read permissions. This is the closest we can get..
+ */
+#define __P000 PAGE_NONE_C
+#define __P001 PAGE_READONLY_C
+#define __P010 PAGE_COPY_C
+#define __P011 PAGE_COPY_C
+#define __P100 PAGE_READONLY_C
+#define __P101 PAGE_READONLY_C
+#define __P110 PAGE_COPY_C
+#define __P111 PAGE_COPY_C
+
+#define __S000 PAGE_NONE_C
+#define __S001 PAGE_READONLY_C
+#define __S010 PAGE_SHARED_C
+#define __S011 PAGE_SHARED_C
+#define __S100 PAGE_READONLY_C
+#define __S101 PAGE_READONLY_C
+#define __S110 PAGE_SHARED_C
+#define __S111 PAGE_SHARED_C
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define __mk_pte(page, pgprot) \
+({ \
+ pte_t __pte; \
+ \
+ pte_val(__pte) = __pa(page) + pgprot_val(pgprot); \
+ __pte; \
+})
+#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot))
+#define mk_pte_phys(physpage, pgprot) \
+({ \
+ pte_t __pte; \
+ \
+ pte_val(__pte) = (physpage) + pgprot_val(pgprot); \
+ __pte; \
+})
+
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+
+extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{
+ unsigned long ptbl = virt_to_phys(ptep) | _PAGE_TABLE | _PAGE_ACCESSED;
+ unsigned long *ptr = pmdp->pmd;
+ short i = 16;
+ while (--i >= 0) {
+ *ptr++ = ptbl;
+ ptbl += (sizeof(pte_t)*PTRS_PER_PTE/16);
+ }
+}
+
+extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
+{ pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | __pa(pmdp); }
+
+#define __pte_page(pte) ((unsigned long)__va(pte_val(pte) & PAGE_MASK))
+#define __pmd_page(pmd) ((unsigned long)__va(pmd_val(pmd) & _TABLE_MASK))
+#define __pgd_page(pgd) ((unsigned long)__va(pgd_val(pgd) & _TABLE_MASK))
+
+
+#define pte_none(pte) (!pte_val(pte))
+#define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_FAKE_SUPER))
+#define pte_clear(ptep) ({ pte_val(*(ptep)) = 0; })
+#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT)
+
+#define pmd_none(pmd) (!pmd_val(pmd))
+#define pmd_bad(pmd) ((pmd_val(pmd) & _DESCTYPE_MASK) != _PAGE_TABLE)
+#define pmd_present(pmd) (pmd_val(pmd) & _PAGE_TABLE)
+#define pmd_clear(pmdp) ({ \
+ unsigned long *__ptr = pmdp->pmd; \
+ short __i = 16; \
+ while (--__i >= 0) \
+ *__ptr++ = 0; \
+})
+
+
+#define pgd_none(pgd) (!pgd_val(pgd))
+#define pgd_bad(pgd) ((pgd_val(pgd) & _DESCTYPE_MASK) != _PAGE_TABLE)
+#define pgd_present(pgd) (pgd_val(pgd) & _PAGE_TABLE)
+#define pgd_clear(pgdp) ({ pgd_val(*pgdp) = 0; })
+/* Permanent address of a page. */
+#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; })
+#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define pte_page(pte) (mem_map+pte_pagenr(pte))
+
+#define pte_ERROR(e) \
+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+extern inline int pte_read(pte_t pte) { return 1; }
+extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_RONLY); }
+extern inline int pte_exec(pte_t pte) { return 1; }
+extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+
+extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_RONLY; return pte; }
+extern inline pte_t pte_rdprotect(pte_t pte) { return pte; }
+extern inline pte_t pte_exprotect(pte_t pte) { return pte; }
+extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_RONLY; return pte; }
+extern inline pte_t pte_mkread(pte_t pte) { return pte; }
+extern inline pte_t pte_mkexec(pte_t pte) { return pte; }
+extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_mknocache(pte_t pte)
+{
+ pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_pgtable_cachemode;
+ return pte;
+}
+extern inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode; return pte; }
+
+#define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
+
+#define pgd_index(address) ((address) >> PGDIR_SHIFT)
+
+/* to find an entry in a page-table-directory */
+extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+{
+ return mm->pgd + pgd_index(address);
+}
+
+#define swapper_pg_dir kernel_pg_dir
+extern pgd_t kernel_pg_dir[128];
+
+extern inline pgd_t * pgd_offset_k(unsigned long address)
+{
+ return kernel_pg_dir + (address >> PGDIR_SHIFT);
+}
+
+
+/* Find an entry in the second-level page table.. */
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+ return (pmd_t *)__pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1));
+}
+
+/* Find an entry in the third-level page table.. */
+extern inline pte_t * pte_offset(pmd_t * pmdp, unsigned long address)
+{
+ return (pte_t *)__pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+}
+
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any.
+ */
+
+/* Prior to calling these routines, the page should have been flushed
+ * from both the cache and ATC, or the CPU might not notice that the
+ * cache setting for the page has been changed. -jskov
+ */
+static inline void nocache_page (unsigned long vaddr)
+{
+ if (CPU_IS_040_OR_060) {
+ pgd_t *dir;
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ dir = pgd_offset_k(vaddr);
+ pmdp = pmd_offset(dir,vaddr);
+ ptep = pte_offset(pmdp,vaddr);
+ *ptep = pte_mknocache(*ptep);
+ }
+}
+
+static inline void cache_page (unsigned long vaddr)
+{
+ if (CPU_IS_040_OR_060) {
+ pgd_t *dir;
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ dir = pgd_offset_k(vaddr);
+ pmdp = pmd_offset(dir,vaddr);
+ ptep = pte_offset(pmdp,vaddr);
+ *ptep = pte_mkcache(*ptep);
+ }
+}
+
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _MOTOROLA_PGTABLE_H */
diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h
index 80e5269a2..40915d41c 100644
--- a/include/asm-m68k/page.h
+++ b/include/asm-m68k/page.h
@@ -160,7 +160,7 @@ static inline void *__va(unsigned long x)
#endif /* CONFIG_SUN3 */
#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
-#define virt_to_page(kaddr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
+#define virt_to_page(kaddr) (mem_map + (((unsigned long)(kaddr)-PAGE_OFFSET) >> PAGE_SHIFT))
#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
#ifndef CONFIG_SUN3
diff --git a/include/asm-m68k/param.h b/include/asm-m68k/param.h
index ffd640baa..7d37eb540 100644
--- a/include/asm-m68k/param.h
+++ b/include/asm-m68k/param.h
@@ -26,4 +26,8 @@
#define MAXHOSTNAMELEN 64 /* max length of hostname */
+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC HZ /* frequency at which times() counts */
+#endif
+
#endif /* _M68K_PARAM_H */
diff --git a/include/asm-m68k/parport.h b/include/asm-m68k/parport.h
new file mode 100644
index 000000000..98a228ac7
--- /dev/null
+++ b/include/asm-m68k/parport.h
@@ -0,0 +1,23 @@
+/*
+ * parport.h: platform-specific PC-style parport initialisation
+ *
+ * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
+ *
+ * This file should only be included by drivers/parport/parport_pc.c.
+ *
+ * RZ: for use with Q40 and other ISA machines
+ */
+
+#ifndef _ASM_M68K_PARPORT_H
+#define _ASM_M68K_PARPORT_H 1
+
+/* no dma, or IRQ autoprobing */
+static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
+static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+{
+ if (! (MACH_IS_Q40))
+ return 0; /* count=0 */
+ return parport_pc_find_isa_ports (PARPORT_IRQ_NONE, PARPORT_DMA_NONE);
+}
+
+#endif /* !(_ASM_M68K_PARPORT_H) */
diff --git a/include/asm-m68k/pgalloc.h b/include/asm-m68k/pgalloc.h
index 028b7c40e..9f307b343 100644
--- a/include/asm-m68k/pgalloc.h
+++ b/include/asm-m68k/pgalloc.h
@@ -1,183 +1,11 @@
-#ifndef _M68K_PGALLOC_H
-#define _M68K_PGALLOC_H
+#ifndef M68K_PGALLOC_H
+#define M68K_PGALLOC_H
+
+#include <linux/config.h>
#include <asm/setup.h>
#include <asm/virtconvert.h>
-extern struct pgtable_cache_struct {
- unsigned long *pmd_cache;
- unsigned long *pte_cache;
-/* This counts in units of pointer tables, of which can be eight per page. */
- unsigned long pgtable_cache_sz;
-} quicklists;
-
-#define pgd_quicklist ((unsigned long *)0)
-#define pmd_quicklist (quicklists.pmd_cache)
-#define pte_quicklist (quicklists.pte_cache)
-/* This isn't accurate because of fragmentation of allocated pages for
- pointer tables, but that should not be a problem. */
-#define pgtable_cache_size ((quicklists.pgtable_cache_sz+7)/8)
-
-extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset);
-extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset);
-
-extern pmd_t *get_pointer_table(void);
-extern int free_pointer_table(pmd_t *);
-
-extern inline pte_t *get_pte_fast(void)
-{
- unsigned long *ret;
-
- ret = pte_quicklist;
- if (ret) {
- pte_quicklist = (unsigned long *)*ret;
- ret[0] = 0;
- quicklists.pgtable_cache_sz -= 8;
- }
- return (pte_t *)ret;
-}
-
-extern inline void free_pte_fast(pte_t *pte)
-{
- *(unsigned long *)pte = (unsigned long)pte_quicklist;
- pte_quicklist = (unsigned long *)pte;
- quicklists.pgtable_cache_sz += 8;
-}
-
-extern inline void free_pte_slow(pte_t *pte)
-{
- cache_page((unsigned long)pte);
- free_page((unsigned long) pte);
-}
-
-extern inline pmd_t *get_pmd_fast(void)
-{
- unsigned long *ret;
-
- ret = pmd_quicklist;
- if (ret) {
- pmd_quicklist = (unsigned long *)*ret;
- ret[0] = 0;
- quicklists.pgtable_cache_sz--;
- }
- return (pmd_t *)ret;
-}
-
-extern inline void free_pmd_fast(pmd_t *pmd)
-{
- *(unsigned long *)pmd = (unsigned long)pmd_quicklist;
- pmd_quicklist = (unsigned long *) pmd;
- quicklists.pgtable_cache_sz++;
-}
-
-extern inline int free_pmd_slow(pmd_t *pmd)
-{
- return free_pointer_table(pmd);
-}
-
-/* The pgd cache is folded into the pmd cache, so these are dummy routines. */
-extern inline pgd_t *get_pgd_fast(void)
-{
- return (pgd_t *)0;
-}
-
-extern inline void free_pgd_fast(pgd_t *pgd)
-{
-}
-
-extern inline void free_pgd_slow(pgd_t *pgd)
-{
-}
-
-extern void __bad_pte(pmd_t *pmd);
-extern void __bad_pmd(pgd_t *pgd);
-
-extern inline void pte_free(pte_t *pte)
-{
- free_pte_fast(pte);
-}
-
-extern inline pte_t *pte_alloc(pmd_t *pmd, unsigned long address)
-{
- address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
- if (pmd_none(*pmd)) {
- pte_t *page = get_pte_fast();
-
- if (!page)
- return get_pte_slow(pmd, address);
- pmd_set(pmd,page);
- return page + address;
- }
- if (pmd_bad(*pmd)) {
- __bad_pte(pmd);
- return NULL;
- }
- return (pte_t *)__pmd_page(*pmd) + address;
-}
-
-extern inline void pmd_free(pmd_t *pmd)
-{
- free_pmd_fast(pmd);
-}
-
-extern inline pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
-{
- address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
- if (pgd_none(*pgd)) {
- pmd_t *page = get_pmd_fast();
-
- if (!page)
- return get_pmd_slow(pgd, address);
- pgd_set(pgd, page);
- return page + address;
- }
- if (pgd_bad(*pgd)) {
- __bad_pmd(pgd);
- return NULL;
- }
- return (pmd_t *)__pgd_page(*pgd) + address;
-}
-
-extern inline void pte_free_kernel(pte_t *pte)
-{
- free_pte_fast(pte);
-}
-
-extern inline pte_t *pte_alloc_kernel(pmd_t *pmd, unsigned long address)
-{
- return pte_alloc(pmd, address);
-}
-
-extern inline void pmd_free_kernel(pmd_t *pmd)
-{
- free_pmd_fast(pmd);
-}
-
-extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
-{
- return pmd_alloc(pgd, address);
-}
-
-extern inline void pgd_free(pgd_t *pgd)
-{
- free_pmd_fast((pmd_t *)pgd);
-}
-
-extern inline pgd_t *pgd_alloc(void)
-{
- pgd_t *pgd = (pgd_t *)get_pmd_fast();
- if (!pgd)
- pgd = (pgd_t *)get_pointer_table();
- return pgd;
-}
-
-extern int do_check_pgt_cache(int, int);
-
-extern inline void set_pgdir(unsigned long address, pgd_t entry)
-{
-}
-
-
/*
* Cache handling functions
*/
@@ -325,82 +153,13 @@ extern inline void flush_icache_range (unsigned long address,
}
}
+#define flush_icache_page(vma,pg) do { } while (0)
-/*
- * flush all user-space atc entries.
- */
-static inline void __flush_tlb(void)
-{
- if (CPU_IS_040_OR_060)
- __asm__ __volatile__(".chip 68040\n\t"
- "pflushan\n\t"
- ".chip 68k");
- else
- __asm__ __volatile__("pflush #0,#4");
-}
-
-static inline void __flush_tlb_one(unsigned long addr)
-{
- if (CPU_IS_040_OR_060) {
- __asm__ __volatile__(".chip 68040\n\t"
- "pflush (%0)\n\t"
- ".chip 68k"
- : : "a" (addr));
- } else
- __asm__ __volatile__("pflush #0,#4,(%0)" : : "a" (addr));
-}
-
-#define flush_tlb() __flush_tlb()
-
-/*
- * flush all atc entries (both kernel and user-space entries).
- */
-static inline void flush_tlb_all(void)
-{
- if (CPU_IS_040_OR_060)
- __asm__ __volatile__(".chip 68040\n\t"
- "pflusha\n\t"
- ".chip 68k");
- else
- __asm__ __volatile__("pflusha");
-}
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
- if (mm == current->mm)
- __flush_tlb();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
-{
- if (vma->vm_mm == current->mm)
- __flush_tlb_one(addr);
-}
-
-static inline void flush_tlb_range(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- if (mm == current->mm)
- __flush_tlb();
-}
-extern inline void flush_tlb_kernel_page(unsigned long addr)
-{
- if (CPU_IS_040_OR_060) {
- mm_segment_t old_fs = get_fs();
- set_fs(KERNEL_DS);
- __asm__ __volatile__(".chip 68040\n\t"
- "pflush (%0)\n\t"
- ".chip 68k"
- : : "a" (addr));
- set_fs(old_fs);
- } else
- __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr));
-}
-
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
-}
+#ifdef CONFIG_SUN3
+#include <asm/sun3_pgalloc.h>
+#else
+#include <asm/motorola_pgalloc.h>
+#endif
-#endif /* _M68K_PGALLOC_H */
+#endif /* M68K_PGALLOC_H */
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 655d604d2..71fd0ae75 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -26,12 +26,20 @@
/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#ifdef CONFIG_SUN3
+#define PMD_SHIFT 17
+#else
#define PMD_SHIFT 22
+#endif
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#ifdef CONFIG_SUN3
+#define PGDIR_SHIFT 17
+#else
#define PGDIR_SHIFT 25
+#endif
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
@@ -39,16 +47,28 @@
* entries per page directory level: the m68k is configured as three-level,
* so we do have PMD level physically.
*/
+#ifdef CONFIG_SUN3
+#define PTRS_PER_PTE 16
+#define PTRS_PER_PMD 1
+#define PTRS_PER_PGD 2048
+#else
#define PTRS_PER_PTE 1024
#define PTRS_PER_PMD 8
#define PTRS_PER_PGD 128
+#endif
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
#define FIRST_USER_PGD_NR 0
/* Virtual address region for use by kernel_map() */
+#ifdef CONFIG_SUN3
+#define KMAP_START 0x0DC00000
+#define KMAP_END 0x0E000000
+#else
#define KMAP_START 0xd0000000
#define KMAP_END 0xf0000000
+#endif
+#ifndef CONFIG_SUN3
/* 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
@@ -60,102 +80,12 @@
#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
#define VMALLOC_END KMAP_START
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * Definitions for MMU descriptors
- */
-#define _PAGE_PRESENT 0x001
-#define _PAGE_SHORT 0x002
-#define _PAGE_RONLY 0x004
-#define _PAGE_ACCESSED 0x008
-#define _PAGE_DIRTY 0x010
-#define _PAGE_SUPER 0x080 /* 68040 supervisor only */
-#define _PAGE_FAKE_SUPER 0x200 /* fake supervisor only on 680[23]0 */
-#define _PAGE_GLOBAL040 0x400 /* 68040 global bit, used for kva descs */
-#define _PAGE_COW 0x800 /* implemented in software */
-#define _PAGE_NOCACHE030 0x040 /* 68030 no-cache mode */
-#define _PAGE_NOCACHE 0x060 /* 68040 cache mode, non-serialized */
-#define _PAGE_NOCACHE_S 0x040 /* 68040 no-cache mode, serialized */
-#define _PAGE_CACHE040 0x020 /* 68040 cache mode, cachable, copyback */
-#define _PAGE_CACHE040W 0x000 /* 68040 cache mode, cachable, write-through */
-
-/* Page protection values within PTE. */
-#define SUN3_PAGE_VALID (0x80000000)
-#define SUN3_PAGE_WRITEABLE (0x40000000)
-#define SUN3_PAGE_SYSTEM (0x20000000)
-#define SUN3_PAGE_NOCACHE (0x10000000)
-#define SUN3_PAGE_ACCESSED (0x02000000)
-#define SUN3_PAGE_MODIFIED (0x01000000)
-
-#define _DESCTYPE_MASK 0x003
-
-#define _CACHEMASK040 (~0x060)
-#define _TABLE_MASK (0xfffffe00)
-
-#define _PAGE_TABLE (_PAGE_SHORT)
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NOCACHE)
-
-#ifndef __ASSEMBLY__
-
-/* This is the cache mode to be used for pages containing page descriptors for
- * processors >= '040. It is in pte_mknocache(), and the variable is defined
- * and initialized in head.S */
-extern int m68k_pgtable_cachemode;
-
-/* This is the cache mode for normal pages, for supervisor access on
- * processors >= '040. It is used in pte_mkcache(), and the variable is
- * defined and initialized in head.S */
-
-#if defined(CONFIG_060_WRITETHROUGH)
-extern int m68k_supervisor_cachemode;
-#else
-#define m68k_supervisor_cachemode _PAGE_CACHE040
-#endif
-
-#if defined(CPU_M68040_OR_M68060_ONLY)
-#define mm_cachebits _PAGE_CACHE040
-#elif defined(CPU_M68020_OR_M68030_ONLY)
-#define mm_cachebits 0
#else
-extern unsigned long mm_cachebits;
-#endif
-
-#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
-#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | mm_cachebits)
-#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
-#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits)
-#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED | mm_cachebits)
-
-/* Alternate definitions that are compile time constants, for
- initializing protection_map. The cachebits are fixed later. */
-#define PAGE_NONE_C __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
-#define PAGE_SHARED_C __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_COPY_C __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
-#define PAGE_READONLY_C __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED)
-
-/*
- * The m68k can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
- */
-#define __P000 PAGE_NONE_C
-#define __P001 PAGE_READONLY_C
-#define __P010 PAGE_COPY_C
-#define __P011 PAGE_COPY_C
-#define __P100 PAGE_READONLY_C
-#define __P101 PAGE_READONLY_C
-#define __P110 PAGE_COPY_C
-#define __P111 PAGE_COPY_C
-
-#define __S000 PAGE_NONE_C
-#define __S001 PAGE_READONLY_C
-#define __S010 PAGE_SHARED_C
-#define __S011 PAGE_SHARED_C
-#define __S100 PAGE_READONLY_C
-#define __S101 PAGE_READONLY_C
-#define __S110 PAGE_SHARED_C
-#define __S111 PAGE_SHARED_C
+extern unsigned long vmalloc_end;
+#define VMALLOC_START 0x0f800000
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END vmalloc_end
+#endif /* CONFIG_SUN3 */
/* zero page used for uninitialized stuff */
extern unsigned long empty_zero_page;
@@ -182,176 +112,7 @@ extern pte_t * __bad_pagetable(void);
/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
/* 64-bit machines, beware! SRB. */
-#define SIZEOF_PTR_LOG2 2
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-#define __mk_pte(page, pgprot) \
-({ \
- pte_t __pte; \
- \
- pte_val(__pte) = __pa((page) + pgprot_val(pgprot); \
- __pte; \
-})
-#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot))
-#define mk_pte_phys(physpage, pgprot) \
-({ \
- pte_t __pte; \
- \
- pte_val(__pte) = (physpage) + pgprot_val(pgprot); \
- __pte; \
-})
-
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
-
-extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
-{
- unsigned long ptbl = virt_to_phys(ptep) | _PAGE_TABLE | _PAGE_ACCESSED;
- unsigned long *ptr = pmdp->pmd;
- short i = 16;
- while (--i >= 0) {
- *ptr++ = ptbl;
- ptbl += (sizeof(pte_t)*PTRS_PER_PTE/16);
- }
-}
-
-extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
-{ pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | __pa(pmdp); }
-
-#define __pte_page(pte) ((unsigned long)__va(pte_val(pte) & PAGE_MASK))
-#define __pmd_page(pmd) ((unsigned long)__va(pmd_val(pmd) & _TABLE_MASK))
-#define __pgd_page(pgd) ((unsigned long)__va(pgd_val(pgd) & _TABLE_MASK))
-
-#define pte_none(pte) (!pte_val(pte))
-#define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_FAKE_SUPER))
-#define pte_clear(ptep) ({ pte_val(*(ptep)) = 0; })
-
-#define pmd_none(pmd) (!pmd_val(pmd))
-#define pmd_bad(pmd) ((pmd_val(pmd) & _DESCTYPE_MASK) != _PAGE_TABLE)
-#define pmd_present(pmd) (pmd_val(pmd) & _PAGE_TABLE)
-#define pmd_clear(pmdp) ({ \
- unsigned long *__ptr = pmdp->pmd; \
- short __i = 16; \
- while (--__i >= 0) \
- *__ptr++ = 0; \
-})
-
-#define pgd_none(pgd) (!pgd_val(pgd))
-#define pgd_bad(pgd) ((pgd_val(pgd) & _DESCTYPE_MASK) != _PAGE_TABLE)
-#define pgd_present(pgd) (pgd_val(pgd) & _PAGE_TABLE)
-#define pgd_clear(pgdp) ({ pgd_val(*pgdp) = 0; })
-
-/* Permanent address of a page. */
-#define page_address(page) ((page)->virtual)
-#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
-#define pte_page(pte) (mem_map+((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT))
-
-#define pte_ERROR(e) \
- printk("%s:%d: bad pte %p(%08lx).\n", __FILE__, __LINE__, &(e), pte_val(e))
-#define pmd_ERROR(e) \
- printk("%s:%d: bad pmd %p(%08lx).\n", __FILE__, __LINE__, &(e), pmd_val(e))
-#define pgd_ERROR(e) \
- printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
-
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-extern inline int pte_read(pte_t pte) { return 1; }
-extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_RONLY); }
-extern inline int pte_exec(pte_t pte) { return 1; }
-extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-
-extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_RONLY; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte) { return pte; }
-extern inline pte_t pte_exprotect(pte_t pte) { return pte; }
-extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_RONLY; return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { return pte; }
-extern inline pte_t pte_mkexec(pte_t pte) { return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mknocache(pte_t pte)
-{
- pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_pgtable_cachemode;
- return pte;
-}
-extern inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode; return pte; }
-
-#define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
-
-#define pgd_index(address) ((address) >> PGDIR_SHIFT)
-
-/* to find an entry in a page-table-directory */
-extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
- return mm->pgd + pgd_index(address);
-}
-
-#define swapper_pg_dir kernel_pg_dir
-extern pgd_t kernel_pg_dir[128];
-
-extern inline pgd_t * pgd_offset_k(unsigned long address)
-{
- return kernel_pg_dir + (address >> PGDIR_SHIFT);
-}
-
-
-/* Find an entry in the second-level page table.. */
-extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
-{
- return (pmd_t *)__pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD-1));
-}
-
-/* Find an entry in the third-level page table.. */
-extern inline pte_t * pte_offset(pmd_t * pmdp, unsigned long address)
-{
- return (pte_t *)__pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
-}
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-
-/* Prior to calling these routines, the page should have been flushed
- * from both the cache and ATC, or the CPU might not notice that the
- * cache setting for the page has been changed. -jskov
- */
-static inline void nocache_page (unsigned long vaddr)
-{
- if (CPU_IS_040_OR_060) {
- pgd_t *dir;
- pmd_t *pmdp;
- pte_t *ptep;
-
- dir = pgd_offset_k(vaddr);
- pmdp = pmd_offset(dir,vaddr);
- ptep = pte_offset(pmdp,vaddr);
- *ptep = pte_mknocache(*ptep);
- }
-}
-
-static inline void cache_page (unsigned long vaddr)
-{
- if (CPU_IS_040_OR_060) {
- pgd_t *dir;
- pmd_t *pmdp;
- pte_t *ptep;
-
- dir = pgd_offset_k(vaddr);
- pmdp = pmd_offset(dir,vaddr);
- ptep = pte_offset(pmdp,vaddr);
- *ptep = pte_mkcache(*ptep);
- }
-}
-
+#define SIZEOF_PTR_LOG2 2
/*
* Check if the addr/len goes up to the end of a physical
@@ -374,13 +135,24 @@ extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);
/*
* The m68k doesn't have any external MMU info: the kernel page
- * tables contain all the necessary information.
+ * tables contain all the necessary information. The Sun3 does, but
+ * they are updated on demand.
*/
extern inline void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t pte)
{
}
+#ifdef CONFIG_SUN3
+/* Macros to (de)construct the fake PTEs representing swap pages. */
+#define SWP_TYPE(x) ((x).val & 0x7F)
+#define SWP_OFFSET(x) (((x).val) >> 7)
+#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) | ((offset) << 7)) })
+#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+#else
+
/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
#define SWP_TYPE(x) (((x).val >> 1) & 0xff)
#define SWP_OFFSET(x) ((x).val >> 10)
@@ -388,7 +160,9 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma,
#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define swp_entry_to_pte(x) ((pte_t) { (x).val })
-#endif /* __ASSEMBLY__ */
+#endif CONFIG_SUN3
+
+#endif /* !__ASSEMBLY__ */
/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
#define PageSkip(page) (0)
@@ -396,6 +170,16 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma,
#define io_remap_page_range remap_page_range
+/* MMU-specific headers */
+
+#ifdef CONFIG_SUN3
+#include <asm/sun3_pgtable.h>
+#else
+#include <asm/motorola_pgtable.h>
+#endif
+
+#ifndef __ASSEMBLY__
#include <asm-generic/pgtable.h>
+#endif /* !__ASSEMBLY__ */
#endif /* _M68K_PGTABLE_H */
diff --git a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h
index 79d81adc2..1bba1277f 100644
--- a/include/asm-m68k/processor.h
+++ b/include/asm-m68k/processor.h
@@ -71,6 +71,8 @@ struct thread_struct {
unsigned short fs; /* saved fs (sfc, dfc) */
unsigned long crp[2]; /* cpu root pointer */
unsigned long esp0; /* points to SR of stack frame */
+ unsigned long faddr; /* info about last fault */
+ int signo, code;
unsigned long fp[8*3];
unsigned long fpcntl[3]; /* fp control regs */
unsigned char fpstate[FPSTATESIZE]; /* floating point state */
@@ -81,7 +83,6 @@ struct thread_struct {
#define INIT_THREAD { \
sizeof(init_stack) + (unsigned long) init_stack, 0, \
PS_S, __KERNEL_DS, \
- {0, 0}, 0, {0,}, {0, 0, 0}, {0,}, \
}
/*
diff --git a/include/asm-m68k/q40_keyboard.h b/include/asm-m68k/q40_keyboard.h
index 9083bc1ec..88993462d 100644
--- a/include/asm-m68k/q40_keyboard.h
+++ b/include/asm-m68k/q40_keyboard.h
@@ -23,7 +23,6 @@ extern int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode);
extern char q40kbd_unexpected_up(unsigned char keycode);
extern void q40kbd_leds(unsigned char leds);
-extern int q40kbd_is_sysrq(unsigned char keycode);
extern void q40kbd_init_hw(void);
extern unsigned char q40kbd_sysrq_xlate[128];
@@ -36,7 +35,6 @@ extern unsigned char q40kbd_sysrq_xlate[128];
#define kbd_unexpected_up q40kbd_unexpected_up
#define kbd_leds q40kbd_leds
#define kbd_init_hw q40kbd_init_hw
-#define kbd_is_sysrq q40kbd_is_sysrq
#define kbd_sysrq_xlate q40kbd_sysrq_xlate
diff --git a/include/asm-m68k/q40_master.h b/include/asm-m68k/q40_master.h
index b7e365b0f..dd34c1b93 100644
--- a/include/asm-m68k/q40_master.h
+++ b/include/asm-m68k/q40_master.h
@@ -3,13 +3,14 @@
* RTC stuff merged for compactnes..
*/
-#if 1
+#ifndef _Q40_MASTER_H
+#define _Q40_MASTER_H
+
+#include <asm/io.h>
+
+
#define q40_master_addr 0xff000000
#define q40_rtc_addr 0xff021ffc
-#else
-extern unsigned long q40_master_addr; /* wherever it is mapped ... */
-extern unsigned long q40_rtc_addr;
-#endif
#define IIRQ_REG 0x0 /* internal IRQ reg */
#define EIRQ_REG 0x4 /* external ... */
@@ -22,7 +23,7 @@ extern unsigned long q40_rtc_addr;
#define KEYBOARD_UNLOCK_REG 0x20 /* clear kb int */
#define SAMPLE_ENABLE_REG 0x14 /* generate SAMPLE ints */
-#define SAMPLE_RATE_REG 0x28
+#define SAMPLE_RATE_REG 0x2c
#define SAMPLE_CLEAR_REG 0x28
#define SAMPLE_LOW 0x00
#define SAMPLE_HIGH 0x01
@@ -34,9 +35,13 @@ extern unsigned long q40_rtc_addr;
#endif
#define EXT_ENABLE_REG 0x10 /* ... rest of the ISA ints ... */
+#if 0
#define master_inb(_reg_) (*(((unsigned char *)q40_master_addr)+_reg_))
#define master_outb(_b_,_reg_) (*(((unsigned char *)q40_master_addr)+_reg_)=(_b_))
-
+#else
+#define master_inb(_reg_) native_inb((unsigned char *)q40_master_addr+_reg_)
+#define master_outb(_b_,_reg_) native_outb(_b_,(unsigned char *)q40_master_addr+_reg_)
+#endif
/* define some Q40 specific ints */
#include "q40ints.h"
@@ -55,21 +60,13 @@ extern unsigned long q40_rtc_addr;
#define RTC_CTRL (*(unsigned char *)(Q40_RTC_BASE-28))
-#if 0
-struct RTC_STRUCT{
- unsigned char bcd_year;
- unsigned char bcd_mth;
- unsigned char bcd_dom;
- unsigned char bcd_dayofweek;
- unsigned char bcd_hr;
- unsigned char bcd_min;
- unsigned char bcd_sec;
- unsigned char ctrl;
-};
-typedef struct RTC_STRUCT *RtcPtr_t;
-#endif
-
-
/* some control bits */
#define RTC_READ 64 /* prepare for reading */
#define RTC_WRITE 128
+
+
+/* misc defs */
+#define DAC_LEFT ((unsigned char *)0xff008000)
+#define DAC_RIGHT ((unsigned char *)0xff008004)
+
+#endif /* _Q40_MASTER_H */
diff --git a/include/asm-m68k/q40ints.h b/include/asm-m68k/q40ints.h
index f5e29c982..8aaca406e 100644
--- a/include/asm-m68k/q40ints.h
+++ b/include/asm-m68k/q40ints.h
@@ -4,7 +4,7 @@
#define Q40_IRQ_MAX (34)
-#define Q40_IRQ_TIMER (34)
+#define Q40_IRQ_SAMPLE (34)
#define Q40_IRQ_KEYBOARD (32)
#define Q40_IRQ_FRAME (33)
diff --git a/include/asm-m68k/siginfo.h b/include/asm-m68k/siginfo.h
index 2a5782905..6b48063af 100644
--- a/include/asm-m68k/siginfo.h
+++ b/include/asm-m68k/siginfo.h
@@ -23,8 +23,9 @@ typedef struct siginfo {
/* kill() */
struct {
- pid_t _pid; /* sender's pid */
- uid_t _uid; /* sender's uid */
+ __kernel_pid_t _pid; /* sender's pid */
+ __kernel_uid_t _uid; /* backwards compatibility */
+ __kernel_uid32_t _uid32; /* sender's uid */
} _kill;
/* POSIX.1b timers */
@@ -35,18 +36,20 @@ typedef struct siginfo {
/* POSIX.1b signals */
struct {
- pid_t _pid; /* sender's pid */
- uid_t _uid; /* sender's uid */
+ __kernel_pid_t _pid; /* sender's pid */
+ __kernel_uid_t _uid; /* backwards compatibility */
sigval_t _sigval;
+ __kernel_uid32_t _uid32; /* sender's uid */
} _rt;
/* SIGCHLD */
struct {
- pid_t _pid; /* which child */
- uid_t _uid; /* sender's uid */
+ __kernel_pid_t _pid; /* which child */
+ __kernel_uid_t _uid; /* backwards compatibility */
int _status; /* exit code */
clock_t _utime;
clock_t _stime;
+ __kernel_uid32_t _uid32; /* sender's uid */
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -62,11 +65,18 @@ typedef struct siginfo {
} _sifields;
} siginfo_t;
+#define UID16_SIGINFO_COMPAT_NEEDED
+
/*
* How these fields are to be accessed.
*/
#define si_pid _sifields._kill._pid
+#ifdef __KERNEL__
+#define si_uid _sifields._kill._uid32
+#define si_uid16 _sifields._kill._uid
+#else
#define si_uid _sifields._kill._uid
+#endif /* __KERNEL__ */
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
diff --git a/include/asm-m68k/softirq.h b/include/asm-m68k/softirq.h
index 89a3e3971..3a346780b 100644
--- a/include/asm-m68k/softirq.h
+++ b/include/asm-m68k/softirq.h
@@ -7,14 +7,12 @@
#include <asm/atomic.h>
-#define local_bh_disable() (local_bh_count(smp_processor_id())++)
-#define local_bh_enable() (local_bh_count(smp_processor_id())--)
+#define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0)
+#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0)
-#define in_softirq() (local_bh_count != 0)
+#define local_bh_disable() cpu_bh_disable(smp_processor_id())
+#define local_bh_enable() cpu_bh_enable(smp_processor_id())
-/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu) (local_bh_count(cpu) ? 0 : (local_bh_count(cpu)=1))
-#define softirq_endlock(cpu) (local_bh_count(cpu) = 0)
-#define synchronize_bh() barrier()
+#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
#endif
diff --git a/include/asm-m68k/spinlock.h b/include/asm-m68k/spinlock.h
index fec148175..20f46e27b 100644
--- a/include/asm-m68k/spinlock.h
+++ b/include/asm-m68k/spinlock.h
@@ -1,6 +1,6 @@
#ifndef __M68K_SPINLOCK_H
#define __M68K_SPINLOCK_H
-#error "m68k doesn't do SMP"
+#error "m68k doesn't do SMP yet"
#endif
diff --git a/include/asm-m68k/stat.h b/include/asm-m68k/stat.h
index 1d5b008e0..81b225ef4 100644
--- a/include/asm-m68k/stat.h
+++ b/include/asm-m68k/stat.h
@@ -44,8 +44,10 @@ struct stat {
struct stat64 {
unsigned char __pad0[6];
unsigned short st_dev;
+ unsigned char __pad1[4];
- unsigned long long st_ino;
+#define STAT64_HAS_BROKEN_ST_INO 1
+ unsigned long __st_ino;
unsigned int st_mode;
unsigned int st_nlink;
@@ -53,14 +55,15 @@ struct stat64 {
unsigned long st_uid;
unsigned long st_gid;
+ unsigned char __pad2[6];
unsigned short st_rdev;
- unsigned char __pad3[10];
+ unsigned char __pad3[4];
long long st_size;
unsigned long st_blksize;
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long __pad4; /* future possible st_blocks high bits */
+ unsigned long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long st_atime;
unsigned long __pad5;
@@ -71,8 +74,7 @@ struct stat64 {
unsigned long st_ctime;
unsigned long __pad7; /* will be high 32 bits of ctime someday */
- unsigned long __unused1;
- unsigned long __unused2;
+ unsigned long long st_ino;
};
#endif /* _M68K_STAT_H */
diff --git a/include/asm-m68k/sun3_pgalloc.h b/include/asm-m68k/sun3_pgalloc.h
new file mode 100644
index 000000000..32a810aa5
--- /dev/null
+++ b/include/asm-m68k/sun3_pgalloc.h
@@ -0,0 +1,274 @@
+/* sun3_pgalloc.h --
+ * reorganization around 2.3.39, routines moved from sun3_pgtable.h
+ *
+ * moved 1/26/2000 Sam Creasey
+ */
+
+#ifndef _SUN3_PGALLOC_H
+#define _SUN3_PGALLOC_H
+
+/* Pagetable caches. */
+//todo: should implement for at least ptes. --m
+#define pgd_quicklist ((unsigned long *) 0)
+#define pmd_quicklist ((unsigned long *) 0)
+#define pte_quicklist ((unsigned long *) 0)
+#define pgtable_cache_size (0L)
+
+/* Allocation and deallocation of various flavours of pagetables. */
+extern inline int free_pmd_fast (pmd_t *pmdp) { return 0; }
+extern inline int free_pmd_slow (pmd_t *pmdp) { return 0; }
+extern inline pmd_t *get_pmd_fast (void) { return (pmd_t *) 0; }
+
+//todo: implement the following properly.
+#define get_pte_fast() ((pte_t *) 0)
+#define get_pte_slow pte_alloc
+#define free_pte_fast(pte)
+#define free_pte_slow pte_free
+
+/* FIXME - when we get this compiling */
+/* erm, now that it's compiling, what do we do with it? */
+#define _KERNPG_TABLE 0
+
+extern inline void pte_free_kernel(pte_t * pte)
+{
+ free_page((unsigned long) pte);
+}
+
+extern const char bad_pmd_string[];
+
+extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+{
+ address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+ if (pmd_none(*pmd)) {
+ pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
+ if (pmd_none(*pmd)) {
+ if (page) {
+ pmd_val(*pmd) = _KERNPG_TABLE + __pa(page);
+ return page + address;
+ }
+ pmd_val(*pmd) = _KERNPG_TABLE + __pa((unsigned long)BAD_PAGETABLE);
+ return NULL;
+ }
+ free_page((unsigned long) page);
+ }
+ if (pmd_bad(*pmd)) {
+ printk(bad_pmd_string, pmd_val(*pmd));
+ printk("at kernel pgd off %08x\n", (unsigned int)pmd);
+ pmd_val(*pmd) = _KERNPG_TABLE + __pa((unsigned long)BAD_PAGETABLE);
+ return NULL;
+ }
+ return (pte_t *) __pmd_page(*pmd) + address;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free_kernel(pmd_t * pmd)
+{
+// pmd_val(*pmd) = 0;
+}
+
+extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
+{
+ return (pmd_t *) pgd;
+}
+
+extern inline void pte_free(pte_t * pte)
+{
+ free_page((unsigned long) pte);
+}
+
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+ address = (address >> (PAGE_SHIFT-2)) & 4*(PTRS_PER_PTE - 1);
+
+repeat:
+ if (pmd_none(*pmd))
+ goto getnew;
+ if (pmd_bad(*pmd))
+ goto fix;
+ return (pte_t *) (__pmd_page(*pmd) + address);
+
+getnew:
+{
+ unsigned long page = __get_free_page(GFP_KERNEL);
+ if (!pmd_none(*pmd))
+ goto freenew;
+ if (!page)
+ goto oom;
+ memset((void *)page, 0, PAGE_SIZE);
+// pmd_val(*pmd) = SUN3_PMD_MAGIC + __pa(page);
+ pmd_val(*pmd) = __pa(page);
+ return (pte_t *) (page + address);
+freenew:
+ free_page(page);
+ goto repeat;
+}
+
+fix:
+ printk(bad_pmd_string, pmd_val(*pmd));
+ printk("in normal pgd offset %08x\n", (unsigned int)pmd);
+oom:
+// pmd_val(*pmd) = SUN3_PMD_MAGIC + __pa(BAD_PAGETABLE);
+ pmd_val(*pmd) = __pa(BAD_PAGETABLE);
+ return NULL;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free(pmd_t * pmd)
+{
+ pmd_val(*pmd) = 0;
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+ return (pmd_t *) pgd;
+}
+
+extern inline void pgd_free(pgd_t * pgd)
+{
+ free_page((unsigned long) pgd);
+}
+
+extern inline pgd_t * pgd_alloc(void)
+{
+ pgd_t *new_pgd;
+
+ new_pgd = (pgd_t *)get_free_page(GFP_KERNEL);
+ memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
+ memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT));
+ return new_pgd;
+}
+
+/* FIXME: the sun3 doesn't have a page table cache!
+ (but the motorola routine should just return 0) */
+
+extern int do_check_pgt_cache(int, int);
+
+extern inline void set_pgdir(unsigned long address, pgd_t entry)
+{
+}
+
+/* Reserved PMEGs. */
+extern char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
+extern unsigned long pmeg_vaddr[SUN3_PMEGS_NUM];
+extern unsigned char pmeg_alloc[SUN3_PMEGS_NUM];
+extern unsigned char pmeg_ctx[SUN3_PMEGS_NUM];
+
+/* Flush all userspace mappings one by one... (why no flush command,
+ sun?) */
+static inline void flush_tlb_all(void)
+{
+ unsigned long addr;
+ unsigned char ctx, oldctx;
+
+ oldctx = sun3_get_context();
+ for(addr = 0x00000000; addr < TASK_SIZE; addr += SUN3_PMEG_SIZE) {
+ for(ctx = 0; ctx < 8; ctx++) {
+ sun3_put_context(ctx);
+ sun3_put_segmap(addr, SUN3_INVALID_PMEG);
+ }
+ }
+
+ sun3_put_context(oldctx);
+ /* erase all of the userspace pmeg maps, we've clobbered them
+ all anyway */
+ for(addr = 0; addr < SUN3_INVALID_PMEG; addr++) {
+ if(pmeg_alloc[addr] == 1) {
+ pmeg_alloc[addr] = 0;
+ pmeg_ctx[addr] = 0;
+ pmeg_vaddr[addr] = 0;
+ }
+ }
+
+}
+
+/* Clear user TLB entries within the context named in mm */
+static inline void flush_tlb_mm (struct mm_struct *mm)
+{
+ unsigned char oldctx;
+ unsigned char seg;
+ unsigned long i;
+
+ oldctx = sun3_get_context();
+ sun3_put_context(mm->context);
+
+ for(i = 0; i < TASK_SIZE; i += SUN3_PMEG_SIZE) {
+ seg = sun3_get_segmap(i);
+ if(seg == SUN3_INVALID_PMEG)
+ continue;
+
+ sun3_put_segmap(i, SUN3_INVALID_PMEG);
+ pmeg_alloc[seg] = 0;
+ pmeg_ctx[seg] = 0;
+ pmeg_vaddr[seg] = 0;
+ }
+
+ sun3_put_context(oldctx);
+
+}
+
+/* Flush a single TLB page. In this case, we're limited to flushing a
+ single PMEG */
+static inline void flush_tlb_page (struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ unsigned char oldctx;
+ unsigned char i;
+
+ oldctx = sun3_get_context();
+ sun3_put_context(vma->vm_mm->context);
+ addr &= ~SUN3_PMEG_MASK;
+ if((i = sun3_get_segmap(addr)) != SUN3_INVALID_PMEG)
+ {
+ pmeg_alloc[i] = 0;
+ pmeg_ctx[i] = 0;
+ pmeg_vaddr[i] = 0;
+ sun3_put_segmap (addr, SUN3_INVALID_PMEG);
+ }
+ sun3_put_context(oldctx);
+
+}
+/* Flush a range of pages from TLB. */
+
+static inline void flush_tlb_range (struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+ unsigned char seg, oldctx;
+
+ start &= ~SUN3_PMEG_MASK;
+
+ oldctx = sun3_get_context();
+ sun3_put_context(mm->context);
+
+ while(start < end)
+ {
+ if((seg = sun3_get_segmap(start)) == SUN3_INVALID_PMEG)
+ goto next;
+ if(pmeg_ctx[seg] == mm->context) {
+ pmeg_alloc[seg] = 0;
+ pmeg_ctx[seg] = 0;
+ pmeg_vaddr[seg] = 0;
+ }
+ sun3_put_segmap(start, SUN3_INVALID_PMEG);
+ next:
+ start += SUN3_PMEG_SIZE;
+ }
+}
+
+/* Flush kernel page from TLB. */
+static inline void flush_tlb_kernel_page (unsigned long addr)
+{
+ sun3_put_segmap (addr & ~(SUN3_PMEG_SIZE - 1), SUN3_INVALID_PMEG);
+}
+
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+}
+
+#endif /* SUN3_PGALLOC_H */
diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
new file mode 100644
index 000000000..ce9e09a2c
--- /dev/null
+++ b/include/asm-m68k/sun3_pgtable.h
@@ -0,0 +1,219 @@
+#ifndef _SUN3_PGTABLE_H
+#define _SUN3_PGTABLE_H
+
+#include <asm/sun3mmu.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/virtconvert.h>
+#include <linux/linkage.h>
+
+/*
+ * This file contains all the things which change drastically for the sun3
+ * pagetable stuff, to avoid making too much of a mess of the generic m68k
+ * `pgtable.h'; this should only be included from the generic file. --m
+ */
+
+/* For virtual address to physical address conversion */
+#define VTOP(addr) __pa(addr)
+#define PTOV(addr) __va(addr)
+
+
+#endif /* !__ASSEMBLY__ */
+
+/* These need to be defined for compatibility although the sun3 doesn't use them */
+#define _PAGE_NOCACHE030 0x040
+#define _CACHEMASK040 (~0x060)
+#define _PAGE_NOCACHE_S 0x040
+
+/* Page protection values within PTE. */
+#define SUN3_PAGE_VALID (0x80000000)
+#define SUN3_PAGE_WRITEABLE (0x40000000)
+#define SUN3_PAGE_SYSTEM (0x20000000)
+#define SUN3_PAGE_NOCACHE (0x10000000)
+#define SUN3_PAGE_ACCESSED (0x02000000)
+#define SUN3_PAGE_MODIFIED (0x01000000)
+
+
+/* Externally used page protection values. */
+#define _PAGE_PRESENT (SUN3_PAGE_VALID)
+#define _PAGE_ACCESSED (SUN3_PAGE_ACCESSED)
+
+/* Compound page protection values. */
+//todo: work out which ones *should* have SUN3_PAGE_NOCACHE and fix...
+// is it just PAGE_KERNEL and PAGE_SHARED?
+#define PAGE_NONE __pgprot(SUN3_PAGE_VALID \
+ | SUN3_PAGE_ACCESSED \
+ | SUN3_PAGE_NOCACHE)
+#define PAGE_SHARED __pgprot(SUN3_PAGE_VALID \
+ | SUN3_PAGE_WRITEABLE \
+ | SUN3_PAGE_ACCESSED \
+ | SUN3_PAGE_NOCACHE)
+#define PAGE_COPY __pgprot(SUN3_PAGE_VALID \
+ | SUN3_PAGE_ACCESSED \
+ | SUN3_PAGE_NOCACHE)
+#define PAGE_READONLY __pgprot(SUN3_PAGE_VALID \
+ | SUN3_PAGE_ACCESSED \
+ | SUN3_PAGE_NOCACHE)
+#define PAGE_KERNEL __pgprot(SUN3_PAGE_VALID \
+ | SUN3_PAGE_WRITEABLE \
+ | SUN3_PAGE_SYSTEM \
+ | SUN3_PAGE_NOCACHE \
+ | SUN3_PAGE_ACCESSED \
+ | SUN3_PAGE_MODIFIED)
+#define PAGE_INIT __pgprot(SUN3_PAGE_VALID \
+ | SUN3_PAGE_WRITEABLE \
+ | SUN3_PAGE_SYSTEM \
+ | SUN3_PAGE_NOCACHE)
+
+/*
+ * Page protections for initialising protection_map. The sun3 has only two
+ * protection settings, valid (implying read and execute) and writeable. These
+ * are as close as we can get...
+ */
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY
+#define __P110 PAGE_COPY
+#define __P111 PAGE_COPY
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED
+
+/* Use these fake page-protections on PMDs. */
+#define SUN3_PMD_VALID (0x00000001)
+#define SUN3_PMD_MASK (0x0000003F)
+#define SUN3_PMD_MAGIC (0x0000002B)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define __mk_pte(page, pgprot) \
+({ pte_t __pte; pte_val(__pte) = (__pa(page) >> PAGE_SHIFT) | pgprot_val(pgprot); __pte; })
+#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot))
+#define mk_pte_phys(physpage, pgprot) \
+({ pte_t __pte; pte_val(__pte) = ((physpage) >> PAGE_SHIFT) | pgprot_val(pgprot); __pte; })
+extern inline pte_t pte_modify (pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & SUN3_PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+
+#define pmd_set(pmdp,ptep) do {} while (0)
+
+extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
+{ pgd_val(*pgdp) = virt_to_phys(pmdp); }
+
+#define __pte_page(pte) \
+((unsigned long) __va ((pte_val (pte) & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT))
+#define __pmd_page(pmd) \
+((unsigned long) __va (pmd_val (pmd) & PAGE_MASK))
+
+extern inline int pte_none (pte_t pte) { return !pte_val (pte); }
+extern inline int pte_present (pte_t pte) { return pte_val (pte) & SUN3_PAGE_VALID; }
+extern inline void pte_clear (pte_t *ptep) { pte_val (*ptep) = 0; }
+
+/* FIXME: this is only a guess */
+#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT)
+/* Permanent address of a page. */
+#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; })
+#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define pte_page(pte) (mem_map+pte_pagenr(pte))
+
+
+extern inline int pmd_none2 (pmd_t *pmd) { return !pmd_val (*pmd); }
+#define pmd_none(pmd) pmd_none2(&(pmd))
+//extern inline int pmd_bad (pmd_t pmd) { return (pmd_val (pmd) & SUN3_PMD_MASK) != SUN3_PMD_MAGIC; }
+extern inline int pmd_bad2 (pmd_t *pmd) { return 0; }
+#define pmd_bad(pmd) pmd_bad2(&(pmd))
+extern inline int pmd_present2 (pmd_t *pmd) { return pmd_val (*pmd) & SUN3_PMD_VALID; }
+#define pmd_present(pmd) pmd_present2(&(pmd))
+extern inline void pmd_clear (pmd_t *pmdp) { pmd_val (*pmdp) = 0; }
+
+extern inline int pgd_none (pgd_t pgd) { return 0; }
+extern inline int pgd_bad (pgd_t pgd) { return 0; }
+extern inline int pgd_present (pgd_t pgd) { return 0; }
+extern inline void pgd_clear (pgd_t *pgdp) {}
+
+
+#define pte_ERROR(e) \
+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not...
+ * [we have the full set here even if they don't change from m68k]
+ */
+extern inline int pte_read(pte_t pte) { return 1; }
+extern inline int pte_write(pte_t pte) { return pte_val(pte) & SUN3_PAGE_WRITEABLE; }
+extern inline int pte_exec(pte_t pte) { return 1; }
+extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & SUN3_PAGE_MODIFIED; }
+extern inline int pte_young(pte_t pte) { return pte_val(pte) & SUN3_PAGE_ACCESSED; }
+
+extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_WRITEABLE; return pte; }
+extern inline pte_t pte_rdprotect(pte_t pte) { return pte; }
+extern inline pte_t pte_exprotect(pte_t pte) { return pte; }
+extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_MODIFIED; return pte; }
+extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~SUN3_PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= SUN3_PAGE_WRITEABLE; return pte; }
+extern inline pte_t pte_mkread(pte_t pte) { return pte; }
+extern inline pte_t pte_mkexec(pte_t pte) { return pte; }
+extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= SUN3_PAGE_MODIFIED; return pte; }
+extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= SUN3_PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_mknocache(pte_t pte) { pte_val(pte) |= SUN3_PAGE_NOCACHE; return pte; }
+// use this version when caches work...
+//extern inline pte_t pte_mkcache(pte_t pte) { pte_val(pte) &= SUN3_PAGE_NOCACHE; return pte; }
+// until then, use:
+extern inline pte_t pte_mkcache(pte_t pte) { return pte; }
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern pgd_t kernel_pg_dir[PTRS_PER_PGD];
+
+/* Find an entry in a pagetable directory. */
+#define pgd_index(address) ((address) >> PGDIR_SHIFT)
+
+#define pgd_offset(mm, address) \
+((mm)->pgd + pgd_index(address))
+
+/* Find an entry in a kernel pagetable directory. */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* Find an entry in the second-level pagetable. */
+extern inline pmd_t *pmd_offset (pgd_t *pgd, unsigned long address)
+{
+ return (pmd_t *) pgd;
+}
+
+/* Find an entry in the third-level pagetable. */
+#define pte_offset(pmd, address) \
+((pte_t *) __pmd_page (*pmd) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1)))
+
+/* Disable caching for page at given kernel virtual address. */
+static inline void nocache_page (unsigned long vaddr)
+{
+ /* Don't think this is required on sun3. --m */
+}
+
+/* Enable caching for page at given kernel virtual address. */
+static inline void cache_page (unsigned long vaddr)
+{
+ /* Don't think this is required on sun3. --m */
+}
+
+
+
+#endif /* !__ASSEMBLY__ */
+#endif /* !_SUN3_PGTABLE_H */
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h
index a33bb7c14..3da1d58d7 100644
--- a/include/asm-m68k/system.h
+++ b/include/asm-m68k/system.h
@@ -3,6 +3,7 @@
#include <linux/config.h> /* get configuration macros */
#include <linux/linkage.h>
+#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/entry.h>
@@ -70,19 +71,23 @@ asmlinkage void resume(void);
#define sti() __sti()
#define save_flags(x) __save_flags(x)
#define restore_flags(x) __restore_flags(x)
-
+#define save_and_cli(flags) do { save_flags(flags); cli(); } while(0)
/*
* Force strict CPU ordering.
* Not really required on m68k...
*/
-#define nop() asm volatile ("nop"::)
-#define mb() asm volatile ("" : : :"memory")
-#define rmb() asm volatile ("" : : :"memory")
-#define wmb() asm volatile ("" : : :"memory")
+#define nop() do { asm volatile ("nop"); barrier(); } while (0)
+#define mb() barrier()
+#define rmb() barrier()
+#define wmb() barrier()
#define set_mb(var, value) do { xchg(&var, value); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+#define smp_mb() barrier()
+#define smp_rmb() barrier()
+#define smp_wmb() barrier()
+
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
#define tas(ptr) (xchg((ptr),1))
diff --git a/include/asm-m68k/types.h b/include/asm-m68k/types.h
index b0ece7bda..45d1588f2 100644
--- a/include/asm-m68k/types.h
+++ b/include/asm-m68k/types.h
@@ -49,6 +49,10 @@ typedef unsigned long long u64;
#define BITS_PER_LONG 32
+/* DMA addresses are 32-bits wide */
+
+typedef u32 dma_addr_t;
+
#endif /* __KERNEL__ */
#endif /* _M68K_TYPES_H */
diff --git a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
index 9b88477aa..4c43eb814 100644
--- a/include/asm-m68k/unistd.h
+++ b/include/asm-m68k/unistd.h
@@ -80,7 +80,7 @@
#define __NR_sigpending 73
#define __NR_sethostname 74
#define __NR_setrlimit 75
-#define __NR_old_getrlimit 76
+#define __NR_getrlimit 76
#define __NR_getrusage 77
#define __NR_gettimeofday 78
#define __NR_settimeofday 79
@@ -170,6 +170,7 @@
#define __NR_mremap 163
#define __NR_setresuid 164
#define __NR_getresuid 165
+#define __NR_getpagesize 166
#define __NR_query_module 167
#define __NR_poll 168
#define __NR_nfsservctl 169
@@ -194,7 +195,7 @@
#define __NR_getpmsg 188 /* some people actually want streams */
#define __NR_putpmsg 189 /* some people actually want streams */
#define __NR_vfork 190
-#define __NR_getrlimit 191
+#define __NR_ugetrlimit 191
#define __NR_mmap2 192
#define __NR_truncate64 193
#define __NR_ftruncate64 194
diff --git a/include/asm-parisc/a.out.h b/include/asm-parisc/a.out.h
new file mode 100644
index 000000000..2a490cc9e
--- /dev/null
+++ b/include/asm-parisc/a.out.h
@@ -0,0 +1,29 @@
+#ifndef __PARISC_A_OUT_H__
+#define __PARISC_A_OUT_H__
+
+struct exec
+{
+ unsigned int a_info; /* Use macros N_MAGIC, etc for access */
+ unsigned a_text; /* length of text, in bytes */
+ unsigned a_data; /* length of data, in bytes */
+ unsigned a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned a_syms; /* length of symbol table data in file, in bytes */
+ unsigned a_entry; /* start address */
+ unsigned a_trsize; /* length of relocation info for text, in bytes */
+ unsigned a_drsize; /* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a) ((a).a_trsize)
+#define N_DRSIZE(a) ((a).a_drsize)
+#define N_SYMSIZE(a) ((a).a_syms)
+
+#ifdef __KERNEL__
+
+/* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc.
+ * prumpf */
+
+#define STACK_TOP TASK_SIZE
+
+#endif
+
+#endif /* __A_OUT_GNU_H__ */
diff --git a/include/asm-parisc/asmregs.h b/include/asm-parisc/asmregs.h
new file mode 100644
index 000000000..d93c646e1
--- /dev/null
+++ b/include/asm-parisc/asmregs.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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 _PARISC_ASMREGS_H
+#define _PARISC_ASMREGS_H
+
+;! General Registers
+
+rp: .reg %r2
+arg3: .reg %r23
+arg2: .reg %r24
+arg1: .reg %r25
+arg0: .reg %r26
+dp: .reg %r27
+ret0: .reg %r28
+ret1: .reg %r29
+sl: .reg %r29
+sp: .reg %r30
+
+#if 0
+/* PA20_REVISIT */
+arg7: .reg r19
+arg6: .reg r20
+arg5: .reg r21
+arg4: .reg r22
+gp: .reg r27
+ap: .reg r29
+#endif
+
+
+r0: .reg %r0
+r1: .reg %r1
+r2: .reg %r2
+r3: .reg %r3
+r4: .reg %r4
+r5: .reg %r5
+r6: .reg %r6
+r7: .reg %r7
+r8: .reg %r8
+r9: .reg %r9
+r10: .reg %r10
+r11: .reg %r11
+r12: .reg %r12
+r13: .reg %r13
+r14: .reg %r14
+r15: .reg %r15
+r16: .reg %r16
+r17: .reg %r17
+r18: .reg %r18
+r19: .reg %r19
+r20: .reg %r20
+r21: .reg %r21
+r22: .reg %r22
+r23: .reg %r23
+r24: .reg %r24
+r25: .reg %r25
+r26: .reg %r26
+r27: .reg %r27
+r28: .reg %r28
+r29: .reg %r29
+r30: .reg %r30
+r31: .reg %r31
+
+
+;! Space Registers
+
+sr0: .reg %sr0
+sr1: .reg %sr1
+sr2: .reg %sr2
+sr3: .reg %sr3
+sr4: .reg %sr4
+sr5: .reg %sr5
+sr6: .reg %sr6
+sr7: .reg %sr7
+
+
+;! Floating Point Registers
+
+fr0: .reg %fr0
+fr1: .reg %fr1
+fr2: .reg %fr2
+fr3: .reg %fr3
+fr4: .reg %fr4
+fr5: .reg %fr5
+fr6: .reg %fr6
+fr7: .reg %fr7
+fr8: .reg %fr8
+fr9: .reg %fr9
+fr10: .reg %fr10
+fr11: .reg %fr11
+fr12: .reg %fr12
+fr13: .reg %fr13
+fr14: .reg %fr14
+fr15: .reg %fr15
+fr16: .reg %fr16
+fr17: .reg %fr17
+fr18: .reg %fr18
+fr19: .reg %fr19
+fr20: .reg %fr20
+fr21: .reg %fr21
+fr22: .reg %fr22
+fr23: .reg %fr23
+fr24: .reg %fr24
+fr25: .reg %fr25
+fr26: .reg %fr26
+fr27: .reg %fr27
+fr28: .reg %fr28
+fr29: .reg %fr29
+fr30: .reg %fr30
+fr31: .reg %fr31
+
+
+;! Control Registers
+
+rctr: .reg %cr0
+pidr1: .reg %cr8
+pidr2: .reg %cr9
+ccr: .reg %cr10
+sar: .reg %cr11
+pidr3: .reg %cr12
+pidr4: .reg %cr13
+iva: .reg %cr14
+eiem: .reg %cr15
+itmr: .reg %cr16
+pcsq: .reg %cr17
+pcoq: .reg %cr18
+iir: .reg %cr19
+isr: .reg %cr20
+ior: .reg %cr21
+ipsw: .reg %cr22
+eirr: .reg %cr23
+tr0: .reg %cr24
+tr1: .reg %cr25
+tr2: .reg %cr26
+tr3: .reg %cr27
+tr4: .reg %cr28
+tr5: .reg %cr29
+tr6: .reg %cr30
+tr7: .reg %cr31
+
+
+cr0: .reg %cr0
+cr8: .reg %cr8
+cr9: .reg %cr9
+cr10: .reg %cr10
+cr11: .reg %cr11
+cr12: .reg %cr12
+cr13: .reg %cr13
+cr14: .reg %cr14
+cr15: .reg %cr15
+cr16: .reg %cr16
+cr17: .reg %cr17
+cr18: .reg %cr18
+cr19: .reg %cr19
+cr20: .reg %cr20
+cr21: .reg %cr21
+cr22: .reg %cr22
+cr23: .reg %cr23
+cr24: .reg %cr24
+cr25: .reg %cr25
+cr26: .reg %cr26
+cr27: .reg %cr27
+cr28: .reg %cr28
+cr29: .reg %cr29
+cr30: .reg %cr30
+cr31: .reg %cr31
+
+#endif
diff --git a/include/asm-parisc/assembly.h b/include/asm-parisc/assembly.h
new file mode 100644
index 000000000..8d60681b2
--- /dev/null
+++ b/include/asm-parisc/assembly.h
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
+ * Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 1999 SuSE GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any 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 _PARISC_ASSEMBLY_H
+#define _PARISC_ASSEMBLY_H
+
+#if defined(__LP64__) && defined(__ASSEMBLY__)
+/* the 64-bit pa gnu assembler unfortunately defaults to .level 1.1 or 2.0 so
+ * work around that for now... */
+ .level 2.0w
+#endif
+
+#include <asm/offset.h>
+#include <asm/page.h>
+
+#include <asm/asmregs.h>
+
+ sp = 30
+ gp = 27
+ ipsw = 22
+
+#if __PAGE_OFFSET == 0xc0000000
+ .macro tophys gr
+ zdep \gr, 31, 30, \gr
+ .endm
+
+ .macro tovirt gr
+ depi 3,1,2,\gr
+ .endm
+#else
+#error unknown __PAGE_OFFSET
+#endif
+
+ .macro delay value
+ ldil L%\value, 1
+ ldo R%\value(1), 1
+ addib,UV,n -1,1,.
+ addib,NUV,n -1,1,.+8
+ nop
+ .endm
+
+ .macro debug value
+ .endm
+
+#ifdef __LP64__
+# define LDIL_FIXUP(reg) depdi 0,31,32,reg
+#else
+# define LDIL_FIXUP(reg)
+#endif
+
+ /* load 32-bit 'value' into 'reg' compensating for the ldil
+ * sign-extension when running in wide mode.
+ * WARNING!! neither 'value' nor 'reg' can be expressions
+ * containing '.'!!!! */
+ .macro load32 value, reg
+ ldil L%\value, \reg
+ ldo R%\value(\reg), \reg
+ LDIL_FIXUP(\reg)
+ .endm
+
+#ifdef __LP64__
+#define LDREG ldd
+#define STREG std
+#define RP_OFFSET 16
+#else
+#define LDREG ldw
+#define STREG stw
+#define RP_OFFSET 20
+#endif
+
+ .macro loadgp
+#ifdef __LP64__
+ ldil L%__gp, %r27
+ ldo R%__gp(%r27), %r27
+ LDIL_FIXUP(%r27)
+#else
+ ldil L%$global$, %r27
+ ldo R%$global$(%r27), %r27
+#endif
+ .endm
+
+#define SAVE_SP(r, where) mfsp r, %r1 ! STREG %r1, where
+#define REST_SP(r, where) LDREG where, %r1 ! mtsp %r1, r
+#define SAVE_CR(r, where) mfctl r, %r1 ! STREG %r1, where
+#define REST_CR(r, where) LDREG where, %r1 ! mtctl %r1, r
+
+ .macro save_general regs
+ STREG %r2, PT_GR2 (\regs)
+ STREG %r3, PT_GR3 (\regs)
+ STREG %r4, PT_GR4 (\regs)
+ STREG %r5, PT_GR5 (\regs)
+ STREG %r6, PT_GR6 (\regs)
+ STREG %r7, PT_GR7 (\regs)
+ STREG %r8, PT_GR8 (\regs)
+ STREG %r9, PT_GR9 (\regs)
+ STREG %r10, PT_GR10(\regs)
+ STREG %r11, PT_GR11(\regs)
+ STREG %r12, PT_GR12(\regs)
+ STREG %r13, PT_GR13(\regs)
+ STREG %r14, PT_GR14(\regs)
+ STREG %r15, PT_GR15(\regs)
+ STREG %r16, PT_GR16(\regs)
+ STREG %r17, PT_GR17(\regs)
+ STREG %r18, PT_GR18(\regs)
+ STREG %r19, PT_GR19(\regs)
+ STREG %r20, PT_GR20(\regs)
+ STREG %r21, PT_GR21(\regs)
+ STREG %r22, PT_GR22(\regs)
+ STREG %r23, PT_GR23(\regs)
+ STREG %r24, PT_GR24(\regs)
+ STREG %r25, PT_GR25(\regs)
+ /* r26 is clobbered by cr19 and assumed to be saved before hand */
+ STREG %r27, PT_GR27(\regs)
+ STREG %r28, PT_GR28(\regs)
+ /* r29 is already saved and points to PT_xxx struct */
+ /* r30 stack pointer saved in get_stack */
+ STREG %r31, PT_GR31(\regs)
+ .endm
+
+ .macro rest_general regs
+ LDREG PT_GR2 (\regs), %r2
+ LDREG PT_GR3 (\regs), %r3
+ LDREG PT_GR4 (\regs), %r4
+ LDREG PT_GR5 (\regs), %r5
+ LDREG PT_GR6 (\regs), %r6
+ LDREG PT_GR7 (\regs), %r7
+ LDREG PT_GR8 (\regs), %r8
+ LDREG PT_GR9 (\regs), %r9
+ LDREG PT_GR10(\regs), %r10
+ LDREG PT_GR11(\regs), %r11
+ LDREG PT_GR12(\regs), %r12
+ LDREG PT_GR13(\regs), %r13
+ LDREG PT_GR14(\regs), %r14
+ LDREG PT_GR15(\regs), %r15
+ LDREG PT_GR16(\regs), %r16
+ LDREG PT_GR17(\regs), %r17
+ LDREG PT_GR18(\regs), %r18
+ LDREG PT_GR19(\regs), %r19
+ LDREG PT_GR20(\regs), %r20
+ LDREG PT_GR21(\regs), %r21
+ LDREG PT_GR22(\regs), %r22
+ LDREG PT_GR23(\regs), %r23
+ LDREG PT_GR24(\regs), %r24
+ LDREG PT_GR25(\regs), %r25
+ LDREG PT_GR26(\regs), %r26
+ LDREG PT_GR27(\regs), %r27
+ LDREG PT_GR28(\regs), %r28
+ /* r30 stack pointer restored in rest_stack */
+ LDREG PT_GR31(\regs), %r31
+ .endm
+
+ .macro save_fp regs
+ fstd,ma %fr0, 8(\regs)
+ fstd,ma %fr1, 8(\regs)
+ fstd,ma %fr2, 8(\regs)
+ fstd,ma %fr3, 8(\regs)
+ fstd,ma %fr4, 8(\regs)
+ fstd,ma %fr5, 8(\regs)
+ fstd,ma %fr6, 8(\regs)
+ fstd,ma %fr7, 8(\regs)
+ fstd,ma %fr8, 8(\regs)
+ fstd,ma %fr9, 8(\regs)
+ fstd,ma %fr10, 8(\regs)
+ fstd,ma %fr11, 8(\regs)
+ fstd,ma %fr12, 8(\regs)
+ fstd,ma %fr13, 8(\regs)
+ fstd,ma %fr14, 8(\regs)
+ fstd,ma %fr15, 8(\regs)
+ fstd,ma %fr16, 8(\regs)
+ fstd,ma %fr17, 8(\regs)
+ fstd,ma %fr18, 8(\regs)
+ fstd,ma %fr19, 8(\regs)
+ fstd,ma %fr20, 8(\regs)
+ fstd,ma %fr21, 8(\regs)
+ fstd,ma %fr22, 8(\regs)
+ fstd,ma %fr23, 8(\regs)
+ fstd,ma %fr24, 8(\regs)
+ fstd,ma %fr25, 8(\regs)
+ fstd,ma %fr26, 8(\regs)
+ fstd,ma %fr27, 8(\regs)
+ fstd,ma %fr28, 8(\regs)
+ fstd,ma %fr29, 8(\regs)
+ fstd,ma %fr30, 8(\regs)
+ fstd %fr31, 0(\regs)
+ .endm
+
+ .macro rest_fp regs
+ fldd 0(\regs), %fr31
+ fldd,mb -8(\regs), %fr30
+ fldd,mb -8(\regs), %fr29
+ fldd,mb -8(\regs), %fr28
+ fldd,mb -8(\regs), %fr27
+ fldd,mb -8(\regs), %fr26
+ fldd,mb -8(\regs), %fr25
+ fldd,mb -8(\regs), %fr24
+ fldd,mb -8(\regs), %fr23
+ fldd,mb -8(\regs), %fr22
+ fldd,mb -8(\regs), %fr21
+ fldd,mb -8(\regs), %fr20
+ fldd,mb -8(\regs), %fr19
+ fldd,mb -8(\regs), %fr18
+ fldd,mb -8(\regs), %fr17
+ fldd,mb -8(\regs), %fr16
+ fldd,mb -8(\regs), %fr15
+ fldd,mb -8(\regs), %fr14
+ fldd,mb -8(\regs), %fr13
+ fldd,mb -8(\regs), %fr12
+ fldd,mb -8(\regs), %fr11
+ fldd,mb -8(\regs), %fr10
+ fldd,mb -8(\regs), %fr9
+ fldd,mb -8(\regs), %fr8
+ fldd,mb -8(\regs), %fr7
+ fldd,mb -8(\regs), %fr6
+ fldd,mb -8(\regs), %fr5
+ fldd,mb -8(\regs), %fr4
+ fldd,mb -8(\regs), %fr3
+ fldd,mb -8(\regs), %fr2
+ fldd,mb -8(\regs), %fr1
+ fldd,mb -8(\regs), %fr0
+ .endm
+
+#ifdef __LP64__
+ .macro callee_save
+ ldo 144(%r30), %r30
+ std %r3, -144(%r30)
+ std %r4, -136(%r30)
+ std %r5, -128(%r30)
+ std %r6, -120(%r30)
+ std %r7, -112(%r30)
+ std %r8, -104(%r30)
+ std %r9, -96(%r30)
+ std %r10, -88(%r30)
+ std %r11, -80(%r30)
+ std %r12, -72(%r30)
+ std %r13, -64(%r30)
+ std %r14, -56(%r30)
+ std %r15, -48(%r30)
+ std %r16, -40(%r30)
+ std %r17, -32(%r30)
+ std %r18, -24(%r30)
+ .endm
+
+ .macro callee_rest
+ ldd -24(%r30), %r18
+ ldd -32(%r30), %r17
+ ldd -40(%r30), %r16
+ ldd -48(%r30), %r15
+ ldd -56(%r30), %r14
+ ldd -64(%r30), %r13
+ ldd -72(%r30), %r12
+ ldd -80(%r30), %r11
+ ldd -88(%r30), %r10
+ ldd -96(%r30), %r9
+ ldd -104(%r30), %r8
+ ldd -112(%r30), %r7
+ ldd -120(%r30), %r6
+ ldd -128(%r30), %r5
+ ldd -136(%r30), %r4
+ ldd -144(%r30), %r3
+ ldo -144(%r30), %r30
+ .endm
+
+#else /* __LP64__ */
+
+ .macro callee_save
+ ldo 128(30), 30
+ stw 3, -128(30)
+ stw 4, -124(30)
+ stw 5, -120(30)
+ stw 6, -116(30)
+ stw 7, -112(30)
+ stw 8, -108(30)
+ stw 9, -104(30)
+ stw 10, -100(30)
+ stw 11, -96(30)
+ stw 12, -92(30)
+ stw 13, -88(30)
+ stw 14, -84(30)
+ stw 15, -80(30)
+ stw 16, -76(30)
+ stw 17, -72(30)
+ stw 18, -68(30)
+ .endm
+
+ .macro callee_rest
+ ldw -68(30), 18
+ ldw -72(30), 17
+ ldw -76(30), 16
+ ldw -80(30), 15
+ ldw -84(30), 14
+ ldw -88(30), 13
+ ldw -92(30), 12
+ ldw -96(30), 11
+ ldw -100(30), 10
+ ldw -104(30), 9
+ ldw -108(30), 8
+ ldw -112(30), 7
+ ldw -116(30), 6
+ ldw -120(30), 5
+ ldw -124(30), 4
+ ldw -128(30), 3
+ ldo -128(30), 30
+ .endm
+#endif /* __LP64__ */
+
+ .macro save_specials regs
+
+ SAVE_SP (%sr0, PT_SR0 (\regs))
+ SAVE_SP (%sr1, PT_SR1 (\regs))
+ SAVE_SP (%sr2, PT_SR2 (\regs))
+ SAVE_SP (%sr3, PT_SR3 (\regs))
+ SAVE_SP (%sr4, PT_SR4 (\regs))
+ SAVE_SP (%sr5, PT_SR5 (\regs))
+ SAVE_SP (%sr6, PT_SR6 (\regs))
+ SAVE_SP (%sr7, PT_SR7 (\regs))
+
+ SAVE_CR (%cr17, PT_IASQ0(\regs))
+ mtctl %r0, %cr17
+ SAVE_CR (%cr17, PT_IASQ1(\regs))
+
+ SAVE_CR (%cr18, PT_IAOQ0(\regs))
+ mtctl %r0, %cr18
+ SAVE_CR (%cr18, PT_IAOQ1(\regs))
+
+ SAVE_CR (%cr11, PT_SAR (\regs))
+ SAVE_CR (%cr22, PT_PSW (\regs))
+ SAVE_CR (%cr19, PT_IIR (\regs))
+ SAVE_CR (%cr28, PT_GR1 (\regs))
+ SAVE_CR (%cr31, PT_GR29 (\regs))
+
+ STREG %r26, PT_GR26 (\regs)
+ mfctl %cr29, %r26
+ .endm
+
+ .macro rest_specials regs
+
+ REST_SP (%sr0, PT_SR0 (\regs))
+ REST_SP (%sr1, PT_SR1 (\regs))
+ REST_SP (%sr2, PT_SR2 (\regs))
+ REST_SP (%sr3, PT_SR3 (\regs))
+ REST_SP (%sr4, PT_SR4 (\regs))
+ REST_SP (%sr5, PT_SR5 (\regs))
+ REST_SP (%sr6, PT_SR6 (\regs))
+ REST_SP (%sr7, PT_SR7 (\regs))
+
+ REST_CR (%cr17, PT_IASQ0(\regs))
+ REST_CR (%cr17, PT_IASQ1(\regs))
+
+ REST_CR (%cr18, PT_IAOQ0(\regs))
+ REST_CR (%cr18, PT_IAOQ1(\regs))
+
+ REST_CR (%cr11, PT_SAR (\regs))
+
+ REST_CR (%cr22, PT_PSW (\regs))
+ .endm
+
+#endif
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h
new file mode 100644
index 000000000..5b374fc1a
--- /dev/null
+++ b/include/asm-parisc/atomic.h
@@ -0,0 +1,103 @@
+#ifndef _ASM_PARISC_ATOMIC_H_
+#define _ASM_PARISC_ATOMIC_H_
+
+#include <linux/config.h>
+#include <asm/system.h>
+
+/* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>. */
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ *
+ * And probably incredibly slow on parisc. OTOH, we don't
+ * have to write any serious assembly. prumpf
+ */
+
+#ifdef CONFIG_SMP
+/* we have an array of spinlocks for our atomic_ts, and a hash function
+ * to get the right index */
+# define ATOMIC_HASH_SIZE 1
+# define ATOMIC_HASH(a) (&__atomic_hash[0])
+
+extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE];
+/* copied from <asm/spinlock.h> and modified */
+# define SPIN_LOCK(x) \
+ do { while(__ldcw(&(x)->lock) == 0); } while(0)
+
+# define SPIN_UNLOCK(x) \
+ do { (x)->lock = 1; } while(0)
+#else
+# define ATOMIC_HASH_SIZE 1
+# define ATOMIC_HASH(a) (0)
+
+/* copied from <linux/spinlock.h> and modified */
+# define SPIN_LOCK(x) (void)(x)
+
+# define SPIN_UNLOCK(x) do { } while(0)
+#endif
+
+/* copied from <linux/spinlock.h> and modified */
+#define SPIN_LOCK_IRQSAVE(lock, flags) do { local_irq_save(flags); SPIN_LOCK(lock); } while (0)
+#define SPIN_UNLOCK_IRQRESTORE(lock, flags) do { SPIN_UNLOCK(lock); local_irq_restore(flags); } while (0)
+
+/* Note that we need not lock read accesses - aligned word writes/reads
+ * are atomic, so a reader never sees unconsistent values.
+ *
+ * Cache-line alignment would conflict with, for example, linux/module.h */
+
+typedef struct {
+ volatile int counter;
+} atomic_t;
+
+/* It's possible to reduce all atomic operations to either
+ * __atomic_add_return, __atomic_set and __atomic_ret (the latter
+ * is there only for consistency). */
+
+static __inline__ int __atomic_add_return(int i, atomic_t *v)
+{
+ int ret;
+ unsigned long flags;
+ SPIN_LOCK_IRQSAVE(ATOMIC_HASH(v), flags);
+
+ ret = (v->counter += i);
+
+ SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(v), flags);
+ return ret;
+}
+
+static __inline__ void __atomic_set(atomic_t *v, int i)
+{
+ unsigned long flags;
+ SPIN_LOCK_IRQSAVE(ATOMIC_HASH(v), flags);
+
+ v->counter = i;
+
+ SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(v), flags);
+}
+
+static __inline__ int __atomic_read(atomic_t *v)
+{
+ return v->counter;
+}
+
+/* exported interface */
+
+#define atomic_add(i,v) ((void)(__atomic_add_return( (i),(v))))
+#define atomic_sub(i,v) ((void)(__atomic_add_return(-(i),(v))))
+#define atomic_inc(v) ((void)(__atomic_add_return( 1,(v))))
+#define atomic_dec(v) ((void)(__atomic_add_return( -1,(v))))
+
+#define atomic_add_return(i,v) (__atomic_add_return( (i),(v)))
+#define atomic_sub_return(i,v) (__atomic_add_return(-(i),(v)))
+#define atomic_inc_return(v) (__atomic_add_return( 1,(v)))
+#define atomic_dec_return(v) (__atomic_add_return( -1,(v)))
+
+#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
+
+#define atomic_set(v,i) (__atomic_set((v),i))
+#define atomic_read(v) (__atomic_read(v))
+
+#define ATOMIC_INIT(i) { (i) }
+
+#endif
diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
new file mode 100644
index 000000000..f3f8e0e5b
--- /dev/null
+++ b/include/asm-parisc/bitops.h
@@ -0,0 +1,247 @@
+#ifndef _PARISC_BITOPS_H
+#define _PARISC_BITOPS_H
+
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+
+#ifdef __LP64__
+# define SHIFT_PER_LONG 6
+#ifndef BITS_PER_LONG
+# define BITS_PER_LONG 64
+#endif
+#else
+# define SHIFT_PER_LONG 5
+#ifndef BITS_PER_LONG
+# define BITS_PER_LONG 32
+#endif
+#endif
+
+#define CHOP_SHIFTCOUNT(x) ((x) & (BITS_PER_LONG - 1))
+
+static __inline__ int test_and_set_bit(int nr, void * address)
+{
+ unsigned long mask;
+ unsigned long *addr = (unsigned long *) address;
+ int oldbit;
+ unsigned long flags;
+
+ addr += (nr >> SHIFT_PER_LONG);
+ SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
+
+ mask = 1L << CHOP_SHIFTCOUNT(nr);
+ oldbit = (*addr & mask) ? 1 : 0;
+ *addr |= mask;
+
+ SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
+
+ return oldbit;
+}
+
+static __inline__ int test_and_clear_bit(int nr, void * address)
+{
+ unsigned long mask;
+ unsigned long *addr = (unsigned long *) address;
+ int oldbit;
+ unsigned long flags;
+
+ addr += (nr >> SHIFT_PER_LONG);
+ SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
+
+ mask = 1L << CHOP_SHIFTCOUNT(nr);
+ oldbit = (*addr & mask) ? 1 : 0;
+ *addr &= ~mask;
+
+ SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
+
+ return oldbit;
+}
+
+static __inline__ int test_and_change_bit(int nr, void * address)
+{
+ unsigned long mask;
+ unsigned long *addr = (unsigned long *) address;
+ int oldbit;
+ unsigned long flags;
+
+ addr += (nr >> SHIFT_PER_LONG);
+ SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
+
+ mask = 1L << CHOP_SHIFTCOUNT(nr);
+ oldbit = (*addr & mask) ? 1 : 0;
+ *addr ^= mask;
+
+ SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
+
+ return oldbit;
+}
+
+/* again, the read-only case doesn't have to do any locking */
+
+static __inline__ int test_bit(int nr, const volatile void *address)
+{
+ unsigned long mask;
+ unsigned long *addr = (unsigned long *) address;
+
+ addr += (nr >> SHIFT_PER_LONG);
+ mask = 1L << CHOP_SHIFTCOUNT(nr);
+
+ return !!(*addr & mask);
+}
+
+/* sparc does this, other arch's don't -- what's the right answer? XXX */
+#define smp_mb__before_clear_bit() do { } while(0)
+#define smp_mb__after_clear_bit() do { } while(0)
+#define set_bit(nr,addr) ((void)test_and_set_bit(nr,addr))
+#define clear_bit(nr,addr) ((void)test_and_clear_bit(nr,addr))
+#define change_bit(nr,addr) ((void)test_and_change_bit(nr,addr))
+
+/* XXX We'd need some binary search here */
+
+extern __inline__ unsigned long ffz(unsigned long word)
+{
+ unsigned long result;
+
+ result = 0;
+ while(word & 1) {
+ result++;
+ word >>= 1;
+ }
+
+ return result;
+}
+
+#ifdef __KERNEL__
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+#define ffs(x) generic_ffs(x)
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
+
+/*
+ * This implementation of find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h.
+ */
+#define find_first_zero_bit(addr, size) \
+ find_next_zero_bit((addr), (size), 0)
+
+static __inline__ unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
+{
+ unsigned long * p = ((unsigned long *) addr) + (offset >> SHIFT_PER_LONG);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= (BITS_PER_LONG-1);
+ if (offset) {
+ tmp = *(p++);
+ tmp |= ~0UL >> (BITS_PER_LONG-offset);
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (~tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
+ }
+ while (size & ~(BITS_PER_LONG -1)) {
+ if (~(tmp = *(p++)))
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+found_first:
+ tmp |= ~0UL << size;
+found_middle:
+ return result + ffz(tmp);
+}
+
+#define _EXT2_HAVE_ASM_BITOPS_
+
+#ifdef __KERNEL__
+/*
+ * test_and_{set,clear}_bit guarantee atomicity without
+ * disabling interrupts.
+ */
+#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr)
+#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr)
+
+#endif /* __KERNEL__ */
+
+static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
+{
+ __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
+
+ return (ADDR[nr >> 3] >> (nr & 7)) & 1;
+}
+
+/*
+ * This implementation of ext2_find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
+ */
+
+#define ext2_find_first_zero_bit(addr, size) \
+ ext2_find_next_zero_bit((addr), (size), 0)
+
+extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
+ unsigned long size, unsigned long offset)
+{
+ unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
+ unsigned int result = offset & ~31UL;
+ unsigned int tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= 31UL;
+ if (offset) {
+ tmp = cpu_to_le32p(p++);
+ tmp |= ~0UL >> (32-offset);
+ if (size < 32)
+ goto found_first;
+ if (tmp != ~0U)
+ goto found_middle;
+ size -= 32;
+ result += 32;
+ }
+ while (size >= 32) {
+ if ((tmp = cpu_to_le32p(p++)) != ~0U)
+ goto found_middle;
+ result += 32;
+ size -= 32;
+ }
+ if (!size)
+ return result;
+ tmp = cpu_to_le32p(p);
+found_first:
+ tmp |= ~0U << size;
+found_middle:
+ return result + ffz(tmp);
+}
+
+/* Bitmap functions for the minix filesystem. */
+#define minix_set_bit(nr,addr) ext2_set_bit(nr,addr)
+#define minix_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
+
+#endif /* _PARISC_BITOPS_H */
diff --git a/include/asm-parisc/bootdata.h b/include/asm-parisc/bootdata.h
new file mode 100644
index 000000000..e4de299b3
--- /dev/null
+++ b/include/asm-parisc/bootdata.h
@@ -0,0 +1,16 @@
+#ifndef _PARISC_BOOTDATA_H
+#define _PARISC_BOOTDATA_H
+
+/* structure given from bootloader... */
+typedef struct {
+ unsigned data_valid_signature,
+ initrd_start,
+ initrd_end;
+ char commandline[1024];
+} bootdata_t;
+
+#define BOOTDATA_DATA_VALID_SIGNATURE 0xC0400000
+
+#define BOOTDATA_PTR ((bootdata_t*) 0xC0400000)
+
+#endif
diff --git a/include/asm-parisc/bugs.h b/include/asm-parisc/bugs.h
new file mode 100644
index 000000000..9e6284342
--- /dev/null
+++ b/include/asm-parisc/bugs.h
@@ -0,0 +1,19 @@
+/*
+ * include/asm-parisc/bugs.h
+ *
+ * Copyright (C) 1999 Mike Shaver
+ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ * void check_bugs(void);
+ */
+
+#include <asm/processor.h>
+
+static inline void check_bugs(void)
+{
+// identify_cpu(&boot_cpu_data);
+}
diff --git a/include/asm-parisc/byteorder.h b/include/asm-parisc/byteorder.h
new file mode 100644
index 000000000..7b3a2ab4c
--- /dev/null
+++ b/include/asm-parisc/byteorder.h
@@ -0,0 +1,75 @@
+#ifndef _PARISC_BYTEORDER_H
+#define _PARISC_BYTEORDER_H
+
+#include <asm/types.h>
+
+#ifdef __GNUC__
+
+static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+{
+ unsigned int temp;
+ __asm__("shd %0, %0, 16, %1\n\t" /* shift abcdabcd -> cdab */
+ "dep %1, 15, 8, %1\n\t" /* deposit cdab -> cbab */
+ "shd %0, %1, 8, %0" /* shift abcdcbab -> dcba */
+ : "=r" (x), "=&r" (temp)
+ : "0" (x));
+ return x;
+}
+
+
+#if BITS_PER_LONG > 32
+/*
+** From "PA-RISC 2.0 Architecture", HP Professional Books.
+** See Appendix I page 8 , "Endian Byte Swapping".
+**
+** Pretty cool algorithm: (* == zero'd bits)
+** PERMH 01234567 -> 67452301 into %0
+** HSHL 67452301 -> 7*5*3*1* into %1
+** HSHR 67452301 -> *6*4*2*0 into %0
+** OR %0 | %1 -> 76543210 into %0 (all done!)
+*/
+static __inline__ __const__ __u64 ___arch__swab64(__u64 x) {
+ __u64 temp;
+ __asm__("permh 3210, %0, %0\n\t"
+ "hshl %0, 8, %1\n\t"
+ "hshr u, %0, 8, %0\n\t"
+ "or %1, %0, %0"
+ : "=r" (x), "=&r" (temp)
+ : "0" (x));
+ return x;
+}
+#define __arch__swab64(x) ___arch__swab64(x)
+#else
+static __inline__ __const__ __u64 ___arch__swab64(__u64 x)
+{
+ __u32 t1 = (__u32) x;
+ __u32 t2 = (__u32) ((x) >> 32);
+ ___arch__swab32(t1);
+ ___arch__swab32(t2);
+ return (((__u64) t1 << 32) + ((__u64) t2));
+}
+#endif
+
+
+static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+ __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */
+ "shd %r0, %0, 8, %0" /* shift 000000ab -> 00ba */
+ : "=r" (x)
+ : "0" (x));
+ return x;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __BYTEORDER_HAS_U64__
+# define __SWAB_64_THRU_32__
+#endif
+
+#endif /* __GNUC__ */
+
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _PARISC_BYTEORDER_H */
diff --git a/include/asm-parisc/cache.h b/include/asm-parisc/cache.h
new file mode 100644
index 000000000..2460121b6
--- /dev/null
+++ b/include/asm-parisc/cache.h
@@ -0,0 +1,58 @@
+/*
+ * include/asm-parisc/cache.h
+ */
+
+#ifndef __ARCH_PARISC_CACHE_H
+#define __ARCH_PARISC_CACHE_H
+
+/*
+** XXX FIXME : L1_CACHE_BYTES (cacheline size) should be a boot time thing.
+**
+** 32-bit on PA2.0 is not covered well by the #ifdef __LP64__ below.
+** PA2.0 processors have 64-byte cachelines.
+**
+** The issue is mostly cacheline ping-ponging on SMP boxes.
+** To avoid this, code should define stuff to be per CPU on cacheline
+** aligned boundaries. This can make a 2x or more difference in perf
+** depending on how badly the thrashing is.
+**
+** We don't need to worry about I/O since all PA2.0 boxes (except T600)
+** are I/O coherent. That means flushing less than you needed to generally
+** doesn't matter - the I/O MMU will read/modify/write the cacheline.
+**
+** (Digression: it is possible to program I/O MMU's to not first read
+** a cacheline for inbound data - ie just grab ownership and start writing.
+** While it improves I/O throughput, you gotta know the device driver
+** is well behaved and can deal with the issues.)
+*/
+#if defined(__LP64__)
+#define L1_CACHE_BYTES 64
+#else
+#define L1_CACHE_BYTES 32
+#endif
+
+#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
+
+#define SMP_CACHE_BYTES L1_CACHE_BYTES
+
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+
+extern void init_cache(void); /* initializes cache-flushing */
+extern void flush_data_cache(void); /* flushes data-cache only */
+extern void flush_instruction_cache(void);/* flushes code-cache only */
+extern void flush_all_caches(void); /* flushes code and data-cache */
+
+extern int get_cache_info(char *);
+
+extern struct pdc_cache_info cache_info;
+
+#define fdce(addr) asm volatile("fdce 0(%0)" : : "r" (addr))
+#define fice(addr) asm volatile("fice 0(%%sr1,%0)" : : "r" (addr))
+
+#define pdtlbe(addr) asm volatile("pdtlbe 0(%%sr1,%0)" : : "r" (addr))
+#define pdtlb_kernel(addr) asm volatile("pdtlb 0(%0)" : : "r" (addr));
+#define pitlbe(addr) asm volatile("pitlbe 0(%%sr1,%0)" : : "r" (addr))
+
+#define kernel_fdc(addr) asm volatile("fdc 0(%%sr0, %0)" : : "r" (addr))
+
+#endif
diff --git a/include/asm-parisc/checksum.h b/include/asm-parisc/checksum.h
new file mode 100644
index 000000000..9088f9795
--- /dev/null
+++ b/include/asm-parisc/checksum.h
@@ -0,0 +1,174 @@
+#ifndef _PARISC_CHECKSUM_H
+#define _PARISC_CHECKSUM_H
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern unsigned int csum_partial(const unsigned char *, int, unsigned int);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+extern unsigned int csum_partial_copy(const char *, char *, int, unsigned int);
+
+/*
+ * the same as csum_partial, but copies from user space
+ *
+ * this is obsolete and will go away.
+ */
+#define csum_partial_copy_fromuser csum_partial_copy
+
+/*
+ * this is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
+
+/*
+ * Note: when you get a NULL pointer exception here this means someone
+ * passed in an incorrect kernel address to one of these functions.
+ *
+ * If you use these functions directly please don't forget the
+ * verify_area().
+ */
+extern __inline__
+unsigned int csum_partial_copy_nocheck (const char *src, char *dst,
+ int len, int sum)
+{
+ return csum_partial_copy (src, dst, len, sum);
+}
+
+/*
+ * Optimized for IP headers, which always checksum on 4 octet boundaries.
+ *
+ * Written by Randolph Chung <tausq@debian.org>
+ */
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+ unsigned int ihl) {
+ unsigned int sum;
+
+
+ __asm__ __volatile__ ("
+ ldws,ma 4(%1), %0
+ addi -4, %2, %2
+ comib,>= 0, %2, 2f
+
+ ldws,ma 4(%1), %%r19
+ add %0, %%r19, %0
+ ldws,ma 4(%1), %%r19
+ addc %0, %%r19, %0
+ ldws,ma 4(%1), %%r19
+ addc %0, %%r19, %0
+1: ldws,ma 4(%1), %%r19
+ addib,<> -1, %2, 1b
+ addc %0, %%r19, %0
+ addc %0, %%r0, %0
+
+ zdepi -1, 31, 16, %%r19
+ and %0, %%r19, %%r20
+ extru %0, 15, 16, %%r21
+ add %%r20, %%r21, %0
+ and %0, %%r19, %%r20
+ extru %0, 15, 16, %%r21
+ add %%r20, %%r21, %0
+ subi -1, %0, %0
+2:
+ "
+ : "=r" (sum), "=r" (iph), "=r" (ihl)
+ : "1" (iph), "2" (ihl)
+ : "r19", "r20", "r21" );
+
+ return(sum);
+}
+
+/*
+ * Fold a partial checksum
+ */
+static inline unsigned int csum_fold(unsigned int sum)
+{
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = (sum & 0xffff) + (sum >> 16);
+ return ~sum;
+}
+
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__("
+ add %1, %0, %0
+ addc %2, %0, %0
+ addc %3, %0, %0
+ addc %%r0, %0, %0 "
+ : "=r" (sum)
+ : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+static inline unsigned short ip_compute_csum(unsigned char * buf, int len) {
+ return csum_fold (csum_partial(buf, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u16 len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ BUG();
+ return csum_fold(sum);
+}
+
+/*
+ * Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ /* code stolen from include/asm-mips64 */
+ sum = csum_partial(src, len, sum);
+
+ if (copy_to_user(dst, src, len)) {
+ *err_ptr = -EFAULT;
+ return -1;
+ }
+
+ return sum;
+}
+
+#endif
+
diff --git a/include/asm-parisc/current.h b/include/asm-parisc/current.h
new file mode 100644
index 000000000..f3452d340
--- /dev/null
+++ b/include/asm-parisc/current.h
@@ -0,0 +1,19 @@
+#ifndef _PARISC_CURRENT_H
+#define _PARISC_CURRENT_H
+
+#include <asm/processor.h>
+
+struct task_struct;
+
+static inline struct task_struct * get_current(void)
+{
+ struct task_struct *current;
+
+ asm("copy 30,%0" : "=r" (current));
+
+ return (struct task_struct *)((long) current & ~(THREAD_SIZE-1));
+}
+
+#define current get_current()
+
+#endif /* !(_PARISC_CURRENT_H) */
diff --git a/include/asm-parisc/delay.h b/include/asm-parisc/delay.h
new file mode 100644
index 000000000..705c4a792
--- /dev/null
+++ b/include/asm-parisc/delay.h
@@ -0,0 +1,45 @@
+#ifndef _PARISC_DELAY_H
+#define _PARISC_DELAY_H
+
+#include <asm/system.h> /* for mfctl() */
+#include <asm/processor.h> /* for boot_cpu_data */
+
+
+/*
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines
+ */
+
+extern unsigned long loops_per_sec;
+
+static __inline__ void __delay(unsigned long loops) {
+ asm volatile(
+ " .balignl 64,0x34000034
+ addib,UV -1,%0,.
+ nop"
+ : "=r" (loops) : "0" (loops));
+}
+
+static __inline__ void __cr16_delay(unsigned long clocks) {
+ unsigned long start;
+
+ /*
+ * Note: Due to unsigned math, cr16 rollovers shouldn't be
+ * a problem here. However, on 32 bit, we need to make sure
+ * we don't pass in too big a value. The current default
+ * value of MAX_UDELAY_MS should help prevent this.
+ */
+
+ start = mfctl(16);
+ while ((mfctl(16) - start) < clocks)
+ ;
+}
+
+static __inline__ void __udelay(unsigned long usecs) {
+ __cr16_delay(usecs * ((unsigned long)boot_cpu_data.cpu_hz / 1000000UL));
+}
+
+#define udelay(n) __udelay(n)
+
+#endif /* defined(_PARISC_DELAY_H) */
diff --git a/include/asm-parisc/div64.h b/include/asm-parisc/div64.h
new file mode 100644
index 000000000..e86e35e8a
--- /dev/null
+++ b/include/asm-parisc/div64.h
@@ -0,0 +1,54 @@
+#ifndef __ASM_PARISC_DIV64
+#define __ASM_PARISC_DIV64
+
+#ifdef __LP64__
+
+/*
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
+ * This is incredibly hard on IA-64 and HPPA
+ */
+
+#define do_div(n,base) \
+({ \
+ int _res; \
+ _res = ((unsigned long) (n)) % (unsigned) (base); \
+ (n) = ((unsigned long) (n)) / (unsigned) (base); \
+ _res; \
+})
+
+#else
+/*
+ * unsigned long long division. Yuck Yuck! What is Linux coming to?
+ * This is 100% disgusting
+ */
+#define do_div(n,base) \
+({ \
+ unsigned long __low, __low2, __high, __rem; \
+ __low = (n) & 0xffffffff; \
+ __high = (n) >> 32; \
+ if (__high) { \
+ __rem = __high % (unsigned long)base; \
+ __high = __high / (unsigned long)base; \
+ __low2 = __low >> 16; \
+ __low2 += __rem << 16; \
+ __rem = __low2 % (unsigned long)base; \
+ __low2 = __low2 / (unsigned long)base; \
+ __low = __low & 0xffff; \
+ __low += __rem << 16; \
+ __rem = __low % (unsigned long)base; \
+ __low = __low / (unsigned long)base; \
+ n = __low + ((long long)__low2 << 16) + \
+ ((long long) __high << 32); \
+ } else { \
+ __rem = __low % (unsigned long)base; \
+ n = (__low / (unsigned long)base); \
+ } \
+ __rem; \
+})
+#endif
+
+#endif
+
diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h
new file mode 100644
index 000000000..c478db079
--- /dev/null
+++ b/include/asm-parisc/elf.h
@@ -0,0 +1,97 @@
+#ifndef __ASMPARISC_ELF_H
+#define __ASMPARISC_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+#define EM_PARISC 15
+
+#define ELF_NGREG 32
+#define ELF_NFPREG 32
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+#define ELF_CORE_COPY_REGS(gregs, regs) \
+ memcpy(gregs, regs, \
+ sizeof(struct pt_regs) < sizeof(elf_gregset_t)? \
+ sizeof(struct pt_regs): sizeof(elf_gregset_t));
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ *
+ * Note that this header file is used by default in fs/binfmt_elf.c. So
+ * the following macros are for the default case. However, for the 64
+ * bit kernel we also support 32 bit parisc binaries. To do that
+ * arch/parisc64/kernel/binfmt_elf32.c defines its own set of these
+ * macros, and then if includes fs/binfmt_elf.c to provide an alternate
+ * elf binary handler for 32 bit binaries (on the 64 bit kernel).
+ */
+
+#ifdef __LP64__
+#define ELF_CLASS ELFCLASS64
+#else
+#define ELF_CLASS ELFCLASS32
+#endif
+
+#define elf_check_arch(x) ((x)->e_machine == EM_PARISC && (x)->e_ident[EI_CLASS] == ELF_CLASS)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_DATA ELFDATA2MSB
+#define ELF_ARCH EM_PARISC
+
+/* %r23 is set by ld.so to a pointer to a function which might be
+ registered using atexit. This provides a mean for the dynamic
+ linker to call DT_FINI functions for shared libraries that have
+ been loaded before the code runs.
+
+ So that we can use the same startup file with static executables,
+ we start programs with a value of 0 to indicate that there is no
+ such function. */
+#define ELF_PLAT_INIT(_r) _r->gr[23] = 0
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk.
+
+ (2 * TASK_SIZE / 3) turns into something undefined when run through a
+ 32 bit preprocessor and in some cases results in the kernel trying to map
+ ld.so to the kernel virtual base. Use a sane value instead. /Jes
+ */
+
+#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000)
+
+/* This yields a mask that user programs can use to figure out what
+ instruction set this CPU supports. This could be done in user space,
+ but it's not easy, and we've already done it here. */
+
+#define ELF_HWCAP 0
+/* (boot_cpu_data.x86_capability) */
+
+/* This yields a string that ld.so will use to load implementation
+ specific libraries for optimization. This is more specific in
+ intent than poking at uname or /proc/cpuinfo.
+
+ For the moment, we have only optimizations for the Intel generations,
+ but that could change... */
+
+#define ELF_PLATFORM ("PARISC\0" /*+((boot_cpu_data.x86-3)*5) */)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex, ibcs2) \
+ current->personality = PER_LINUX
+#endif
+
+#endif
diff --git a/include/asm-parisc/errno.h b/include/asm-parisc/errno.h
new file mode 100644
index 000000000..b7348c553
--- /dev/null
+++ b/include/asm-parisc/errno.h
@@ -0,0 +1,147 @@
+#ifndef _PARISC_ERRNO_H
+#define _PARISC_ERRNO_H
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Arg list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+#define ENOMSG 35 /* No message of desired type */
+#define EIDRM 36 /* Identifier removed */
+#define ECHRNG 37 /* Channel number out of range */
+#define EL2NSYNC 38 /* Level 2 not synchronized */
+#define EL3HLT 39 /* Level 3 halted */
+#define EL3RST 40 /* Level 3 reset */
+#define ELNRNG 41 /* Link number out of range */
+#define EUNATCH 42 /* Protocol driver not attached */
+#define ENOCSI 43 /* No CSI structure available */
+#define EL2HLT 44 /* Level 2 halted */
+#define EDEADLK 45 /* Resource deadlock would occur */
+#define EDEADLOCK EDEADLK
+#define ENOLCK 46 /* No record locks available */
+#define EILSEQ 47 /* Illegal byte sequence */
+
+#define ENONET 50 /* Machine is not on the network */
+#define ENODATA 51 /* No data available */
+#define ETIME 52 /* Timer expired */
+#define ENOSR 53 /* Out of streams resources */
+#define ENOSTR 54 /* Device not a stream */
+#define ENOPKG 55 /* Package not installed */
+
+#define ENOLINK 57 /* Link has been severed */
+#define EADV 58 /* Advertise error */
+#define ESRMNT 59 /* Srmount error */
+#define ECOMM 60 /* Communication error on send */
+#define EPROTO 61 /* Protocol error */
+
+#define EMULTIHOP 64 /* Multihop attempted */
+
+#define EDOTDOT 66 /* RFS specific error */
+#define EBADMSG 67 /* Not a data message */
+#define EUSERS 68 /* Too many users */
+#define EDQUOT 69 /* Quota exceeded */
+#define ESTALE 70 /* Stale NFS file handle */
+#define EREMOTE 71 /* Object is remote */
+#define EOVERFLOW 72 /* Value too large for defined data type */
+
+/* these errnos are defined by Linux but not HPUX. */
+
+#define EBADE 160 /* Invalid exchange */
+#define EBADR 161 /* Invalid request descriptor */
+#define EXFULL 162 /* Exchange full */
+#define ENOANO 163 /* No anode */
+#define EBADRQC 164 /* Invalid request code */
+#define EBADSLT 165 /* Invalid slot */
+#define EBFONT 166 /* Bad font file format */
+#define ENOTUNIQ 167 /* Name not unique on network */
+#define EBADFD 168 /* File descriptor in bad state */
+#define EREMCHG 169 /* Remote address changed */
+#define ELIBACC 170 /* Can not access a needed shared library */
+#define ELIBBAD 171 /* Accessing a corrupted shared library */
+#define ELIBSCN 172 /* .lib section in a.out corrupted */
+#define ELIBMAX 173 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 174 /* Cannot exec a shared library directly */
+#define ERESTART 175 /* Interrupted system call should be restarted */
+#define ESTRPIPE 176 /* Streams pipe error */
+#define EUCLEAN 177 /* Structure needs cleaning */
+#define ENOTNAM 178 /* Not a XENIX named type file */
+#define ENAVAIL 179 /* No XENIX semaphores available */
+#define EISNAM 180 /* Is a named type file */
+#define EREMOTEIO 181 /* Remote I/O error */
+#define ENOMEDIUM 182 /* No medium found */
+#define EMEDIUMTYPE 183 /* Wrong medium type */
+
+/* We now return you to your regularly scheduled HPUX. */
+
+#define ENOSYM 215 /* symbol does not exist in executable */
+#define ENOTSOCK 216 /* Socket operation on non-socket */
+#define EDESTADDRREQ 217 /* Destination address required */
+#define EMSGSIZE 218 /* Message too long */
+#define EPROTOTYPE 219 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 220 /* Protocol not available */
+#define EPROTONOSUPPORT 221 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 222 /* Socket type not supported */
+#define EOPNOTSUPP 223 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 224 /* Protocol family not supported */
+#define EAFNOSUPPORT 225 /* Address family not supported by protocol */
+#define EADDRINUSE 226 /* Address already in use */
+#define EADDRNOTAVAIL 227 /* Cannot assign requested address */
+#define ENETDOWN 228 /* Network is down */
+#define ENETUNREACH 229 /* Network is unreachable */
+#define ENETRESET 230 /* Network dropped connection because of reset */
+#define ECONNABORTED 231 /* Software caused connection abort */
+#define ECONNRESET 232 /* Connection reset by peer */
+#define ENOBUFS 233 /* No buffer space available */
+#define EISCONN 234 /* Transport endpoint is already connected */
+#define ENOTCONN 235 /* Transport endpoint is not connected */
+#define ESHUTDOWN 236 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 237 /* Too many references: cannot splice */
+#define EREFUSED ECONNREFUSED /* for HP's NFS apparently */
+#define ETIMEDOUT 238 /* Connection timed out */
+#define ECONNREFUSED 239 /* Connection refused */
+#define EREMOTERELEASE 240 /* Remote peer released connection */
+#define EHOSTDOWN 241 /* Host is down */
+#define EHOSTUNREACH 242 /* No route to host */
+
+#define EALREADY 244 /* Operation already in progress */
+#define EINPROGRESS 245 /* Operation now in progress */
+#define EWOULDBLOCK 246 /* Operation would block (Linux returns EAGAIN) */
+#define ENOTEMPTY 247 /* Directory not empty */
+#define ENAMETOOLONG 248 /* File name too long */
+#define ELOOP 249 /* Too many symbolic links encountered */
+#define ENOSYS 251 /* Function not implemented */
+
+#define ENOTSUP 252 /* Function not implemented (POSIX.4 / HPUX) */
+#define ECANCELLED 253 /* aio request was canceled before complete (POSIX.4 / HPUX) */
+
+
+#endif
diff --git a/include/asm-parisc/fcntl.h b/include/asm-parisc/fcntl.h
new file mode 100644
index 000000000..94fa13fa5
--- /dev/null
+++ b/include/asm-parisc/fcntl.h
@@ -0,0 +1,90 @@
+#ifndef _PARISC_FCNTL_H
+#define _PARISC_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+ located on an ext2 file system */
+#define O_ACCMODE 00000003
+#define O_RDONLY 00000000
+#define O_WRONLY 00000001
+#define O_RDWR 00000002
+#define O_APPEND 00000010
+#define O_BLKSEEK 00000100 /* HPUX only */
+#define O_CREAT 00000400 /* not fcntl */
+#define O_TRUNC 00001000 /* not fcntl */
+#define O_EXCL 00002000 /* not fcntl */
+#define O_LARGEFILE 00004000
+#define O_SYNC 00100000
+#define O_NONBLOCK 00200004 /* HPUX has separate NDELAY & NONBLOCK */
+#define O_NDELAY O_NONBLOCK
+#define O_NOCTTY 00400000 /* not fcntl */
+#define O_DSYNC 01000000 /* HPUX only */
+#define O_RSYNC 02000000 /* HPUX only */
+
+#define FASYNC 00020000 /* fcntl, for BSD compatibility */
+#define O_DIRECT 00040000 /* direct disk access hint - currently ignored */
+#define O_DIRECTORY 00010000 /* must be a directory */
+#define O_NOFOLLOW 00000200 /* don't follow links */
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get f_flags */
+#define F_SETFD 2 /* set f_flags */
+#define F_GETFL 3 /* more flags (cloexec) */
+#define F_SETFL 4
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+#define F_GETLK64 8
+#define F_SETLK64 9
+#define F_SETLKW64 10
+
+#define F_GETOWN 11 /* for sockets. */
+#define F_SETOWN 12 /* for sockets. */
+#define F_SETSIG 13 /* for sockets. */
+#define F_GETSIG 14 /* for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK 01
+#define F_WRLCK 02
+#define F_UNLCK 03
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+
+/* for leases */
+#define F_INPROGRESS 16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#define LOCK_MAND 32 /* This is a mandatory flock */
+#define LOCK_READ 64 /* ... Which allows concurrent read operations */
+#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
+#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
+
+struct flock {
+ short l_type;
+ short l_whence;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+};
+
+struct flock64 {
+ short l_type;
+ short l_whence;
+ loff_t l_start;
+ loff_t l_len;
+ pid_t l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE 1024
+
+#endif
diff --git a/include/asm-parisc/fixmap.h b/include/asm-parisc/fixmap.h
new file mode 100644
index 000000000..013ea2182
--- /dev/null
+++ b/include/asm-parisc/fixmap.h
@@ -0,0 +1,8 @@
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+#define FIXADDR_TOP (0xffffe000UL)
+#define FIXADDR_SIZE (0 << PAGE_SHIFT)
+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+
+#endif
diff --git a/include/asm-parisc/gsc.h b/include/asm-parisc/gsc.h
new file mode 100644
index 000000000..0cf1e6d68
--- /dev/null
+++ b/include/asm-parisc/gsc.h
@@ -0,0 +1,79 @@
+#ifndef ASM_PARISC_GSC_H
+#define ASM_PARISC_GSC_H
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/hardware.h> /* for struct hp_device */
+
+/*
+ * The convention used for inb/outb etc. is that names starting with
+ * two underscores are the inline versions, names starting with a
+ * single underscore are proper functions, and names starting with a
+ * letter are macros that map in some way to inline or proper function
+ * versions. Not all that pretty, but before you change it, be sure
+ * to convince yourself that it won't break anything (in particular
+ * module support).
+ */
+extern u8 _gsc_readb(void *);
+extern u16 _gsc_readw(void *);
+extern u32 _gsc_readl(void *);
+extern u64 _gsc_readq(void *);
+extern void _gsc_writeb(u8, void *);
+extern void _gsc_writew(u16,void *);
+extern void _gsc_writel(u32,void *);
+extern void _gsc_writeq(u64,void *);
+
+#define gsc_readb(a) _gsc_readb((void *)(a))
+#define gsc_readw(a) _gsc_readw((void *)(a))
+#define gsc_readl(a) _gsc_readl((void *)(a))
+#define gsc_readq(a) _gsc_readq((void *)(a))
+#define gsc_writeb(v,a) _gsc_writeb((v),(void *)(a))
+#define gsc_writew(v,a) _gsc_writew((v),(void *)(a))
+#define gsc_writel(v,a) _gsc_writel((v),(void *)(a))
+#define gsc_writeq(v,a) _gsc_writeq((v),(void *)(a))
+
+struct gsc_dev {
+ struct gsc_bus *bus; /* bus this device is on */
+ struct gsc_dev *next; /* chain of all devices */
+ struct gsc_dev *next_bus; /* chain of all devices on a bus */
+ struct gsc_dev *next_submod; /* chain of all devices on a module */
+
+ unsigned irq; /* irq generated by this device */
+ void *hpa; /* hard physical address */
+
+ u16 hversion;
+ u8 spa; /* SPA requirements */
+ u8 type;
+ u32 sversion;
+};
+
+struct gsc_irq {
+ unsigned long txn_addr; /* IRQ "target" */
+ int txn_data; /* HW "IRQ" */
+ int irq; /* virtual IRQ */
+};
+
+/* PA I/O Architected devices support at least 5 bits in the EIM register. */
+#define GSC_EIM_WIDTH 5
+
+extern int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */
+extern int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */
+
+struct gsc_bus {
+ void *hpa; /* HPA of device 0, function 0 of this bus */
+};
+
+/*
+ * There is one gsc_dev structure for each slot-number/function-number
+ * combination:
+ */
+
+struct gsc_dev *gsc_find_device(u16 hversion, struct gsc_dev *from);
+
+extern void probe_serial_gsc(void);
+
+/* returns a virtual irq for device at dev->hpa (works for all LASI/ASP/WAX) */
+extern int busdevice_alloc_irq( struct hp_device *dev );
+
+#endif /* __KERNEL__ */
+#endif /* LINUX_GSC_H */
diff --git a/include/asm-parisc/hardirq.h b/include/asm-parisc/hardirq.h
new file mode 100644
index 000000000..2c717bfd5
--- /dev/null
+++ b/include/asm-parisc/hardirq.h
@@ -0,0 +1,87 @@
+/* hardirq.h: 32-bit Sparc hard IRQ support.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au)
+ */
+
+#ifndef __PARISC_HARDIRQ_H
+#define __PARISC_HARDIRQ_H
+
+#include <linux/config.h>
+#include <linux/threads.h>
+
+typedef struct {
+ unsigned int __softirq_active;
+ unsigned int __softirq_mask;
+ unsigned int __local_irq_count;
+ unsigned int __local_bh_count;
+ unsigned int __syscall_count;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
+/*
+ * Are we in an interrupt context? Either doing bottom half
+ * or hardware interrupt processing?
+ */
+#define in_interrupt() ({ int __cpu = smp_processor_id(); \
+ (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
+
+#define in_irq() ({ int __cpu = smp_processor_id(); \
+ (local_irq_count(__cpu) != 0); })
+
+#ifndef CONFIG_SMP
+
+#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0)
+#define hardirq_endlock(cpu) do { } while (0)
+
+#define irq_enter(cpu, irq) (local_irq_count(cpu)++)
+#define irq_exit(cpu, irq) (local_irq_count(cpu)--)
+
+#define synchronize_irq() barrier()
+
+#else
+
+#include <asm/atomic.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/smp.h>
+
+extern unsigned char global_irq_holder;
+extern spinlock_t global_irq_lock;
+extern atomic_t global_irq_count;
+
+static inline void release_irqlock(int cpu)
+{
+ /* if we didn't own the irq lock, just ignore.. */
+ if (global_irq_holder == (unsigned char) cpu) {
+ global_irq_holder = NO_PROC_ID;
+ spin_unlock(&global_irq_lock);
+ }
+}
+
+static inline void irq_enter(int cpu)
+{
+ ++local_irq_count(cpu);
+ atomic_inc(&global_irq_count);
+}
+
+static inline void irq_exit(int cpu)
+{
+ atomic_dec(&global_irq_count);
+ --local_irq_count(cpu);
+}
+
+static inline int hardirq_trylock(int cpu)
+{
+ return (! atomic_read(&global_irq_count) &&
+ ! spin_is_locked (&global_irq_lock));
+}
+
+#define hardirq_endlock(cpu) do { } while (0)
+
+extern void synchronize_irq(void);
+
+#endif /* CONFIG_SMP */
+
+#endif /* __PARISC_HARDIRQ_H */
diff --git a/include/asm-parisc/hardware.h b/include/asm-parisc/hardware.h
new file mode 100644
index 000000000..c44e941ad
--- /dev/null
+++ b/include/asm-parisc/hardware.h
@@ -0,0 +1,103 @@
+#ifndef _PARISC_HP_MACHINES_H_
+#define _PARISC_HP_MACHINES_H_
+
+struct hp_hardware {
+ unsigned short hw_type:5; /* HPHW_xxx */
+ unsigned short hversion;
+ unsigned long sversion:28;
+ unsigned short opt;
+ char *name;
+};
+
+struct hp_device {
+ unsigned short hw_type:5; /* HPHW_xxx */
+ unsigned short hversion; /* HP-UX uses hv_model:12 */
+ unsigned int sversion; /* HP-UX uses sv_model:20 sv_opt:8 */
+ unsigned short opt;
+ unsigned int hversion_rev;
+ unsigned int sversion_rev;
+ struct hp_hardware * reference; /* This is a pointer to the
+ reference */
+ unsigned int managed; /* this is if the device has a driver for it */
+ void * hpa;
+
+#ifdef __LP64__
+ /* parms for pdc_pat_cell_module() call */
+ unsigned long pcell_loc; /* Physical Cell location */
+ unsigned long mod_index; /* PAT specific - Misc Module info */
+
+ /* generic info returned from pdc_pat_cell_module() */
+ unsigned long mod_info; /* PAT specific - Misc Module info */
+ unsigned long pmod_loc; /* physical Module location */
+ unsigned long mod_path; /* Module HW path */
+#endif
+};
+
+enum cpu_type {
+ pcx = 0, /* pa7000 pa 1.0 */
+ pcxs = 1, /* pa7000 pa 1.1a */
+ pcxt = 2, /* pa7100 pa 1.1b */
+ pcxt_ = 3, /* pa7200 (t') pa 1.1c */
+ pcxl = 4, /* pa7100lc pa 1.1d */
+ pcxl2 = 5, /* pa7300lc pa 1.1e */
+ pcxu = 6, /* pa8000 pa 2.0 */
+ pcxu_ = 7, /* pa8200 (u+) pa 2.0 */
+ pcxw = 8, /* pa8500 pa 2.0 */
+ pcxw_ = 9 /* pa8600 (w+) pa 2.0 */
+};
+
+extern char *cpu_name_version[][2]; /* mapping from enum cpu_type to strings */
+
+struct pa_iodc_driver {
+ unsigned short hw_type:5; /* HPHW_xxx */
+ unsigned short hversion;
+ unsigned short hversion_rev;
+ unsigned long sversion:28;
+ unsigned short sversion_rev;
+ unsigned short opt;
+ unsigned int check; /* Components that are significant */
+ char *name;
+ char *version;
+ int (* callback)(struct hp_device *d, struct pa_iodc_driver *dri);
+};
+
+#define DRIVER_CHECK_HWTYPE 1
+#define DRIVER_CHECK_HVERSION 2
+#define DRIVER_CHECK_SVERSION 4
+#define DRIVER_CHECK_OPT 8
+/* The following two are useless right now */
+#define DRIVER_CHECK_HVERSION_REV 16
+#define DRIVER_CHECK_SVERSION_REV 32
+#define DRIVER_CHECK_EVERYTHING 63
+
+
+#define HPHW_NPROC 0
+#define HPHW_MEMORY 1
+#define HPHW_B_DMA 2
+#define HPHW_OBSOLETE 3
+#define HPHW_A_DMA 4
+#define HPHW_A_DIRECT 5
+#define HPHW_OTHER 6
+#define HPHW_BCPORT 7
+#define HPHW_CIO 8
+#define HPHW_CONSOLE 9
+#define HPHW_FIO 10
+#define HPHW_BA 11
+#define HPHW_IOA 12
+#define HPHW_BRIDGE 13
+#define HPHW_FABRIC 14
+#define HPHW_FAULTY 31
+
+extern struct hp_hardware hp_hardware_list[];
+
+char *parisc_getHWtype( unsigned short hw_type );
+
+/* Attention: first hversion, then sversion...! */
+char *parisc_getHWdescription( unsigned short hw_type,
+ unsigned long hversion, /* have to be long ! */
+ unsigned long sversion );
+
+enum cpu_type parisc_get_cpu_type( unsigned long hversion );
+
+extern int register_driver(struct pa_iodc_driver *driver);
+#endif
diff --git a/include/asm-parisc/hdreg.h b/include/asm-parisc/hdreg.h
new file mode 100644
index 000000000..629b220f2
--- /dev/null
+++ b/include/asm-parisc/hdreg.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_HDREG_H
+#define _ASM_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif
diff --git a/include/asm-parisc/hil.h b/include/asm-parisc/hil.h
new file mode 100644
index 000000000..9112f9bf5
--- /dev/null
+++ b/include/asm-parisc/hil.h
@@ -0,0 +1,26 @@
+#ifndef _ASM_HIL_H
+#define _ASM_HIL_H
+
+/*
+ * linux/asm-parisc/hil.h
+ *
+ * (c) 1999 Matthew Wilcox
+ */
+
+extern unsigned long hil_base; /* declared in drivers/gsc/hil.c */
+extern unsigned int hil_irq;
+
+#define HILBASE hil_base /* 0xf0821000 (old) or 0xf0201000 (new) */
+#define HIL_DATA 0x800
+#define HIL_CMD 0x801
+
+#define HIL_IRQ hil_irq
+
+#define hil_busy() (gsc_readb(HILBASE + HIL_CMD) & HIL_BUSY)
+#define hil_data_available() (gsc_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
+#define hil_status() (gsc_readb(HILBASE + HIL_CMD))
+#define hil_command(x) do { gsc_writeb((x), HILBASE + HIL_CMD); } while (0)
+#define hil_read_data() (gsc_readb(HILBASE + HIL_DATA))
+#define hil_write_data(x) do { gsc_writeb((x), HILBASE + HIL_DATA); } while (0)
+
+#endif
diff --git a/include/asm-parisc/hw_irq.h b/include/asm-parisc/hw_irq.h
new file mode 100644
index 000000000..f35c91da6
--- /dev/null
+++ b/include/asm-parisc/hw_irq.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_HW_IRQ_H
+#define _ASM_HW_IRQ_H
+
+/*
+ * linux/include/asm/hw_irq.h
+ *
+ * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
+ *
+ * moved some of the old arch/i386/kernel/irq.h to here. VY
+ *
+ * IRQ/IPI changes taken from work by Thomas Radke
+ * <tomsoft@informatik.tu-chemnitz.de>
+ */
+
+#include <asm/irq.h>
+
+#endif
diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
new file mode 100644
index 000000000..08d1c9408
--- /dev/null
+++ b/include/asm-parisc/ide.h
@@ -0,0 +1,111 @@
+/*
+ * linux/include/asm-parisc/ide.h
+ *
+ * Copyright (C) 1994-1996 Linus Torvalds & authors
+ */
+
+/*
+ * This file contains the i386 architecture specific IDE code.
+ */
+
+#ifndef __ASMi386_IDE_H
+#define __ASMi386_IDE_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#ifndef MAX_HWIFS
+#define MAX_HWIFS 10
+#endif
+
+#define ide__sti() __sti()
+
+static __inline__ int ide_default_irq(ide_ioreg_t base)
+{
+ switch (base) {
+ case 0x1f0: return 14;
+ case 0x170: return 15;
+ case 0x1e8: return 11;
+ case 0x168: return 10;
+ case 0x1e0: return 8;
+ case 0x160: return 12;
+ default:
+ return 0;
+ }
+}
+
+static __inline__ ide_ioreg_t ide_default_io_base(int index)
+{
+ switch (index) {
+ case 0: return 0x1f0;
+ case 1: return 0x170;
+ case 2: return 0x1e8;
+ case 3: return 0x168;
+ case 4: return 0x1e0;
+ case 5: return 0x160;
+ default:
+ return 0;
+ }
+}
+
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+{
+ ide_ioreg_t reg = data_port;
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg;
+ reg += 1;
+ }
+ if (ctrl_port) {
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ } else {
+ hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+ }
+ if (irq != NULL)
+ *irq = 0;
+}
+
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifndef CONFIG_BLK_DEV_IDEPCI
+ hw_regs_t hw;
+ int index;
+
+ for(index = 0; index < MAX_HWIFS; index++) {
+ ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+ hw.irq = ide_default_irq(ide_default_io_base(index));
+ ide_register_hw(&hw, NULL);
+ }
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+}
+
+typedef union {
+ unsigned all : 8; /* all of the bits together */
+ struct {
+ unsigned head : 4; /* always zeros here */
+ unsigned unit : 1; /* drive select number, 0 or 1 */
+ unsigned bit5 : 1; /* always 1 */
+ unsigned lba : 1; /* using LBA instead of CHS */
+ unsigned bit7 : 1; /* always 1 */
+ } b;
+ } select_t;
+
+#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
+#define ide_check_region(from,extent) check_region((from), (extent))
+#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
+#define ide_release_region(from,extent) release_region((from), (extent))
+
+/*
+ * The following are not needed for the non-m68k ports
+ */
+#define ide_ack_intr(hwif) (1)
+#define ide_fix_driveid(id) do {} while (0)
+#define ide_release_lock(lock) do {} while (0)
+#define ide_get_lock(lock, hdlr, data) do {} while (0)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASMi386_IDE_H */
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
new file mode 100644
index 000000000..ca40fdf2d
--- /dev/null
+++ b/include/asm-parisc/io.h
@@ -0,0 +1,61 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/gsc.h>
+
+#define virt_to_phys(a) ((unsigned long)__pa(a))
+#define phys_to_virt(a) __va(a)
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+#define inb_p inb
+#define inw_p inw
+#define inl_p inl
+#define outb_p outb
+#define outw_p outw
+#define outl_p outl
+
+#define readb gsc_readb
+#define readw gsc_readw
+#define readl gsc_readl
+#define writeb gsc_writeb
+#define writew gsc_writew
+#define writel gsc_writel
+
+
+#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+/*
+ * So we get clear link errors
+ */
+extern u8 inb(unsigned long addr);
+extern u16 inw(unsigned long addr);
+extern u32 inl(unsigned long addr);
+
+extern void outb(unsigned char b, unsigned long addr);
+extern void outw(unsigned short b, unsigned long addr);
+extern void outl(u32 b, unsigned long addr);
+
+static inline void memcpy_toio(void *dest, void *src, int count)
+{
+ while(count--)
+ writeb(*((char *)src)++, (char *)dest++);
+}
+
+#endif
+
+/* IO Port space is : BBiiii where BB is HBA number. */
+#define IO_SPACE_LIMIT 0x00ffffff
+
+/* Right now we don't support Dino-on-a-card and V class which do PCI MMIO
+ * through address/data registers. */
+
+#define ioremap(__offset, __size) ((void *)(__offset))
+#define iounmap(__addr)
+
+#define dma_cache_inv(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while(0)
+#define dma_cache_wback(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0)
+#define dma_cache_wback_inv(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0)
+
+#endif
diff --git a/include/asm-parisc/ioctl.h b/include/asm-parisc/ioctl.h
new file mode 100644
index 000000000..ff78546f6
--- /dev/null
+++ b/include/asm-parisc/ioctl.h
@@ -0,0 +1,67 @@
+/* $Id: ioctl.h,v 1.2 1999/12/29 22:18:15 willy Exp $
+ *
+ * linux/ioctl.h for Linux by H.H. Bergman.
+ */
+
+#ifndef _ASM_PARISC_IOCTL_H
+#define _ASM_PARISC_IOCTL_H
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+#define _IOC_NRBITS 8
+#define _IOC_TYPEBITS 8
+#define _IOC_SIZEBITS 14
+#define _IOC_DIRBITS 2
+
+#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT 0
+#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE 0U
+#define _IOC_WRITE 2U
+#define _IOC_READ 1U
+
+#define _IOC(dir,type,nr,size) \
+ (((dir) << _IOC_DIRSHIFT) | \
+ ((type) << _IOC_TYPESHIFT) | \
+ ((nr) << _IOC_NRSHIFT) | \
+ ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
+
+#endif /* _ASM_PARISC_IOCTL_H */
diff --git a/include/asm-parisc/ioctls.h b/include/asm-parisc/ioctls.h
new file mode 100644
index 000000000..332027f38
--- /dev/null
+++ b/include/asm-parisc/ioctls.h
@@ -0,0 +1,82 @@
+#ifndef __ARCH_PARISC_IOCTLS_H__
+#define __ARCH_PARISC_IOCTLS_H__
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS _IOR('T', 16, struct termios) /* TCGETATTR */
+#define TCSETS _IOW('T', 17, struct termios) /* TCSETATTR */
+#define TCSETSW _IOW('T', 18, struct termios) /* TCSETATTRD */
+#define TCSETSF _IOW('T', 19, struct termios) /* TCSETATTRF */
+#define TCGETA _IOR('T', 1, struct termio)
+#define TCSETA _IOW('T', 2, struct termio)
+#define TCSETAW _IOW('T', 3, struct termio)
+#define TCSETAF _IOW('T', 4, struct termio)
+#define TCSBRK _IO('T', 5)
+#define TCXONC _IO('T', 6)
+#define TCFLSH _IO('T', 7)
+#define TIOCEXCL 0x540C
+#define TIOCNXCL 0x540D
+#define TIOCSCTTY 0x540E
+#define TIOCGPGRP _IOR('T', 30, int)
+#define TIOCSPGRP _IOW('T', 29, int)
+#define TIOCOUTQ 0x5411
+#define TIOCSTI 0x5412
+#define TIOCGWINSZ 0x5413
+#define TIOCSWINSZ 0x5414
+#define TIOCMGET 0x5415
+#define TIOCMBIS 0x5416
+#define TIOCMBIC 0x5417
+#define TIOCMSET 0x5418
+#define TIOCGSOFTCAR 0x5419
+#define TIOCSSOFTCAR 0x541A
+#define FIONREAD 0x541B
+#define TIOCINQ FIONREAD
+#define TIOCLINUX 0x541C
+#define TIOCCONS 0x541D
+#define TIOCGSERIAL 0x541E
+#define TIOCSSERIAL 0x541F
+#define TIOCPKT 0x5420
+#define FIONBIO 0x5421
+#define TIOCNOTTY 0x5422
+#define TIOCSETD 0x5423
+#define TIOCGETD 0x5424
+#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
+#define TIOCSBRK 0x5427 /* BSD compatibility */
+#define TIOCCBRK 0x5428 /* BSD compatibility */
+#define TIOCGSID _IOR('T', 20, int) /* Return the session ID of FD */
+#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+
+#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
+#define FIOCLEX 0x5451
+#define FIOASYNC 0x5452
+#define TIOCSERCONFIG 0x5453
+#define TIOCSERGWILD 0x5454
+#define TIOCSERSWILD 0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TIOCSERGETLSR 0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
+#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
+
+/* Used for packet mode */
+#define TIOCPKT_DATA 0
+#define TIOCPKT_FLUSHREAD 1
+#define TIOCPKT_FLUSHWRITE 2
+#define TIOCPKT_STOP 4
+#define TIOCPKT_START 8
+#define TIOCPKT_NOSTOP 16
+#define TIOCPKT_DOSTOP 32
+
+#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+
+#endif /* _ASM_PARISC_IOCTLS_H */
diff --git a/include/asm-parisc/iosapic.h b/include/asm-parisc/iosapic.h
new file mode 100644
index 000000000..d22509fb0
--- /dev/null
+++ b/include/asm-parisc/iosapic.h
@@ -0,0 +1,53 @@
+/*
+** This file is private to iosapic driver.
+** If stuff needs to be used by another driver, move it to a common file.
+**
+** WARNING: fields most data structures here are ordered to make sure
+** they pack nicely for 64-bit compilation. (ie sizeof(long) == 8)
+*/
+
+
+/*
+** I/O SAPIC init function
+** Caller knows where an I/O SAPIC is. LBA has an integrated I/O SAPIC.
+** Call setup as part of per instance initialization.
+** (ie *not* init_module() function unless only one is present.)
+** fixup_irq is to initialize PCI IRQ line support and
+** virtualize pcidev->irq value. To be called by pci_fixup_bus().
+*/
+extern void *iosapic_register(void *hpa);
+extern int iosapic_fixup_irq(void *obj, struct pci_dev *pcidev);
+
+
+#ifdef __IA64__
+/*
+** PA: PIB (Processor Interrupt Block) is handled by Runway bus adapter.
+** and is hardcoded to 0xfeeNNNN0 where NNNN is id_eid field.
+**
+** IA64: PIB is handled by "Local SAPIC" (integrated in the processor).
+*/
+struct local_sapic_info {
+ struct local_sapic_info *lsi_next; /* point to next CPU info */
+ int *lsi_cpu_id; /* point to logical CPU id */
+ unsigned long *lsi_id_eid; /* point to IA-64 CPU id */
+ int *lsi_status; /* point to CPU status */
+ void *lsi_private; /* point to special info */
+};
+
+/*
+** "root" data structure which ties everything together.
+** Should always be able to start with sapic_root and locate
+** the desired information.
+*/
+struct sapic_info {
+ struct sapic_info *si_next; /* info is per cell */
+ int si_cellid; /* cell id */
+ unsigned int si_status; /* status */
+ char *si_pib_base; /* intr blk base address */
+ local_sapic_info_t *si_local_info;
+ io_sapic_info_t *si_io_info;
+ extint_info_t *si_extint_info;/* External Intr info */
+};
+
+#endif /* IA64 */
+
diff --git a/include/asm-parisc/ipcbuf.h b/include/asm-parisc/ipcbuf.h
new file mode 100644
index 000000000..f576ce5e0
--- /dev/null
+++ b/include/asm-parisc/ipcbuf.h
@@ -0,0 +1,11 @@
+#ifndef __PARISC_IPCBUF_H__
+#define __PARISC_IPCBUF_H__
+
+/*
+ * The ipc64_perm structure for PA-RISC is identical to kern_ipc_perm
+ * as we have always had 32-bit UIDs and GIDs in the kernel.
+ */
+
+#define ipc64_perm kern_ipc_perm
+
+#endif /* __PARISC_IPCBUF_H__ */
diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h
new file mode 100644
index 000000000..b52415f41
--- /dev/null
+++ b/include/asm-parisc/irq.h
@@ -0,0 +1,89 @@
+#ifndef _ASM_IRQ_H
+#define _ASM_IRQ_H
+
+#include <linux/string.h>
+#include <asm/ptrace.h>
+#include <linux/interrupt.h>
+
+#include <asm/types.h>
+/*
+ * linux/include/asm/irq.h
+ *
+ * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar,
+ * Copyright 1999 SuSE GmbH
+ *
+ * IRQ/IPI changes taken from work by Thomas Radke
+ * <tomsoft@informatik.tu-chemnitz.de>
+ */
+
+#define CPU_IRQ_REGION 1
+#define TIMER_IRQ (IRQ_FROM_REGION(CPU_IRQ_REGION) | 0)
+#define IPI_IRQ (IRQ_FROM_REGION(CPU_IRQ_REGION) | 1)
+
+/* This should be 31 for PA1.1 binaries and 63 for PA-2.0 wide mode) */
+#define MAX_CPU_IRQ (BITS_PER_LONG - 1)
+
+#if 1 /* set to 1 to get the new irq offsets, or ... */
+# if BITS_PER_LONG == 32
+# define IRQ_REGION_SHIFT 5
+# else
+# define IRQ_REGION_SHIFT 6
+# endif
+#else /* 256 irq-entries per region (wastes memory, maybe gains speed? :-))*/
+# define IRQ_REGION_SHIFT 8
+#endif
+
+#define IRQ_PER_REGION (1 << IRQ_REGION_SHIFT)
+#define NR_IRQ_REGS 8
+#define NR_IRQS (NR_IRQ_REGS * IRQ_PER_REGION)
+
+#define IRQ_REGION(irq) ((irq) >> IRQ_REGION_SHIFT)
+#define IRQ_OFFSET(irq) ((irq) & ((1<<IRQ_REGION_SHIFT)-1))
+#define IRQ_FROM_REGION(reg) ((reg) << IRQ_REGION_SHIFT)
+
+#define IRQ_REG_DIS 1 /* support disable_irq / enable_irq */
+#define IRQ_REG_MASK 2 /* require IRQs to be masked */
+
+struct irq_region_ops {
+ void (*disable_irq)(void *dev, int irq);
+ void (* enable_irq)(void *dev, int irq);
+ void (* mask_irq)(void *dev, int irq);
+ void (* unmask_irq)(void *dev, int irq);
+};
+
+struct irq_region_data {
+ void *dev;
+ const char *name;
+ unsigned flags;
+ int irqbase;
+};
+
+struct irq_region {
+ struct irq_region_ops ops;
+ struct irq_region_data data;
+
+ struct irqaction *action;
+};
+
+extern struct irq_region *irq_region[NR_IRQ_REGS];
+
+static __inline__ int irq_cannonicalize(int irq)
+{
+ return irq;
+}
+
+extern void disable_irq(int);
+extern void enable_irq(int);
+
+extern void do_irq_mask(unsigned long mask, struct irq_region *region,
+ struct pt_regs *regs);
+
+extern struct irq_region *alloc_irq_region(int count, struct irq_region_ops *ops,
+ unsigned long flags, const char *name, void *dev);
+
+extern int txn_alloc_irq(void);
+extern int txn_claim_irq(int);
+extern unsigned int txn_alloc_data(int, unsigned int);
+extern unsigned long txn_alloc_addr(int);
+
+#endif /* _ASM_IRQ_H */
diff --git a/include/asm-parisc/keyboard.h b/include/asm-parisc/keyboard.h
new file mode 100644
index 000000000..e47761017
--- /dev/null
+++ b/include/asm-parisc/keyboard.h
@@ -0,0 +1,67 @@
+/*
+ * linux/include/asm-parisc/keyboard.h
+ *
+ * Original by Geert Uytterhoeven
+ * updates by Alex deVries <adevries@thepuffingroup.com>
+ * portions copyright (1999) The Puffin Group
+ * mostly rewritten by Philipp Rumpf <prumpf@tux.org>,
+ * Copyright 2000 Philipp Rumpf
+ */
+
+/*
+ * We try to keep the amount of generic code as low as possible -
+ * we want to support all HIL, PS/2, and untranslated USB keyboards
+ */
+
+#ifndef _PARISC_KEYBOARD_H
+#define _PARISC_KEYBOARD_H
+
+#include <linux/config.h>
+
+#ifdef __KERNEL__
+#ifdef CONFIG_VT
+
+/* These are basically the generic functions / variables. The only
+ * unexpected detail is the initialization sequence for the keyboard
+ * driver is something like this:
+ *
+ * detect keyboard port
+ * detect keyboard
+ * call register_kbd_ops
+ * wait for init_hw
+ *
+ * only after init_hw has been called you're allowed to call
+ * handle_scancode. This means you either have to be extremely
+ * careful or use a global flag or something - I strongly suggest
+ * the latter. prumpf */
+
+extern struct kbd_ops {
+ int (*setkeycode)(unsigned int, unsigned int);
+ int (*getkeycode)(unsigned int);
+ int (*translate)(unsigned char, unsigned char *, char);
+ char (*unexpected_up)(unsigned char);
+ void (*leds)(unsigned char);
+ void (*init_hw)(void);
+
+ unsigned char sysrq_key;
+ unsigned char *sysrq_xlate;
+} *kbd_ops;
+
+#define kbd_setkeycode (*kbd_ops->setkeycode)
+#define kbd_getkeycode (*kbd_ops->getkeycode)
+#define kbd_translate (*kbd_ops->translate)
+#define kbd_unexpected_up (*kbd_ops->unexpected_up)
+#define kbd_leds (*kbd_ops->leds)
+#define kbd_init_hw (*kbd_ops->init_hw)
+
+#define SYSRQ_KEY (kbd_ops->sysrq_key)
+#define kbd_sysrq_xlate (kbd_ops->sysrq_xlate)
+extern unsigned char hp_ps2kbd_sysrq_xlate[128]; /* from drivers/char/hp_keyb.c */
+
+extern void register_kbd_ops(struct kbd_ops *ops);
+
+#endif /* CONFIG_VT */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASMPARISC_KEYBOARD_H */
diff --git a/include/asm-parisc/led.h b/include/asm-parisc/led.h
new file mode 100644
index 000000000..e4c9b2cc5
--- /dev/null
+++ b/include/asm-parisc/led.h
@@ -0,0 +1,33 @@
+#ifndef LED_H
+#define LED_H
+
+
+#define LED7 0x80 /* top (or furthest right) LED */
+#define LED6 0x40
+#define LED5 0x20
+#define LED4 0x10
+#define LED3 0x08
+#define LED2 0x04
+#define LED1 0x02
+#define LED0 0x01 /* bottom (or furthest left) LED */
+
+#define LED_LAN_TX LED0 /* for LAN transmit activity */
+#define LED_LAN_RCV LED1 /* for LAN receive activity */
+#define LED_DISK_IO LED2 /* for disk activity */
+#define LED_HEARTBEAT LED3 /* heartbeat */
+
+
+/* irq function */
+extern void led_interrupt_func(void);
+
+/* LASI & ASP specific LED initialization funcs */
+extern void __init lasi_led_init( unsigned long lasi_hpa );
+extern void __init asp_led_init( unsigned long led_ptr );
+
+/* registers the LED regions for procfs */
+extern void __init register_led_regions(void);
+
+/* main LED initialization function (uses the PDC) */
+extern int __init led_init(void);
+
+#endif /* LED_H */
diff --git a/include/asm-parisc/linux_logo.h b/include/asm-parisc/linux_logo.h
new file mode 100644
index 000000000..f431e4256
--- /dev/null
+++ b/include/asm-parisc/linux_logo.h
@@ -0,0 +1,48 @@
+/* $Id: linux_logo.h,v 1.1.1.1 1999/03/15 19:41:01 pjlahaie Exp $
+ * include/asm-parisc/linux_logo.h: This is a linux logo
+ * to be displayed on boot.
+ *
+ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from 0x20
+ * (i.e. RGB(linux_logo_red[0],
+ * linux_logo_green[0],
+ * linux_logo_blue[0]) is color 0x20)
+ * BW image has to be 80x80 as well, with MS bit
+ * on the left
+ * Serial_console ascii image can be any size,
+ * but should contain %s to display the version
+ */
+
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define linux_logo_banner "Linux/PA-RISC version " UTS_RELEASE
+
+#define LINUX_LOGO_COLORS 214
+
+#ifdef INCLUDE_LINUX_LOGO_DATA
+
+#define INCLUDE_LINUX_LOGOBW
+#define INCLUDE_LINUX_LOGO16
+
+#include <linux/linux_logo.h>
+
+#else
+
+/* prototypes only */
+extern unsigned char linux_logo_red[];
+extern unsigned char linux_logo_green[];
+extern unsigned char linux_logo_blue[];
+extern unsigned char linux_logo[];
+extern unsigned char linux_logo_bw[];
+extern unsigned char linux_logo16_red[];
+extern unsigned char linux_logo16_green[];
+extern unsigned char linux_logo16_blue[];
+extern unsigned char linux_logo16[];
+
+#endif
diff --git a/include/asm-parisc/machdep.h b/include/asm-parisc/machdep.h
new file mode 100644
index 000000000..a231c97d7
--- /dev/null
+++ b/include/asm-parisc/machdep.h
@@ -0,0 +1,16 @@
+#ifndef _PARISC_MACHDEP_H
+#define _PARISC_MACHDEP_H
+
+#include <linux/notifier.h>
+
+#define MACH_RESTART 1
+#define MACH_HALT 2
+#define MACH_POWER_ON 3
+#define MACH_POWER_OFF 4
+
+extern struct notifier_block *mach_notifier;
+extern void pa7300lc_init(void);
+
+extern void (*cpu_lpmc)(int, struct pt_regs *);
+
+#endif
diff --git a/include/asm-parisc/mc146818rtc.h b/include/asm-parisc/mc146818rtc.h
new file mode 100644
index 000000000..adf416314
--- /dev/null
+++ b/include/asm-parisc/mc146818rtc.h
@@ -0,0 +1,9 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef _ASM_MC146818RTC_H
+#define _ASM_MC146818RTC_H
+
+/* empty include file to satisfy the include in genrtc.c */
+
+#endif /* _ASM_MC146818RTC_H */
diff --git a/include/asm-parisc/md.h b/include/asm-parisc/md.h
new file mode 100644
index 000000000..67aace80e
--- /dev/null
+++ b/include/asm-parisc/md.h
@@ -0,0 +1,13 @@
+/* $Id: md.h,v 1.1.1.1 1999/03/15 19:41:02 pjlahaie Exp $
+ * md.h: High speed xor_block operation for RAID4/5
+ *
+ */
+
+#ifndef __ASM_MD_H
+#define __ASM_MD_H
+
+/* #define HAVE_ARCH_XORBLOCK */
+
+#define MD_XORBLOCK_ALIGNMENT sizeof(long)
+
+#endif /* __ASM_MD_H */
diff --git a/include/asm-parisc/mman.h b/include/asm-parisc/mman.h
new file mode 100644
index 000000000..b04014203
--- /dev/null
+++ b/include/asm-parisc/mman.h
@@ -0,0 +1,52 @@
+#ifndef __PARISC_MMAN_H__
+#define __PARISC_MMAN_H__
+
+#define PROT_READ 0x1 /* page can be read */
+#define PROT_WRITE 0x2 /* page can be written */
+#define PROT_EXEC 0x4 /* page can be executed */
+#define PROT_NONE 0x0 /* page can not be accessed */
+
+#define MAP_SHARED 0x01 /* Share changes */
+#define MAP_PRIVATE 0x02 /* Changes are private */
+#define MAP_TYPE 0x03 /* Mask for type of mapping */
+#define MAP_FIXED 0x04 /* Interpret addr exactly */
+#define MAP_ANONYMOUS 0x10 /* don't use a file */
+
+#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
+#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
+#define MAP_LOCKED 0x2000 /* pages are locked */
+#define MAP_NORESERVE 0x4000 /* don't check for reservations */
+#define MAP_GROWSDOWN 0x8000 /* stack-like segment */
+
+#define MS_SYNC 1 /* synchronous memory sync */
+#define MS_ASYNC 2 /* sync memory asynchronously */
+#define MS_INVALIDATE 4 /* invalidate the caches */
+
+#define MCL_CURRENT 1 /* lock all current mappings */
+#define MCL_FUTURE 2 /* lock all future mappings */
+
+#define MADV_NORMAL 0 /* no further special treatment */
+#define MADV_RANDOM 1 /* expect random page references */
+#define MADV_SEQUENTIAL 2 /* expect sequential page references */
+#define MADV_WILLNEED 3 /* will need these pages */
+#define MADV_DONTNEED 4 /* dont need these pages */
+#define MADV_SPACEAVAIL 5 /* insure that resources are reserved */
+#define MADV_VPS_PURGE 6 /* Purge pages from VM page cache */
+#define MADV_VPS_INHERIT 7 /* Inherit parents page size */
+
+/* The range 12-64 is reserved for page size specification. */
+#define MADV_4K_PAGES 12 /* Use 4K pages */
+#define MADV_16K_PAGES 14 /* Use 16K pages */
+#define MADV_64K_PAGES 16 /* Use 64K pages */
+#define MADV_256K_PAGES 18 /* Use 256K pages */
+#define MADV_1M_PAGES 20 /* Use 1 Megabyte pages */
+#define MADV_4M_PAGES 22 /* Use 4 Megabyte pages */
+#define MADV_16M_PAGES 24 /* Use 16 Megabyte pages */
+#define MADV_64M_PAGES 26 /* Use 64 Megabyte pages */
+
+/* compatibility flags */
+#define MAP_ANON MAP_ANONYMOUS
+#define MAP_FILE 0
+#define MAP_VARIABLE 0
+
+#endif /* __PARISC_MMAN_H__ */
diff --git a/include/asm-parisc/mmu.h b/include/asm-parisc/mmu.h
new file mode 100644
index 000000000..c311f8ae7
--- /dev/null
+++ b/include/asm-parisc/mmu.h
@@ -0,0 +1,64 @@
+/*
+ * parisc mmu structures
+ */
+
+#ifndef _PARISC_MMU_H_
+#define _PARISC_MMU_H_
+
+#ifndef __ASSEMBLY__
+/* Hardware Page Table Entry */
+typedef struct _PTE {
+ unsigned long v:1; /* Entry is valid */
+ unsigned long tag:31; /* Unique Tag */
+
+ unsigned long r:1; /* referenced */
+ unsigned long os_1:1; /* */
+ unsigned long t:1; /* page reference trap */
+ unsigned long d:1; /* dirty */
+ unsigned long b:1; /* break */
+ unsigned long type:3; /* access type */
+ unsigned long pl1:2; /* PL1 (execute) */
+ unsigned long pl2:2; /* PL2 (write) */
+ unsigned long u:1; /* uncacheable */
+ unsigned long id:1; /* access id */
+ unsigned long os_2:1; /* */
+
+ unsigned long os_3:3; /* */
+ unsigned long res_1:4; /* */
+ unsigned long phys:20; /* physical page number */
+ unsigned long os_4:2; /* */
+ unsigned long res_2:3; /* */
+
+ unsigned long next; /* pointer to next page */
+} PTE;
+
+/*
+ * Simulated two-level MMU. This structure is used by the kernel
+ * to keep track of MMU mappings and is used to update/maintain
+ * the hardware HASH table which is really a cache of mappings.
+ *
+ * The simulated structures mimic the hardware available on other
+ * platforms, notably the 80x86 and 680x0.
+ */
+
+typedef struct _pte {
+ unsigned long page_num:20;
+ unsigned long flags:12; /* Page flags (some unused bits) */
+} pte;
+
+#define PD_SHIFT (10+12) /* Page directory */
+#define PD_MASK 0x02FF
+#define PT_SHIFT (12) /* Page Table */
+#define PT_MASK 0x02FF
+#define PG_SHIFT (12) /* Page Entry */
+
+/* MMU context */
+
+typedef struct _MMU_context {
+ long pid[4];
+ pte **pmap; /* Two-level page-map structure */
+} MMU_context;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PARISC_MMU_H_ */
diff --git a/include/asm-parisc/mmu_context.h b/include/asm-parisc/mmu_context.h
new file mode 100644
index 000000000..64531f986
--- /dev/null
+++ b/include/asm-parisc/mmu_context.h
@@ -0,0 +1,67 @@
+#ifndef __PARISC_MMU_CONTEXT_H
+#define __PARISC_MMU_CONTEXT_H
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
+
+/* on PA-RISC, we actually have enough contexts to justify an allocator
+ * for them. prumpf */
+
+extern unsigned long alloc_sid(void);
+extern void free_sid(unsigned long);
+
+static inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+ /*
+ * Init_new_context can be called for a cloned mm, so we
+ * only allocate a space id if one hasn't been allocated
+ * yet AND mm != &init_mm (cloned kernel thread which
+ * will run in the kernel space with spaceid 0).
+ */
+
+ if ((mm != &init_mm) && (mm->context == 0)) {
+ mm->context = alloc_sid();
+ }
+
+ return 0;
+}
+
+static inline void
+destroy_context(struct mm_struct *mm)
+{
+ free_sid(mm->context);
+ mm->context = 0;
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+{
+
+ if (prev != next) {
+ /* Re-load page tables */
+ tsk->thread.pg_tables = __pa(next->pgd);
+
+ mtctl(tsk->thread.pg_tables, 25);
+ mtsp(next->context,3);
+ }
+}
+
+static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+ /*
+ * Activate_mm is our one chance to allocate a space id
+ * for a new mm created in the exec path. There's also
+ * some lazy tlb stuff, which is currently dead code, but
+ * we only allocate a space id if one hasn't been allocated
+ * already, so we should be OK.
+ */
+
+ if (next == &init_mm) BUG(); /* Should never happen */
+
+ if (next->context == 0)
+ next->context = alloc_sid();
+
+ switch_mm(prev,next,current,0);
+}
+#endif
diff --git a/include/asm-parisc/msgbuf.h b/include/asm-parisc/msgbuf.h
new file mode 100644
index 000000000..9dd868a1f
--- /dev/null
+++ b/include/asm-parisc/msgbuf.h
@@ -0,0 +1,31 @@
+#ifndef _PARISC_MSGBUF_H
+#define _PARISC_MSGBUF_H
+
+/*
+ * The msqid64_ds structure for parisc architecture, copied from sparc.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+ struct ipc64_perm msg_perm;
+ unsigned int __pad1;
+ __kernel_time_t msg_stime; /* last msgsnd time */
+ unsigned int __pad2;
+ __kernel_time_t msg_rtime; /* last msgrcv time */
+ unsigned int __pad3;
+ __kernel_time_t msg_ctime; /* last change time */
+ unsigned int msg_cbytes; /* current number of bytes on queue */
+ unsigned int msg_qnum; /* number of messages in queue */
+ unsigned int msg_qbytes; /* max number of bytes on queue */
+ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_pid_t msg_lrpid; /* last receive pid */
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+#endif /* _PARISC_MSGBUF_H */
diff --git a/include/asm-parisc/namei.h b/include/asm-parisc/namei.h
new file mode 100644
index 000000000..2b8132d79
--- /dev/null
+++ b/include/asm-parisc/namei.h
@@ -0,0 +1,17 @@
+/* $Id: namei.h,v 1.1.1.1 1999/03/15 19:41:02 pjlahaie Exp $
+ * linux/include/asm-parisc/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+
+#ifndef __PARISC_NAMEI_H
+#define __PARISC_NAMEI_H
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif /* __PARISC_NAMEI_H */
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
new file mode 100644
index 000000000..39f19f601
--- /dev/null
+++ b/include/asm-parisc/page.h
@@ -0,0 +1,86 @@
+#ifndef _PARISC_PAGE_H
+#define _PARISC_PAGE_H
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr) clear_page(page)
+#define copy_user_page(to, from, vaddr) copy_page(to, from)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define pmd_val(x) ((x).pmd)
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+/* Pure 2^n version of get_order */
+extern __inline__ int get_order(unsigned long size)
+{
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+/*
+ * Tell the user there is some problem. Beep too, so we can
+ * see^H^H^Hhear bugs in early bootup as well!
+ *
+ * We don't beep yet. prumpf
+ */
+#define BUG() do { \
+ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+} while (0)
+
+#define PAGE_BUG(page) do { \
+ BUG(); \
+} while (0)
+
+
+#define LINUX_GATEWAY_SPACE 0
+#define __PAGE_OFFSET (0xc0000000)
+
+#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
+/* These macros don't work for 64-bit C code -- don't allow in C at all */
+#ifdef __ASSEMBLY__
+# define PA(x) ((x)-__PAGE_OFFSET)
+# define VA(x) ((x)+__PAGE_OFFSET)
+#endif
+#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
+#define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
+
+#endif /* __KERNEL__ */
+
+#endif /* _PARISC_PAGE_H */
diff --git a/include/asm-parisc/param.h b/include/asm-parisc/param.h
new file mode 100644
index 000000000..d6ee56cea
--- /dev/null
+++ b/include/asm-parisc/param.h
@@ -0,0 +1,24 @@
+#ifndef _ASMPARISC_PARAM_H
+#define _ASMPARISC_PARAM_H
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE 4096
+
+#ifndef NGROUPS
+#define NGROUPS 32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP (-1)
+#endif
+
+#define MAXHOSTNAMELEN 64 /* max length of hostname */
+
+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC HZ /* frequency at which times() counts */
+#endif
+
+#endif
diff --git a/include/asm-parisc/parport.h b/include/asm-parisc/parport.h
new file mode 100644
index 000000000..00d9cc3e7
--- /dev/null
+++ b/include/asm-parisc/parport.h
@@ -0,0 +1,18 @@
+/*
+ *
+ * parport.h: ia32-compatible parport initialisation
+ *
+ * This file should only be included by drivers/parport/parport_pc.c.
+ */
+#ifndef _ASM_PARPORT_H
+#define _ASM_PARPORT_H 1
+
+
+static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+{
+ /* nothing ! */
+ return 0;
+}
+
+
+#endif /* !(_ASM_PARPORT_H) */
diff --git a/include/asm-parisc/parport_gsc.h b/include/asm-parisc/parport_gsc.h
new file mode 100644
index 000000000..686d4f127
--- /dev/null
+++ b/include/asm-parisc/parport_gsc.h
@@ -0,0 +1,193 @@
+#ifndef __LINUX_PARPORT_GSC_H
+#define __LINUX_PARPORT_GSC_H
+
+#include <asm/io.h>
+#include <linux/delay.h>
+
+#undef DEBUG_PARPORT /* undefine for production */
+#define DELAY_TIME 0
+
+#if DELAY_TIME == 0
+#define parport_readb gsc_readb
+#define parport_writeb gsc_writeb
+#else
+static __inline__ unsigned char parport_readb( unsigned long port )
+{
+ udelay(DELAY_TIME);
+ return gsc_readb(port);
+}
+
+static __inline__ void parport_writeb( unsigned char value, unsigned long port )
+{
+ gsc_writeb(value,port);
+ udelay(DELAY_TIME);
+}
+#endif
+
+/* --- register definitions ------------------------------- */
+
+#define EPPDATA(p) ((p)->base + 0x4)
+#define EPPADDR(p) ((p)->base + 0x3)
+#define CONTROL(p) ((p)->base + 0x2)
+#define STATUS(p) ((p)->base + 0x1)
+#define DATA(p) ((p)->base + 0x0)
+
+struct parport_gsc_private {
+ /* Contents of CTR. */
+ unsigned char ctr;
+
+ /* Bitmask of writable CTR bits. */
+ unsigned char ctr_writable;
+
+ /* Number of bytes per portword. */
+ int pword;
+
+ /* Not used yet. */
+ int readIntrThreshold;
+ int writeIntrThreshold;
+
+ /* buffer suitable for DMA, if DMA enabled */
+ char *dma_buf;
+ dma_addr_t dma_handle;
+ struct pci_dev *dev;
+};
+
+extern __inline__ void parport_gsc_write_data(struct parport *p, unsigned char d)
+{
+#ifdef DEBUG_PARPORT
+ printk (KERN_DEBUG "parport_gsc_write_data(%p,0x%02x)\n", p, d);
+#endif
+ parport_writeb(d, DATA(p));
+}
+
+extern __inline__ unsigned char parport_gsc_read_data(struct parport *p)
+{
+ unsigned char val = parport_readb (DATA (p));
+#ifdef DEBUG_PARPORT
+ printk (KERN_DEBUG "parport_gsc_read_data(%p) = 0x%02x\n",
+ p, val);
+#endif
+ return val;
+}
+
+/* __parport_gsc_frob_control differs from parport_gsc_frob_control in that
+ * it doesn't do any extra masking. */
+static __inline__ unsigned char __parport_gsc_frob_control (struct parport *p,
+ unsigned char mask,
+ unsigned char val)
+{
+ struct parport_gsc_private *priv = p->physport->private_data;
+ unsigned char ctr = priv->ctr;
+#ifdef DEBUG_PARPORT
+ printk (KERN_DEBUG
+ "__parport_gsc_frob_control(%02x,%02x): %02x -> %02x\n",
+ mask, val, ctr, ((ctr & ~mask) ^ val) & priv->ctr_writable);
+#endif
+ ctr = (ctr & ~mask) ^ val;
+ ctr &= priv->ctr_writable; /* only write writable bits. */
+ parport_writeb (ctr, CONTROL (p));
+ priv->ctr = ctr; /* Update soft copy */
+ return ctr;
+}
+
+extern __inline__ void parport_gsc_data_reverse (struct parport *p)
+{
+ __parport_gsc_frob_control (p, 0x20, 0x20);
+}
+
+extern __inline__ void parport_gsc_data_forward (struct parport *p)
+{
+ __parport_gsc_frob_control (p, 0x20, 0x00);
+}
+
+extern __inline__ void parport_gsc_write_control (struct parport *p,
+ unsigned char d)
+{
+ const unsigned char wm = (PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_INIT |
+ PARPORT_CONTROL_SELECT);
+
+ /* Take this out when drivers have adapted to newer interface. */
+ if (d & 0x20) {
+ printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
+ p->name, p->cad->name);
+ parport_gsc_data_reverse (p);
+ }
+
+ __parport_gsc_frob_control (p, wm, d & wm);
+}
+
+extern __inline__ unsigned char parport_gsc_read_control(struct parport *p)
+{
+ const unsigned char rm = (PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_INIT |
+ PARPORT_CONTROL_SELECT);
+ const struct parport_gsc_private *priv = p->physport->private_data;
+ return priv->ctr & rm; /* Use soft copy */
+}
+
+extern __inline__ unsigned char parport_gsc_frob_control (struct parport *p,
+ unsigned char mask,
+ unsigned char val)
+{
+ const unsigned char wm = (PARPORT_CONTROL_STROBE |
+ PARPORT_CONTROL_AUTOFD |
+ PARPORT_CONTROL_INIT |
+ PARPORT_CONTROL_SELECT);
+
+ /* Take this out when drivers have adapted to newer interface. */
+ if (mask & 0x20) {
+ printk (KERN_DEBUG "%s (%s): use data_%s for this!\n",
+ p->name, p->cad->name,
+ (val & 0x20) ? "reverse" : "forward");
+ if (val & 0x20)
+ parport_gsc_data_reverse (p);
+ else
+ parport_gsc_data_forward (p);
+ }
+
+ /* Restrict mask and val to control lines. */
+ mask &= wm;
+ val &= wm;
+
+ return __parport_gsc_frob_control (p, mask, val);
+}
+
+extern __inline__ unsigned char parport_gsc_read_status(struct parport *p)
+{
+ return parport_readb (STATUS(p));
+}
+
+
+extern __inline__ void parport_gsc_disable_irq(struct parport *p)
+{
+ __parport_gsc_frob_control (p, 0x10, 0x00);
+}
+
+extern __inline__ void parport_gsc_enable_irq(struct parport *p)
+{
+ __parport_gsc_frob_control (p, 0x10, 0x10);
+}
+
+extern void parport_gsc_release_resources(struct parport *p);
+
+extern int parport_gsc_claim_resources(struct parport *p);
+
+extern void parport_gsc_init_state(struct pardevice *, struct parport_state *s);
+
+extern void parport_gsc_save_state(struct parport *p, struct parport_state *s);
+
+extern void parport_gsc_restore_state(struct parport *p, struct parport_state *s);
+
+extern void parport_gsc_inc_use_count(void);
+
+extern void parport_gsc_dec_use_count(void);
+
+extern struct parport *parport_gsc_probe_port (unsigned long base,
+ unsigned long base_hi,
+ int irq, int dma,
+ struct pci_dev *dev);
+
+#endif
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
new file mode 100644
index 000000000..89ea37048
--- /dev/null
+++ b/include/asm-parisc/pci.h
@@ -0,0 +1,215 @@
+#ifndef __ASM_PARISC_PCI_H
+#define __ASM_PARISC_PCI_H
+
+#include <asm/scatterlist.h>
+
+#define MIN_PCI_PORT 0x000000
+#define MAX_PCI_PORT 0xffffff
+
+/*
+** HP PCI platforms generally support multiple bus adapters.
+** (workstations 1-~4, servers 2-~32)
+**
+** Newer platforms number the busses across PCI bus adapters *sparsely*.
+** E.g. 0, 8, 16, ...
+**
+** Under a PCI bus, most HP platforms support PPBs up to two or three
+** levels deep. See "Bit3" product line.
+*/
+#define PCI_MAX_BUSSES 256
+
+/* [soapbox on]
+** Who the hell can develope stuff without ASSERT or VASSERT?
+** No one understands all the modules across all platforms.
+** For linux add another dimension - processor architectures.
+**
+** This should be a standard/global macro used liberally
+** in all code. Every respectable engineer I know in HP
+** would support this argument. - grant
+** [soapbox off]
+*/
+#ifdef PCI_DEBUG
+#define ASSERT(expr) \
+ if(!(expr)) { \
+ printk( "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \
+ panic(#expr); \
+ }
+#else
+#define ASSERT(expr)
+#endif
+
+
+/*
+** pci_hba_data (aka H2P_OBJECT in HP/UX)
+**
+** This is the "common" or "base" data structure which HBA drivers
+** (eg Dino or LBA) are required to place at the top of their own
+** dev->sysdata structure. I've heard this called "C inheritance" too.
+**
+** Data needed by pcibios layer belongs here.
+*/
+struct pci_hba_data {
+ struct pci_hba_data *next; /* global chain of HBAs */
+ char *base_addr; /* aka Host Physical Address */
+ struct hp_device *iodc_info; /* Info from PA bus walk */
+ struct pci_bus *hba_bus; /* primary PCI bus below HBA */
+ int hba_num; /* I/O port space access "key" */
+ struct resource bus_num; /* PCI bus numbers */
+ struct resource io_space; /* PIOP */
+ struct resource mem_space; /* LMMIO */
+ unsigned long mem_space_offset; /* VCLASS support */
+ /* REVISIT - spinlock to protect resources? */
+};
+
+
+/*
+** KLUGE: linux/pci.h include asm/pci.h BEFORE declaring struct pci_bus
+** (This eliminates some of the warnings).
+*/
+struct pci_bus;
+struct pci_dev;
+
+/*
+** Most PCI devices (eg Tulip, NCR720) also export the same registers
+** to both MMIO and I/O port space. Due to poor performance of I/O Port
+** access under HP PCI bus adapters, strongly reccomend use of MMIO
+** address space.
+**
+** While I'm at it more PA programming notes:
+**
+** 1) MMIO stores (writes) are posted operations. This means the processor
+** gets an "ACK" before the write actually gets to the device. A read
+** to the same device (or typically the bus adapter above it) will
+** force in-flight write transaction(s) out to the targeted device
+** before the read can complete.
+**
+** 2) The Programmed I/O (PIO) data may not always be strongly ordered with
+** respect to DMA on all platforms. Ie PIO data can reach the processor
+** before in-flight DMA reaches memory. Since most SMP PA platforms
+** are I/O coherent, it generally doesn't matter...but sometimes
+** it does.
+**
+** I've helped device driver writers debug both types of problems.
+*/
+struct pci_port_ops {
+ u8 (*inb) (struct pci_hba_data *hba, u16 port);
+ u16 (*inw) (struct pci_hba_data *hba, u16 port);
+ u32 (*inl) (struct pci_hba_data *hba, u16 port);
+ void (*outb) (struct pci_hba_data *hba, u16 port, u8 data);
+ void (*outw) (struct pci_hba_data *hba, u16 port, u16 data);
+ void (*outl) (struct pci_hba_data *hba, u16 port, u32 data);
+};
+
+
+struct pci_bios_ops {
+ void (*init)(void);
+ void (*fixup_bus)(struct pci_bus *bus);
+};
+
+extern void pcibios_size_bridge(struct pci_bus *, struct pbus_set_ranges_data *);
+
+
+/*
+** See Documentation/DMA-mapping.txt
+*/
+struct pci_dma_ops {
+ int (*dma_supported)(struct pci_dev *dev, dma_addr_t mask);
+ void *(*alloc_consistent)(struct pci_dev *dev, size_t size, dma_addr_t *iova);
+ void (*free_consistent)(struct pci_dev *dev, size_t size, void *vaddr, dma_addr_t iova);
+ dma_addr_t (*map_single)(struct pci_dev *dev, void *addr, size_t size, int direction);
+ void (*unmap_single)(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction);
+ int (*map_sg)(struct pci_dev *dev, struct scatterlist *sg, int nents, int direction);
+ void (*unmap_sg)(struct pci_dev *dev, struct scatterlist *sg, int nhwents, int direction);
+ void (*dma_sync_single)(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction);
+ void (*dma_sync_sg)(struct pci_dev *dev, struct scatterlist *sg, int nelems, int direction);
+};
+
+
+/*
+** We could live without the hppa_dma_ops indirection if we didn't want
+** to support 4 different dma models with one binary or they were
+** all loadable modules:
+** I/O MMU consistent method dma_sync behavior
+** ============= ====================== =======================
+** a) PA-7x00LC uncachable host memory flush/purge
+** b) U2/Uturn cachable host memory NOP
+** c) Ike/Astro cachable host memory NOP
+** d) EPIC/SAGA memory on EPIC/SAGA flush/reset DMA channel
+**
+** PA-7[13]00LC processors have a GSC bus interface and no I/O MMU.
+**
+** Systems (eg PCX-T workstations) that don't fall into the above
+** categories will need to modify the needed drivers to perform
+** flush/purge and allocate "regular" cacheable pages for everything.
+*/
+
+extern struct pci_dma_ops *hppa_dma_ops;
+extern struct pci_dma_ops pcxl_dma_ops;
+extern struct pci_dma_ops pcx_dma_ops;
+
+/*
+** Oops hard if we haven't setup hppa_dma_ops by the time the first driver
+** attempts to initialize.
+** Since panic() is a (void)(), pci_dma_panic() is needed to satisfy
+** the (int)() required by pci_dma_supported() interface.
+*/
+static inline int pci_dma_panic(char *msg)
+{
+ panic(msg);
+ return -1;
+}
+
+#define pci_dma_supported(p, m) ( \
+ (NULL == hppa_dma_ops) \
+ ? pci_dma_panic("Dynamic DMA support missing...OOPS!\n(Hint: was Astro/Ike/U2/Uturn not claimed?)\n") \
+ : hppa_dma_ops->dma_supported(p,m) \
+)
+
+#define pci_alloc_consistent(p, s, a) hppa_dma_ops->alloc_consistent(p,s,a)
+#define pci_free_consistent(p, s, v, a) hppa_dma_ops->free_consistent(p,s,v,a)
+#define pci_map_single(p, v, s, d) hppa_dma_ops->map_single(p, v, s, d)
+#define pci_unmap_single(p, a, s, d) hppa_dma_ops->unmap_single(p, a, s, d)
+#define pci_map_sg(p, sg, n, d) hppa_dma_ops->map_sg(p, sg, n, d)
+#define pci_unmap_sg(p, sg, n, d) hppa_dma_ops->unmap_sg(p, sg, n, d)
+
+/* For U2/Astro/Ike based platforms (which are fully I/O coherent)
+** dma_sync is a NOP. Let's keep the performance path short here.
+*/
+#define pci_dma_sync_single(p, a, s, d) { if (hppa_dma_ops->dma_sync_single) \
+ hppa_dma_ops->dma_sync_single(p, a, s, d); \
+ }
+#define pci_dma_sync_sg(p, sg, n, d) { if (hppa_dma_ops->dma_sync_sg) \
+ hppa_dma_ops->dma_sync_sg(p, sg, n, d); \
+ }
+
+/*
+** Stuff declared in arch/parisc/kernel/pci.c
+*/
+extern struct pci_port_ops *pci_port;
+extern struct pci_bios_ops *pci_bios;
+extern int pci_post_reset_delay; /* delay after de-asserting #RESET */
+
+extern void pcibios_register_hba(struct pci_hba_data *);
+extern void pcibios_assign_unassigned_resources(struct pci_bus *);
+
+
+/*
+** used by drivers/pci/pci.c:pci_do_scan_bus()
+** 0 == check if bridge is numbered before re-numbering.
+** 1 == pci_do_scan_bus() should automatically number all PCI-PCI bridges.
+**
+** REVISIT:
+** To date, only alpha sets this to one. We'll need to set this
+** to zero for legacy platforms and one for PAT platforms.
+*/
+#ifdef __LP64__
+extern int pdc_pat; /* arch/parisc/kernel/inventory.c */
+#define pcibios_assign_all_busses() pdc_pat
+#else
+#define pcibios_assign_all_busses() 0
+#endif
+
+#define PCIBIOS_MIN_IO 0x10
+#define PCIBIOS_MIN_MEM 0x1000 /* NBPG - but pci/setup-res.c dies */
+
+#endif /* __ASM_PARISC_PCI_H */
diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h
new file mode 100644
index 000000000..debd3f5b8
--- /dev/null
+++ b/include/asm-parisc/pdc.h
@@ -0,0 +1,629 @@
+#ifndef _PARISC_PDC_H
+#define _PARISC_PDC_H
+
+/*
+ PDC entry points...
+*/
+
+#define PDC_POW_FAIL 1 /* perform a power-fail */
+#define PDC_POW_FAIL_PREPARE 0 /* prepare for powerfail */
+
+#define PDC_CHASSIS 2 /* PDC-chassis functions */
+#define PDC_CHASSIS_DISP 0 /* update chassis display */
+#define PDC_CHASSIS_WARN 1 /* return chassis warnings */
+#define PDC_CHASSIS_DISPWARN 2 /* update&return chassis status */
+#define PDC_RETURN_CHASSIS_INFO 128 /* HVERSION dependend: return chassis LED/LCD info */
+
+#define PDC_PIM 3 /* Get PIM data */
+#define PDC_PIM_HPMC 0 /* Transfer HPMC data */
+#define PDC_PIM_RETURN_SIZE 1 /* Get Max buffer needed for PIM*/
+#define PDC_PIM_LPMC 2 /* Transfer HPMC data */
+#define PDC_PIM_SOFT_BOOT 3 /* Transfer Soft Boot data */
+#define PDC_PIM_TOC 4 /* Transfer TOC data */
+
+#define PDC_MODEL 4 /* PDC model information call */
+#define PDC_MODEL_INFO 0 /* returns information */
+#define PDC_MODEL_BOOTID 1 /* set the BOOT_ID */
+#define PDC_MODEL_VERSIONS 2 /* returns cpu-internal versions*/
+#define PDC_MODEL_SYSMODEL 3 /* return system model info */
+#define PDC_MODEL_ENSPEC 4 /* ??? */
+#define PDC_MODEL_DISPEC 5 /* ??? */
+#define PDC_MODEL_CPU_ID 6 /* returns cpu-id (only newer machines!) */
+#define PDC_MODEL_CAPABILITIES 7 /* returns OS32/OS64-flags */
+#define PDC_MODEL_GET_BOOT__OP 8 /* returns boot test options */
+#define PDC_MODEL_SET_BOOT__OP 9 /* set boot test options */
+
+#define PDC_CACHE 5 /* return/set cache (& TLB) info*/
+#define PDC_CACHE_INFO 0 /* returns information */
+#define PDC_CACHE_SET_COH 1 /* set coherence state */
+#define PDC_CACHE_RET_SPID 2 /* returns space-ID bits */
+
+#define PDC_HPA 6 /* return HPA of processor */
+#define PDC_HPA_PROCESSOR 0
+#define PDC_HPA_MODULES 1
+
+#define PDC_IODC 8 /* talk to IODC */
+#define PDC_IODC_READ 0 /* read IODC entry point */
+/* PDC_IODC_RI_* INDEX parameter of PDC_IODC_READ */
+#define PDC_IODC_RI_DATA_BYTES 0 /* IODC Data Bytes */
+/* 1, 2 obsolete - HVERSION dependent */
+#define PDC_IODC_RI_INIT 3 /* Initialize module */
+#define PDC_IODC_RI_IO 4 /* Module input/output */
+#define PDC_IODC_RI_SPA 5 /* Module input/output */
+#define PDC_IODC_RI_CONFIG 6 /* Module input/output */
+/* 7 obsolete - HVERSION dependent */
+#define PDC_IODC_RI_TEST 8 /* Module input/output */
+#define PDC_IODC_RI_TLB 9 /* Module input/output */
+#define PDC_IODC_NINIT 2 /* non-destructive init */
+#define PDC_IODC_DINIT 3 /* destructive init */
+#define PDC_IODC_MEMERR 4 /* check for memory errors */
+#define PDC_IODC_INDEX_DATA 0 /* get first 16 bytes from mod IODC */
+#define PDC_IODC_BUS_ERROR -4 /* bus error return value */
+#define PDC_IODC_INVALID_INDEX -5 /* invalid index return value */
+#define PDC_IODC_COUNT -6 /* count is too small */
+
+#define PDC_TOD 9 /* time-of-day clock (TOD) */
+#define PDC_TOD_READ 0 /* read TOD */
+#define PDC_TOD_WRITE 1 /* write TOD */
+#define PDC_TOD_ITIMER 2 /* calibrate Interval Timer (CR16) */
+
+#define PDC_ADD_VALID 12 /* Memory validation PDC call */
+#define PDC_ADD_VALID_VERIFY 0 /* Make PDC_ADD_VALID verify region */
+
+#define PDC_INSTR 15 /* get instr to invoke PDCE_CHECK() */
+
+#define PDC_BLOCK_TLB 18 /* manage hardware block-TLB */
+#define PDC_BTLB_INFO 0 /* returns parameter */
+#define PDC_BTLB_INSERT 1 /* insert BTLB entry */
+#define PDC_BTLB_PURGE 2 /* purge BTLB entries */
+#define PDC_BTLB_PURGE_ALL 3 /* purge all BTLB entries */
+
+#define PDC_TLB 19 /* manage hardware TLB miss handling */
+#define PDC_TLB_INFO 0 /* returns parameter */
+#define PDC_TLB_SETUP 1 /* set up miss handling */
+
+#define PDC_SYSTEM_MAP 22 /* find system modules */
+#define PDC_FIND_MODULE 0
+
+
+/* HVERSION dependent */
+
+#define PDC_IO 135 /* log error info, reset IO system */
+
+#define PDC_BROADCAST_RESET 136 /* reset all processors */
+#define PDC_DO_RESET 0UL /* option: perform a broadcast reset */
+#define PDC_DO_FIRM_TEST_RESET 1UL /* Do broadcast reset with bitmap */
+#define PDC_BR_RECONFIGURATION 2UL /* reset w/reconfiguration */
+#define PDC_FIRM_TEST_MAGIC 0xab9ec36fUL /* for this reboot only */
+
+#define PDC_LAN_STATION_ID 138 /* Hversion dependent mechanism for */
+#define PDC_LAN_STATION_ID_READ 0 /* getting the lan station address */
+
+#define PDC_LAN_STATION_ID_SIZE 6
+
+/* Legacy PDC definitions for same stuff */
+#define PDC_PCI_INDEX 147UL
+#define PDC_PCI_GET_INT_TBL_SIZE 13UL
+#define PDC_PCI_GET_INT_TBL 14UL
+
+/* generic error codes returned by all PDC-functions */
+
+#define PDC_WARN 3 /* Call completed with a warning */
+#define PDC_REQ_ERR_1 2 /* See above */
+#define PDC_REQ_ERR_0 1 /* Call would generate a requestor error */
+#define PDC_OK 0 /* Call completed successfully */
+#define PDC_BAD_PROC -1 /* Called non-existant procedure */
+#define PDC_BAD_OPTION -2 /* Called with non-existant option */
+#define PDC_ERROR -3 /* Call could not complete without an error */
+#define PDC_INVALID_ARG -10 /* Called with an invalid argument */
+#define PDC_BUS_POW_WARN -12 /* Call could not complete in allowed power budget */
+
+
+/* The following are from the HPUX .h files, and are just for
+compatibility */
+
+#define PDC_RET_OK 0L /* Call completed successfully */
+#define PDC_RET_NE_PROC -1L /* Non-existent procedure */
+#define PDC_RET_NE_OPT -2L /* non-existant option - arg1 */
+#define PDC_RET_NE_MOD -5L /* Module not found */
+#define PDC_RET_NE_CELL_MOD -7L /* Cell module not found */
+#define PDC_RET_INV_ARG -10L /* Invalid argument */
+#define PDC_RET_NOT_NARROW -17L /* Narrow mode not supported */
+
+
+/* Error codes for PDC_ADD_VALID */
+
+#define PDC_ADD_VALID_WARN 3 /* Call completed with a warning */
+#define PDC_ADD_VALID_REQ_ERR_1 2 /* See above */
+#define PDC_ADD_VALID_REQ_ERR_0 1 /* Call would generate a requestor error */
+#define PDC_ADD_VALID_OK 0 /* Call completed successfully */
+#define PDC_ADD_VALID_BAD_OPTION -2 /* Called with non-existant option */
+#define PDC_ADD_VALID_ERROR -3 /* Call could not complete without an error */
+#define PDC_ADD_VALID_INVALID_ARG -10 /* Called with an invalid argument */
+#define PDC_ADD_VALID_BUS_POW_WARN -12 /* Call could not complete in allowed power budget */
+
+/* The PDC_MEM_MAP calls */
+
+#define PDC_MEM_MAP 128
+#define PDC_MEM_MAP_HPA 0
+
+/* constants for OS (NVM...) */
+#define OS_ID_NONE 0
+#define OS_ID_HPUX 1
+#define OS_ID_MPEXL 2
+#define OS_ID_OSF 3
+#define OS_ID_LINUX OS_ID_HPUX
+
+/* constants for PDC_CHASSIS */
+#define OSTAT_OFF 0
+#define OSTAT_FLT 1
+#define OSTAT_TEST 2
+#define OSTAT_INIT 3
+#define OSTAT_SHUT 4
+#define OSTAT_WARN 5
+#define OSTAT_RUN 6
+#define OSTAT_ON 7
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct pdc_model { /* for PDC_MODEL */
+ unsigned long hversion;
+ unsigned long sversion;
+ unsigned long hw_id;
+ unsigned long boot_id;
+ unsigned long sw_id;
+ unsigned long sw_cap;
+ unsigned long arch_rev;
+ unsigned long pot_key;
+ unsigned long curr_key;
+ unsigned long pad[32-9];
+} __attribute__((aligned(8))) ;
+
+
+#if 0
+struct pdc_chassis_warn { /* for PDC_CHASSIS */
+ unsigned long warn;
+ unsigned long pad[32-1];
+} __attribute__((aligned(8))) ;
+#endif
+
+struct pdc_model_sysmodel { /* for PDC_MODEL_SYSMODEL */
+ unsigned long mod_len;
+ unsigned long pad[32-1];
+} __attribute__((aligned(8))) ;
+
+struct pdc_model_cpuid { /* for PDC_MODEL_CPU_ID */
+ unsigned long cpuid;
+ unsigned long pad[32-1];
+} __attribute__((aligned(8))) ;
+
+struct pdc_cache_cf { /* for PDC_CACHE (I/D-caches) */
+ unsigned long
+#ifdef __LP64__
+ cc_padW:32,
+#endif
+ cc_alias:4, /* alias boundaries for virtual adresses */
+ cc_block: 4, /* to determine most efficient stride */
+ cc_line : 3, /* maximum amount written back as a result of store (multiple of 16 bytes) */
+ cc_pad0 : 2, /* reserved */
+ cc_wt : 1, /* 0 = WT-Dcache, 1 = WB-Dcache */
+ cc_sh : 2, /* 0 = separate I/D-cache, else shared I/D-cache */
+ cc_cst : 3, /* 0 = incoherent D-cache, 1=coherent D-cache */
+ cc_pad1 : 5, /* reserved */
+ cc_assoc: 8; /* associativity of I/D-cache */
+};
+
+struct pdc_tlb_cf { /* for PDC_CACHE (I/D-TLB's) */
+ unsigned long tc_pad0:12, /* reserved */
+#ifdef __LP64__
+ tc_padW:32,
+#endif
+ tc_sh : 2, /* 0 = separate I/D-TLB, else shared I/D-TLB */
+ tc_hv : 1, /* HV */
+ tc_page : 1, /* 0 = 2K page-size-machine, 1 = 4k page size */
+ tc_cst : 3, /* 0 = incoherent operations, else coherent operations */
+ tc_aid : 5, /* ITLB: width of access ids of processor (encoded!) */
+ tc_pad1 : 8; /* ITLB: width of space-registers (encoded) */
+};
+
+struct pdc_cache_info { /* main-PDC_CACHE-structure (caches & TLB's) */
+ /* I-cache */
+ unsigned long ic_size; /* size in bytes */
+ struct pdc_cache_cf ic_conf; /* configuration */
+ unsigned long ic_base; /* base-addr */
+ unsigned long ic_stride;
+ unsigned long ic_count;
+ unsigned long ic_loop;
+ /* D-cache */
+ unsigned long dc_size; /* size in bytes */
+ struct pdc_cache_cf dc_conf; /* configuration */
+ unsigned long dc_base; /* base-addr */
+ unsigned long dc_stride;
+ unsigned long dc_count;
+ unsigned long dc_loop;
+ /* Instruction-TLB */
+ unsigned long it_size; /* number of entries in I-TLB */
+ struct pdc_tlb_cf it_conf; /* I-TLB-configuration */
+ unsigned long it_sp_base;
+ unsigned long it_sp_stride;
+ unsigned long it_sp_count;
+ unsigned long it_off_base;
+ unsigned long it_off_stride;
+ unsigned long it_off_count;
+ unsigned long it_loop;
+ /* data-TLB */
+ unsigned long dt_size; /* number of entries in D-TLB */
+ struct pdc_tlb_cf dt_conf; /* D-TLB-configuration */
+ unsigned long dt_sp_base;
+ unsigned long dt_sp_stride;
+ unsigned long dt_sp_count;
+ unsigned long dt_off_base;
+ unsigned long dt_off_stride;
+ unsigned long dt_off_count;
+ unsigned long dt_loop;
+ /* padded to 32 entries... */
+ unsigned long pad[32-30];
+} __attribute__((aligned(8))) ;
+
+struct pdc_hpa { /* PDC_HPA */
+ unsigned long hpa;
+ unsigned long filler[31];
+} __attribute__((aligned(8))) ;
+
+#if 0
+/* If you start using the next struct, you'll have to adjust it to
+ * work with 64-bit firmware I think -PB
+ */
+struct pdc_iodc { /* PDC_IODC */
+ unsigned char hversion_model;
+ unsigned char hversion;
+ unsigned char spa;
+ unsigned char type;
+ unsigned int sversion_rev:4;
+ unsigned int sversion_model:19;
+ unsigned int sversion_opt:8;
+ unsigned char rev;
+ unsigned char dep;
+ unsigned char features;
+ unsigned char filler1;
+ unsigned int checksum:16;
+ unsigned int length:16;
+ unsigned int filler[15];
+} __attribute__((aligned(8))) ;
+#endif
+
+#ifndef __LP64__
+/* no BLTBs in pa2.0 processors */
+struct pdc_btlb_info_range {
+ __u8 res00;
+ __u8 num_i;
+ __u8 num_d;
+ __u8 num_comb;
+};
+
+struct pdc_btlb_info { /* PDC_BLOCK_TLB, return of PDC_BTLB_INFO */
+ unsigned int min_size; /* minimum size of BTLB in pages */
+ unsigned int max_size; /* maximum size of BTLB in pages */
+ struct pdc_btlb_info_range fixed_range_info;
+ struct pdc_btlb_info_range variable_range_info;
+ unsigned int pad[32-4];
+} __attribute__((aligned(8))) ;
+#endif
+
+struct pdc_tlb { /* for PDC_TLB */
+ unsigned long min_size;
+ unsigned long max_size;
+ unsigned long pad[32-2];
+} __attribute__((aligned(8))) ;
+
+struct pdc_system_map { /* PDC_SYTEM_MAP/FIND_MODULE */
+ void * mod_addr;
+ unsigned long mod_pgs;
+ unsigned long add_addrs;
+ unsigned long filler[29];
+} __attribute__((aligned(8))) ;
+
+/*
+ * Device path specifications used by PDC.
+ */
+struct pdc_module_path {
+ char flags; /* see bit definitions below */
+ char bc[6]; /* Bus Converter routing info to a specific */
+ /* I/O adaptor (< 0 means none, > 63 resvd) */
+ char mod; /* fixed field of specified module */
+ unsigned int layers[6]; /* device-specific info (ctlr #, unit # ...) */
+} __attribute__((aligned(8))) ;
+
+#ifndef __LP64__
+/* Probably needs 64-bit porting -PB */
+struct pdc_memory_map { /* PDC_MEMORY_MAP */
+ unsigned int hpa; /* mod's register set address */
+ unsigned int more_pgs; /* number of additional I/O pgs */
+} __attribute__((aligned(8))) ;
+
+struct pdc_lan_station_id { /* PDC_LAN_STATION_ID */
+ unsigned char addr[PDC_LAN_STATION_ID_SIZE];
+ unsigned char pad0[2];
+ int pad1[30];
+};
+#endif
+
+struct pdc_tod {
+ unsigned long tod_sec;
+ unsigned long tod_usec;
+ long pad[30];
+} __attribute__((aligned(8))) ;
+
+/* architected results from PDC_PIM/transfer hpmc on a PA1.1 machine */
+
+struct pdc_hpmc_pim_11 { /* PDC_PIM */
+ __u32 gr[32];
+ __u32 cr[32];
+ __u32 sr[8];
+ __u32 iasq_back;
+ __u32 iaoq_back;
+ __u32 check_type;
+ __u32 cpu_state;
+ __u32 rsvd1;
+ __u32 cache_check;
+ __u32 tlb_check;
+ __u32 bus_check;
+ __u32 assists_check;
+ __u32 rsvd2;
+ __u32 assist_state;
+ __u32 responder_addr;
+ __u32 requestor_addr;
+ __u32 path_info;
+ __u64 fr[32];
+};
+
+/*
+ * architected results from PDC_PIM/transfer hpmc on a PA2.0 machine
+ *
+ * Note that PDC_PIM doesn't care whether or not wide mode was enabled
+ * so the results are different on PA1.1 vs. PA2.0 when in narrow mode.
+ *
+ * Note also that there are unarchitected results available, which
+ * are hversion dependent. Do a "ser pim 0 hpmc" after rebooting, since
+ * the firmware is probably the best way of printing hversion dependent
+ * data.
+ */
+
+struct pdc_hpmc_pim_20 { /* PDC_PIM */
+ __u64 gr[32];
+ __u64 cr[32];
+ __u64 sr[8];
+ __u64 iasq_back;
+ __u64 iaoq_back;
+ __u32 check_type;
+ __u32 cpu_state;
+ __u32 cache_check;
+ __u32 tlb_check;
+ __u32 bus_check;
+ __u32 assists_check;
+ __u32 assist_state;
+ __u32 path_info;
+ __u64 responder_addr;
+ __u64 requestor_addr;
+ __u64 fr[32];
+};
+
+#endif /* __ASSEMBLY__ */
+
+/* flags of the device_path (see below) */
+#define PF_AUTOBOOT 0x80
+#define PF_AUTOSEARCH 0x40
+#define PF_TIMER 0x0F
+
+#ifndef __ASSEMBLY__
+
+struct device_path { /* page 1-69 */
+ unsigned char flags; /* flags see above! */
+ unsigned char bc[6]; /* bus converter routing info */
+ unsigned char mod;
+ unsigned int layers[6];/* device-specific layer-info */
+} __attribute__((aligned(8))) ;
+
+struct pz_device {
+ struct device_path dp; /* see above */
+ /* struct iomod *hpa; */
+ unsigned int hpa; /* HPA base address */
+ /* char *spa; */
+ unsigned int spa; /* SPA base address */
+ /* int (*iodc_io)(struct iomod*, ...); */
+ unsigned int iodc_io; /* device entry point */
+ short pad; /* reserved */
+ unsigned short cl_class;/* see below */
+} __attribute__((aligned(8))) ;
+
+#endif /* __ASSEMBLY__ */
+
+/* cl_class
+ * page 3-33 of IO-Firmware ARS
+ * IODC ENTRY_INIT(Search first) RET[1]
+ */
+#define CL_NULL 0 /* invalid */
+#define CL_RANDOM 1 /* random access (as disk) */
+#define CL_SEQU 2 /* sequential access (as tape) */
+#define CL_DUPLEX 7 /* full-duplex point-to-point (RS-232, Net) */
+#define CL_KEYBD 8 /* half-duplex console (HIL Keyboard) */
+#define CL_DISPL 9 /* half-duplex console (display) */
+#define CL_FC 10 /* FiberChannel access media */
+
+#if 0
+/* FIXME: DEVCLASS_* duplicates CL_* (above). Delete DEVCLASS_*? */
+#define DEVCLASS_RANDOM 1
+#define DEVCLASS_SEQU 2
+#define DEVCLASS_DUPLEX 7
+#define DEVCLASS_KEYBD 8
+#define DEVCLASS_DISP 9
+#endif
+
+/* IODC ENTRY_INIT() */
+#define ENTRY_INIT_SRCH_FRST 2
+#define ENTRY_INIT_SRCH_NEXT 3
+#define ENTRY_INIT_MOD_DEV 4
+#define ENTRY_INIT_DEV 5
+#define ENTRY_INIT_MOD 6
+#define ENTRY_INIT_MSG 9
+
+/* IODC ENTRY_IO() */
+#define ENTRY_IO_BOOTIN 0
+#define ENTRY_IO_CIN 2
+#define ENTRY_IO_COUT 3
+#define ENTRY_IO_CLOSE 4
+#define ENTRY_IO_GETMSG 9
+
+/* IODC ENTRY_SPA() */
+
+/* IODC ENTRY_CONFIG() */
+
+/* IODC ENTRY_TEST() */
+
+/* IODC ENTRY_TLB() */
+
+
+/* DEFINITION OF THE ZERO-PAGE (PAG0) */
+/* based on work by Jason Eckhardt (jason@equator.com) */
+
+#ifndef __ASSEMBLY__
+
+#define PAGE0 ((struct zeropage *)0xc0000000)
+
+struct zeropage {
+ /* [0x000] initialize vectors (VEC) */
+ unsigned int vec_special; /* must be zero */
+ /* int (*vec_pow_fail)(void);*/
+ unsigned int vec_pow_fail; /* power failure handler */
+ /* int (*vec_toc)(void); */
+ unsigned int vec_toc;
+ unsigned int vec_toclen;
+ /* int (*vec_rendz)(void); */
+ unsigned int vec_rendz;
+ int vec_pow_fail_flen;
+ int vec_pad[10];
+
+ /* [0x040] reserved processor dependent */
+ int pad0[112];
+
+ /* [0x200] reserved */
+ int pad1[84];
+
+ /* [0x350] memory configuration (MC) */
+ int memc_cont; /* contiguous mem size (bytes) */
+ int memc_phsize; /* physical memory size */
+ int memc_adsize; /* additional mem size, bytes of SPA space used by PDC */
+ unsigned int mem_pdc_hi; /* used for 64-bit */
+
+ /* [0x360] various parameters for the boot-CPU */
+ /* unsigned int *mem_booterr[8]; */
+ unsigned int mem_booterr[8]; /* ptr to boot errors */
+ unsigned int mem_free; /* first location, where OS can be loaded */
+ /* struct iomod *mem_hpa; */
+ unsigned int mem_hpa; /* HPA of the boot-CPU */
+ /* int (*mem_pdc)(int, ...); */
+ unsigned int mem_pdc; /* PDC entry point */
+ unsigned int mem_10msec; /* number of clock ticks in 10msec */
+
+ /* [0x390] initial memory module (IMM) */
+ /* struct iomod *imm_hpa; */
+ unsigned int imm_hpa; /* HPA of the IMM */
+ int imm_soft_boot; /* 0 = was hard boot, 1 = was soft boot */
+ unsigned int imm_spa_size; /* SPA size of the IMM in bytes */
+ unsigned int imm_max_mem; /* bytes of mem in IMM */
+
+ /* [0x3A0] boot console, display device and keyboard */
+ struct pz_device mem_cons; /* description of console device */
+ struct pz_device mem_boot; /* description of boot device */
+ struct pz_device mem_kbd; /* description of keyboard device */
+
+ /* [0x430] reserved */
+ int pad430[116];
+
+ /* [0x600] processor dependent */
+ __u32 pad600[1];
+ __u32 proc_sti; /* pointer to STI ROM */
+ __u32 pad608[126];
+};
+
+#endif /* __ASSEMBLY__ */
+
+/* Page Zero constant offsets used by the HPMC handler */
+
+#define BOOT_CONSOLE_HPA_OFFSET 0x3c0
+#define BOOT_CONSOLE_SPA_OFFSET 0x3c4
+#define BOOT_CONSOLE_PATH_OFFSET 0x3a8
+
+#ifndef __ASSEMBLY__
+
+struct pdc_pat_io_num {
+ unsigned long num;
+ unsigned long reserved[31];
+};
+
+
+
+extern void pdc_console_init(void);
+extern int pdc_getc(void); /* wait for char */
+extern void pdc_putc(unsigned char); /* print char */
+
+
+/* wrapper-functions from pdc.c */
+
+int pdc_add_valid(void *address);
+int pdc_hpa_processor(void *address);
+#if 0
+int pdc_hpa_modules(void *address);
+#endif
+int pdc_iodc_read(void *address, void *hpa, unsigned int index,
+ void *iodc_data, unsigned int iodc_data_size);
+int pdc_system_map_find_mods(void *pdc_mod_info, void *mod_path, int index);
+int pdc_model_info(struct pdc_model *model);
+int pdc_model_sysmodel(char *name);
+int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id);
+int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id);
+int pdc_cache_info(struct pdc_cache_info *cache);
+#ifndef __LP64__
+int pdc_btlb_info( struct pdc_btlb_info *btlb);
+int pdc_lan_station_id( char *lan_addr, void *net_hpa);
+#endif
+int pdc_mem_map_hpa(void *r_addr, void *mod_path);
+
+extern int pdc_chassis_disp(unsigned long disp);
+extern int pdc_chassis_info(void *pdc_result, void *chassis_info, unsigned long len);
+
+#ifdef __LP64__
+int pdc_pat_get_irt_size(void *r_addr, unsigned long cell_num);
+int pdc_pat_get_irt(void *r_addr, unsigned long cell_num);
+#else
+/* No PAT support for 32-bit kernels...sorry */
+#define pdc_pat_get_irt_size(r_addr, cell_numn) PDC_RET_NE_PROC
+#define pdc_pat_get_irt(r_addr, cell_num) PDC_RET_NE_PROC
+#endif
+int pdc_pci_irt_size(void *r_addr, void *hpa);
+int pdc_pci_irt(void *r_addr, void *hpa, void *tbl);
+
+int pdc_tod_read(struct pdc_tod *tod);
+int pdc_tod_set(unsigned long sec, unsigned long usec);
+
+/* on all currently-supported platforms, IODC I/O calls are always
+ * 32-bit calls, and MEM_PDC calls are always the same width as the OS.
+ * This means Cxxx boxes can't run wide kernels right now. -PB
+ *
+ * Note that some PAT boxes may have 64-bit IODC I/O...
+ */
+#ifdef __LP64__
+# define mem_pdc_call(args...) real64_call(0L, ##args)
+#else
+# define mem_pdc_call(args...) real32_call(0L, ##args)
+#endif
+/* yes 'int', not 'long' -- IODC I/O is always 32-bit stuff */
+extern long real64_call(unsigned long function, ...);
+extern long real32_call(unsigned long function, ...);
+extern void pdc_init(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PARISC_PDC_H */
diff --git a/include/asm-parisc/pdcpat.h b/include/asm-parisc/pdcpat.h
new file mode 100644
index 000000000..38fb2597f
--- /dev/null
+++ b/include/asm-parisc/pdcpat.h
@@ -0,0 +1,247 @@
+#ifndef __PARISC_PATPDC_H
+#define __PARISC_PATPDC_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) Hewlett Packard (Paul Bame <bame@puffin.external.hp.com>)
+ * Copyright 2000 (c) Grant Grundler <grundler@puffin.external.hp.com>
+ */
+
+
+/* PDC PAT CELL */
+#define PDC_PAT_CELL 64L /* Interface for gaining and
+ * manipulatin g cell state within PD */
+#define PDC_PAT_CELL_GET_NUMBER 0L /* Return Cell number */
+#define PDC_PAT_CELL_GET_INFO 1L /* Returns info about Cell */
+#define PDC_PAT_CELL_MODULE 2L /* Returns info about Module */
+#define PDC_PAT_CELL_SET_ATTENTION 9L /* Set Cell Attention indicator */
+#define PDC_PAT_CELL_NUMBER_TO_LOC 10L /* Cell Number -> Location */
+#define PDC_PAT_CELL_WALK_FABRIC 11L /* Walk the Fabric */
+#define PDC_PAT_CELL_GET_RDT_SIZE 12L /* Return Route Distance Table Sizes */
+#define PDC_PAT_CELL_GET_RDT 13L /* Return Route Distance Tables */
+#define PDC_PAT_CELL_GET_LOCAL_PDH_SZ 14L /* Read Local PDH Buffer Size */
+#define PDC_PAT_CELL_SET_LOCAL_PDH 15L /* Write Local PDH Buffer */
+#define PDC_PAT_CELL_GET_REMOTE_PDH_SZ 16L /* Return Remote PDH Buffer Size */
+#define PDC_PAT_CELL_GET_REMOTE_PDH 17L /* Read Remote PDH Buffer */
+#define PDC_PAT_CELL_GET_DBG_INFO 128L /* Return DBG Buffer Info */
+#define PDC_PAT_CELL_CHANGE_ALIAS 129L /* Change Non-Equivalent Alias Chacking */
+
+
+/*
+** Arg to PDC_PAT_CELL_MODULE memaddr[4]
+**
+** Addresses on the Merced Bus != all Runway Bus addresses.
+** This is intended for programming SBA/LBA chips range registers.
+*/
+#define IO_VIEW 0UL
+#define PA_VIEW 1UL
+
+/* PDC_PAT_CELL_MODULE entity type values */
+#define PAT_ENTITY_CA 0 /* central agent */
+#define PAT_ENTITY_PROC 1 /* processor */
+#define PAT_ENTITY_MEM 2 /* memory controller */
+#define PAT_ENTITY_SBA 3 /* system bus adapter */
+#define PAT_ENTITY_LBA 4 /* local bus adapter */
+#define PAT_ENTITY_PBC 5 /* processor bus converter */
+#define PAT_ENTITY_XBC 6 /* crossbar fabric connect */
+#define PAT_ENTITY_RC 7 /* fabric interconnect */
+
+/* PDC_PAT_CELL_MODULE address range type values */
+#define PAT_PBNUM 0 /* PCI Bus Number */
+#define PAT_LMMIO 1 /* < 4G MMIO Space */
+#define PAT_GMMIO 2 /* > 4G MMIO Space */
+#define PAT_NPIOP 3 /* Non Postable I/O Port Space */
+#define PAT_PIOP 4 /* Postable I/O Port Space */
+#define PAT_AHPA 5 /* Addional HPA Space */
+#define PAT_UFO 6 /* HPA Space (UFO for Mariposa) */
+#define PAT_GNIP 7 /* GNI Reserved Space */
+
+
+/* PDC PAT CHASSIS LOG */
+
+#define PDC_PAT_CHASSIS_LOG 65L /* Platform logging & forward
+ ** progress functions */
+#define PDC_PAT_CHASSIS_WRITE_LOG 0L /* Write Log Entry */
+#define PDC_PAT_CHASSIS_READ_LOG 1L /* Read Log Entry */
+
+/* PDC PAT CPU */
+
+#define PDC_PAT_CPU 67L /* Interface to CPU configuration
+ * within the protection domain */
+#define PDC_PAT_CPU_INFO 0L /* Return CPU config info */
+#define PDC_PAT_CPU_DELETE 1L /* Delete CPU */
+#define PDC_PAT_CPU_ADD 2L /* Add CPU */
+#define PDC_PAT_CPU_GET_NUMBER 3L /* Return CPU Number */
+#define PDC_PAT_CPU_GET_HPA 4L /* Return CPU HPA */
+#define PDC_PAT_CPU_STOP 5L /* Stop CPU */
+#define PDC_PAT_CPU_RENDEZVOUS 6L /* Rendezvous CPU */
+#define PDC_PAT_CPU_GET_CLOCK_INFO 7L /* Return CPU Clock info */
+#define PDC_PAT_CPU_GET_RENDEZVOUS_STATE 8L /* Return Rendezvous State */
+#define PDC_PAT_CPU_PLUNGE_FABRIC 128L /* Plunge Fabric */
+#define PDC_PAT_CPU_UPDATE_CACHE_CLEANSING 129L /* Manipulate Cache
+ * Cleansing Mode */
+/* PDC PAT EVENT */
+
+#define PDC_PAT_EVENT 68L /* Interface to Platform Events */
+#define PDC_PAT_EVENT_GET_CAPS 0L /* Get Capabilities */
+#define PDC_PAT_EVENT_SET_MODE 1L /* Set Notification Mode */
+#define PDC_PAT_EVENT_SCAN 2L /* Scan Event */
+#define PDC_PAT_EVENT_HANDLE 3L /* Handle Event */
+#define PDC_PAT_EVENT_GET_NB_CALL 4L /* Get Non-Blocking call Args */
+
+/* PDC PAT HPMC */
+
+#define PDC_PAT_HPMC 70L /* Cause processor to go into spin
+ ** loop, and wait for wake up from
+ ** Monarch Processor */
+#define PDC_PAT_HPMC_RENDEZ_CPU 0L /* go into spin loop */
+#define PDC_PAT_HPMC_SET_PARAMS 1L /* Allows OS to specify intr which PDC
+ * will use to interupt OS during machine
+ * check rendezvous */
+
+/* parameters for PDC_PAT_HPMC_SET_PARAMS: */
+#define HPMC_SET_PARAMS_INTR 1L /* Rendezvous Interrupt */
+#define HPMC_SET_PARAMS_WAKE 2L /* Wake up processor */
+
+/* PDC PAT IO */
+
+#define PDC_PAT_IO 71L /* On-line services for I/O modules */
+#define PDC_PAT_IO_GET_SLOT_STATUS 5L /* Get Slot Status Info*/
+#define PDC_PAT_IO_GET_LOC_FROM_HARDWARE 6L /* Get Physical Location from */
+ /* Hardware Path */
+#define PDC_PAT_IO_GET_HARDWARE_FROM_LOC 7L /* Get Hardware Path from
+ * Physical Location */
+#define PDC_PAT_IO_GET_PCI_CONFIG_FROM_HW 11L /* Get PCI Configuration
+ * Address from Hardware Path */
+#define PDC_PAT_IO_GET_HW_FROM_PCI_CONFIG 12L /* Get Hardware Path
+ * from PCI Configuration Address */
+#define PDC_PAT_IO_READ_HOST_BRIDGE_INFO 13L /* Read Host Bridge State Info */
+#define PDC_PAT_IO_CLEAR_HOST_BRIDGE_INFO 14L /* Clear Host Bridge State Info*/
+#define PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE 15L /* Get PCI INT Routing Table
+ * Size */
+#define PDC_PAT_IO_GET_PCI_ROUTING_TABLE 16L /* Get PCI INT Routing Table */
+#define PDC_PAT_IO_GET_HINT_TABLE_SIZE 17L /* Get Hint Table Size */
+#define PDC_PAT_IO_GET_HINT_TABLE 18L /* Get Hint Table */
+#define PDC_PAT_IO_PCI_CONFIG_READ 19L /* PCI Config Read */
+#define PDC_PAT_IO_PCI_CONFIG_WRITE 20L /* PCI Config Write */
+#define PDC_PAT_IO_GET_NUM_IO_SLOTS 21L /* Get Number of I/O Bay Slots in
+ * Cabinet */
+#define PDC_PAT_IO_GET_LOC_IO_SLOTS 22L /* Get Physical Location of I/O */
+ /* Bay Slots in Cabinet */
+#define PDC_PAT_IO_BAY_STATUS_INFO 28L /* Get I/O Bay Slot Status Info */
+#define PDC_PAT_IO_GET_PROC_VIEW 29L /* Get Processor view of IO address */
+#define PDC_PAT_IO_PROG_SBA_DIR_RANGE 30L /* Program directed range */
+
+/* PDC PAT MEM */
+
+#define PDC_PAT_MEM 72L /* Manage memory page deallocation */
+#define PDC_PAT_MEM_PD_INFO 0L /* Return PDT info for PD */
+#define PDC_PAT_MEM_PD_CLEAR 1L /* Clear PDT for PD */
+#define PDC_PAT_MEM_PD_READ 2L /* Read PDT entries for PD */
+#define PDC_PAT_MEM_PD_RESET 3L /* Reset clear bit for PD */
+#define PDC_PAT_MEM_CELL_INFO 5L /* Return PDT info For Cell */
+#define PDC_PAT_MEM_CELL_CLEAR 6L /* Clear PDT For Cell */
+#define PDC_PAT_MEM_CELL_READ 7L /* Read PDT entries For Cell */
+#define PDC_PAT_MEM_CELL_RESET 8L /* Reset clear bit For Cell */
+#define PDC_PAT_MEM_SETGM 9L /* Set Golden Memory value */
+#define PDC_PAT_MEM_ADD_PAGE 10L /* ADDs a page to the cell */
+#define PDC_PAT_MEM_ADDRESS 11L /* Get Physical Location From */
+ /* Memory Address */
+#define PDC_PAT_MEM_GET_TXT_SIZE 12L /* Get Formatted Text Size */
+#define PDC_PAT_MEM_GET_PD_TXT 13L /* Get PD Formatted Text */
+#define PDC_PAT_MEM_GET_CELL_TXT 14L /* Get Cell Formatted Text */
+#define PDC_PAT_MEM_RD_STATE_INFO 15L /* Read Mem Module State Info*/
+#define PDC_PAT_MEM_CLR_STATE_INFO 16L /*Clear Mem Module State Info*/
+#define PDC_PAT_MEM_CLEAN_RANGE 128L /*Clean Mem in specific range*/
+#define PDC_PAT_MEM_GET_TBL_SIZE 131L /* Get Memory Table Size */
+#define PDC_PAT_MEM_GET_TBL 132L /* Get Memory Table */
+
+/* PDC PAT NVOLATILE */
+
+#define PDC_PAT_NVOLATILE 73L /* Access Non-Volatile Memory */
+#define PDC_PAT_NVOLATILE_READ 0L /* Read Non-Volatile Memory */
+#define PDC_PAT_NVOLATILE_WRITE 1L /* Write Non-Volatile Memory */
+#define PDC_PAT_NVOLATILE_GET_SIZE 2L /* Return size of NVM */
+#define PDC_PAT_NVOLATILE_VERIFY 3L /* Verify contents of NVM */
+#define PDC_PAT_NVOLATILE_INIT 4L /* Initialize NVM */
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+
+/*
+** PDC_PAT_CELL_GET_INFO return block
+*/
+typedef struct pdc_pat_cell_info_rtn_block {
+ unsigned long cpu_info;
+ unsigned long cell_info;
+ unsigned long cell_location;
+ unsigned long reo_location;
+ unsigned long mem_size;
+ unsigned long dimm_status;
+ unsigned long pdc_rev;
+ unsigned long fabric_info0;
+ unsigned long fabric_info1;
+ unsigned long fabric_info2;
+ unsigned long fabric_info3;
+ unsigned long reserved[21];
+} pdc_pat_cell_info_rtn_block_t;
+
+
+/* FIXME: mod[508] should really be a union of the various mod components */
+struct pdc_pat_cell_mod_maddr_block { /* PDC_PAT_CELL_MODULE */
+ unsigned long cba; /* function 0 configuration space address */
+ unsigned long mod_info; /* module information */
+ unsigned long mod_location; /* physical location of the module */
+ unsigned long mod_path; /* module path (device path - layers) */
+ unsigned long mod[508]; /* PAT cell module components */
+} __attribute__((aligned(8))) ;
+
+typedef struct pdc_pat_cell_mod_maddr_block pdc_pat_cell_mod_maddr_block_t;
+
+
+extern int pdc_pat_cell_get_number(void *);
+extern int pdc_pat_cell_module(void *, unsigned long, unsigned long, unsigned long, void *);
+extern int pdc_pat_cell_num_to_loc(void *, unsigned long);
+
+/* Flag to indicate this is a PAT box...don't use this unless you
+** really have to...it might go away some day.
+*/
+#ifdef __LP64__
+extern int pdc_pat; /* arch/parisc/kernel/inventory.c */
+#endif
+
+/********************************************************************
+* PDC_PAT_CELL[Return Cell Module] memaddr[0] conf_base_addr
+* ----------------------------------------------------------
+* Bit 0 to 51 - conf_base_addr
+* Bit 52 to 62 - reserved
+* Bit 63 - endianess bit
+********************************************************************/
+#define PAT_GET_CBA(value) ((value) & 0xfffffffffffff000UL)
+
+/********************************************************************
+* PDC_PAT_CELL[Return Cell Module] memaddr[1] mod_info
+* ----------------------------------------------------
+* Bit 0 to 7 - entity type
+* 0 = central agent, 1 = processor,
+* 2 = memory controller, 3 = system bus adapter,
+* 4 = local bus adapter, 5 = processor bus converter,
+* 6 = crossbar fabric connect, 7 = fabric interconnect,
+* 8 to 254 reserved, 255 = unknown.
+* Bit 8 to 15 - DVI
+* Bit 16 to 23 - IOC functions
+* Bit 24 to 39 - reserved
+* Bit 40 to 63 - mod_pages
+* number of 4K pages a module occupies starting at conf_base_addr
+********************************************************************/
+#define PAT_GET_ENTITY(value) (((value) >> 56) & 0xffUL)
+#define PAT_GET_DVI(value) (((value) >> 48) & 0xffUL)
+#define PAT_GET_IOC(value) (((value) >> 40) & 0xffUL)
+#define PAT_GET_MOD_PAGES(value)(((value) & 0xffffffUL)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* ! __PARISC_PATPDC_H */
diff --git a/include/asm-parisc/pgalloc.h b/include/asm-parisc/pgalloc.h
new file mode 100644
index 000000000..1d9365252
--- /dev/null
+++ b/include/asm-parisc/pgalloc.h
@@ -0,0 +1,404 @@
+#ifndef _ASM_PGALLOC_H
+#define _ASM_PGALLOC_H
+
+/* The usual comment is "Caches aren't brain-dead on the <architecture>".
+ * Unfortunately, that doesn't apply to PA-RISC. */
+
+#include <asm/processor.h>
+#include <asm/fixmap.h>
+#include <linux/threads.h>
+
+#include <asm/pgtable.h>
+#include <asm/cache.h>
+
+
+/* Internal use D/I cache flushing routines... */
+/* XXX: these functions must not access memory between f[di]ce instructions. */
+
+static inline void __flush_dcache_range(unsigned long start, unsigned long size)
+{
+#if 0
+ register unsigned long count = (size / L1_CACHE_BYTES);
+ register unsigned long loop = cache_info.dc_loop;
+ register unsigned long i, j;
+
+ if (size > 64 * 1024) {
+ /* Just punt and clear the whole damn thing */
+ flush_data_cache();
+ return;
+ }
+
+ for(i = 0; i <= count; i++, start += L1_CACHE_BYTES)
+ for(j = 0; j < loop; j++)
+ fdce(start);
+#else
+ flush_data_cache();
+#endif
+}
+
+
+static inline void __flush_icache_range(unsigned long start, unsigned long size)
+{
+#if 0
+ register unsigned long count = (size / L1_CACHE_BYTES);
+ register unsigned long loop = cache_info.ic_loop;
+ register unsigned long i, j;
+
+ if (size > 64 * 1024) {
+ /* Just punt and clear the whole damn thing */
+ flush_instruction_cache();
+ return;
+ }
+
+ for(i = 0; i <= count; i++, start += L1_CACHE_BYTES)
+ for(j = 0; j < loop; j++)
+ fice(start);
+#else
+ flush_instruction_cache();
+#endif
+}
+
+static inline void
+flush_kernel_dcache_range(unsigned long start, unsigned long size)
+{
+ register unsigned long end = start + size;
+ register unsigned long i;
+
+ start &= ~(L1_CACHE_BYTES - 1);
+ for (i = start; i < end; i += L1_CACHE_BYTES) {
+ kernel_fdc(i);
+ }
+ asm volatile("sync" : : );
+ asm volatile("syncdma" : : );
+}
+
+extern void __flush_page_to_ram(unsigned long address);
+
+#define flush_cache_all() flush_all_caches()
+#define flush_cache_mm(foo) flush_all_caches()
+
+#if 0
+/* This is how I think the cache flushing should be done -- mrw */
+extern inline void flush_cache_mm(struct mm_struct *mm) {
+ if (mm == current->mm) {
+ flush_user_dcache_range(mm->start_data, mm->end_data);
+ flush_user_icache_range(mm->start_code, mm->end_code);
+ } else {
+ flush_other_dcache_range(mm->context, mm->start_data, mm->end_data);
+ flush_other_icache_range(mm->context, mm->start_code, mm->end_code);
+ }
+}
+#endif
+
+#define flush_cache_range(mm, start, end) do { \
+ __flush_dcache_range(start, (unsigned long)end - (unsigned long)start); \
+ __flush_icache_range(start, (unsigned long)end - (unsigned long)start); \
+} while(0)
+
+#define flush_cache_page(vma, vmaddr) do { \
+ __flush_dcache_range(vmaddr, PAGE_SIZE); \
+ __flush_icache_range(vmaddr, PAGE_SIZE); \
+} while(0)
+
+#define flush_page_to_ram(page) \
+ __flush_page_to_ram((unsigned long)page_address(page))
+
+#define flush_icache_range(start, end) \
+ __flush_icache_range(start, end - start)
+
+#define flush_icache_page(vma, page) \
+ __flush_icache_range(page_address(page), PAGE_SIZE)
+
+#define flush_dcache_page(page) \
+ __flush_dcache_range(page_address(page), PAGE_SIZE)
+
+/* TLB flushing routines.... */
+
+extern void flush_data_tlb(void);
+extern void flush_instruction_tlb(void);
+
+#define flush_tlb() do { \
+ flush_data_tlb(); \
+ flush_instruction_tlb(); \
+} while(0);
+
+#define flush_tlb_all() flush_tlb() /* XXX p[id]tlb */
+
+extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+}
+
+static inline void flush_instruction_tlb_range(unsigned long start,
+ unsigned long size)
+{
+#if 0
+ register unsigned long count = (size / PAGE_SIZE);
+ register unsigned long loop = cache_info.it_loop;
+ register unsigned long i, j;
+
+ for(i = 0; i <= count; i++, start += PAGE_SIZE)
+ for(j = 0; j < loop; j++)
+ pitlbe(start);
+#else
+ flush_instruction_tlb();
+#endif
+}
+
+static inline void flush_data_tlb_range(unsigned long start,
+ unsigned long size)
+{
+#if 0
+ register unsigned long count = (size / PAGE_SIZE);
+ register unsigned long loop = cache_info.dt_loop;
+ register unsigned long i, j;
+
+ for(i = 0; i <= count; i++, start += PAGE_SIZE)
+ for(j = 0; j < loop; j++)
+ pdtlbe(start);
+#else
+ flush_data_tlb();
+#endif
+}
+
+
+
+static inline void __flush_tlb_range(unsigned long space, unsigned long start,
+ unsigned long size)
+{
+ unsigned long old_sr1;
+
+ if(!size)
+ return;
+
+ old_sr1 = mfsp(1);
+ mtsp(space, 1);
+
+ flush_data_tlb_range(start, size);
+ flush_instruction_tlb_range(start, size);
+
+ mtsp(old_sr1, 1);
+}
+
+extern void __flush_tlb_space(unsigned long space);
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+#if 0
+ __flush_tlb_space(mm->context);
+#else
+ flush_tlb();
+#endif
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ __flush_tlb_range(vma->vm_mm->context, addr, PAGE_SIZE);
+
+}
+
+static inline void flush_tlb_range(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+ __flush_tlb_range(mm->context, start, end - start);
+}
+
+/*
+ * NOTE: Many of the below macros use PT_NLEVELS because
+ * it is convenient that PT_NLEVELS == LOG2(pte size in bytes),
+ * i.e. we use 3 level page tables when we use 8 byte pte's
+ * (for 64 bit) and 2 level page tables when we use 4 byte pte's
+ */
+
+#ifdef __LP64__
+#define PT_NLEVELS 3
+#define PT_INITIAL 4 /* Number of initial page tables */
+#else
+#define PT_NLEVELS 2
+#define PT_INITIAL 2 /* Number of initial page tables */
+#endif
+
+/* Definitions for 1st level */
+
+#define PGDIR_SHIFT (PAGE_SHIFT + (PT_NLEVELS - 1)*(PAGE_SHIFT - PT_NLEVELS))
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+#define PTRS_PER_PGD (1UL << (PAGE_SHIFT - PT_NLEVELS))
+#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
+
+/* Definitions for 2nd level */
+
+#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PT_NLEVELS))
+#define PMD_SIZE (1UL << PMD_SHIFT)
+#define PMD_MASK (~(PMD_SIZE-1))
+#if PT_NLEVELS == 3
+#define PTRS_PER_PMD (1UL << (PAGE_SHIFT - PT_NLEVELS))
+#else
+#define PTRS_PER_PMD 1
+#endif
+
+/* Definitions for 3rd level */
+
+#define PTRS_PER_PTE (1UL << (PAGE_SHIFT - PT_NLEVELS))
+
+
+#define get_pgd_fast get_pgd_slow
+#define free_pgd_fast free_pgd_slow
+
+extern __inline__ pgd_t *get_pgd_slow(void)
+{
+ extern unsigned long gateway_pgd_offset;
+ extern unsigned long gateway_pgd_entry;
+ pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+ if (ret) {
+ memset (ret, 0, PTRS_PER_PGD * sizeof(pgd_t));
+
+ /* Install HP-UX and Linux gateway page translations */
+
+ pgd_val(*(ret + gateway_pgd_offset)) = gateway_pgd_entry;
+ }
+ return ret;
+}
+
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
+{
+ free_page((unsigned long)pgd);
+}
+
+#if PT_NLEVELS == 3
+
+/* Three Level Page Table Support for pmd's */
+
+extern __inline__ pmd_t *get_pmd_fast(void)
+{
+ return NULL; /* la la */
+}
+
+#if 0
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
+{
+}
+#else
+#define free_pmd_fast free_pmd_slow
+#endif
+
+extern __inline__ pmd_t *get_pmd_slow(void)
+{
+ pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+
+ if (pmd)
+ clear_page(pmd);
+ return pmd;
+}
+
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
+{
+ free_page((unsigned long)pmd);
+}
+
+extern void __bad_pgd(pgd_t *pgd);
+
+extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
+{
+ address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
+
+ if (pgd_none(*pgd))
+ goto getnew;
+ if (pgd_bad(*pgd))
+ goto fix;
+ return (pmd_t *) pgd_page(*pgd) + address;
+getnew:
+{
+ pmd_t *page = get_pmd_fast();
+
+ if (!page)
+ page = get_pmd_slow();
+ if (page) {
+ if (pgd_none(*pgd)) {
+ pgd_val(*pgd) = _PAGE_TABLE + __pa((unsigned long)page);
+ return page + address;
+ }
+ else
+ free_pmd_fast(page);
+ }
+ else {
+ return NULL;
+ }
+}
+fix:
+ __bad_pgd(pgd);
+ return NULL;
+}
+
+#else
+
+/* Two Level Page Table Support for pmd's */
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+ return (pmd_t *) pgd;
+}
+
+extern inline void free_pmd_fast(pmd_t * pmd)
+{
+}
+
+#endif
+
+extern __inline__ pte_t *get_pte_fast(void)
+{
+ return NULL; /* la la */
+}
+
+#if 0
+extern __inline__ void free_pte_fast(pte_t *pte)
+{
+}
+#else
+#define free_pte_fast free_pte_slow
+#endif
+
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+
+extern __inline__ void free_pte_slow(pte_t *pte)
+{
+ free_page((unsigned long)pte);
+}
+
+#define pmd_alloc_kernel pmd_alloc
+#define pte_alloc_kernel pte_alloc
+
+#define pte_free(pte) free_pte_fast(pte)
+#define pmd_free(pmd) free_pmd_fast(pmd)
+#define pgd_free(pgd) free_pgd_fast(pgd)
+#define pgd_alloc() get_pgd_fast()
+
+extern void __bad_pmd(pmd_t *pmd);
+
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+ address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+
+ if (pmd_none(*pmd))
+ goto getnew;
+ if (pmd_bad(*pmd))
+ goto fix;
+ return (pte_t *) pmd_page(*pmd) + address;
+getnew:
+{
+ pte_t *page = get_pte_fast();
+
+ if (!page)
+ return get_pte_slow(pmd, address);
+ pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)page);
+ return page + address;
+}
+fix:
+ __bad_pmd(pmd);
+ return NULL;
+}
+
+extern int do_check_pgt_cache(int, int);
+
+#endif
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
new file mode 100644
index 000000000..6213ab850
--- /dev/null
+++ b/include/asm-parisc/pgtable.h
@@ -0,0 +1,337 @@
+#ifndef _PARISC_PGTABLE_H
+#define _PARISC_PGTABLE_H
+
+#ifndef __ASSEMBLY__
+/*
+ * we simulate an x86-style page table for the linux mm code
+ */
+
+#include <asm/processor.h>
+#include <asm/fixmap.h>
+#include <asm/cache.h>
+
+/* To make 53c7xx.c happy */
+
+#define IOMAP_FULL_CACHING 2 /* used for 'what' below */
+#define IOMAP_NOCACHE_SER 3
+
+extern void kernel_set_cachemode(unsigned long addr,
+ unsigned long size, int what);
+
+/*
+ * cache_clear() semantics: Clear any cache entries for the area in question,
+ * without writing back dirty entries first. This is useful if the data will
+ * be overwritten anyway, e.g. by DMA to memory. The range is defined by a
+ * _physical_ address.
+ */
+#define cache_clear(paddr, len) do { } while (0)
+/*
+ * cache_push() semantics: Write back any dirty cache data in the given area,
+ * and invalidate the range in the instruction cache. It needs not (but may)
+ * invalidate those entries also in the data cache. The range is defined by a
+ * _physical_ address.
+ */
+#define cache_push(paddr, len) \
+ do { \
+ unsigned long vaddr = phys_to_virt(paddr); \
+ flush_cache_range(&init_mm, vaddr, vaddr + len); \
+ } while(0)
+#define cache_push_v(vaddr, len) \
+ flush_cache_range(&init_mm, vaddr, vaddr + len)
+
+/*
+ * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
+ * memory. For the return value to be meaningful, ADDR must be >=
+ * PAGE_OFFSET. This operation can be relatively expensive (e.g.,
+ * require a hash-, or multi-level tree-lookup or something of that
+ * sort) but it guarantees to return TRUE only if accessing the page
+ * at that address does not cause an error. Note that there may be
+ * addresses for which kern_addr_valid() returns FALSE even though an
+ * access would not cause an error (e.g., this is typically true for
+ * memory mapped I/O regions.
+ *
+ * XXX Need to implement this for parisc.
+ */
+#define kern_addr_valid(addr) (1)
+
+/* Certain architectures need to do special things when PTEs
+ * within a page table are directly modified. Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) \
+ do{ \
+ *(pteptr) = (pteval); \
+ } while(0)
+
+
+
+#endif /* !__ASSEMBLY__ */
+
+#define pte_ERROR(e) \
+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+/*
+ * pgd entries used up by user/kernel:
+ */
+
+#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+#define FIRST_USER_PGD_NR 0
+
+#ifndef __ASSEMBLY__
+extern void *vmalloc_start;
+#define PCXL_DMA_MAP_SIZE (8*1024*1024)
+#define VMALLOC_START ((unsigned long)vmalloc_start)
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END (FIXADDR_START)
+#endif
+
+#define _PAGE_READ 0x001 /* read access allowed */
+#define _PAGE_WRITE 0x002 /* write access allowed */
+#define _PAGE_EXEC 0x004 /* execute access allowed */
+#define _PAGE_GATEWAY 0x008 /* privilege promotion allowed */
+#define _PAGE_GATEWAY_BIT 28 /* _PAGE_GATEWAY & _PAGE_GATEWAY_BIT need */
+ /* to agree. One could be defined in relation */
+ /* to the other, but that's kind of ugly. */
+
+ /* 0x010 reserved (B bit) */
+#define _PAGE_DIRTY 0x020 /* D: dirty */
+ /* 0x040 reserved (T bit) */
+#define _PAGE_NO_CACHE 0x080 /* Software: Uncacheable */
+#define _PAGE_NO_CACHE_BIT 24 /* Needs to agree with _PAGE_NO_CACHE above */
+#define _PAGE_ACCESSED 0x100 /* R: page cache referenced */
+#define _PAGE_PRESENT 0x200 /* Software: pte contains a translation */
+#define _PAGE_PRESENT_BIT 22 /* Needs to agree with _PAGE_PRESENT above */
+#define _PAGE_USER 0x400 /* Software: User accessable page */
+#define _PAGE_USER_BIT 21 /* Needs to agree with _PAGE_USER above */
+ /* 0x800 still available */
+
+#ifdef __ASSEMBLY__
+#define _PGB_(x) (1 << (63 - (x)))
+#define __PAGE_O _PGB_(13)
+#define __PAGE_U _PGB_(12)
+#define __PAGE_T _PGB_(2)
+#define __PAGE_D _PGB_(3)
+#define __PAGE_B _PGB_(4)
+#define __PAGE_P _PGB_(14)
+#endif
+#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED)
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_KERNEL (_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED)
+
+#ifndef __ASSEMBLY__
+
+#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED)
+/* Others seem to make this executable, I don't know if that's correct
+ or not. The stack is mapped this way though so this is necessary
+ in the short term - dhd@linuxcare.com, 2000-08-08 */
+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
+#define PAGE_WRITEONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_WRITE | _PAGE_ACCESSED)
+#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED)
+#define PAGE_COPY PAGE_EXECREAD
+#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED)
+#define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
+#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_DIRTY | _PAGE_ACCESSED)
+#define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
+#define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ)
+
+
+/*
+ * We could have an execute only page using "gateway - promote to priv
+ * level 3", but that is kind of silly. So, the way things are defined
+ * now, we must always have read permission for pages with execute
+ * permission. For the fun of it we'll go ahead and support write only
+ * pages.
+ */
+
+ /*xwr*/
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY
+#define __P010 __P000 /* copy on write */
+#define __P011 __P001 /* copy on write */
+#define __P100 PAGE_EXECREAD
+#define __P101 PAGE_EXECREAD
+#define __P110 __P100 /* copy on write */
+#define __P111 __P101 /* copy on write */
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_WRITEONLY
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_EXECREAD
+#define __S101 PAGE_EXECREAD
+#define __S110 PAGE_RWX
+#define __S111 PAGE_RWX
+
+extern unsigned long swapper_pg_dir[]; /* declared in init_task.c */
+
+/* initial page tables for 0-8MB for kernel */
+
+extern unsigned long pg0[];
+
+/* zero page used for uninitialized stuff */
+
+extern unsigned long *empty_zero_page;
+
+/*
+ * BAD_PAGETABLE is used when we need a bogus page-table, while
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t __bad_page(void);
+extern pte_t * __bad_pagetable(void);
+
+#define BAD_PAGETABLE __bad_pagetable()
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+#define pte_none(x) (!pte_val(x))
+#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
+#define pte_clear(xp) do { pte_val(*(xp)) = 0; } while (0)
+#define pte_pagenr(x) ((unsigned long)((pte_val(x) >> PAGE_SHIFT)))
+
+#define pmd_none(x) (!pmd_val(x))
+#define pmd_bad(x) ((pmd_val(x) & ~PAGE_MASK) != _PAGE_TABLE)
+#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
+#define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0)
+
+
+
+#ifdef __LP64__
+#define pgd_page(pgd) ((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
+
+/* For 64 bit we have three level tables */
+
+#define pgd_none(x) (!pgd_val(x))
+#define pgd_bad(x) ((pgd_val(x) & ~PAGE_MASK) != _PAGE_TABLE)
+#define pgd_present(x) (pgd_val(x) & _PAGE_PRESENT)
+#define pgd_clear(xp) do { pgd_val(*(xp)) = 0; } while (0)
+#else
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+extern inline int pgd_none(pgd_t pgd) { return 0; }
+extern inline int pgd_bad(pgd_t pgd) { return 0; }
+extern inline int pgd_present(pgd_t pgd) { return 1; }
+extern inline void pgd_clear(pgd_t * pgdp) { }
+#endif
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+
+extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_READ; return pte; }
+extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
+extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_READ; return pte; }
+extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define __mk_pte(addr,pgprot) \
+({ \
+ pte_t __pte; \
+ \
+ pte_val(__pte) = ((addr)+pgprot_val(pgprot)); \
+ \
+ __pte; \
+})
+
+#define mk_pte(page,pgprot) \
+({ \
+ pte_t __pte; \
+ \
+ pte_val(__pte) = ((page)-mem_map)*PAGE_SIZE + \
+ pgprot_val(pgprot); \
+ __pte; \
+})
+
+/* This takes a physical page address that is used by the remapping functions */
+#define mk_pte_phys(physpage, pgprot) \
+({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
+
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+
+/*
+ * Permanent address of a page. Obviously must never be
+ * called on a highmem page.
+ */
+#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; })
+#define __page_address(page) ({ if (PageHighMem(page)) BUG(); PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT); })
+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+#define pte_page(x) (mem_map+pte_pagenr(x))
+
+#define pmd_page(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+#define pgd_index(address) ((address) >> PGDIR_SHIFT)
+
+/* to find an entry in a page-table-directory */
+#define pgd_offset(mm, address) \
+((mm)->pgd + ((address) >> PGDIR_SHIFT))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* Find an entry in the second-level page table.. */
+
+#ifdef __LP64__
+#define pmd_offset(dir,address) \
+((pmd_t *) pgd_page(*(dir)) + (((address)>>PMD_SHIFT) & (PTRS_PER_PMD-1)))
+#else
+#define pmd_offset(dir,addr) ((pmd_t *) dir)
+#endif
+
+/* Find an entry in the third-level page table.. */
+#define pte_offset(pmd, address) \
+((pte_t *) pmd_page(*(pmd)) + (((address)>>PAGE_SHIFT) & (PTRS_PER_PTE-1)))
+
+extern void paging_init (void);
+
+extern inline void update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+}
+
+/* Encode and de-code a swap entry */
+
+#define SWP_TYPE(x) ((x).val & 0x3f)
+#define SWP_OFFSET(x) ( (((x).val >> 6) & 0x7) | \
+ (((x).val >> 7) & ~0x7) )
+#define SWP_ENTRY(type, offset) ((swp_entry_t) { (type) | \
+ ((offset & 0x7) << 6) | \
+ ((offset & ~0x7) << 7) })
+#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+#define module_map vmalloc
+#define module_unmap vfree
+
+#include <asm-generic/pgtable.h>
+
+#endif /* !__ASSEMBLY__ */
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define PageSkip(page) (0)
+
+#define io_remap_page_range remap_page_range
+
+#endif /* _PARISC_PAGE_H */
diff --git a/include/asm-parisc/poll.h b/include/asm-parisc/poll.h
new file mode 100644
index 000000000..55ebfcc44
--- /dev/null
+++ b/include/asm-parisc/poll.h
@@ -0,0 +1,25 @@
+#ifndef __PARISC_POLL_H
+#define __PARISC_POLL_H
+
+/* These are specified by iBCS2 */
+#define POLLIN 0x0001
+#define POLLPRI 0x0002
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
+
+/* The rest seem to be more-or-less nonstandard. Check them! */
+#define POLLRDNORM 0x0040
+#define POLLRDBAND 0x0080
+#define POLLWRNORM 0x0100
+#define POLLWRBAND 0x0200
+#define POLLMSG 0x0400
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+#endif
diff --git a/include/asm-parisc/posix_types.h b/include/asm-parisc/posix_types.h
new file mode 100644
index 000000000..58f20853d
--- /dev/null
+++ b/include/asm-parisc/posix_types.h
@@ -0,0 +1,140 @@
+#ifndef __ARCH_PARISC_POSIX_TYPES_H
+#define __ARCH_PARISC_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+typedef unsigned int __kernel_dev_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+typedef int __kernel_suseconds_t;
+typedef int __kernel_clock_t;
+typedef int __kernel_daddr_t;
+/* Note these change from narrow to wide kernels */
+typedef unsigned long __kernel_size_t;
+typedef long __kernel_ssize_t;
+typedef long __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef char * __kernel_caddr_t;
+
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
+typedef long long __kernel_off64_t;
+typedef unsigned long long __kernel_ino64_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+ int val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+ int __val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) && defined(__LP64__)
+/* Now 32bit compatibility types */
+typedef unsigned int __kernel_dev_t32;
+typedef unsigned int __kernel_ino_t32;
+typedef unsigned short __kernel_mode_t32;
+typedef unsigned short __kernel_nlink_t32;
+typedef int __kernel_off_t32;
+typedef int __kernel_pid_t32;
+typedef unsigned short __kernel_ipc_pid_t32;
+typedef unsigned int __kernel_uid_t32;
+typedef unsigned int __kernel_gid_t32;
+typedef unsigned int __kernel_size_t32;
+typedef int __kernel_ssize_t32;
+typedef int __kernel_ptrdiff_t32;
+typedef int __kernel_time_t32;
+typedef int __kernel_suseconds_t32;
+typedef int __kernel_clock_t32;
+typedef int __kernel_daddr_t32;
+typedef unsigned int __kernel_caddr_t32;
+#endif
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+ unsigned long __tmp = __fd / __NFDBITS;
+ unsigned long __rem = __fd % __NFDBITS;
+ __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+ unsigned long __tmp = __fd / __NFDBITS;
+ unsigned long __rem = __fd % __NFDBITS;
+ __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
+{
+ unsigned long __tmp = __fd / __NFDBITS;
+ unsigned long __rem = __fd % __NFDBITS;
+ return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
+{
+ unsigned long *__tmp = __p->fds_bits;
+ int __i;
+
+ if (__builtin_constant_p(__FDSET_LONGS)) {
+ switch (__FDSET_LONGS) {
+ case 16:
+ __tmp[ 0] = 0; __tmp[ 1] = 0;
+ __tmp[ 2] = 0; __tmp[ 3] = 0;
+ __tmp[ 4] = 0; __tmp[ 5] = 0;
+ __tmp[ 6] = 0; __tmp[ 7] = 0;
+ __tmp[ 8] = 0; __tmp[ 9] = 0;
+ __tmp[10] = 0; __tmp[11] = 0;
+ __tmp[12] = 0; __tmp[13] = 0;
+ __tmp[14] = 0; __tmp[15] = 0;
+ return;
+
+ case 8:
+ __tmp[ 0] = 0; __tmp[ 1] = 0;
+ __tmp[ 2] = 0; __tmp[ 3] = 0;
+ __tmp[ 4] = 0; __tmp[ 5] = 0;
+ __tmp[ 6] = 0; __tmp[ 7] = 0;
+ return;
+
+ case 4:
+ __tmp[ 0] = 0; __tmp[ 1] = 0;
+ __tmp[ 2] = 0; __tmp[ 3] = 0;
+ return;
+ }
+ }
+ __i = __FDSET_LONGS;
+ while (__i) {
+ __i--;
+ *__tmp = 0;
+ __tmp++;
+ }
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
new file mode 100644
index 000000000..406366292
--- /dev/null
+++ b/include/asm-parisc/processor.h
@@ -0,0 +1,341 @@
+/*
+ * include/asm-parisc/processor.h
+ *
+ * Copyright (C) 1994 Linus Torvalds
+ */
+
+#ifndef __ASM_PARISC_PROCESSOR_H
+#define __ASM_PARISC_PROCESSOR_H
+
+#ifndef __ASSEMBLY__
+#include <linux/threads.h>
+
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/ptrace.h>
+#include <asm/types.h>
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+
+/* We cannot use MFIA as it was added for PA2.0 - prumpf
+
+ At one point there were no "0f/0b" type local symbols in gas for
+ PA-RISC. This is no longer true, but this still seems like the
+ nicest way to implement this. */
+
+#define current_text_addr() ({ void *pc; __asm__("\n\tblr 0,%0\n\tnop":"=r" (pc)); pc; })
+
+#define TASK_SIZE (PAGE_OFFSET)
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+#ifndef __ASSEMBLY__
+
+/*
+** Data detected about CPUs at boot time which is the same for all CPU's.
+** HP boxes are SMP - ie identical processors.
+**
+** FIXME: some CPU rev info may be processor specific...
+*/
+struct system_cpuinfo_parisc {
+ unsigned int cpu_count;
+ unsigned int cpu_hz;
+ unsigned int hversion;
+ unsigned int sversion;
+ enum cpu_type cpu_type;
+
+ struct {
+ struct pdc_model model;
+ struct pdc_model_cpuid /* ARGH */ versions;
+ struct pdc_model_cpuid cpuid;
+#if 0
+ struct pdc_model_caps caps;
+#endif
+ char sys_model_name[81]; /* PDC-ROM returnes this model name */
+ } pdc;
+
+ char *model_name;
+ char *cpu_name;
+ char *family_name;
+};
+
+
+/*
+** Per CPU data structure - ie varies per CPU.
+*/
+struct cpuinfo_parisc {
+ unsigned cpuid;
+
+ struct irq_region *region;
+
+ unsigned long it_value; /* Interval Timer value at last timer interrupt */
+ unsigned long it_delta; /* Interval Timer delta (tic_10ms / HZ * 100) */
+
+ unsigned long hpa; /* Host Physical address */
+ unsigned long txn_addr; /* External Interrupt Register or id_eid */
+
+ unsigned long bh_count; /* number of times bh was invoked */
+ unsigned long irq_count; /* number of IRQ's since boot */
+ unsigned long irq_max_cr16; /* longest time to handle a single IRQ */
+};
+
+extern struct system_cpuinfo_parisc boot_cpu_data;
+extern struct cpuinfo_parisc cpu_data[NR_CPUS];
+#define current_cpu_data cpu_data[smp_processor_id()]
+
+extern void identify_cpu(struct cpuinfo_parisc *);
+
+#define EISA_bus 0 /* we don't have ISA support yet */
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
+#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+typedef struct {
+ int seg;
+} mm_segment_t;
+
+struct thread_struct {
+ struct pt_regs regs;
+ unsigned long pg_tables;
+ unsigned long flags;
+};
+
+/* Thread struct flags. */
+#define PARISC_KERNEL_DEATH (1UL << 31) /* see die_if_kernel()... */
+
+#define INIT_MMAP { &init_mm, 0, 0, NULL, PAGE_SHARED, \
+ VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
+
+#define INIT_THREAD { { \
+ { 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }, \
+ { 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }, \
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, \
+ { 0, 0}, { 0, 0}, 0, 0, 0, 0 \
+ }, __pa((unsigned long) swapper_pg_dir) }
+
+/*
+ * Return saved PC of a blocked thread. This is used by ps mostly.
+ */
+
+extern inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+ return 0xabcdef;
+}
+
+/*
+ * Start user thread in another space.
+ *
+ * Note that we set both the iaoq and r31 to the new pc. When
+ * the kernel initially calls execve it will return through an
+ * rfi path that will use the values in the iaoq. The execve
+ * syscall path will return through the gateway page, and
+ * that uses r31 to branch to.
+ *
+ * For ELF we clear r23, because the dynamic linker uses it to pass
+ * the address of the finalizer function.
+ *
+ * We also initialize sr3 to an illegal value (illegal for our
+ * implementation, not for the architecture).
+ */
+
+/* The ELF abi wants things done a "wee bit" differently than
+ * som does. Supporting this behavior here avoids
+ * having our own version of create_elf_tables.
+ *
+ * Oh, and yes, that is not a typo, we are really passing argc in r25
+ * and argv in r24 (rather than r26 and r25). This is because that's
+ * where __libc_start_main wants them.
+ *
+ * Duplicated from dl-machine.h for the benefit of readers:
+ *
+ * Our initial stack layout is rather different from everyone else's
+ * due to the unique PA-RISC ABI. As far as I know it looks like
+ * this:
+
+ ----------------------------------- (user startup code creates this frame)
+ | 32 bytes of magic |
+ |---------------------------------|
+ | 32 bytes argument/sp save area |
+ |---------------------------------| ((current->mm->env_end) + 63 & ~63)
+ | N bytes of slack |
+ |---------------------------------|
+ | envvar and arg strings |
+ |---------------------------------|
+ | ELF auxiliary info |
+ | (up to 28 words) |
+ |---------------------------------|
+ | Environment variable pointers |
+ | upwards to NULL |
+ |---------------------------------|
+ | Argument pointers |
+ | upwards to NULL |
+ |---------------------------------|
+ | argc (1 word) |
+ -----------------------------------
+
+ * The pleasant part of this is that if we need to skip arguments we
+ * can just decrement argc and move argv, because the stack pointer
+ * is utterly unrelated to the location of the environment and
+ * argument vectors.
+ *
+ * Note that the S/390 people took the easy way out and hacked their
+ * GCC to make the stack grow downwards. */
+
+#define start_thread_som(regs, new_pc, new_sp) do { \
+ unsigned long *sp = (unsigned long *)new_sp; \
+ __u32 spaceid = (__u32)current->mm->context; \
+ unsigned long pc = (unsigned long)new_pc; \
+ /* offset pc for priv. level */ \
+ pc |= 3; \
+ \
+ set_fs(USER_DS); \
+ regs->iasq[0] = spaceid; \
+ regs->iasq[1] = spaceid; \
+ regs->iaoq[0] = pc; \
+ regs->iaoq[1] = pc; \
+ regs->sr[2] = LINUX_GATEWAY_SPACE; \
+ regs->sr[3] = 0xffff; \
+ regs->sr[4] = spaceid; \
+ regs->sr[5] = spaceid; \
+ regs->sr[6] = spaceid; \
+ regs->sr[7] = spaceid; \
+ regs->gr[ 0] = USER_INIT_PSW; \
+ regs->gr[30] = ((new_sp)+63)&~63; \
+ regs->gr[31] = pc; \
+ \
+ get_user(regs->gr[26],&sp[0]); \
+ get_user(regs->gr[25],&sp[-1]); \
+ get_user(regs->gr[24],&sp[-2]); \
+ get_user(regs->gr[23],&sp[-3]); \
+ \
+ regs->cr30 = (u32) current; \
+} while(0)
+
+
+#define start_thread(regs, new_pc, new_sp) do { \
+ unsigned long *sp = (unsigned long *)new_sp; \
+ __u32 spaceid = (__u32)current->mm->context; \
+ unsigned long pc = (unsigned long)new_pc; \
+ /* offset pc for priv. level */ \
+ pc |= 3; \
+ \
+ \
+ set_fs(USER_DS); \
+ regs->iasq[0] = spaceid; \
+ regs->iasq[1] = spaceid; \
+ regs->iaoq[0] = pc; \
+ regs->iaoq[1] = pc; \
+ regs->sr[2] = LINUX_GATEWAY_SPACE; \
+ regs->sr[3] = 0xffff; \
+ regs->sr[4] = spaceid; \
+ regs->sr[5] = spaceid; \
+ regs->sr[6] = spaceid; \
+ regs->sr[7] = spaceid; \
+ regs->gr[ 0] = USER_INIT_PSW; \
+ regs->fr[ 0] = 0LL; \
+ regs->fr[ 1] = 0LL; \
+ regs->fr[ 2] = 0LL; \
+ regs->fr[ 3] = 0LL; \
+ regs->gr[30] = ((current->mm->env_end)+63)&~63; \
+ regs->gr[31] = pc; \
+ \
+ get_user(regs->gr[25],&sp[0]); \
+ regs->gr[24] = (unsigned long) &sp[1]; \
+ regs->gr[23] = 0; \
+ \
+ regs->cr30 = (u32) current; \
+} while(0)
+
+#ifdef __LP64__
+
+/*
+ * For 64 bit kernels we need a version of start thread for 32 bit
+ * elf files.
+ *
+ * FIXME: It should be possible to not duplicate the above code
+ * by playing games with concatenation to form both
+ * macros at compile time. The only difference between
+ * this macro and the above is the name and the types
+ * for sp and pc.
+ */
+
+#define start_thread32(regs, new_pc, new_sp) do { \
+ __u32 *sp = (__u32 *)new_sp; \
+ __u32 spaceid = (__u32)current->mm->context; \
+ __u32 pc = (__u32)new_pc; \
+ /* offset pc for priv. level */ \
+ pc |= 3; \
+ \
+ set_fs(USER_DS); \
+ regs->iasq[0] = spaceid; \
+ regs->iasq[1] = spaceid; \
+ regs->iaoq[0] = pc; \
+ regs->iaoq[1] = pc; \
+ regs->sr[2] = LINUX_GATEWAY_SPACE; \
+ regs->sr[3] = 0xffff; \
+ regs->sr[4] = spaceid; \
+ regs->sr[5] = spaceid; \
+ regs->sr[6] = spaceid; \
+ regs->sr[7] = spaceid; \
+ regs->gr[ 0] = USER_INIT_PSW; \
+ regs->fr[ 0] = 0LL; \
+ regs->fr[ 1] = 0LL; \
+ regs->fr[ 2] = 0LL; \
+ regs->fr[ 3] = 0LL; \
+ regs->gr[30] = ((current->mm->env_end)+63)&~63; \
+ regs->gr[31] = pc; \
+ \
+ get_user(regs->gr[25],&sp[0]); \
+ regs->gr[24] = (unsigned long) &sp[1]; \
+ regs->gr[23] = 0; \
+ \
+ regs->cr30 = (u32) current; \
+} while(0)
+
+#endif
+
+struct task_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+#define copy_segments(tsk, mm) do { } while (0)
+#define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
+
+extern inline unsigned long get_wchan(struct task_struct *p)
+{
+ return 0xdeadbeef; /* XXX */
+}
+
+#define KSTK_EIP(tsk) (0xdeadbeef)
+#define KSTK_ESP(tsk) (0xdeadbeef)
+
+/* Be sure to hunt all references to this down when you change the size of
+ * the kernel stack */
+
+#endif /* __ASSEMBLY__ */
+
+#define THREAD_SIZE (4*PAGE_SIZE)
+
+#define alloc_task_struct() \
+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,2))
+#define free_task_struct(p) free_pages((unsigned long)(p),2)
+#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count)
+
+#define init_task (init_task_union.task)
+#define init_stack (init_task_union.stack)
+
+
+#endif /* __ASM_PARISC_PROCESSOR_H */
diff --git a/include/asm-parisc/psw.h b/include/asm-parisc/psw.h
new file mode 100644
index 000000000..5d425e490
--- /dev/null
+++ b/include/asm-parisc/psw.h
@@ -0,0 +1,54 @@
+#ifndef _PARISC_PSW_H
+#define PSW_I 0x00000001
+#define PSW_D 0x00000002
+#define PSW_P 0x00000004
+#define PSW_Q 0x00000008
+
+#define PSW_R 0x00000010
+#define PSW_F 0x00000020
+#define PSW_G 0x00000040 /* PA1.x only */
+#define PSW_O 0x00000080 /* PA2.0 only */
+
+#define PSW_M 0x00010000
+#define PSW_V 0x00020000
+#define PSW_C 0x00040000
+#define PSW_B 0x00080000
+
+#define PSW_X 0x00100000
+#define PSW_N 0x00200000
+#define PSW_L 0x00400000
+#define PSW_H 0x00800000
+
+#define PSW_T 0x01000000
+#define PSW_S 0x02000000
+#define PSW_E 0x04000000
+#define PSW_W 0x08000000 /* PA2.0 only */
+
+#define PSW_Z 0x40000000 /* PA1.x only */
+#define PSW_Y 0x80000000 /* PA1.x only */
+
+/* PSW bits to be used with ssm/rsm */
+#define PSW_SM_I 0x1
+#define PSW_SM_D 0x2
+#define PSW_SM_P 0x4
+#define PSW_SM_Q 0x8
+#define PSW_SM_R 0x10
+#define PSW_SM_F 0x20
+#define PSW_SM_G 0x40
+#define PSW_SM_O 0x80
+#define PSW_SM_E 0x100
+#define PSW_SM_W 0x200
+
+#ifdef __LP64__
+# define USER_PSW (PSW_C | PSW_D | PSW_Q | PSW_I)
+# define USER_INIT_PSW (PSW_C | PSW_D | PSW_Q | PSW_I | PSW_N)
+# define KERNEL_PSW (PSW_C | PSW_D | PSW_Q | PSW_W)
+# define PDC_PSW (PSW_Q | PSW_W)
+#else
+# define USER_PSW (PSW_C | PSW_D | PSW_Q | PSW_I | PSW_P)
+# define USER_INIT_PSW (PSW_C | PSW_D | PSW_Q | PSW_I | PSW_N)
+# define KERNEL_PSW (PSW_C | PSW_D | PSW_Q)
+# define PDC_PSW (PSW_Q)
+#endif
+
+#endif
diff --git a/include/asm-parisc/ptrace.h b/include/asm-parisc/ptrace.h
new file mode 100644
index 000000000..81ea038ac
--- /dev/null
+++ b/include/asm-parisc/ptrace.h
@@ -0,0 +1,56 @@
+#ifndef _PARISC_PTRACE_H
+#define _PARISC_PTRACE_H
+
+/* written by Philipp Rumpf, Copyright (C) 1999 SuSE GmbH Nuernberg
+** Copyright (C) 2000 Grant Grundler, Hewlett-Packard
+*/
+
+#include <linux/types.h>
+
+/* This struct defines the way the registers are stored on the
+ stack during a system call. */
+
+struct pt_regs {
+ unsigned long gr[32]; /* PSW is in gr[0] */
+ __u64 fr[32];
+ unsigned long sr[ 8];
+ unsigned long iasq[2];
+ unsigned long iaoq[2];
+ unsigned long cr24;
+ unsigned long cr25;
+ unsigned long cr26;
+ unsigned long cr27;
+ unsigned long cr30;
+ unsigned long orig_r28;
+ unsigned long ksp;
+ unsigned long kpc;
+ unsigned long sar; /* CR11 */
+ unsigned long iir; /* CR19 */
+ unsigned long isr; /* CR20 */
+ unsigned long ior; /* CR21 */
+ unsigned long ipsw; /* CR22 */
+ unsigned long cr_pid[4]; /* CR8,9,12,13 */
+};
+
+#define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
+/*
+ * The numbers chosen here are somewhat arbitrary but absolutely MUST
+ * not overlap with any of the number assigned in <linux/ptrace.h>.
+ *
+ * These ones are taken from IA-64 on the assumption that theirs are
+ * the most correct (and we also want to support PTRACE_SINGLEBLOCK
+ * since we have taken branch traps too)
+ */
+#define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */
+#define PTRACE_GETSIGINFO 13 /* get child's siginfo structure */
+#define PTRACE_SETSIGINFO 14 /* set child's siginfo structure */
+
+#ifdef __KERNEL__
+
+/* XXX should we use iaoq[1] or iaoq[0] ? */
+#define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0)
+#define instruction_pointer(regs) ((regs)->iaoq[0] & ~3)
+extern void show_regs(struct pt_regs *);
+#endif
+
+#endif
diff --git a/include/asm-parisc/real.h b/include/asm-parisc/real.h
new file mode 100644
index 000000000..82acb25db
--- /dev/null
+++ b/include/asm-parisc/real.h
@@ -0,0 +1,5 @@
+#ifndef _PARISC_REAL_H
+#define _PARISC_REAL_H
+
+
+#endif
diff --git a/include/asm-parisc/resource.h b/include/asm-parisc/resource.h
new file mode 100644
index 000000000..f9088848f
--- /dev/null
+++ b/include/asm-parisc/resource.h
@@ -0,0 +1,47 @@
+#ifndef _ASM_PARISC_RESOURCE_H
+#define _ASM_PARISC_RESOURCE_H
+
+/*
+ * Resource limits
+ */
+
+#define RLIMIT_CPU 0 /* CPU time in ms */
+#define RLIMIT_FSIZE 1 /* Maximum filesize */
+#define RLIMIT_DATA 2 /* max data size */
+#define RLIMIT_STACK 3 /* max stack size */
+#define RLIMIT_CORE 4 /* max core file size */
+#define RLIMIT_RSS 5 /* max resident set size */
+#define RLIMIT_NPROC 6 /* max number of processes */
+#define RLIMIT_NOFILE 7 /* max number of open files */
+#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
+#define RLIMIT_AS 9 /* address space limit */
+#define RLIMIT_LOCKS 10 /* maximum file locks held */
+
+#define RLIM_NLIMITS 11
+
+/*
+ * SuS says limits have to be unsigned.
+ * Which makes a ton more sense anyway.
+ */
+#define RLIM_INFINITY (~0UL)
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS \
+{ \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { _STK_LIM, 10 * _STK_LIM }, \
+ { 0, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { 0, 0 }, \
+ { INR_OPEN, INR_OPEN }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+}
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/asm-parisc/runway.h b/include/asm-parisc/runway.h
new file mode 100644
index 000000000..a1dea786d
--- /dev/null
+++ b/include/asm-parisc/runway.h
@@ -0,0 +1,9 @@
+#ifndef ASM_PARISC_RUNWAY_H
+#define ASM_PARISC_RUNWAY_H
+#ifdef __KERNEL__
+
+/* declared in arch/parisc/kernel/setup.c */
+extern struct proc_dir_entry * proc_runway_root;
+
+#endif /* __KERNEL__ */
+#endif /* ASM_PARISC_RUNWAY_H */
diff --git a/include/asm-parisc/scatterlist.h b/include/asm-parisc/scatterlist.h
new file mode 100644
index 000000000..3ef9a113d
--- /dev/null
+++ b/include/asm-parisc/scatterlist.h
@@ -0,0 +1,20 @@
+#ifndef _ASM_PARISC_SCATTERLIST_H
+#define _ASM_PARISC_SCATTERLIST_H
+
+struct scatterlist {
+ char * address; /* Location data is to be transferred to */
+ char * alt_address; /* Location of actual if address is a
+ * dma indirect buffer. NULL otherwise */
+ unsigned int length;
+
+ /* an IOVA can be 64-bits on some PA-Risc platforms. */
+ dma_addr_t iova; /* I/O Virtual Address */
+ __u32 iova_length; /* bytes mapped */
+};
+
+#define sg_dma_address(sg) ((sg)->iova)
+#define sg_dma_len(sg) ((sg)->iova_length)
+
+#define ISA_DMA_THRESHOLD (~0UL)
+
+#endif /* _ASM_PARISC_SCATTERLIST_H */
diff --git a/include/asm-parisc/segment.h b/include/asm-parisc/segment.h
new file mode 100644
index 000000000..26794ddb6
--- /dev/null
+++ b/include/asm-parisc/segment.h
@@ -0,0 +1,6 @@
+#ifndef __PARISC_SEGMENT_H
+#define __PARISC_SEGMENT_H
+
+/* Only here because we have some old header files that expect it.. */
+
+#endif
diff --git a/include/asm-parisc/semaphore-helper.h b/include/asm-parisc/semaphore-helper.h
new file mode 100644
index 000000000..387f7c127
--- /dev/null
+++ b/include/asm-parisc/semaphore-helper.h
@@ -0,0 +1,89 @@
+#ifndef _ASM_PARISC_SEMAPHORE_HELPER_H
+#define _ASM_PARISC_SEMAPHORE_HELPER_H
+
+/*
+ * SMP- and interrupt-safe semaphores helper functions.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ * (C) Copyright 1999 Andrea Arcangeli
+ */
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ *
+ * This is trivially done with load_locked/store_cond,
+ * which we have. Let the rest of the losers suck eggs.
+ */
+static __inline__ void wake_one_more(struct semaphore * sem)
+{
+ atomic_inc((atomic_t *)&sem->waking);
+}
+
+static __inline__ int waking_non_zero(struct semaphore *sem)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking > 0) {
+ sem->waking--;
+ ret = 1;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+/*
+ * waking_non_zero_interruptible:
+ * 1 got the lock
+ * 0 go to sleep
+ * -EINTR interrupted
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+ struct task_struct *tsk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking > 0) {
+ sem->waking--;
+ ret = 1;
+ } else if (signal_pending(tsk)) {
+ atomic_inc(&sem->count);
+ ret = -EINTR;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+/*
+ * waking_non_zero_trylock:
+ * 1 failed to lock
+ * 0 got the lock
+ *
+ * We must undo the sem->count down_trylock() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+{
+ unsigned long flags;
+ int ret = 1;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking <= 0)
+ atomic_inc(&sem->count);
+ else {
+ sem->waking--;
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+#endif /* _ASM_PARISC_SEMAPHORE_HELPER_H */
diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
new file mode 100644
index 000000000..12deca83c
--- /dev/null
+++ b/include/asm-parisc/semaphore.h
@@ -0,0 +1,301 @@
+#ifndef _ASM_PARISC_SEMAPHORE_H
+#define _ASM_PARISC_SEMAPHORE_H
+
+#include <linux/linkage.h>
+
+/*
+ * SMP- and interrupt-safe semaphores.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ *
+ * SuperH verison by Niibe Yutaka
+ *
+ */
+
+/* if you're going to use out-of-line slowpaths, use .section .lock.text,
+ * not .text.lock or the -ffunction-sections monster will eat you alive
+ */
+
+#include <linux/spinlock.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+struct semaphore {
+ atomic_t count;
+ int waking;
+ wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+ long __magic;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+ , (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+ __SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+ __SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+/*
+ * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+ *
+ * i'd rather use the more flexible initialization above, but sadly
+ * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+ */
+ atomic_set(&sem->count, val);
+ sem->waking = 0;
+ init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+ sem->__magic = (long)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+ sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+ sema_init(sem, 0);
+}
+
+asmlinkage void __down_failed(void /* special register calling convention */);
+asmlinkage int __down_failed_interruptible(void /* params in registers */);
+asmlinkage int __down_failed_trylock(void /* params in registers */);
+asmlinkage void __up_wakeup(void /* special register calling convention */);
+
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int __down_interruptible(struct semaphore * sem);
+asmlinkage int __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
+
+extern spinlock_t semaphore_wake_lock;
+
+extern __inline__ void down(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+ CHECK_MAGIC(sem->__magic);
+#endif
+
+ if (atomic_dec_return(&sem->count) < 0)
+ __down(sem);
+}
+
+extern __inline__ int down_interruptible(struct semaphore * sem)
+{
+ int ret = 0;
+#if WAITQUEUE_DEBUG
+ CHECK_MAGIC(sem->__magic);
+#endif
+
+ if (atomic_dec_return(&sem->count) < 0)
+ ret = __down_interruptible(sem);
+ return ret;
+}
+
+extern __inline__ int down_trylock(struct semaphore * sem)
+{
+ int ret = 0;
+#if WAITQUEUE_DEBUG
+ CHECK_MAGIC(sem->__magic);
+#endif
+
+ if (atomic_dec_return(&sem->count) < 0)
+ ret = __down_trylock(sem);
+ return ret;
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ */
+extern __inline__ void up(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+ CHECK_MAGIC(sem->__magic);
+#endif
+ if (atomic_inc_return(&sem->count) <= 0)
+ __up(sem);
+}
+
+/* rw mutexes (should that be mutices? =) -- throw rw
+ * spinlocks and semaphores together, and this is what we
+ * end up with...
+ *
+ * The lock is initialized to BIAS. This way, a writer
+ * subtracts BIAS ands gets 0 for the case of an uncontended
+ * lock. Readers decrement by 1 and see a positive value
+ * when uncontended, negative if there are writers waiting
+ * (in which case it goes to sleep).
+ *
+ * The value 0x01000000 supports up to 128 processors and
+ * lots of processes. BIAS must be chosen such that subl'ing
+ * BIAS once per CPU will result in the long remaining
+ * negative.
+ *
+ * In terms of fairness, this should result in the lock
+ * flopping back and forth between readers and writers
+ * under heavy use.
+ *
+ * -ben
+ */
+struct rw_semaphore {
+ atomic_t count;
+ volatile unsigned char write_bias_granted;
+ volatile unsigned char read_bias_granted;
+ volatile unsigned char pad1;
+ volatile unsigned char pad2;
+ wait_queue_head_t wait;
+ wait_queue_head_t write_bias_wait;
+#if WAITQUEUE_DEBUG
+ long __magic;
+ atomic_t readers;
+ atomic_t writers;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+#define __RWSEM_DEBUG_INIT , ATOMIC_INIT(0), ATOMIC_INIT(0)
+#else
+#define __RWSEM_DEBUG_INIT /* */
+#endif
+
+#define RW_LOCK_BIAS 0x01000000
+
+#define __RWSEM_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
+ __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
+ __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
+
+#define __DECLARE_RWSEM_GENERIC(name,count) \
+ struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
+
+#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
+#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
+#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
+
+extern inline void init_rwsem(struct rw_semaphore *sem)
+{
+ atomic_set(&sem->count, RW_LOCK_BIAS);
+ sem->read_bias_granted = 0;
+ sem->write_bias_granted = 0;
+ init_waitqueue_head(&sem->wait);
+ init_waitqueue_head(&sem->write_bias_wait);
+#if WAITQUEUE_DEBUG
+ sem->__magic = (long)&sem->__magic;
+ atomic_set(&sem->readers, 0);
+ atomic_set(&sem->writers, 0);
+#endif
+}
+
+#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
+extern struct rw_semaphore *__build_read_lock(struct rw_semaphore *sem, const char *what);
+extern struct rw_semaphore *__build_write_lock(struct rw_semaphore *sem, const char *what);
+#endif
+
+/* we use FASTCALL convention for the helpers */
+extern struct rw_semaphore *FASTCALL(__down_read_failed(struct rw_semaphore *sem));
+extern struct rw_semaphore *FASTCALL(__down_write_failed(struct rw_semaphore *sem));
+extern struct rw_semaphore *FASTCALL(__rwsem_wake(struct rw_semaphore *sem));
+
+extern inline void down_read(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+ if (sem->__magic != (long)&sem->__magic)
+ BUG();
+#endif
+#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
+ __build_read_lock(sem, "__down_read_failed");
+#endif
+#if WAITQUEUE_DEBUG
+ if (sem->write_bias_granted)
+ BUG();
+ if (atomic_read(&sem->writers))
+ BUG();
+ atomic_inc(&sem->readers);
+#endif
+}
+
+extern inline void down_write(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+ if (sem->__magic != (long)&sem->__magic)
+ BUG();
+#endif
+#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
+ __build_write_lock(sem, "__down_write_failed");
+#endif
+#if WAITQUEUE_DEBUG
+ if (atomic_read(&sem->writers))
+ BUG();
+ if (atomic_read(&sem->readers))
+ BUG();
+ if (sem->read_bias_granted)
+ BUG();
+ if (sem->write_bias_granted)
+ BUG();
+ atomic_inc(&sem->writers);
+#endif
+}
+
+/* When a reader does a release, the only significant
+ * case is when there was a writer waiting, and we've
+ * bumped the count to 0: we must wake the writer up.
+ */
+extern inline void __up_read(struct rw_semaphore *sem)
+{
+}
+
+/* releasing the writer is easy -- just release it and
+ * wake up any sleepers.
+ */
+extern inline void __up_write(struct rw_semaphore *sem)
+{
+}
+
+extern inline void up_read(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+ if (sem->write_bias_granted)
+ BUG();
+ if (atomic_read(&sem->writers))
+ BUG();
+ atomic_dec(&sem->readers);
+#endif
+ __up_read(sem);
+}
+
+extern inline void up_write(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+ if (sem->read_bias_granted)
+ BUG();
+ if (sem->write_bias_granted)
+ BUG();
+ if (atomic_read(&sem->readers))
+ BUG();
+ if (atomic_read(&sem->writers) != 1)
+ BUG();
+ atomic_dec(&sem->writers);
+#endif
+ __up_write(sem);
+}
+
+#endif /* _ASM_PARISC_SEMAPHORE_H */
diff --git a/include/asm-parisc/sembuf.h b/include/asm-parisc/sembuf.h
new file mode 100644
index 000000000..25f3ef8f3
--- /dev/null
+++ b/include/asm-parisc/sembuf.h
@@ -0,0 +1,25 @@
+#ifndef _PARISC_SEMBUF_H
+#define _PARISC_SEMBUF_H
+
+/*
+ * The semid64_ds structure for parisc architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
+ unsigned int __pad1;
+ __kernel_time_t sem_otime; /* last semop time */
+ unsigned int __pad2;
+ __kernel_time_t sem_ctime; /* last change time */
+ unsigned int sem_nsems; /* no. of semaphores in array */
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+#endif /* _PARISC_SEMBUF_H */
diff --git a/include/asm-parisc/serial.h b/include/asm-parisc/serial.h
new file mode 100644
index 000000000..a9cef8e95
--- /dev/null
+++ b/include/asm-parisc/serial.h
@@ -0,0 +1,47 @@
+/*
+ * include/asm-parisc/serial.h
+ */
+
+#include <linux/config.h>
+#include <asm/gsc.h>
+
+/*
+ * This assumes you have a 7.272727 MHz clock for your UART.
+ * The documentation implies a 40Mhz clock, and elsewhere a 7Mhz clock
+ * Clarified: 7.2727MHz on LASI. Not yet clarified for DINO
+ */
+
+#define LASI_BASE_BAUD ( 7272727 / 16 )
+#define BASE_BAUD LASI_BASE_BAUD
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
+#endif
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define FOURPORT_FLAGS ASYNC_FOURPORT
+#define ACCENT_FLAGS 0
+#define BOCA_FLAGS 0
+#define HUB6_FLAGS 0
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 4
+#endif
+
+/*
+ * The base is relative to the LASI base. We can fix that
+ * up later. We could also virtually map LASI so that we get
+ * nice constants all over our kernel...
+ */
+
+#define STD_SERIAL_PORT_DEFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, LASI_BASE_BAUD, -1, 4, ASYNC_SKIP_TEST, 0, PORT_UNKNOWN,}, /* ttyS0 */
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DEFNS
+
diff --git a/include/asm-parisc/setup.h b/include/asm-parisc/setup.h
new file mode 100644
index 000000000..ae25cc427
--- /dev/null
+++ b/include/asm-parisc/setup.h
@@ -0,0 +1,10 @@
+/*
+ * Just a place holder. We don't want to have to test x86 before
+ * we include stuff
+ */
+
+#ifndef _i386_SETUP_H
+#define _i386_SETUP_H
+
+
+#endif /* _i386_SETUP_H */
diff --git a/include/asm-parisc/shmbuf.h b/include/asm-parisc/shmbuf.h
new file mode 100644
index 000000000..ea45e96b3
--- /dev/null
+++ b/include/asm-parisc/shmbuf.h
@@ -0,0 +1,50 @@
+#ifndef _PARISC_SHMBUF_H
+#define _PARISC_SHMBUF_H
+
+/*
+ * The shmid64_ds structure for parisc architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+ struct ipc64_perm shm_perm; /* operation perms */
+ unsigned int __pad1;
+ __kernel_time_t shm_atime; /* last attach time */
+ unsigned int __pad2;
+ __kernel_time_t shm_dtime; /* last detach time */
+ unsigned int __pad3;
+ __kernel_time_t shm_ctime; /* last change time */
+ size_t shm_segsz; /* size of segment (bytes) */
+ __kernel_pid_t shm_cpid; /* pid of creator */
+ __kernel_pid_t shm_lpid; /* pid of last operator */
+ unsigned int shm_nattch; /* no. of current attaches */
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+#ifdef __LP64__
+#warning shminfo64 is an undocumented struct
+/* The 'unsigned int' (formerly 'unsigned long') data types below will
+ * ensure that a 32-bit app calling shmctl(*,IPC_INFO,*) will work on
+ * a wide kernel, but if some of these values are meant to contain pointers
+ * they may need to be 'long long' instead. -PB
+ */
+#endif
+struct shminfo64 {
+ unsigned int shmmax;
+ unsigned int shmmin;
+ unsigned int shmmni;
+ unsigned int shmseg;
+ unsigned int shmall;
+ unsigned int __unused1;
+ unsigned int __unused2;
+ unsigned int __unused3;
+ unsigned int __unused4;
+};
+
+#endif /* _PARISC_SHMBUF_H */
diff --git a/include/asm-parisc/shmparam.h b/include/asm-parisc/shmparam.h
new file mode 100644
index 000000000..bbc52f028
--- /dev/null
+++ b/include/asm-parisc/shmparam.h
@@ -0,0 +1,6 @@
+#ifndef _ASMPARISC_SHMPARAM_H
+#define _ASMPARISC_SHMPARAM_H
+
+#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
+
+#endif /* _ASMPARISC_SHMPARAM_H */
diff --git a/include/asm-parisc/sigcontext.h b/include/asm-parisc/sigcontext.h
new file mode 100644
index 000000000..27ef31bb3
--- /dev/null
+++ b/include/asm-parisc/sigcontext.h
@@ -0,0 +1,20 @@
+#ifndef _ASMPARISC_SIGCONTEXT_H
+#define _ASMPARISC_SIGCONTEXT_H
+
+#define PARISC_SC_FLAG_ONSTACK 1<<0
+#define PARISC_SC_FLAG_IN_SYSCALL 1<<1
+
+/* We will add more stuff here as it becomes necessary, until we know
+ it works. */
+struct sigcontext {
+ unsigned long sc_flags;
+
+ unsigned long sc_gr[32]; /* PSW in sc_gr[0] */
+ unsigned long long sc_fr[32]; /* FIXME, do we need other state info? */
+ unsigned long sc_iasq[2];
+ unsigned long sc_iaoq[2];
+ unsigned long sc_sar; /* cr11 */
+};
+
+
+#endif
diff --git a/include/asm-parisc/siginfo.h b/include/asm-parisc/siginfo.h
new file mode 100644
index 000000000..143fe7eef
--- /dev/null
+++ b/include/asm-parisc/siginfo.h
@@ -0,0 +1,234 @@
+#ifndef _PARISC_SIGINFO_H
+#define _PARISC_SIGINFO_H
+
+#include <linux/types.h>
+
+/* XXX: This structure was copied from the Alpha; is there an iBCS version? */
+
+typedef union sigval {
+ int sival_int;
+ void *sival_ptr;
+} sigval_t;
+
+#define SI_MAX_SIZE 128
+#define SI_PAD_SIZE ((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct siginfo {
+ int si_signo;
+ int si_errno;
+ int si_code;
+
+ union {
+ int _pad[SI_PAD_SIZE];
+
+ /* kill() */
+ struct {
+ pid_t _pid; /* sender's pid */
+ uid_t _uid; /* sender's uid */
+ } _kill;
+
+ /* POSIX.1b timers */
+ struct {
+ unsigned int _timer1;
+ unsigned int _timer2;
+ } _timer;
+
+ /* POSIX.1b signals */
+ struct {
+ pid_t _pid; /* sender's pid */
+ uid_t _uid; /* sender's uid */
+ sigval_t _sigval;
+ } _rt;
+
+ /* SIGCHLD */
+ struct {
+ pid_t _pid; /* which child */
+ uid_t _uid; /* sender's uid */
+ int _status; /* exit code */
+ clock_t _utime;
+ clock_t _stime;
+ } _sigchld;
+
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ struct {
+ void *_addr; /* faulting insn/memory ref. */
+ } _sigfault;
+
+ /* SIGPOLL */
+ struct {
+ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ int _fd;
+ } _sigpoll;
+ } _sifields;
+} siginfo_t;
+
+/*
+ * How these fields are to be accessed.
+ */
+#define si_pid _sifields._kill._pid
+#define si_uid _sifields._kill._uid
+#define si_status _sifields._sigchld._status
+#define si_utime _sifields._sigchld._utime
+#define si_stime _sifields._sigchld._stime
+#define si_value _sifields._rt._sigval
+#define si_int _sifields._rt._sigval.sival_int
+#define si_ptr _sifields._rt._sigval.sival_ptr
+#define si_addr _sifields._sigfault._addr
+#define si_band _sifields._sigpoll._band
+#define si_fd _sifields._sigpoll._fd
+
+#ifdef __KERNEL__
+#define __SI_MASK 0xffff0000
+#define __SI_KILL (0 << 16)
+#define __SI_TIMER (1 << 16)
+#define __SI_POLL (2 << 16)
+#define __SI_FAULT (3 << 16)
+#define __SI_CHLD (4 << 16)
+#define __SI_RT (5 << 16)
+#define __SI_CODE(T,N) ((T) << 16 | ((N) & 0xffff))
+#else
+#define __SI_KILL 0
+#define __SI_TIMER 0
+#define __SI_POLL 0
+#define __SI_FAULT 0
+#define __SI_CHLD 0
+#define __SI_RT 0
+#define __SI_CODE(T,N) (N)
+#endif
+
+/*
+ * si_code values
+ * Digital reserves positive values for kernel-generated signals.
+ */
+#define SI_USER 0 /* sent by kill, sigsend, raise */
+#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
+#define SI_QUEUE -1 /* sent by sigqueue */
+#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
+#define SI_MESGQ -3 /* sent by real time mesq state change */
+#define SI_ASYNCIO -4 /* sent by AIO completion */
+#define SI_SIGIO -5 /* sent by queued SIGIO */
+
+#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
+#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
+
+/*
+ * SIGILL si_codes
+ */
+#define ILL_ILLOPC (__SI_FAULT|1) /* illegal opcode */
+#define ILL_ILLOPN (__SI_FAULT|2) /* illegal operand */
+#define ILL_ILLADR (__SI_FAULT|3) /* illegal addressing mode */
+#define ILL_ILLTRP (__SI_FAULT|4) /* illegal trap */
+#define ILL_PRVOPC (__SI_FAULT|5) /* privileged opcode */
+#define ILL_PRVREG (__SI_FAULT|6) /* privileged register */
+#define ILL_COPROC (__SI_FAULT|7) /* coprocessor error */
+#define ILL_BADSTK (__SI_FAULT|8) /* internal stack error */
+#define NSIGILL 8
+
+/*
+ * SIGFPE si_codes
+ */
+#define FPE_INTDIV (__SI_FAULT|1) /* integer divide by zero */
+#define FPE_INTOVF (__SI_FAULT|2) /* integer overflow */
+#define FPE_FLTDIV (__SI_FAULT|3) /* floating point divide by zero */
+#define FPE_FLTOVF (__SI_FAULT|4) /* floating point overflow */
+#define FPE_FLTUND (__SI_FAULT|5) /* floating point underflow */
+#define FPE_FLTRES (__SI_FAULT|6) /* floating point inexact result */
+#define FPE_FLTINV (__SI_FAULT|7) /* floating point invalid operation */
+#define FPE_FLTSUB (__SI_FAULT|8) /* subscript out of range */
+#define NSIGFPE 8
+
+/*
+ * SIGSEGV si_codes
+ */
+#define SEGV_MAPERR (__SI_FAULT|1) /* address not mapped to object */
+#define SEGV_ACCERR (__SI_FAULT|2) /* invalid permissions for mapped object */
+#define NSIGSEGV 2
+
+/*
+ * SIGBUS si_codes
+ */
+#define BUS_ADRALN (__SI_FAULT|1) /* invalid address alignment */
+#define BUS_ADRERR (__SI_FAULT|2) /* non-existant physical address */
+#define BUS_OBJERR (__SI_FAULT|3) /* object specific hardware error */
+#define NSIGBUS 3
+
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRKPT (__SI_FAULT|1) /* process breakpoint */
+#define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */
+#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */
+#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */
+#define NSIGTRAP 4
+
+/*
+ * SIGCHLD si_codes
+ */
+#define CLD_EXITED (__SI_CHLD|1) /* child has exited */
+#define CLD_KILLED (__SI_CHLD|2) /* child was killed */
+#define CLD_DUMPED (__SI_CHLD|3) /* child terminated abnormally */
+#define CLD_TRAPPED (__SI_CHLD|4) /* traced child has trapped */
+#define CLD_STOPPED (__SI_CHLD|5) /* child has stopped */
+#define CLD_CONTINUED (__SI_CHLD|6) /* stopped child has continued */
+#define NSIGCHLD 6
+
+/*
+ * SIGPOLL si_codes
+ */
+#define POLL_IN (__SI_POLL|1) /* data input available */
+#define POLL_OUT (__SI_POLL|2) /* output buffers available */
+#define POLL_MSG (__SI_POLL|3) /* input message available */
+#define POLL_ERR (__SI_POLL|4) /* i/o error */
+#define POLL_PRI (__SI_POLL|5) /* high priority input available */
+#define POLL_HUP (__SI_POLL|6) /* device disconnected */
+#define NSIGPOLL 6
+
+/*
+ * sigevent definitions
+ *
+ * It seems likely that SIGEV_THREAD will have to be handled from
+ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
+ * thread manager then catches and does the appropriate nonsense.
+ * However, everything is written out here so as to not get lost.
+ */
+#define SIGEV_SIGNAL 0 /* notify via signal */
+#define SIGEV_NONE 1 /* other notification: meaningless */
+#define SIGEV_THREAD 2 /* deliver via thread creation */
+
+#define SIGEV_MAX_SIZE 64
+#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct sigevent {
+ sigval_t sigev_value;
+ int sigev_signo;
+ int sigev_notify;
+ union {
+ int _pad[SIGEV_PAD_SIZE];
+
+ struct {
+ void (*_function)(sigval_t);
+ void *_attribute; /* really pthread_attr_t */
+ } _sigev_thread;
+ } _sigev_un;
+} sigevent_t;
+
+#define sigev_notify_function _sigev_un._sigev_thread._function
+#define sigev_notify_attributes _sigev_un._sigev_thread._attribute
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+
+extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from)
+{
+ if (from->si_code < 0)
+ memcpy(to, from, sizeof(siginfo_t));
+ else
+ /* _sigchld is currently the largest know union member */
+ memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
+}
+
+extern int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from);
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/asm-parisc/signal.h b/include/asm-parisc/signal.h
new file mode 100644
index 000000000..9295c212b
--- /dev/null
+++ b/include/asm-parisc/signal.h
@@ -0,0 +1,163 @@
+#ifndef _ASM_PARISC_SIGNAL_H
+#define _ASM_PARISC_SIGNAL_H
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGEMT 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGBUS 10
+#define SIGSEGV 11
+#define SIGSYS 12 /* Linux doesn't use this */
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGUSR1 16
+#define SIGUSR2 17
+#define SIGCHLD 18
+#define SIGPWR 19
+#define SIGVTALRM 20
+#define SIGPROF 21
+#define SIGIO 22
+#define SIGPOLL SIGIO
+#define SIGWINCH 23
+#define SIGSTOP 24
+#define SIGTSTP 25
+#define SIGCONT 26
+#define SIGTTIN 27
+#define SIGTTOU 28
+#define SIGURG 29
+#define SIGLOST 30 /* Linux doesn't use this either */
+#define SIGUNUSED 31
+#define SIGRESERVE SIGUNUSED
+
+#define SIGXCPU 33
+#define SIGXFSZ 34
+#define SIGSTKFLT 36
+
+/* These should not be considered constants from userland. */
+#define SIGRTMIN 37
+#define SIGRTMAX (_NSIG-1) /* it's 44 under HP/UX */
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_ONSTACK 0x00000001
+#define SA_RESETHAND 0x00000004
+#define SA_NOCLDSTOP 0x00000008
+#define SA_SIGINFO 0x00000010
+#define SA_NODEFER 0x00000020
+#define SA_RESTART 0x00000040
+#define SA_NOCLDWAIT 0x00000080 /* not supported yet */
+#define _SA_SIGGFAULT 0x00000100 /* HPUX */
+
+#define SA_NOMASK SA_NODEFER
+#define SA_ONESHOT SA_RESETHAND
+#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER 0x04000000 /* obsolete -- ignored */
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+
+#ifdef __KERNEL__
+
+#define _NSIG 64
+/* bits-per-word, where word apparently means 'long' not 'int' */
+#define _NSIG_BPW BITS_PER_LONG
+#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE SA_ONESHOT
+#define SA_SAMPLE_RANDOM SA_RESTART
+#define SA_SHIRQ 0x04000000
+
+#endif /* __KERNEL__ */
+
+#define SIG_BLOCK 0 /* for blocking signals */
+#define SIG_UNBLOCK 1 /* for unblocking signals */
+#define SIG_SETMASK 2 /* for setting the signal mask */
+
+#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
+#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
+#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
+
+# ifndef __ASSEMBLY__
+
+# include <linux/types.h>
+
+/* Avoid too many header ordering problems. */
+struct siginfo;
+
+/* Type of a signal handler. */
+#ifdef __LP64__
+/* function pointers on 64-bit parisc are pointers to little structs and the
+ * compiler doesn't support code which changes or tests the address of
+ * the function in the little struct. This is really ugly -PB
+ */
+typedef __kernel_caddr_t __sighandler_t;
+#else
+typedef void (*__sighandler_t)(int);
+#endif
+
+typedef struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+
+/* Most things should be clean enough to redefine this at will, if care
+ is taken to make libc match. */
+
+typedef unsigned long old_sigset_t; /* at least 32 bits */
+
+typedef struct {
+ /* next_signal() assumes this is a long - no choice */
+ unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+struct sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ sigset_t sa_mask; /* mask last for extensibility */
+};
+
+struct k_sigaction {
+ struct sigaction sa;
+};
+
+#include <asm/sigcontext.h>
+
+#endif /* __KERNEL__ */
+#endif /* !__ASSEMBLY */
+#endif /* _ASM_PARISC_SIGNAL_H */
diff --git a/include/asm-parisc/smp.h b/include/asm-parisc/smp.h
new file mode 100644
index 000000000..36e78e9bc
--- /dev/null
+++ b/include/asm-parisc/smp.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+extern volatile unsigned long cpu_online_map; /* Bitmap of available cpu's */
+#endif
+
+#endif
diff --git a/include/asm-parisc/smplock.h b/include/asm-parisc/smplock.h
new file mode 100644
index 000000000..1590fafe9
--- /dev/null
+++ b/include/asm-parisc/smplock.h
@@ -0,0 +1,49 @@
+/*
+ * <asm/smplock.h>
+ *
+ * Default SMP lock implementation
+ */
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+extern spinlock_t kernel_flag;
+
+/*
+ * Release global kernel lock and global interrupt lock
+ */
+#define release_kernel_lock(task, cpu) \
+do { \
+ if (task->lock_depth >= 0) \
+ spin_unlock(&kernel_flag); \
+ release_irqlock(cpu); \
+ __sti(); \
+} while (0)
+
+/*
+ * Re-acquire the kernel lock
+ */
+#define reacquire_kernel_lock(task) \
+do { \
+ if (task->lock_depth >= 0) \
+ spin_lock(&kernel_flag); \
+} while (0)
+
+
+/*
+ * Getting the big kernel lock.
+ *
+ * This cannot happen asynchronously,
+ * so we only need to worry about other
+ * CPU's.
+ */
+extern __inline__ void lock_kernel(void)
+{
+ if (!++current->lock_depth)
+ spin_lock(&kernel_flag);
+}
+
+extern __inline__ void unlock_kernel(void)
+{
+ if (--current->lock_depth < 0)
+ spin_unlock(&kernel_flag);
+}
diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h
new file mode 100644
index 000000000..6ce553460
--- /dev/null
+++ b/include/asm-parisc/socket.h
@@ -0,0 +1,59 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET 0xffff
+
+#define SO_DEBUG 0x0001
+#define SO_REUSEADDR 0x0004
+#define SO_KEEPALIVE 0x0008
+#define SO_DONTROUTE 0x0010
+#define SO_BROADCAST 0x0020
+#define SO_LINGER 0x0080
+#define SO_OOBINLINE 0x0100
+/* To add :#define SO_REUSEPORT 0x0200 */
+#define SO_SNDBUF 0x1001
+#define SO_RCVBUF 0x1002
+#define SO_SNDLOWAT 0x1003
+#define SO_RCVLOWAT 0x1004
+#define SO_SNDTIMEO 0x1005
+#define SO_RCVTIMEO 0x1006
+#define SO_ERROR 0x1007
+#define SO_TYPE 0x1008
+#define SO_PEERNAME 0x2000
+
+#define SO_NO_CHECK 0x400b
+#define SO_PRIORITY 0x400c
+#define SO_BSDCOMPAT 0x400e
+#define SO_PASSCRED 0x4010
+#define SO_PEERCRED 0x4011
+#define SO_TIMESTAMP 0x4012
+#define SCM_TIMESTAMP SO_TIMESTAMP
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION 0x4016
+#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x4017
+#define SO_SECURITY_ENCRYPTION_NETWORK 0x4018
+
+#define SO_BINDTODEVICE 0x4019
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER 0x401a
+#define SO_DETACH_FILTER 0x401b
+
+#if defined(__KERNEL__)
+#define SOCK_STREAM 1 /* stream (connection) socket */
+#define SOCK_DGRAM 2 /* datagram (conn.less) socket */
+#define SOCK_RAW 3 /* raw socket */
+#define SOCK_RDM 4 /* reliably-delivered message */
+#define SOCK_SEQPACKET 5 /* sequential packet socket */
+#define SOCK_PACKET 10 /* linux specific way of */
+ /* getting packets at the dev */
+ /* level. For writing rarp and */
+ /* other similar things on the */
+ /* user level. */
+#endif
+
+#endif /* _ASM_SOCKET_H */
diff --git a/include/asm-parisc/sockios.h b/include/asm-parisc/sockios.h
new file mode 100644
index 000000000..aace49629
--- /dev/null
+++ b/include/asm-parisc/sockios.h
@@ -0,0 +1,12 @@
+#ifndef __ARCH_PARISC_SOCKIOS__
+#define __ARCH_PARISC_SOCKIOS__
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 0x8901
+#define SIOCSPGRP 0x8902
+#define FIOGETOWN 0x8903
+#define SIOCGPGRP 0x8904
+#define SIOCATMARK 0x8905
+#define SIOCGSTAMP 0x8906 /* Get stamp */
+
+#endif
diff --git a/include/asm-parisc/softirq.h b/include/asm-parisc/softirq.h
new file mode 100644
index 000000000..4fe26b2b7
--- /dev/null
+++ b/include/asm-parisc/softirq.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_SOFTIRQ_H
+#define __ASM_SOFTIRQ_H
+
+#include <asm/atomic.h>
+#include <asm/hardirq.h>
+
+#define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0)
+#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0)
+
+#define local_bh_disable() cpu_bh_disable(smp_processor_id())
+#define local_bh_enable() cpu_bh_enable(smp_processor_id())
+
+#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
+
+#endif /* __ASM_SOFTIRQ_H */
diff --git a/include/asm-parisc/som.h b/include/asm-parisc/som.h
new file mode 100644
index 000000000..5f90baa4a
--- /dev/null
+++ b/include/asm-parisc/som.h
@@ -0,0 +1,8 @@
+#ifndef _ASM_PARISC_SOM_H
+#define _ASM_PARISC_SOM_H
+
+/* File format definition for SOM executables / shared libraries */
+#include <linux/som.h>
+
+
+#endif /* _ASM_PARISC_SOM_H
diff --git a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
new file mode 100644
index 000000000..7a59ed694
--- /dev/null
+++ b/include/asm-parisc/spinlock.h
@@ -0,0 +1,95 @@
+#ifndef __ASM_SPINLOCK_H
+#define __ASM_SPINLOCK_H
+
+#include <asm/system.h>
+
+/* if you're going to use out-of-line slowpaths, use .section .lock.text,
+ * not .text.lock or the -ffunction-sections monster will eat you alive
+ */
+
+/* we seem to be the only architecture that uses 0 to mean locked - but we
+ * have to. prumpf */
+
+#undef SPIN_LOCK_UNLOCKED
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
+
+#define spin_lock_init(x) do { (x)->lock = 1; } while(0)
+
+#define spin_unlock_wait(x) do { barrier(); } while(((volatile spinlock_t *)(x))->lock == 1)
+
+#define spin_lock(x) \
+ do { while(__ldcw(&(x)->lock) == 0); } while(0)
+
+#define spin_unlock(x) \
+ do { (x)->lock = 1; } while(0)
+
+#define spin_trylock(x) (__ldcw(&(x)->lock) == 1)
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ */
+typedef struct {
+ spinlock_t lock;
+ volatile int counter;
+} rwlock_t;
+
+#define RW_LOCK_UNLOCKED (rwlock_t) { SPIN_LOCK_UNLOCKED, 0 }
+
+/* read_lock, read_unlock are pretty straightforward. Of course it somehow
+ * sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */
+
+static inline void read_lock(rwlock_t *rw)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&rw->lock, flags);
+
+ rw->counter++;
+
+ spin_unlock_irqrestore(&rw->lock, flags);
+}
+
+static inline void read_unlock(rwlock_t *rw)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&rw->lock, flags);
+
+ rw->counter--;
+
+ spin_unlock_irqrestore(&rw->lock, flags);
+}
+
+/* write_lock is less trivial. We optimistically grab the lock and check
+ * if we surprised any readers. If so we release the lock and wait till
+ * they're all gone before trying again
+ *
+ * Also note that we don't use the _irqsave / _irqrestore suffixes here.
+ * If we're called with interrupts enabled and we've got readers (or other
+ * writers) in interrupt handlers someone fucked up and we'd dead-lock
+ * sooner or later anyway. prumpf */
+
+static inline void write_lock(rwlock_t *rw)
+{
+retry:
+ spin_lock(&rw->lock);
+
+ if(rw->counter != 0) {
+ /* this basically never happens */
+ spin_unlock(&rw->lock);
+
+ while(rw->counter != 0);
+
+ goto retry;
+ }
+
+ /* got it. now leave without unlocking */
+}
+
+/* write_unlock is absolutely trivial - we don't have to wait for anything */
+
+static inline void write_unlock(rwlock_t *rw)
+{
+ spin_unlock(&rw->lock);
+}
+
+#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-parisc/stat.h b/include/asm-parisc/stat.h
new file mode 100644
index 000000000..9d09e955a
--- /dev/null
+++ b/include/asm-parisc/stat.h
@@ -0,0 +1,71 @@
+#ifndef _PARISC_STAT_H
+#define _PARISC_STAT_H
+
+#include <linux/types.h>
+
+struct stat {
+ dev_t st_dev; /* dev_t is 32 bits on parisc */
+ ino_t st_ino; /* 32 bits */
+ mode_t st_mode; /* 16 bits */
+ nlink_t st_nlink; /* 16 bits */
+ unsigned short st_reserved1; /* old st_uid */
+ unsigned short st_reserved2; /* old st_gid */
+ dev_t st_rdev;
+ off_t st_size;
+ time_t st_atime;
+ unsigned int st_spare1;
+ time_t st_mtime;
+ unsigned int st_spare2;
+ time_t st_ctime;
+ unsigned int st_spare3;
+ int st_blksize;
+ int st_blocks;
+ unsigned int __unused1; /* ACL stuff */
+ dev_t __unused2; /* network */
+ ino_t __unused3; /* network */
+ unsigned int __unused4; /* cnodes */
+ unsigned short __unused5; /* netsite */
+ short st_fstype;
+ dev_t st_realdev;
+ unsigned short st_basemode;
+ unsigned short st_spareshort;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned int st_spare4[3];
+};
+
+typedef __kernel_off64_t off64_t;
+
+struct hpux_stat64 {
+ dev_t st_dev; /* dev_t is 32 bits on parisc */
+ ino_t st_ino; /* 32 bits */
+ mode_t st_mode; /* 16 bits */
+ nlink_t st_nlink; /* 16 bits */
+ unsigned short st_reserved1; /* old st_uid */
+ unsigned short st_reserved2; /* old st_gid */
+ dev_t st_rdev;
+ off64_t st_size;
+ time_t st_atime;
+ unsigned int st_spare1;
+ time_t st_mtime;
+ unsigned int st_spare2;
+ time_t st_ctime;
+ unsigned int st_spare3;
+ int st_blksize;
+ __u64 st_blocks;
+ unsigned int __unused1; /* ACL stuff */
+ dev_t __unused2; /* network */
+ ino_t __unused3; /* network */
+ unsigned int __unused4; /* cnodes */
+ unsigned short __unused5; /* netsite */
+ short st_fstype;
+ dev_t st_realdev;
+ unsigned short st_basemode;
+ unsigned short st_spareshort;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned int st_spare4[3];
+};
+#define stat64 hpux_stat64
+
+#endif
diff --git a/include/asm-parisc/statfs.h b/include/asm-parisc/statfs.h
new file mode 100644
index 000000000..db72e852e
--- /dev/null
+++ b/include/asm-parisc/statfs.h
@@ -0,0 +1,25 @@
+#ifndef _PARISC_STATFS_H
+#define _PARISC_STATFS_H
+
+#ifndef __KERNEL_STRICT_NAMES
+
+#include <linux/types.h>
+
+typedef __kernel_fsid_t fsid_t;
+
+#endif
+
+struct statfs {
+ long f_type;
+ long f_bsize;
+ long f_blocks;
+ long f_bfree;
+ long f_bavail;
+ long f_files;
+ long f_ffree;
+ __kernel_fsid_t f_fsid;
+ long f_namelen;
+ long f_spare[6];
+};
+
+#endif
diff --git a/include/asm-parisc/string.h b/include/asm-parisc/string.h
new file mode 100644
index 000000000..beede5791
--- /dev/null
+++ b/include/asm-parisc/string.h
@@ -0,0 +1,2 @@
+
+/* This left blank until we do parisc optimizations */
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h
new file mode 100644
index 000000000..1f2563418
--- /dev/null
+++ b/include/asm-parisc/system.h
@@ -0,0 +1,148 @@
+#ifndef __PARISC_SYSTEM_H
+#define __PARISC_SYSTEM_H
+
+#include <linux/config.h>
+#include <asm/psw.h>
+
+/* The program status word as bitfields. */
+struct pa_psw {
+ unsigned int y:1;
+ unsigned int z:1;
+ unsigned int rv:2;
+ unsigned int w:1;
+ unsigned int e:1;
+ unsigned int s:1;
+ unsigned int t:1;
+
+ unsigned int h:1;
+ unsigned int l:1;
+ unsigned int n:1;
+ unsigned int x:1;
+ unsigned int b:1;
+ unsigned int c:1;
+ unsigned int v:1;
+ unsigned int m:1;
+
+ unsigned int cb:8;
+
+ unsigned int o:1;
+ unsigned int g:1;
+ unsigned int f:1;
+ unsigned int r:1;
+ unsigned int q:1;
+ unsigned int p:1;
+ unsigned int d:1;
+ unsigned int i:1;
+};
+
+#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW))
+
+struct task_struct;
+
+extern struct task_struct *_switch_to(struct task_struct *, struct task_struct *);
+
+#define prepare_to_switch() do { } while(0)
+#define switch_to(prev, next, last) do { \
+ (last) = _switch_to(prev, next); \
+} while(0)
+
+/* borrowed this from sparc64 -- probably the SMP case is hosed for us */
+#ifdef CONFIG_SMP
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#else
+/* This is simply the barrier() macro from linux/kernel.h but when serial.c
+ * uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
+ * hasn't yet been included yet so it fails, thus repeating the macro here.
+ */
+#define smp_mb() __asm__ __volatile__("":::"memory");
+#define smp_rmb() __asm__ __volatile__("":::"memory");
+#define smp_wmb() __asm__ __volatile__("":::"memory");
+#endif
+
+/* interrupt control */
+#define __save_flags(x) __asm__ __volatile__("ssm 0, %0" : "=r" (x) : : "memory")
+#define __restore_flags(x) __asm__ __volatile__("mtsm %0" : : "r" (x) : "memory")
+#define __cli() __asm__ __volatile__("rsm %0,%%r0\n" : : "i" (PSW_I) : "memory" )
+#define __sti() __asm__ __volatile__("ssm %0,%%r0\n" : : "i" (PSW_I) : "memory" )
+
+#define local_irq_save(x) \
+ __asm__ __volatile__("rsm %1,%0" : "=r" (x) :"i" (PSW_I) : "memory" )
+#define local_irq_restore(x) \
+ __asm__ __volatile__("mtsm %0" : : "r" (x) : "memory" )
+#define local_irq_disable() __cli()
+#define local_irq_enable() __sti()
+
+#ifdef CONFIG_SMP
+#else
+#define cli() __cli()
+#define sti() __sti()
+#define save_flags(x) __save_flags(x)
+#define restore_flags(x) __restore_flags(x)
+#endif
+
+
+#define mfctl(reg) ({ \
+ unsigned long cr; \
+ __asm__ __volatile__( \
+ "mfctl " #reg ",%0" : \
+ "=r" (cr) \
+ ); \
+ cr; \
+})
+
+#define mtctl(gr, cr) \
+ __asm__ __volatile__("mtctl %0,%1" \
+ : /* no outputs */ \
+ : "r" (gr), "i" (cr))
+
+/* these are here to de-mystefy the calling code, and to provide hooks */
+/* which I needed for debugging EIEM problems -PB */
+#define get_eiem() mfctl(15)
+static inline void set_eiem(unsigned long val)
+{
+ mtctl(val, 15);
+}
+
+#define mfsp(reg) ({ \
+ unsigned long cr; \
+ __asm__ __volatile__( \
+ "mfsp " #reg ",%0" : \
+ "=r" (cr) \
+ ); \
+ cr; \
+})
+
+#define mtsp(gr, cr) \
+ __asm__ __volatile__("mtsp %0,%1" \
+ : /* no outputs */ \
+ : "r" (gr), "i" (cr))
+
+
+#define mb() __asm__ __volatile__ ("sync" : : :"memory")
+#define wmb() mb()
+
+extern unsigned long __xchg(unsigned long, unsigned long *, int);
+
+#define xchg(ptr,x) \
+ (__typeof__(*(ptr)))__xchg((unsigned long)(x),(unsigned long*)(ptr),sizeof(*(ptr)))
+
+/* LDCW, the only atomic read-write operation PA-RISC has. Sigh. */
+#define __ldcw(a) ({ \
+ unsigned __ret; \
+ __asm__ __volatile__("ldcw 0(%1),%0" : "=r" (__ret) : "r" (a)); \
+ __ret; \
+})
+
+#ifdef CONFIG_SMP
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+
+typedef struct {
+ volatile unsigned int __attribute__((aligned(16))) lock;
+} spinlock_t;
+#endif
+
+#endif
diff --git a/include/asm-parisc/termbits.h b/include/asm-parisc/termbits.h
new file mode 100644
index 000000000..4cff59325
--- /dev/null
+++ b/include/asm-parisc/termbits.h
@@ -0,0 +1,174 @@
+#ifndef __ARCH_PARISC_TERMBITS_H__
+#define __ARCH_PARISC_TERMBITS_H__
+
+#include <linux/posix_types.h>
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define NCCS 19
+struct termios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+
+/* c_iflag bits */
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK 0000020
+#define ISTRIP 0000040
+#define INLCR 0000100
+#define IGNCR 0000200
+#define ICRNL 0000400
+#define IUCLC 0001000
+#define IXON 0002000
+#define IXANY 0004000
+#define IXOFF 0010000
+#define IMAXBEL 0040000
+
+/* c_oflag bits */
+#define OPOST 0000001
+#define OLCUC 0000002
+#define ONLCR 0000004
+#define OCRNL 0000010
+#define ONOCR 0000020
+#define ONLRET 0000040
+#define OFILL 0000100
+#define OFDEL 0000200
+#define NLDLY 0000400
+#define NL0 0000000
+#define NL1 0000400
+#define CRDLY 0003000
+#define CR0 0000000
+#define CR1 0001000
+#define CR2 0002000
+#define CR3 0003000
+#define TABDLY 0014000
+#define TAB0 0000000
+#define TAB1 0004000
+#define TAB2 0010000
+#define TAB3 0014000
+#define XTABS 0014000
+#define BSDLY 0020000
+#define BS0 0000000
+#define BS1 0020000
+#define VTDLY 0040000
+#define VT0 0000000
+#define VT1 0040000
+#define FFDLY 0100000
+#define FF0 0000000
+#define FF1 0100000
+
+/* c_cflag bit meaning */
+#define CBAUD 0010017
+#define B0 0000000 /* hang up */
+#define B50 0000001
+#define B75 0000002
+#define B110 0000003
+#define B134 0000004
+#define B150 0000005
+#define B200 0000006
+#define B300 0000007
+#define B600 0000010
+#define B1200 0000011
+#define B1800 0000012
+#define B2400 0000013
+#define B4800 0000014
+#define B9600 0000015
+#define B19200 0000016
+#define B38400 0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE 0000060
+#define CS5 0000000
+#define CS6 0000020
+#define CS7 0000040
+#define CS8 0000060
+#define CSTOPB 0000100
+#define CREAD 0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL 0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define B500000 0010005
+#define B576000 0010006
+#define B921600 0010007
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
+#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CMSPAR 010000000000 /* mark or space (stick) parity */
+#define CRTSCTS 020000000000 /* flow control */
+
+
+/* c_lflag bits */
+#define ISIG 0000001
+#define ICANON 0000002
+#define XCASE 0000004
+#define ECHO 0000010
+#define ECHOE 0000020
+#define ECHOK 0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL 0001000
+#define ECHOPRT 0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+
+/* tcflow() and TCXONC use these */
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+
+/* tcflush() and TCFLSH use these */
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+
+/* tcsetattr uses these */
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+#endif
diff --git a/include/asm-parisc/termios.h b/include/asm-parisc/termios.h
new file mode 100644
index 000000000..6aa0f8ff7
--- /dev/null
+++ b/include/asm-parisc/termios.h
@@ -0,0 +1,103 @@
+#ifndef _PARISC_TERMIOS_H
+#define _PARISC_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+ unsigned short c_iflag; /* input mode flags */
+ unsigned short c_oflag; /* output mode flags */
+ unsigned short c_cflag; /* control mode flags */
+ unsigned short c_lflag; /* local mode flags */
+ unsigned char c_line; /* line discipline */
+ unsigned char c_cc[NCC]; /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE 0x001
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_ST 0x008
+#define TIOCM_SR 0x010
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RNG 0x080
+#define TIOCM_DSR 0x100
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
+#define TIOCM_OUT1 0x2000
+#define TIOCM_OUT2 0x4000
+#define TIOCM_LOOP 0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY 0
+#define N_SLIP 1
+#define N_MOUSE 2
+#define N_PPP 3
+#define N_STRIP 4
+#define N_AX25 5
+#define N_X25 6 /* X.25 async */
+#define N_6PACK 7
+#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964 9 /* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA 11 /* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
+
+#ifdef __KERNEL__
+
+/* intr=^C quit=^\ erase=del kill=^U
+ eof=^D vtime=\0 vmin=\1 sxtc=\0
+ start=^Q stop=^S susp=^Z eol=\0
+ reprint=^R discard=^U werase=^W lnext=^V
+ eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+ unsigned short __tmp; \
+ get_user(__tmp,&(termio)->x); \
+ *(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+ copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+ put_user((termios)->c_iflag, &(termio)->c_iflag); \
+ put_user((termios)->c_oflag, &(termio)->c_oflag); \
+ put_user((termios)->c_cflag, &(termio)->c_cflag); \
+ put_user((termios)->c_lflag, &(termio)->c_lflag); \
+ put_user((termios)->c_line, &(termio)->c_line); \
+ copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif /* __KERNEL__ */
+
+#endif /* _PARISC_TERMIOS_H */
diff --git a/include/asm-parisc/timex.h b/include/asm-parisc/timex.h
new file mode 100644
index 000000000..7b901fc23
--- /dev/null
+++ b/include/asm-parisc/timex.h
@@ -0,0 +1,21 @@
+/*
+ * linux/include/asm-parisc/timex.h
+ *
+ * PARISC architecture timex specifications
+ */
+#ifndef _ASMPARISC_TIMEX_H
+#define _ASMPARISC_TIMEX_H
+
+#include <asm/system.h>
+#include <linux/time.h>
+
+typedef unsigned long cycles_t;
+
+extern cycles_t cacheflush_time;
+
+static inline cycles_t get_cycles (void)
+{
+ return mfctl(16);
+}
+
+#endif
diff --git a/include/asm-parisc/traps.h b/include/asm-parisc/traps.h
new file mode 100644
index 000000000..6ebc4e6e2
--- /dev/null
+++ b/include/asm-parisc/traps.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_TRAPS_H
+#define __ASM_TRAPS_H
+
+#endif
diff --git a/include/asm-parisc/types.h b/include/asm-parisc/types.h
new file mode 100644
index 000000000..6d4698649
--- /dev/null
+++ b/include/asm-parisc/types.h
@@ -0,0 +1,54 @@
+#ifndef _PARISC_TYPES_H
+#define _PARISC_TYPES_H
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#ifdef __LP64__
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif
+
+/* Dma addresses are 32-bits wide. */
+
+typedef u32 dma_addr_t;
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
new file mode 100644
index 000000000..70e834f12
--- /dev/null
+++ b/include/asm-parisc/uaccess.h
@@ -0,0 +1,189 @@
+#ifndef __PARISC_UACCESS_H
+#define __PARISC_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/cache.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+#define KERNEL_DS ((mm_segment_t){0})
+#define USER_DS ((mm_segment_t){1})
+
+#define segment_eq(a,b) ((a).seg == (b).seg)
+
+#define get_ds() (KERNEL_DS)
+#define get_fs() (current->addr_limit)
+#define set_fs(x) (current->addr_limit = (x))
+
+/*
+ * Note that since kernel addresses are in a separate address space on
+ * parisc, we don't need to do anything for access_ok() or verify_area().
+ * We just let the page fault handler do the right thing. This also means
+ * that put_user is the same as __put_user, etc.
+ */
+
+#define access_ok(type,addr,size) (1)
+#define verify_area(type,addr,size) (0)
+
+#define put_user __put_user
+#define get_user __get_user
+
+/*
+ * The exception table contains two values: the first is an address
+ * for an instruction that is allowed to fault, and the second is
+ * the number of bytes to skip if a fault occurs. We also support in
+ * two bit flags: 0x2 tells the exception handler to clear register
+ * r9 and 0x1 tells the exception handler to put -EFAULT in r8.
+ * This allows us to handle the simple cases for put_user and
+ * get_user without having to have .fixup sections.
+ */
+
+struct exception_table_entry {
+ unsigned long addr; /* address of insn that is allowed to fault. */
+ int skip; /* pcoq skip | r9 clear flag | r8 -EFAULT flag */
+};
+
+extern const struct exception_table_entry
+ *search_exception_table(unsigned long addr);
+
+#define __get_user(x,ptr) \
+({ \
+ register long __gu_err __asm__ ("r8") = 0; \
+ register long __gu_val __asm__ ("r9") = 0; \
+ \
+ if (segment_eq(get_fs(),KERNEL_DS)) { \
+ switch (sizeof(*(ptr))) { \
+ case 1: __get_kernel_asm("ldb",ptr); break; \
+ case 2: __get_kernel_asm("ldh",ptr); break; \
+ case 4: __get_kernel_asm("ldw",ptr); break; \
+ case 8: __get_kernel_asm("ldd",ptr); break; \
+ default: BUG(); break; \
+ } \
+ } \
+ else { \
+ switch (sizeof(*(ptr))) { \
+ case 1: __get_user_asm("ldb",ptr); break; \
+ case 2: __get_user_asm("ldh",ptr); break; \
+ case 4: __get_user_asm("ldw",ptr); break; \
+ case 8: __get_user_asm("ldd",ptr); break; \
+ default: BUG(); break; \
+ } \
+ } \
+ \
+ (x) = (__typeof__(*(ptr))) __gu_val; \
+ __gu_err; \
+})
+
+#define __get_kernel_asm(ldx,ptr) \
+ __asm__("\n1:\t" ldx "\t0(%2),%0\n" \
+ "2:\n" \
+ "\t.section __ex_table,\"a\"\n" \
+ "\t.word\t1b\n" \
+ "\t.word\t(2b-1b)+3\n" \
+ "\t.previous" \
+ : "=r"(__gu_val), "=r"(__gu_err) \
+ : "r"(ptr), "1"(__gu_err));
+
+#define __get_user_asm(ldx,ptr) \
+ __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
+ "2:\n" \
+ "\t.section __ex_table,\"a\"\n" \
+ "\t.word\t1b\n" \
+ "\t.word\t(2b-1b)+3\n" \
+ "\t.previous" \
+ : "=r"(__gu_val), "=r"(__gu_err) \
+ : "r"(ptr), "1"(__gu_err));
+
+
+#define __put_user(x,ptr) \
+({ \
+ register long __pu_err __asm__ ("r8") = 0; \
+ \
+ if (segment_eq(get_fs(),KERNEL_DS)) { \
+ switch (sizeof(*(ptr))) { \
+ case 1: __put_kernel_asm("stb",x,ptr); break; \
+ case 2: __put_kernel_asm("sth",x,ptr); break; \
+ case 4: __put_kernel_asm("stw",x,ptr); break; \
+ case 8: __put_kernel_asm("std",x,ptr); break; \
+ default: BUG(); break; \
+ } \
+ } \
+ else { \
+ switch (sizeof(*(ptr))) { \
+ case 1: __put_user_asm("stb",x,ptr); break; \
+ case 2: __put_user_asm("sth",x,ptr); break; \
+ case 4: __put_user_asm("stw",x,ptr); break; \
+ case 8: __put_user_asm("std",x,ptr); break; \
+ default: BUG(); break; \
+ } \
+ } \
+ \
+ __pu_err; \
+})
+
+/*
+ * The "__put_user/kernel_asm()" macros tell gcc they read from memory
+ * instead of writing. This is because they do not write to any memory
+ * gcc knows about, so there are no aliasing issues.
+ */
+
+#define __put_kernel_asm(stx,x,ptr) \
+ __asm__ __volatile__ ( \
+ "\n1:\t" stx "\t%2,0(%1)\n" \
+ "2:\n" \
+ "\t.section __ex_table,\"a\"\n" \
+ "\t.word\t1b\n" \
+ "\t.word\t(2b-1b)+1\n" \
+ "\t.previous" \
+ : "=r"(__pu_err) \
+ : "r"(ptr), "r"(x), "0"(__pu_err))
+
+#define __put_user_asm(stx,x,ptr) \
+ __asm__ __volatile__ ( \
+ "\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
+ "2:\n" \
+ "\t.section __ex_table,\"a\"\n" \
+ "\t.word\t1b\n" \
+ "\t.word\t(2b-1b)+1\n" \
+ "\t.previous" \
+ : "=r"(__pu_err) \
+ : "r"(ptr), "r"(x), "0"(__pu_err))
+
+
+/*
+ * Complex access routines -- external declarations
+ */
+
+extern unsigned long lcopy_to_user(void *, const void *, unsigned long);
+extern unsigned long lcopy_from_user(void *, const void *, unsigned long);
+extern long lstrncpy_from_user(char *, const char *, long);
+extern unsigned lclear_user(void *,unsigned long);
+extern long lstrnlen_user(const char *,long);
+
+/*
+ * Complex access routines -- macros
+ */
+
+#define strncpy_from_user lstrncpy_from_user
+#define strnlen_user lstrnlen_user
+#define strlen_user(str) lstrnlen_user(str, 0x7fffffffL)
+#define clear_user lclear_user
+
+#define copy_from_user lcopy_from_user
+#define __copy_from_user lcopy_from_user
+#define copy_to_user lcopy_to_user
+#define __copy_to_user lcopy_to_user
+
+#define copy_to_user_ret(to,from,n,retval) \
+ ({ if (lcopy_to_user(to,from,n)) return retval; })
+
+#define copy_from_user_ret(to,from,n,retval) \
+ ({ if (lcopy_from_user(to,from,n)) return retval; })
+
+#endif /* __PARISC_UACCESS_H */
diff --git a/include/asm-parisc/ucontext.h b/include/asm-parisc/ucontext.h
new file mode 100644
index 000000000..f2e590499
--- /dev/null
+++ b/include/asm-parisc/ucontext.h
@@ -0,0 +1,12 @@
+#ifndef _ASMPARISC_UCONTEXT_H
+#define _ASMPARISC_UCONTEXT_H
+
+struct ucontext {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask; /* mask last for extensibility */
+};
+
+#endif /* !_ASMPARISC_UCONTEXT_H */
diff --git a/include/asm-parisc/unaligned.h b/include/asm-parisc/unaligned.h
new file mode 100644
index 000000000..531f53841
--- /dev/null
+++ b/include/asm-parisc/unaligned.h
@@ -0,0 +1,20 @@
+#ifndef _ASM_PARISC_UNALIGNED_H_
+#define _ASM_PARISC_UNALIGNED_H_
+
+/* parisc can't handle unaligned accesses. */
+/* copied from asm-sparc/unaligned.h */
+
+#include <linux/string.h>
+
+
+/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+
+#define get_unaligned(ptr) \
+ ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+
+#define put_unaligned(val, ptr) \
+ ({ __typeof__(*(ptr)) __tmp = (val); \
+ memmove((ptr), &__tmp, sizeof(*(ptr))); \
+ (void)0; })
+
+#endif /* _ASM_PARISC_UNALIGNED_H */
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
new file mode 100644
index 000000000..ea0542a35
--- /dev/null
+++ b/include/asm-parisc/unistd.h
@@ -0,0 +1,901 @@
+#ifndef _ASM_PARISC_UNISTD_H_
+#define _ASM_PARISC_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+/*
+ * HP-UX system calls get their native numbers for binary compatibility.
+ */
+
+#define __NR_HPUX_exit 1
+#define __NR_HPUX_fork 2
+#define __NR_HPUX_read 3
+#define __NR_HPUX_write 4
+#define __NR_HPUX_open 5
+#define __NR_HPUX_close 6
+#define __NR_HPUX_wait 7
+#define __NR_HPUX_creat 8
+#define __NR_HPUX_link 9
+#define __NR_HPUX_unlink 10
+#define __NR_HPUX_execv 11
+#define __NR_HPUX_chdir 12
+#define __NR_HPUX_time 13
+#define __NR_HPUX_mknod 14
+#define __NR_HPUX_chmod 15
+#define __NR_HPUX_chown 16
+#define __NR_HPUX_break 17
+#define __NR_HPUX_lchmod 18
+#define __NR_HPUX_lseek 19
+#define __NR_HPUX_getpid 20
+#define __NR_HPUX_mount 21
+#define __NR_HPUX_umount 22
+#define __NR_HPUX_setuid 23
+#define __NR_HPUX_getuid 24
+#define __NR_HPUX_stime 25
+#define __NR_HPUX_ptrace 26
+#define __NR_HPUX_alarm 27
+#define __NR_HPUX_oldfstat 28
+#define __NR_HPUX_pause 29
+#define __NR_HPUX_utime 30
+#define __NR_HPUX_stty 31
+#define __NR_HPUX_gtty 32
+#define __NR_HPUX_access 33
+#define __NR_HPUX_nice 34
+#define __NR_HPUX_ftime 35
+#define __NR_HPUX_sync 36
+#define __NR_HPUX_kill 37
+#define __NR_HPUX_stat 38
+#define __NR_HPUX_setpgrp3 39
+#define __NR_HPUX_lstat 40
+#define __NR_HPUX_dup 41
+#define __NR_HPUX_pipe 42
+#define __NR_HPUX_times 43
+#define __NR_HPUX_profil 44
+#define __NR_HPUX_ki_call 45
+#define __NR_HPUX_setgid 46
+#define __NR_HPUX_getgid 47
+#define __NR_HPUX_sigsys 48
+#define __NR_HPUX_reserved1 49
+#define __NR_HPUX_reserved2 50
+#define __NR_HPUX_acct 51
+#define __NR_HPUX_set_userthreadid 52
+#define __NR_HPUX_oldlock 53
+#define __NR_HPUX_ioctl 54
+#define __NR_HPUX_reboot 55
+#define __NR_HPUX_symlink 56
+#define __NR_HPUX_utssys 57
+#define __NR_HPUX_readlink 58
+#define __NR_HPUX_execve 59
+#define __NR_HPUX_umask 60
+#define __NR_HPUX_chroot 61
+#define __NR_HPUX_fcntl 62
+#define __NR_HPUX_ulimit 63
+#define __NR_HPUX_getpagesize 64
+#define __NR_HPUX_mremap 65
+#define __NR_HPUX_vfork 66
+#define __NR_HPUX_vread 67
+#define __NR_HPUX_vwrite 68
+#define __NR_HPUX_sbrk 69
+#define __NR_HPUX_sstk 70
+#define __NR_HPUX_mmap 71
+#define __NR_HPUX_vadvise 72
+#define __NR_HPUX_munmap 73
+#define __NR_HPUX_mprotect 74
+#define __NR_HPUX_madvise 75
+#define __NR_HPUX_vhangup 76
+#define __NR_HPUX_swapoff 77
+#define __NR_HPUX_mincore 78
+#define __NR_HPUX_getgroups 79
+#define __NR_HPUX_setgroups 80
+#define __NR_HPUX_getpgrp2 81
+#define __NR_HPUX_setpgrp2 82
+#define __NR_HPUX_setitimer 83
+#define __NR_HPUX_wait3 84
+#define __NR_HPUX_swapon 85
+#define __NR_HPUX_getitimer 86
+#define __NR_HPUX_gethostname42 87
+#define __NR_HPUX_sethostname42 88
+#define __NR_HPUX_getdtablesize 89
+#define __NR_HPUX_dup2 90
+#define __NR_HPUX_getdopt 91
+#define __NR_HPUX_fstat 92
+#define __NR_HPUX_select 93
+#define __NR_HPUX_setdopt 94
+#define __NR_HPUX_fsync 95
+#define __NR_HPUX_setpriority 96
+#define __NR_HPUX_socket_old 97
+#define __NR_HPUX_connect_old 98
+#define __NR_HPUX_accept_old 99
+#define __NR_HPUX_getpriority 100
+#define __NR_HPUX_send_old 101
+#define __NR_HPUX_recv_old 102
+#define __NR_HPUX_socketaddr_old 103
+#define __NR_HPUX_bind_old 104
+#define __NR_HPUX_setsockopt_old 105
+#define __NR_HPUX_listen_old 106
+#define __NR_HPUX_vtimes_old 107
+#define __NR_HPUX_sigvector 108
+#define __NR_HPUX_sigblock 109
+#define __NR_HPUX_siggetmask 110
+#define __NR_HPUX_sigpause 111
+#define __NR_HPUX_sigstack 112
+#define __NR_HPUX_recvmsg_old 113
+#define __NR_HPUX_sendmsg_old 114
+#define __NR_HPUX_vtrace_old 115
+#define __NR_HPUX_gettimeofday 116
+#define __NR_HPUX_getrusage 117
+#define __NR_HPUX_getsockopt_old 118
+#define __NR_HPUX_resuba_old 119
+#define __NR_HPUX_readv 120
+#define __NR_HPUX_writev 121
+#define __NR_HPUX_settimeofday 122
+#define __NR_HPUX_fchown 123
+#define __NR_HPUX_fchmod 124
+#define __NR_HPUX_recvfrom_old 125
+#define __NR_HPUX_setresuid 126
+#define __NR_HPUX_setresgid 127
+#define __NR_HPUX_rename 128
+#define __NR_HPUX_truncate 129
+#define __NR_HPUX_ftruncate 130
+#define __NR_HPUX_flock_old 131
+#define __NR_HPUX_sysconf 132
+#define __NR_HPUX_sendto_old 133
+#define __NR_HPUX_shutdown_old 134
+#define __NR_HPUX_socketpair_old 135
+#define __NR_HPUX_mkdir 136
+#define __NR_HPUX_rmdir 137
+#define __NR_HPUX_utimes_old 138
+#define __NR_HPUX_sigcleanup_old 139
+#define __NR_HPUX_setcore 140
+#define __NR_HPUX_getpeername_old 141
+#define __NR_HPUX_gethostid 142
+#define __NR_HPUX_sethostid 143
+#define __NR_HPUX_getrlimit 144
+#define __NR_HPUX_setrlimit 145
+#define __NR_HPUX_killpg_old 146
+#define __NR_HPUX_cachectl 147
+#define __NR_HPUX_quotactl 148
+#define __NR_HPUX_get_sysinfo 149
+#define __NR_HPUX_getsockname_old 150
+#define __NR_HPUX_privgrp 151
+#define __NR_HPUX_rtprio 152
+#define __NR_HPUX_plock 153
+#define __NR_HPUX_reserved3 154
+#define __NR_HPUX_lockf 155
+#define __NR_HPUX_semget 156
+#define __NR_HPUX_osemctl 157
+#define __NR_HPUX_semop 158
+#define __NR_HPUX_msgget 159
+#define __NR_HPUX_omsgctl 160
+#define __NR_HPUX_msgsnd 161
+#define __NR_HPUX_msgrecv 162
+#define __NR_HPUX_shmget 163
+#define __NR_HPUX_oshmctl 164
+#define __NR_HPUX_shmat 165
+#define __NR_HPUX_shmdt 166
+#define __NR_HPUX_m68020_advise 167
+/* [168,189] are for Discless/DUX */
+#define __NR_HPUX_csp 168
+#define __NR_HPUX_cluster 169
+#define __NR_HPUX_mkrnod 170
+#define __NR_HPUX_test 171
+#define __NR_HPUX_unsp_open 172
+#define __NR_HPUX_reserved4 173
+#define __NR_HPUX_getcontext_old 174
+#define __NR_HPUX_osetcontext 175
+#define __NR_HPUX_bigio 176
+#define __NR_HPUX_pipenode 177
+#define __NR_HPUX_lsync 178
+#define __NR_HPUX_getmachineid 179
+#define __NR_HPUX_cnodeid 180
+#define __NR_HPUX_cnodes 181
+#define __NR_HPUX_swapclients 182
+#define __NR_HPUX_rmt_process 183
+#define __NR_HPUX_dskless_stats 184
+#define __NR_HPUX_sigprocmask 185
+#define __NR_HPUX_sigpending 186
+#define __NR_HPUX_sigsuspend 187
+#define __NR_HPUX_sigaction 188
+#define __NR_HPUX_reserved5 189
+#define __NR_HPUX_nfssvc 190
+#define __NR_HPUX_getfh 191
+#define __NR_HPUX_getdomainname 192
+#define __NR_HPUX_setdomainname 193
+#define __NR_HPUX_async_daemon 194
+#define __NR_HPUX_getdirentries 195
+#define __NR_HPUX_statfs 196
+#define __NR_HPUX_fstatfs 197
+#define __NR_HPUX_vfsmount 198
+#define __NR_HPUX_reserved6 199
+#define __NR_HPUX_waitpid 200
+/* 201 - 223 missing */
+#define __NR_HPUX_sigsetreturn 224
+#define __NR_HPUX_sigsetstatemask 225
+/* 226 missing */
+#define __NR_HPUX_cs 227
+#define __NR_HPUX_cds 228
+#define __NR_HPUX_set_no_trunc 229
+#define __NR_HPUX_pathconf 230
+#define __NR_HPUX_fpathconf 231
+/* 232, 233 missing */
+#define __NR_HPUX_nfs_fcntl 234
+#define __NR_HPUX_ogetacl 235
+#define __NR_HPUX_ofgetacl 236
+#define __NR_HPUX_osetacl 237
+#define __NR_HPUX_ofsetacl 238
+#define __NR_HPUX_pstat 239
+#define __NR_HPUX_getaudid 240
+#define __NR_HPUX_setaudid 241
+#define __NR_HPUX_getaudproc 242
+#define __NR_HPUX_setaudproc 243
+#define __NR_HPUX_getevent 244
+#define __NR_HPUX_setevent 245
+#define __NR_HPUX_audwrite 246
+#define __NR_HPUX_audswitch 247
+#define __NR_HPUX_audctl 248
+#define __NR_HPUX_ogetaccess 249
+#define __NR_HPUX_fsctl 250
+/* 251 - 258 missing */
+#define __NR_HPUX_swapfs 259
+#define __NR_HPUX_fss 260
+/* 261 - 266 missing */
+#define __NR_HPUX_tsync 267
+#define __NR_HPUX_getnumfds 268
+#define __NR_HPUX_poll 269
+#define __NR_HPUX_getmsg 270
+#define __NR_HPUX_putmsg 271
+#define __NR_HPUX_fchdir 272
+#define __NR_HPUX_getmount_cnt 273
+#define __NR_HPUX_getmount_entry 274
+#define __NR_HPUX_accept 275
+#define __NR_HPUX_bind 276
+#define __NR_HPUX_connect 277
+#define __NR_HPUX_getpeername 278
+#define __NR_HPUX_getsockname 279
+#define __NR_HPUX_getsockopt 280
+#define __NR_HPUX_listen 281
+#define __NR_HPUX_recv 282
+#define __NR_HPUX_recvfrom 283
+#define __NR_HPUX_recvmsg 284
+#define __NR_HPUX_send 285
+#define __NR_HPUX_sendmsg 286
+#define __NR_HPUX_sendto 287
+#define __NR_HPUX_setsockopt 288
+#define __NR_HPUX_shutdown 289
+#define __NR_HPUX_socket 290
+#define __NR_HPUX_socketpair 291
+#define __NR_HPUX_proc_open 292
+#define __NR_HPUX_proc_close 293
+#define __NR_HPUX_proc_send 294
+#define __NR_HPUX_proc_recv 295
+#define __NR_HPUX_proc_sendrecv 296
+#define __NR_HPUX_proc_syscall 297
+/* 298 - 311 missing */
+#define __NR_HPUX_semctl 312
+#define __NR_HPUX_msgctl 313
+#define __NR_HPUX_shmctl 314
+#define __NR_HPUX_mpctl 315
+#define __NR_HPUX_exportfs 316
+#define __NR_HPUX_getpmsg 317
+#define __NR_HPUX_putpmsg 318
+/* 319 missing */
+#define __NR_HPUX_msync 320
+#define __NR_HPUX_msleep 321
+#define __NR_HPUX_mwakeup 322
+#define __NR_HPUX_msem_init 323
+#define __NR_HPUX_msem_remove 324
+#define __NR_HPUX_adjtime 325
+#define __NR_HPUX_kload 326
+#define __NR_HPUX_fattach 327
+#define __NR_HPUX_fdetach 328
+#define __NR_HPUX_serialize 329
+#define __NR_HPUX_statvfs 330
+#define __NR_HPUX_fstatvfs 331
+#define __NR_HPUX_lchown 332
+#define __NR_HPUX_getsid 333
+#define __NR_HPUX_sysfs 334
+/* 335, 336 missing */
+#define __NR_HPUX_sched_setparam 337
+#define __NR_HPUX_sched_getparam 338
+#define __NR_HPUX_sched_setscheduler 339
+#define __NR_HPUX_sched_getscheduler 340
+#define __NR_HPUX_sched_yield 341
+#define __NR_HPUX_sched_get_priority_max 342
+#define __NR_HPUX_sched_get_priority_min 343
+#define __NR_HPUX_sched_rr_get_interval 344
+#define __NR_HPUX_clock_settime 345
+#define __NR_HPUX_clock_gettime 346
+#define __NR_HPUX_clock_getres 347
+#define __NR_HPUX_timer_create 348
+#define __NR_HPUX_timer_delete 349
+#define __NR_HPUX_timer_settime 350
+#define __NR_HPUX_timer_gettime 351
+#define __NR_HPUX_timer_getoverrun 352
+#define __NR_HPUX_nanosleep 353
+#define __NR_HPUX_toolbox 354
+/* 355 missing */
+#define __NR_HPUX_getdents 356
+#define __NR_HPUX_getcontext 357
+#define __NR_HPUX_sysinfo 358
+#define __NR_HPUX_fcntl64 359
+#define __NR_HPUX_ftruncate64 360
+#define __NR_HPUX_fstat64 361
+#define __NR_HPUX_getdirentries64 362
+#define __NR_HPUX_getrlimit64 363
+#define __NR_HPUX_lockf64 364
+#define __NR_HPUX_lseek64 365
+#define __NR_HPUX_lstat64 366
+#define __NR_HPUX_mmap64 367
+#define __NR_HPUX_setrlimit64 368
+#define __NR_HPUX_stat64 369
+#define __NR_HPUX_truncate64 370
+#define __NR_HPUX_ulimit64 371
+#define __NR_HPUX_pread 372
+#define __NR_HPUX_preadv 373
+#define __NR_HPUX_pwrite 374
+#define __NR_HPUX_pwritev 375
+#define __NR_HPUX_pread64 376
+#define __NR_HPUX_preadv64 377
+#define __NR_HPUX_pwrite64 378
+#define __NR_HPUX_pwritev64 379
+#define __NR_HPUX_setcontext 380
+#define __NR_HPUX_sigaltstack 381
+#define __NR_HPUX_waitid 382
+#define __NR_HPUX_setpgrp 383
+#define __NR_HPUX_recvmsg2 384
+#define __NR_HPUX_sendmsg2 385
+#define __NR_HPUX_socket2 386
+#define __NR_HPUX_socketpair2 387
+#define __NR_HPUX_setregid 388
+#define __NR_HPUX_lwp_create 389
+#define __NR_HPUX_lwp_terminate 390
+#define __NR_HPUX_lwp_wait 391
+#define __NR_HPUX_lwp_suspend 392
+#define __NR_HPUX_lwp_resume 393
+/* 394 missing */
+#define __NR_HPUX_lwp_abort_syscall 395
+#define __NR_HPUX_lwp_info 396
+#define __NR_HPUX_lwp_kill 397
+#define __NR_HPUX_ksleep 398
+#define __NR_HPUX_kwakeup 399
+/* 400 missing */
+#define __NR_HPUX_pstat_getlwp 401
+#define __NR_HPUX_lwp_exit 402
+#define __NR_HPUX_lwp_continue 403
+#define __NR_HPUX_getacl 404
+#define __NR_HPUX_fgetacl 405
+#define __NR_HPUX_setacl 406
+#define __NR_HPUX_fsetacl 407
+#define __NR_HPUX_getaccess 408
+#define __NR_HPUX_lwp_mutex_init 409
+#define __NR_HPUX_lwp_mutex_lock_sys 410
+#define __NR_HPUX_lwp_mutex_unlock 411
+#define __NR_HPUX_lwp_cond_init 412
+#define __NR_HPUX_lwp_cond_signal 413
+#define __NR_HPUX_lwp_cond_broadcast 414
+#define __NR_HPUX_lwp_cond_wait_sys 415
+#define __NR_HPUX_lwp_getscheduler 416
+#define __NR_HPUX_lwp_setscheduler 417
+#define __NR_HPUX_lwp_getstate 418
+#define __NR_HPUX_lwp_setstate 419
+#define __NR_HPUX_lwp_detach 420
+#define __NR_HPUX_mlock 421
+#define __NR_HPUX_munlock 422
+#define __NR_HPUX_mlockall 423
+#define __NR_HPUX_munlockall 424
+#define __NR_HPUX_shm_open 425
+#define __NR_HPUX_shm_unlink 426
+#define __NR_HPUX_sigqueue 427
+#define __NR_HPUX_sigwaitinfo 428
+#define __NR_HPUX_sigtimedwait 429
+#define __NR_HPUX_sigwait 430
+#define __NR_HPUX_aio_read 431
+#define __NR_HPUX_aio_write 432
+#define __NR_HPUX_lio_listio 433
+#define __NR_HPUX_aio_error 434
+#define __NR_HPUX_aio_return 435
+#define __NR_HPUX_aio_cancel 436
+#define __NR_HPUX_aio_suspend 437
+#define __NR_HPUX_aio_fsync 438
+#define __NR_HPUX_mq_open 439
+#define __NR_HPUX_mq_close 440
+#define __NR_HPUX_mq_unlink 441
+#define __NR_HPUX_mq_send 442
+#define __NR_HPUX_mq_receive 443
+#define __NR_HPUX_mq_notify 444
+#define __NR_HPUX_mq_setattr 445
+#define __NR_HPUX_mq_getattr 446
+#define __NR_HPUX_ksem_open 447
+#define __NR_HPUX_ksem_unlink 448
+#define __NR_HPUX_ksem_close 449
+#define __NR_HPUX_ksem_post 450
+#define __NR_HPUX_ksem_wait 451
+#define __NR_HPUX_ksem_read 452
+#define __NR_HPUX_ksem_trywait 453
+#define __NR_HPUX_lwp_rwlock_init 454
+#define __NR_HPUX_lwp_rwlock_destroy 455
+#define __NR_HPUX_lwp_rwlock_rdlock_sys 456
+#define __NR_HPUX_lwp_rwlock_wrlock_sys 457
+#define __NR_HPUX_lwp_rwlock_tryrdlock 458
+#define __NR_HPUX_lwp_rwlock_trywrlock 459
+#define __NR_HPUX_lwp_rwlock_unlock 460
+#define __NR_HPUX_ttrace 461
+#define __NR_HPUX_ttrace_wait 462
+#define __NR_HPUX_lf_wire_mem 463
+#define __NR_HPUX_lf_unwire_mem 464
+#define __NR_HPUX_lf_send_pin_map 465
+#define __NR_HPUX_lf_free_buf 466
+#define __NR_HPUX_lf_wait_nq 467
+#define __NR_HPUX_lf_wakeup_conn_q 468
+#define __NR_HPUX_lf_unused 469
+#define __NR_HPUX_lwp_sema_init 470
+#define __NR_HPUX_lwp_sema_post 471
+#define __NR_HPUX_lwp_sema_wait 472
+#define __NR_HPUX_lwp_sema_trywait 473
+#define __NR_HPUX_lwp_sema_destroy 474
+#define __NR_HPUX_statvfs64 475
+#define __NR_HPUX_fstatvfs64 476
+#define __NR_HPUX_msh_register 477
+#define __NR_HPUX_ptrace64 478
+#define __NR_HPUX_sendfile 479
+#define __NR_HPUX_sendpath 480
+#define __NR_HPUX_sendfile64 481
+#define __NR_HPUX_sendpath64 482
+#define __NR_HPUX_modload 483
+#define __NR_HPUX_moduload 484
+#define __NR_HPUX_modpath 485
+#define __NR_HPUX_getksym 486
+#define __NR_HPUX_modadm 487
+#define __NR_HPUX_modstat 488
+#define __NR_HPUX_lwp_detached_exit 489
+#define __NR_HPUX_crashconf 490
+#define __NR_HPUX_siginhibit 491
+#define __NR_HPUX_sigenable 492
+#define __NR_HPUX_spuctl 493
+#define __NR_HPUX_zerokernelsum 494
+#define __NR_HPUX_nfs_kstat 495
+#define __NR_HPUX_aio_read64 496
+#define __NR_HPUX_aio_write64 497
+#define __NR_HPUX_aio_error64 498
+#define __NR_HPUX_aio_return64 499
+#define __NR_HPUX_aio_cancel64 500
+#define __NR_HPUX_aio_suspend64 501
+#define __NR_HPUX_aio_fsync64 502
+#define __NR_HPUX_lio_listio64 503
+#define __NR_HPUX_recv2 504
+#define __NR_HPUX_recvfrom2 505
+#define __NR_HPUX_send2 506
+#define __NR_HPUX_sendto2 507
+#define __NR_HPUX_acl 508
+#define __NR_HPUX___cnx_p2p_ctl 509
+#define __NR_HPUX___cnx_gsched_ctl 510
+#define __NR_HPUX___cnx_pmon_ctl 511
+
+#define __NR_HPUX_syscalls 512
+
+/*
+ * Linux system call numbers.
+ *
+ * Cary Coutant says that we should just use another syscall gateway
+ * page to avoid clashing with the HPUX space, and I think he's right:
+ * it will would keep a branch out of our syscall entry path, at the
+ * very least. If we decide to change it later, we can ``just'' tweak
+ * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be
+ * 1024 or something. Oh, and recompile libc. =)
+ *
+ * 64-bit HPUX binaries get the syscall gateway address passed in a register
+ * from the kernel at startup, which seems a sane strategy.
+ */
+
+#define __NR_Linux 0
+#define __NR_syscall (__NR_Linux + 0)
+#define __NR_exit (__NR_Linux + 1)
+#define __NR_fork (__NR_Linux + 2)
+#define __NR_read (__NR_Linux + 3)
+#define __NR_write (__NR_Linux + 4)
+#define __NR_open (__NR_Linux + 5)
+#define __NR_close (__NR_Linux + 6)
+#define __NR_waitpid (__NR_Linux + 7)
+#define __NR_creat (__NR_Linux + 8)
+#define __NR_link (__NR_Linux + 9)
+#define __NR_unlink (__NR_Linux + 10)
+#define __NR_execve (__NR_Linux + 11)
+#define __NR_chdir (__NR_Linux + 12)
+#define __NR_time (__NR_Linux + 13)
+#define __NR_mknod (__NR_Linux + 14)
+#define __NR_chmod (__NR_Linux + 15)
+#define __NR_lchown (__NR_Linux + 16)
+#define __NR_socket (__NR_Linux + 17)
+#define __NR_stat (__NR_Linux + 18)
+#define __NR_lseek (__NR_Linux + 19)
+#define __NR_getpid (__NR_Linux + 20)
+#define __NR_mount (__NR_Linux + 21)
+#define __NR_bind (__NR_Linux + 22)
+#define __NR_setuid (__NR_Linux + 23)
+#define __NR_getuid (__NR_Linux + 24)
+#define __NR_stime (__NR_Linux + 25)
+#define __NR_ptrace (__NR_Linux + 26)
+#define __NR_alarm (__NR_Linux + 27)
+#define __NR_fstat (__NR_Linux + 28)
+#define __NR_pause (__NR_Linux + 29)
+#define __NR_utime (__NR_Linux + 30)
+#define __NR_connect (__NR_Linux + 31)
+#define __NR_listen (__NR_Linux + 32)
+#define __NR_access (__NR_Linux + 33)
+#define __NR_nice (__NR_Linux + 34)
+#define __NR_accept (__NR_Linux + 35)
+#define __NR_sync (__NR_Linux + 36)
+#define __NR_kill (__NR_Linux + 37)
+#define __NR_rename (__NR_Linux + 38)
+#define __NR_mkdir (__NR_Linux + 39)
+#define __NR_rmdir (__NR_Linux + 40)
+#define __NR_dup (__NR_Linux + 41)
+#define __NR_pipe (__NR_Linux + 42)
+#define __NR_times (__NR_Linux + 43)
+#define __NR_getsockname (__NR_Linux + 44)
+#define __NR_brk (__NR_Linux + 45)
+#define __NR_setgid (__NR_Linux + 46)
+#define __NR_getgid (__NR_Linux + 47)
+#define __NR_signal (__NR_Linux + 48)
+#define __NR_geteuid (__NR_Linux + 49)
+#define __NR_getegid (__NR_Linux + 50)
+#define __NR_acct (__NR_Linux + 51)
+#define __NR_umount2 (__NR_Linux + 52)
+#define __NR_getpeername (__NR_Linux + 53)
+#define __NR_ioctl (__NR_Linux + 54)
+#define __NR_fcntl (__NR_Linux + 55)
+#define __NR_socketpair (__NR_Linux + 56)
+#define __NR_setpgid (__NR_Linux + 57)
+#define __NR_send (__NR_Linux + 58)
+#define __NR_uname (__NR_Linux + 59)
+#define __NR_umask (__NR_Linux + 60)
+#define __NR_chroot (__NR_Linux + 61)
+#define __NR_ustat (__NR_Linux + 62)
+#define __NR_dup2 (__NR_Linux + 63)
+#define __NR_getppid (__NR_Linux + 64)
+#define __NR_getpgrp (__NR_Linux + 65)
+#define __NR_setsid (__NR_Linux + 66)
+#define __NR_pivot_root (__NR_Linux + 67)
+#define __NR_sgetmask (__NR_Linux + 68)
+#define __NR_ssetmask (__NR_Linux + 69)
+#define __NR_setreuid (__NR_Linux + 70)
+#define __NR_setregid (__NR_Linux + 71)
+#define __NR_mincore (__NR_Linux + 72)
+#define __NR_sigpending (__NR_Linux + 73)
+#define __NR_sethostname (__NR_Linux + 74)
+#define __NR_setrlimit (__NR_Linux + 75)
+#define __NR_getrlimit (__NR_Linux + 76)
+#define __NR_getrusage (__NR_Linux + 77)
+#define __NR_gettimeofday (__NR_Linux + 78)
+#define __NR_settimeofday (__NR_Linux + 79)
+#define __NR_getgroups (__NR_Linux + 80)
+#define __NR_setgroups (__NR_Linux + 81)
+#define __NR_sendto (__NR_Linux + 82)
+#define __NR_symlink (__NR_Linux + 83)
+#define __NR_lstat (__NR_Linux + 84)
+#define __NR_readlink (__NR_Linux + 85)
+#define __NR_uselib (__NR_Linux + 86)
+#define __NR_swapon (__NR_Linux + 87)
+#define __NR_reboot (__NR_Linux + 88)
+#define __NR_readdir (__NR_Linux + 89)
+#define __NR_mmap (__NR_Linux + 90)
+#define __NR_munmap (__NR_Linux + 91)
+#define __NR_truncate (__NR_Linux + 92)
+#define __NR_ftruncate (__NR_Linux + 93)
+#define __NR_fchmod (__NR_Linux + 94)
+#define __NR_fchown (__NR_Linux + 95)
+#define __NR_getpriority (__NR_Linux + 96)
+#define __NR_setpriority (__NR_Linux + 97)
+#define __NR_recv (__NR_Linux + 98)
+#define __NR_statfs (__NR_Linux + 99)
+#define __NR_fstatfs (__NR_Linux + 100)
+#define __NR_ioperm (__NR_Linux + 101)
+#define __NR_socketcall (__NR_Linux + 102)
+#define __NR_syslog (__NR_Linux + 103)
+#define __NR_setitimer (__NR_Linux + 104)
+#define __NR_getitimer (__NR_Linux + 105)
+#define __NR_capget (__NR_Linux + 106)
+#define __NR_capset (__NR_Linux + 107)
+#define __NR_pread (__NR_Linux + 108)
+#define __NR_pwrite (__NR_Linux + 109)
+#define __NR_getcwd (__NR_Linux + 110)
+#define __NR_vhangup (__NR_Linux + 111)
+#define __NR_idle (__NR_Linux + 112)
+#define __NR_vfork (__NR_Linux + 113)
+#define __NR_wait4 (__NR_Linux + 114)
+#define __NR_swapoff (__NR_Linux + 115)
+#define __NR_sysinfo (__NR_Linux + 116)
+#define __NR_shutdown (__NR_Linux + 117)
+#define __NR_fsync (__NR_Linux + 118)
+#define __NR_madvise (__NR_Linux + 119)
+#define __NR_clone (__NR_Linux + 120)
+#define __NR_setdomainname (__NR_Linux + 121)
+#define __NR_sendfile (__NR_Linux + 122)
+#define __NR_recvfrom (__NR_Linux + 123)
+#define __NR_adjtimex (__NR_Linux + 124)
+#define __NR_mprotect (__NR_Linux + 125)
+#define __NR_sigprocmask (__NR_Linux + 126)
+#define __NR_create_module (__NR_Linux + 127)
+#define __NR_init_module (__NR_Linux + 128)
+#define __NR_delete_module (__NR_Linux + 129)
+#define __NR_get_kernel_syms (__NR_Linux + 130)
+#define __NR_quotactl (__NR_Linux + 131)
+#define __NR_getpgid (__NR_Linux + 132)
+#define __NR_fchdir (__NR_Linux + 133)
+#define __NR_bdflush (__NR_Linux + 134)
+#define __NR_sysfs (__NR_Linux + 135)
+#define __NR_personality (__NR_Linux + 136)
+#define __NR_afs_syscall (__NR_Linux + 137) /* Syscall for Andrew File System */
+#define __NR_setfsuid (__NR_Linux + 138)
+#define __NR_setfsgid (__NR_Linux + 139)
+#define __NR__llseek (__NR_Linux + 140)
+#define __NR_getdents (__NR_Linux + 141)
+#define __NR__newselect (__NR_Linux + 142)
+#define __NR_flock (__NR_Linux + 143)
+#define __NR_msync (__NR_Linux + 144)
+#define __NR_readv (__NR_Linux + 145)
+#define __NR_writev (__NR_Linux + 146)
+#define __NR_getsid (__NR_Linux + 147)
+#define __NR_fdatasync (__NR_Linux + 148)
+#define __NR__sysctl (__NR_Linux + 149)
+#define __NR_mlock (__NR_Linux + 150)
+#define __NR_munlock (__NR_Linux + 151)
+#define __NR_mlockall (__NR_Linux + 152)
+#define __NR_munlockall (__NR_Linux + 153)
+#define __NR_sched_setparam (__NR_Linux + 154)
+#define __NR_sched_getparam (__NR_Linux + 155)
+#define __NR_sched_setscheduler (__NR_Linux + 156)
+#define __NR_sched_getscheduler (__NR_Linux + 157)
+#define __NR_sched_yield (__NR_Linux + 158)
+#define __NR_sched_get_priority_max (__NR_Linux + 159)
+#define __NR_sched_get_priority_min (__NR_Linux + 160)
+#define __NR_sched_rr_get_interval (__NR_Linux + 161)
+#define __NR_nanosleep (__NR_Linux + 162)
+#define __NR_mremap (__NR_Linux + 163)
+#define __NR_setresuid (__NR_Linux + 164)
+#define __NR_getresuid (__NR_Linux + 165)
+#define __NR_sigaltstack (__NR_Linux + 166)
+#define __NR_query_module (__NR_Linux + 167)
+#define __NR_poll (__NR_Linux + 168)
+#define __NR_nfsservctl (__NR_Linux + 169)
+#define __NR_setresgid (__NR_Linux + 170)
+#define __NR_getresgid (__NR_Linux + 171)
+#define __NR_prctl (__NR_Linux + 172)
+#define __NR_rt_sigreturn (__NR_Linux + 173)
+#define __NR_rt_sigaction (__NR_Linux + 174)
+#define __NR_rt_sigprocmask (__NR_Linux + 175)
+#define __NR_rt_sigpending (__NR_Linux + 176)
+#define __NR_rt_sigtimedwait (__NR_Linux + 177)
+#define __NR_rt_sigqueueinfo (__NR_Linux + 178)
+#define __NR_rt_sigsuspend (__NR_Linux + 179)
+#define __NR_chown (__NR_Linux + 180)
+#define __NR_setsockopt (__NR_Linux + 181)
+#define __NR_getsockopt (__NR_Linux + 182)
+#define __NR_sendmsg (__NR_Linux + 183)
+#define __NR_recvmsg (__NR_Linux + 184)
+#define __NR_semop (__NR_Linux + 185)
+#define __NR_semget (__NR_Linux + 186)
+#define __NR_semctl (__NR_Linux + 187)
+#define __NR_msgsnd (__NR_Linux + 188)
+#define __NR_msgrcv (__NR_Linux + 189)
+#define __NR_msgget (__NR_Linux + 190)
+#define __NR_msgctl (__NR_Linux + 191)
+#define __NR_shmat (__NR_Linux + 192)
+#define __NR_shmdt (__NR_Linux + 193)
+#define __NR_shmget (__NR_Linux + 194)
+#define __NR_shmctl (__NR_Linux + 195)
+
+#define __NR_getpmsg (__NR_Linux + 196) /* some people actually want streams */
+#define __NR_putpmsg (__NR_Linux + 197) /* some people actually want streams */
+
+#define __NR_Linux_syscalls 197
+
+#define HPUX_GATEWAY_ADDR 0xC0000004
+#define LINUX_GATEWAY_ADDR 0x100
+#define LINUX_GATEWAY_STR "0x100"
+
+/* The old syscall code here didn't work, and it looks like it's only used
+ * by applications such as fdisk which for some reason need to produce
+ * their own syscall instead of using same from libc. The code below
+ * is leveraged from glibc/sysdeps/unix/sysv/linux/hppa/sysdep.h where
+ * it is essentially duplicated -- which sucks. -PB
+ */
+
+#define SYS_ify(syscall_name) __NR_##syscall_name
+
+/* The system call number MUST ALWAYS be loaded in the delay slot of
+ the ble instruction, or restarting system calls WILL NOT WORK. See
+ arch/parisc/kernel/signal.c - dhd, 2000-07-26 */
+#define K_INLINE_SYSCALL(name, nr, args...) ({ \
+ unsigned long __sys_res; \
+ { \
+ register unsigned long __res asm("r28"); \
+ K_LOAD_ARGS_##nr(args) \
+ asm volatile( \
+ "ble 0x100(%%sr2, %%r0)\n\t" \
+ " ldi %1, %%r20" \
+ : "=r" (__res) \
+ : "i" (SYS_ify(name)) K_ASM_ARGS_##nr \
+ ); \
+ __sys_res = __res; \
+ } \
+ if (__sys_res >= (unsigned long)-4095) { \
+ errno = -__sys_res; \
+ __sys_res == (unsigned long)-1; \
+ } \
+ __sys_res; \
+})
+
+#define K_LOAD_ARGS_0()
+#define K_LOAD_ARGS_1(r26) \
+ register unsigned long __r26 __asm__("r26") = (unsigned long)r26; \
+ K_LOAD_ARGS_0()
+#define K_LOAD_ARGS_2(r26,r25) \
+ register unsigned long __r25 __asm__("r25") = (unsigned long)r25; \
+ K_LOAD_ARGS_1(r26)
+#define K_LOAD_ARGS_3(r26,r25,r24) \
+ register unsigned long __r24 __asm__("r24") = (unsigned long)r24; \
+ K_LOAD_ARGS_2(r26,r25)
+#define K_LOAD_ARGS_4(r26,r25,r24,r23) \
+ register unsigned long __r23 __asm__("r23") = (unsigned long)r23; \
+ K_LOAD_ARGS_3(r26,r25,r24)
+#define K_LOAD_ARGS_5(r26,r25,r24,r23,r22) \
+ register unsigned long __r22 __asm__("r22") = (unsigned long)r22; \
+ K_LOAD_ARGS_4(r26,r25,r24,r23)
+#define K_LOAD_ARGS_6(r26,r25,r24,r23,r22,r21) \
+ register unsigned long __r21 __asm__("r21") = (unsigned long)r21; \
+ K_LOAD_ARGS_5(r26,r25,r24,r23,r22)
+
+#define K_ASM_ARGS_0
+#define K_ASM_ARGS_1 , "r" (__r26)
+#define K_ASM_ARGS_2 , "r" (__r26), "r" (__r25)
+#define K_ASM_ARGS_3 , "r" (__r26), "r" (__r25), "r" (__r24)
+#define K_ASM_ARGS_4 , "r" (__r26), "r" (__r25), "r" (__r24), "r" (__r23)
+#define K_ASM_ARGS_5 , "r" (__r26), "r" (__r25), "r" (__r24), "r" (__r23), "r" (__r22)
+#define K_ASM_ARGS_6 , "r" (__r26), "r" (__r25), "r" (__r24), "r" (__r23), "r" (__r22), "r" (__r21)
+
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+ return K_INLINE_SYSCALL(name, 0); \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+ return K_INLINE_SYSCALL(name, 1, arg1); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1, type2 arg2) \
+{ \
+ return K_INLINE_SYSCALL(name, 2, arg1, arg2); \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1, type2 arg2, type3 arg3) \
+{ \
+ return K_INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+ return K_INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \
+}
+
+/* select takes 5 arguments */
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
+{ \
+ return K_INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \
+}
+
+
+/* mmap takes 6 arguments */
+
+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
+{ \
+ return K_INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \
+}
+
+#ifdef __KERNEL_SYSCALLS__
+
+static inline int idle(void)
+{
+ extern int sys_idle(void);
+ return sys_idle();
+}
+
+static inline int pause(void)
+{
+ extern int sys_pause(void);
+ return sys_pause();
+}
+
+static inline int sync(void)
+{
+ extern int sys_sync(void);
+ return sys_sync();
+}
+
+static inline pid_t setsid(void)
+{
+ extern int sys_setsid(void);
+ return sys_setsid();
+}
+
+static inline int write(int fd, const char *buf, off_t count)
+{
+ extern int sys_write(int, const char *, int);
+ return sys_write(fd, buf, count);
+}
+
+static inline int read(int fd, char *buf, off_t count)
+{
+ extern int sys_read(int, char *, int);
+ return sys_read(fd, buf, count);
+}
+
+static inline off_t lseek(int fd, off_t offset, int count)
+{
+ extern off_t sys_lseek(int, off_t, int);
+ return sys_lseek(fd, offset, count);
+}
+
+static inline int dup(int fd)
+{
+ extern int sys_dup(int);
+ return sys_dup(fd);
+}
+
+static inline int open(const char *file, int flag, int mode)
+{
+ extern long sys_open(const char *, int, int);
+ return sys_open(file, flag, mode);
+}
+
+static inline int close(int fd)
+{
+ return sys_close(fd);
+}
+
+static inline int _exit(int exitcode)
+{
+ extern int sys_exit(int) __attribute__((noreturn));
+ return sys_exit(exitcode);
+}
+
+static inline pid_t waitpid(pid_t pid, int *wait_stat, int options)
+{
+ extern int sys_wait4(int, int *, int, struct rusage *);
+ return sys_wait4((int)pid, wait_stat, options, NULL);
+}
+
+static inline int delete_module(const char *name)
+{
+ extern int sys_delete_module(const char *name);
+ return sys_delete_module(name);
+}
+
+static inline pid_t wait(int * wait_stat)
+{
+ extern int sys_wait4(int, int *, int, struct rusage *);
+ return sys_wait4(-1, wait_stat, 0, NULL);
+}
+
+static inline int execve(char *filename, char * argv [],
+ char * envp[])
+{
+ extern int __execve(char *, char **, char **, struct task_struct *);
+ return __execve(filename, argv, envp, current);
+}
+
+#endif
+
+#undef STR
+
+#endif /* _ASM_PARISC_UNISTD_H_ */
diff --git a/include/asm-parisc/user.h b/include/asm-parisc/user.h
new file mode 100644
index 000000000..80224753e
--- /dev/null
+++ b/include/asm-parisc/user.h
@@ -0,0 +1,5 @@
+/* This file should not exist, but lots of generic code still includes
+ it. It's a hangover from old a.out days and the traditional core
+ dump format. We are ELF-only, and so are our core dumps. If we
+ need to support HP/UX core format then we'll do it here
+ eventually. */
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index aa406533f..53d486ef1 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -76,8 +76,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#ifndef __ASSEMBLY__
-extern int console_loglevel;
-
/*
* Tell the user there is some problem.
*/
diff --git a/include/asm-sparc/atops.h b/include/asm-sparc/atops.h
deleted file mode 100644
index 30bdf0fb7..000000000
--- a/include/asm-sparc/atops.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* atops.h: Atomic SPARC operations.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-#ifndef _SPARC_ATOPS_H
-#define _SPARC_ATOPS_H
-
-#include <linux/config.h>
-
-#ifdef CONFIG_SMP
-
-extern __inline__ __volatile__ unsigned char ldstub(volatile unsigned char *lock)
-{
- volatile unsigned char retval;
-
- __asm__ __volatile__("ldstub [%1], %0\n\t" :
- "=&r" (retval) :
- "r" (lock));
- return retval;
-}
-
-#endif
-
-#endif
diff --git a/include/asm-sparc/hdreg.h b/include/asm-sparc/hdreg.h
index 1c321c3e7..8df7a4693 100644
--- a/include/asm-sparc/hdreg.h
+++ b/include/asm-sparc/hdreg.h
@@ -1,4 +1,4 @@
-/* $Id: hdreg.h,v 1.1 2000/01/21 04:56:27 zaitcev Exp $
+/* $Id: hdreg.h,v 1.2 2000/12/05 00:56:36 anton Exp $
* hdreg.h: SPARC PCI specific IDE glue.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -8,6 +8,6 @@
#ifndef __SPARC_HDREG_H
#define __SPARC_HDREG_H
-typedef unsigned int ide_ioreg_t;
+typedef unsigned long ide_ioreg_t;
#endif /* __SPARC_HDREG_H */
diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
index 278c15c80..41b96727a 100644
--- a/include/asm-sparc/processor.h
+++ b/include/asm-sparc/processor.h
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.77 2000/01/21 11:39:17 jj Exp $
+/* $Id: processor.h,v 1.78 2000/11/30 08:37:31 anton Exp $
* include/asm-sparc/processor.h
*
* Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
@@ -90,6 +90,7 @@ struct thread_struct {
#define SPARC_FLAG_KTHREAD 0x1 /* task is a kernel thread */
#define SPARC_FLAG_UNALIGNED 0x2 /* is allowed to do unaligned accesses */
+#define SPARC_FLAG_MMAPSHARED 0x4 /* task wants a shared mmap */
#define INIT_MMAP { &init_mm, (0), (0), \
NULL, __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
index 23603f287..45e1f1828 100644
--- a/include/asm-sparc64/pgalloc.h
+++ b/include/asm-sparc64/pgalloc.h
@@ -1,4 +1,4 @@
-/* $Id: pgalloc.h,v 1.13 2000/11/06 06:59:04 davem Exp $ */
+/* $Id: pgalloc.h,v 1.14 2000/12/09 04:15:24 anton Exp $ */
#ifndef _SPARC64_PGALLOC_H
#define _SPARC64_PGALLOC_H
@@ -18,10 +18,15 @@
#define flush_cache_page(vma, page) \
flush_cache_mm((vma)->vm_mm)
-/* These operations are unnecessary on the SpitFire since D-CACHE is write-through. */
-#define flush_icache_range(start, end) do { } while (0)
+/* This is unnecessary on the SpitFire since D-CACHE is write-through. */
#define flush_page_to_ram(page) do { } while (0)
+/*
+ * icache doesnt snoop local stores and we don't use block commit stores
+ * (which invalidate icache lines) during module load, so we need this.
+ */
+extern void flush_icache_range(unsigned long start, unsigned long end);
+
extern void __flush_dcache_page(void *addr, int flush_icache);
#define flush_dcache_page(page) \
do { if ((page)->mapping && !(page)->mapping->i_mmap && !(page)->mapping->i_mmap_shared) \
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index eae8b7bdb..562cf4ba8 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.65 2000/08/09 00:00:17 davem Exp $
+/* $Id: processor.h,v 1.66 2000/11/29 05:56:12 anton Exp $
* include/asm-sparc64/processor.h
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -80,6 +80,7 @@ struct thread_struct {
#define SPARC_FLAG_32BIT 0x04 /* task is older 32-bit binary */
#define SPARC_FLAG_NEWCHILD 0x08 /* task is just-spawned child process */
#define SPARC_FLAG_PERFCTR 0x10 /* task has performance counters active */
+#define SPARC_FLAG_MMAPSHARED 0x20 /* task wants a shared mmap */
#define FAULT_CODE_WRITE 0x01 /* Write access, implies D-TLB */
#define FAULT_CODE_DTLB 0x02 /* Miss happened in D-TLB */
diff --git a/include/linux/agpgart.h b/include/linux/agpgart.h
index 7457cd114..d18b71dc7 100644
--- a/include/linux/agpgart.h
+++ b/include/linux/agpgart.h
@@ -207,7 +207,7 @@ typedef struct _agp_file_private {
struct _agp_file_private *next;
struct _agp_file_private *prev;
pid_t my_pid;
- u32 access_flags;
+ long access_flags; /* long req'd for set_bit --RR */
} agp_file_private;
struct agp_front_data {
diff --git a/include/linux/apm_bios.h b/include/linux/apm_bios.h
index 69ea9cf48..9dba26eeb 100644
--- a/include/linux/apm_bios.h
+++ b/include/linux/apm_bios.h
@@ -38,7 +38,7 @@ struct apm_bios_info {
unsigned short dseg_len;
};
- /* Results of APM Installation Check */
+/* Results of APM Installation Check */
#define APM_16_BIT_SUPPORT 0x0001
#define APM_32_BIT_SUPPORT 0x0002
#define APM_IDLE_SLOWS_CLOCK 0x0004
@@ -46,6 +46,15 @@ struct apm_bios_info {
#define APM_BIOS_DISENGAGED 0x0010
/*
+ * Data for APM that is persistant across module unload/load
+ */
+struct apm_info {
+ struct apm_bios_info bios;
+ unsigned short connection_version;
+ int get_power_status_broken;
+};
+
+/*
* The APM function codes
*/
#define APM_FUNC_INST_CHECK 0x5300
@@ -91,12 +100,9 @@ struct apm_bios_info {
#define APM_FUNC_TIMER_GET 2
/*
- * in init/main.c
+ * in arch/i386/kernel/setup.c
*/
-extern struct apm_bios_info apm_bios_info;
-
-extern int apm_register_callback(int (*callback)(apm_event_t));
-extern void apm_unregister_callback(int (*callback)(apm_event_t));
+extern struct apm_info apm_info;
#endif /* __KERNEL__ */
@@ -176,7 +182,7 @@ extern void apm_unregister_callback(int (*callback)(apm_event_t));
/*
* This is the "All Devices" ID communicated to the BIOS
*/
-#define APM_DEVICE_BALL ((apm_bios_info.version > 0x0100) ? \
+#define APM_DEVICE_BALL ((apm_info.connection_version > 0x0100) ? \
APM_DEVICE_ALL : APM_DEVICE_OLD_ALL)
#endif
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 4d5ada52b..d169bf7f2 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -257,7 +257,7 @@ enum {
#define ATM_ATMOPT_CLP 1 /* set CLP bit */
-typedef struct { unsigned int bits; } atm_vcc_flags_t;
+typedef struct { unsigned long bits; } atm_vcc_flags_t;
struct atm_vcc {
diff --git a/include/linux/bfs_fs.h b/include/linux/bfs_fs.h
index afe274a4c..a4ffcbb75 100644
--- a/include/linux/bfs_fs.h
+++ b/include/linux/bfs_fs.h
@@ -1,6 +1,6 @@
/*
* include/linux/bfs_fs.h - BFS data structures on disk.
- * Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ * Copyright (C) 1999 Tigran Aivazian <tigran@veritas.com>
*/
#ifndef _LINUX_BFS_FS_H
diff --git a/include/linux/bfs_fs_i.h b/include/linux/bfs_fs_i.h
index 647352882..e939b229e 100644
--- a/include/linux/bfs_fs_i.h
+++ b/include/linux/bfs_fs_i.h
@@ -1,6 +1,6 @@
/*
* include/linux/bfs_fs_i.h
- * Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ * Copyright (C) 1999 Tigran Aivazian <tigran@veritas.com>
*/
#ifndef _LINUX_BFS_FS_I
diff --git a/include/linux/bfs_fs_sb.h b/include/linux/bfs_fs_sb.h
index 5f927f35b..efdc30ec7 100644
--- a/include/linux/bfs_fs_sb.h
+++ b/include/linux/bfs_fs_sb.h
@@ -1,6 +1,6 @@
/*
* include/linux/bfs_fs_sb.h
- * Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ * Copyright (C) 1999 Tigran Aivazian <tigran@veritas.com>
*/
#ifndef _LINUX_BFS_FS_SB
diff --git a/include/linux/compatmac.h b/include/linux/compatmac.h
index 07d8356d0..72f9151b8 100644
--- a/include/linux/compatmac.h
+++ b/include/linux/compatmac.h
@@ -104,7 +104,6 @@ static inline void *ioremap(unsigned long base, long length)
#define capable(x) suser()
-#define queue_task queue_task_irq_off
#define tty_flip_buffer_push(tty) queue_task(&tty->flip.tqueue, &tq_timer)
#define signal_pending(current) (current->signal & ~current->blocked)
#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0)
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index af962e94f..dd9fdcfaf 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -549,9 +549,10 @@ extern int ext2_write (struct inode *, struct file *, char *, int);
/* fsync.c */
extern int ext2_sync_file (struct file *, struct dentry *, int);
+extern int ext2_fsync_inode (struct inode *, int);
/* ialloc.c */
-extern struct inode * ext2_new_inode (const struct inode *, int, int *);
+extern struct inode * ext2_new_inode (const struct inode *, int);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
extern void ext2_check_inodes_bitmap (struct super_block *);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 470186804..2ef374aa1 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -243,6 +243,9 @@ struct buffer_head {
unsigned long b_rsector; /* Real buffer location on disk */
wait_queue_head_t b_wait;
+
+ struct inode * b_inode;
+ struct list_head b_inode_buffers; /* doubly linked list of inode dirty buffers */
};
typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
@@ -349,7 +352,7 @@ struct page;
struct address_space;
struct address_space_operations {
- int (*writepage)(struct file *, struct page *);
+ int (*writepage)(struct page *);
int (*readpage)(struct file *, struct page *);
int (*sync_page)(struct page *);
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
@@ -382,6 +385,8 @@ struct inode {
struct list_head i_hash;
struct list_head i_list;
struct list_head i_dentry;
+
+ struct list_head i_dirty_buffers;
unsigned long i_ino;
atomic_t i_count;
@@ -452,16 +457,25 @@ struct inode {
};
/* Inode state bits.. */
-#define I_DIRTY 1
-#define I_LOCK 2
-#define I_FREEING 4
-#define I_CLEAR 8
+#define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */
+#define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */
+#define I_LOCK 4
+#define I_FREEING 8
+#define I_CLEAR 16
+
+#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
-extern void __mark_inode_dirty(struct inode *);
+extern void __mark_inode_dirty(struct inode *, int);
static inline void mark_inode_dirty(struct inode *inode)
{
- if (!(inode->i_state & I_DIRTY))
- __mark_inode_dirty(inode);
+ if ((inode->i_state & I_DIRTY) != I_DIRTY)
+ __mark_inode_dirty(inode, I_DIRTY);
+}
+
+static inline void mark_inode_dirty_sync(struct inode *inode)
+{
+ if (!(inode->i_state & I_DIRTY_SYNC))
+ __mark_inode_dirty(inode, I_DIRTY_SYNC);
}
struct fown_struct {
@@ -1025,10 +1039,18 @@ static inline void buffer_IO_error(struct buffer_head * bh)
bh->b_end_io(bh, 0);
}
+extern void buffer_insert_inode_queue(struct buffer_head *, struct inode *);
+static inline void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
+{
+ mark_buffer_dirty(bh);
+ buffer_insert_inode_queue(bh, inode);
+}
+
extern void balance_dirty(kdev_t);
extern int check_disk_change(kdev_t);
extern int invalidate_inodes(struct super_block *);
extern void invalidate_inode_pages(struct inode *);
+extern void invalidate_inode_buffers(struct inode *);
#define invalidate_buffers(dev) __invalidate_buffers((dev), 0)
#define destroy_buffers(dev) __invalidate_buffers((dev), 1)
extern void __invalidate_buffers(kdev_t dev, int);
@@ -1036,10 +1058,14 @@ extern void sync_inodes(kdev_t);
extern void write_inode_now(struct inode *, int);
extern void sync_dev(kdev_t);
extern int fsync_dev(kdev_t);
+extern int fsync_inode_buffers(struct inode *);
+extern int osync_inode_buffers(struct inode *);
+extern int inode_has_buffers(struct inode *);
extern void sync_supers(kdev_t);
extern int bmap(struct inode *, int);
extern int notify_change(struct dentry *, struct iattr *);
extern int permission(struct inode *, int);
+extern int vfs_permission(struct inode *, int);
extern int get_write_access(struct inode *);
extern int deny_write_access(struct file *);
static inline void put_write_access(struct inode * inode)
@@ -1167,6 +1193,7 @@ extern void file_moveto(struct file *new, struct file *old);
extern struct buffer_head * get_hash_table(kdev_t, int, int);
extern struct buffer_head * getblk(kdev_t, int, int);
extern void ll_rw_block(int, int, struct buffer_head * bh[]);
+extern void submit_bh(int, struct buffer_head *);
extern int is_read_only(kdev_t);
extern void __brelse(struct buffer_head *);
static inline void brelse(struct buffer_head *buf)
@@ -1183,7 +1210,6 @@ static inline void bforget(struct buffer_head *buf)
extern void set_blocksize(kdev_t, int);
extern unsigned int get_hardblocksize(kdev_t);
extern struct buffer_head * bread(kdev_t, int, int);
-extern struct buffer_head * breada(kdev_t, int, int, unsigned int, unsigned int);
extern void wakeup_bdflush(int wait);
extern int brw_page(int, struct page *, kdev_t, int [], int);
@@ -1249,6 +1275,7 @@ extern ssize_t block_write(struct file *, const char *, size_t, loff_t *);
extern int file_fsync(struct file *, struct dentry *, int);
extern int generic_buffer_fdatasync(struct inode *inode, unsigned long start_idx, unsigned long end_idx);
+extern int generic_osync_inode(struct inode *, int);
extern int inode_change_ok(struct inode *, struct iattr *);
extern void inode_setattr(struct inode *, struct iattr *);
diff --git a/include/linux/hdlcdrv.h b/include/linux/hdlcdrv.h
index 2a55e6018..99a5444da 100644
--- a/include/linux/hdlcdrv.h
+++ b/include/linux/hdlcdrv.h
@@ -199,7 +199,7 @@ struct hdlcdrv_state {
struct hdlcdrv_hdlcrx {
struct hdlcdrv_hdlcbuffer hbuf;
- int in_hdlc_rx;
+ long in_hdlc_rx;
/* 0 = sync hunt, != 0 receiving */
int rx_state;
unsigned int bitstream;
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 9cac7759a..eb5405d33 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -13,8 +13,6 @@ extern struct page *highmem_start_page;
/* declarations for linux/mm/highmem.c */
FASTCALL(unsigned int nr_free_highpages(void));
-extern struct page * prepare_highmem_swapout(struct page *);
-extern struct page * replace_with_highmem(struct page *);
extern struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig);
@@ -31,8 +29,6 @@ static inline void bh_kunmap(struct buffer_head *bh)
#else /* CONFIG_HIGHMEM */
static inline unsigned int nr_free_highpages(void) { return 0; }
-#define prepare_highmem_swapout(page) page
-#define replace_with_highmem(page) page
static inline void *kmap(struct page *page) { return page_address(page); }
diff --git a/include/linux/highuid.h b/include/linux/highuid.h
index 5d287bbb3..d5a9ff5d0 100644
--- a/include/linux/highuid.h
+++ b/include/linux/highuid.h
@@ -41,14 +41,14 @@ extern int overflowgid;
#ifdef CONFIG_UID16
/* prevent uid mod 65536 effect by returning a default value for high UIDs */
-#define high2lowuid(uid) ((uid) > 65535) ? (old_uid_t)overflowuid : (old_uid_t)(uid)
-#define high2lowgid(gid) ((gid) > 65535) ? (old_gid_t)overflowgid : (old_gid_t)(gid)
+#define high2lowuid(uid) ((uid) > 65535 ? (old_uid_t)overflowuid : (old_uid_t)(uid))
+#define high2lowgid(gid) ((gid) > 65535 ? (old_gid_t)overflowgid : (old_gid_t)(gid))
/*
* -1 is different in 16 bits than it is in 32 bits
* these macros are used by chown(), setreuid(), ...,
*/
-#define low2highuid(uid) ((uid) == (old_uid_t)-1) ? (uid_t)-1 : (uid_t)(uid)
-#define low2highgid(gid) ((gid) == (old_gid_t)-1) ? (gid_t)-1 : (gid_t)(gid)
+#define low2highuid(uid) ((uid) == (old_uid_t)-1 ? (uid_t)-1 : (uid_t)(uid))
+#define low2highgid(gid) ((gid) == (old_gid_t)-1 ? (gid_t)-1 : (gid_t)(gid))
/* Avoid extra ifdefs with these macros */
@@ -67,13 +67,13 @@ extern int overflowgid;
#define SET_UID16(var, uid) do { ; } while (0)
#define SET_GID16(var, gid) do { ; } while (0)
-#define NEW_TO_OLD_UID(uid) uid
-#define NEW_TO_OLD_GID(gid) gid
+#define NEW_TO_OLD_UID(uid) (uid)
+#define NEW_TO_OLD_GID(gid) (gid)
-#define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = uid
-#define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = gid
-#define SET_STAT_UID(stat, uid) (stat).st_uid = uid
-#define SET_STAT_GID(stat, gid) (stat).st_gid = gid
+#define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = (uid)
+#define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = (gid)
+#define SET_STAT_UID(stat, uid) (stat).st_uid = (uid)
+#define SET_STAT_GID(stat, gid) (stat).st_gid = (gid)
#endif /* CONFIG_UID16 */
@@ -97,10 +97,10 @@ extern int fs_overflowgid;
* Since these macros are used in architectures that only need limited
* 16-bit UID back compatibility, we won't use old_uid_t and old_gid_t
*/
-#define fs_high2lowuid(uid) (uid > 65535) ? (uid16_t)fs_overflowuid : (uid16_t)uid
-#define fs_high2lowgid(gid) (gid > 65535) ? (gid16_t)fs_overflowgid : (gid16_t)gid
+#define fs_high2lowuid(uid) ((uid) > 65535 ? (uid16_t)fs_overflowuid : (uid16_t)(uid))
+#define fs_high2lowgid(gid) ((gid) > 65535 ? (gid16_t)fs_overflowgid : (gid16_t)(gid))
-#define low_16_bits(x) x & 0xFFFF
-#define high_16_bits(x) (x & 0xFFFF0000) >> 16
+#define low_16_bits(x) ((x) & 0xFFFF)
+#define high_16_bits(x) (((x) & 0xFFFF0000) >> 16)
#endif /* _LINUX_HIGHUID_H */
diff --git a/include/linux/icmp.h b/include/linux/icmp.h
index 292888923..49e3e931d 100644
--- a/include/linux/icmp.h
+++ b/include/linux/icmp.h
@@ -84,11 +84,6 @@ struct icmphdr {
#include <linux/ip.h>
-struct icmp_err {
- int errno;
- unsigned fatal:1;
-};
-
/*
* Build xmit assembly blocks
*/
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index a24e7770a..7c3569949 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -19,6 +19,12 @@ struct resource {
struct resource *parent, *sibling, *child;
};
+struct resource_list {
+ struct resource_list *next;
+ struct resource *res;
+ struct pci_dev *dev;
+};
+
/*
* IO resources have these defined flags.
*/
@@ -34,6 +40,7 @@ struct resource {
#define IORESOURCE_CACHEABLE 0x00004000
#define IORESOURCE_RANGELENGTH 0x00008000
#define IORESOURCE_SHADOWABLE 0x00010000
+#define IORESOURCE_BUS_HAS_VGA 0x00080000
#define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_AUTO 0x40000000
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index 51c06aec7..23cf7ed73 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.110 2000/11/01 17:54:01 detabc Exp $
+/* $Id: isdn.h,v 1.111 2000/11/25 17:01:02 kai Exp $
* Main header for the Linux ISDN subsystem (linklevel).
*
@@ -684,10 +684,8 @@ typedef struct isdn_devt {
extern isdn_dev *dev;
-
/* Utility-Macros */
#define MIN(a,b) ((a<b)?a:b)
#define MAX(a,b) ((a>b)?a:b)
-
#endif /* __KERNEL__ */
#endif /* isdn_h */
diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h
index 15ebaffcb..1d5d4f85b 100644
--- a/include/linux/isdnif.h
+++ b/include/linux/isdnif.h
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.35 2000/06/16 13:19:38 keil Exp $
+/* $Id: isdnif.h,v 1.37 2000/11/19 17:01:54 kai Exp $
* Linux ISDN subsystem
*
@@ -53,6 +53,7 @@
#define ISDN_PROTO_L2_V11038 9 /* V.110 bitrate adaption 38400 Baud */
#define ISDN_PROTO_L2_MODEM 10 /* Analog Modem on Board */
#define ISDN_PROTO_L2_FAX 11 /* Fax Group 2/3 */
+#define ISDN_PROTO_L2_HDLC_56K 12 /* HDLC 56k */
#define ISDN_PROTO_L2_MAX 15 /* Max. 16 Protocols */
/*
@@ -253,6 +254,7 @@ typedef struct
#define ISDN_FEATURE_L2_V11038 (0x0001 << ISDN_PROTO_L2_V11038)
#define ISDN_FEATURE_L2_MODEM (0x0001 << ISDN_PROTO_L2_MODEM)
#define ISDN_FEATURE_L2_FAX (0x0001 << ISDN_PROTO_L2_FAX)
+#define ISDN_FEATURE_L2_HDLC_56K (0x0001 << ISDN_PROTO_L2_HDLC_56K)
#define ISDN_FEATURE_L2_MASK (0x0FFFF) /* Max. 16 protocols */
#define ISDN_FEATURE_L2_SHIFT (0)
diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h
index 471c9af2c..e664eed06 100644
--- a/include/linux/iso_fs.h
+++ b/include/linux/iso_fs.h
@@ -185,8 +185,6 @@ int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct i
int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
extern struct dentry *isofs_lookup(struct inode *, struct dentry *);
-extern int isofs_get_block(struct inode *, long, struct buffer_head *, int);
-extern int isofs_bmap(struct inode *, int);
extern struct buffer_head *isofs_bread(struct inode *, unsigned int, unsigned int);
extern struct inode_operations isofs_dir_inode_operations;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index beb41bfa3..50ee12471 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -56,17 +56,34 @@ NORET_TYPE void up_and_exit(struct semaphore *, long)
ATTRIB_NORET;
extern unsigned long simple_strtoul(const char *,char **,unsigned int);
extern long simple_strtol(const char *,char **,unsigned int);
+extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
+extern long long simple_strtoll(const char *,char **,unsigned int);
extern int sprintf(char * buf, const char * fmt, ...);
extern int vsprintf(char *buf, const char *, va_list);
extern int get_option(char **str, int *pint);
extern char *get_options(char *str, int nints, int *ints);
extern unsigned long memparse(char *ptr, char **retptr);
+extern void dev_probe_lock(void);
+extern void dev_probe_unlock(void);
extern int session_of_pgrp(int pgrp);
asmlinkage int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+extern int console_loglevel;
+
+static inline void console_silent(void)
+{
+ console_loglevel = 0;
+}
+
+static inline void console_verbose(void)
+{
+ if (console_loglevel)
+ console_loglevel = 15;
+}
+
#if DEBUG
#define pr_debug(fmt,arg...) \
printk(KERN_DEBUG fmt,##arg)
diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h
index acbdea338..2677f9646 100644
--- a/include/linux/kernelcapi.h
+++ b/include/linux/kernelcapi.h
@@ -1,5 +1,5 @@
/*
- * $Id: kernelcapi.h,v 1.8 2000/08/22 10:11:00 calle Exp $
+ * $Id: kernelcapi.h,v 1.8.6.1 2000/11/28 09:36:56 kai Exp $
*
* Kernel CAPI 2.0 Interface for Linux
*
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 70ffe28e4..37bc9a4a1 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -204,7 +204,7 @@ typedef struct page {
*/
#define UnlockPage(page) do { \
smp_mb__before_clear_bit(); \
- clear_bit(PG_locked, &(page)->flags); \
+ if (!test_and_clear_bit(PG_locked, &(page)->flags)) BUG(); \
smp_mb__after_clear_bit(); \
if (waitqueue_active(&page->wait)) \
wake_up(&page->wait); \
@@ -454,11 +454,9 @@ extern unsigned long page_unuse(struct page *);
extern void truncate_inode_pages(struct address_space *, loff_t);
/* generic vm_area_ops exported for stackable file systems */
-extern int filemap_swapout(struct page * page, struct file *file);
-extern int filemap_sync(struct vm_area_struct * vma, unsigned long address,
- size_t size, unsigned int flags);
-extern struct page *filemap_nopage(struct vm_area_struct * area,
- unsigned long address, int no_share);
+extern int filemap_swapout(struct page *, struct file *);
+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..
diff --git a/include/linux/module.h b/include/linux/module.h
index 249cb0163..7f416d7fb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -168,6 +168,7 @@ struct module_info
* Keith Owens <kaos@ocs.com.au> 28 Oct 2000.
*/
+#ifdef __KERNEL__
#define HAVE_INTER_MODULE
extern void inter_module_register(const char *, struct module *, const void *);
extern void inter_module_unregister(const char *);
@@ -183,6 +184,7 @@ struct inter_module_entry {
};
extern int try_inc_mod_count(struct module *mod);
+#endif /* __KERNEL__ */
#if defined(MODULE) && !defined(__GENKSYMS__)
@@ -345,7 +347,7 @@ __attribute__((section("__ksymtab"))) = \
#endif /* MODULE */
#ifdef CONFIG_MODULES
-#define SET_MODULE_OWNER(some_struct) do { some_struct->owner = THIS_MODULE; } while (0)
+#define SET_MODULE_OWNER(some_struct) do { (some_struct)->owner = THIS_MODULE; } while (0)
#else
#define SET_MODULE_OWNER(some_struct) do { } while (0)
#endif
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index c8bdd1cd7..4ce69eee8 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -91,8 +91,9 @@ struct cfi_private {
must be of the same type. */
int numchips;
unsigned long chipshift; /* Because they're of the same type */
- struct flchip chips[0]; /* per-chip data structure for each chip */
const char *im_name; /* inter_module name for cmdset_setup */
+ struct flchip chips[0]; /* per-chip data structure for each chip */
+ /* do not add extra fields after "chips" */
};
#define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */
diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h
index 0ed87cdb4..696938aa1 100644
--- a/include/linux/mtd/doc2000.h
+++ b/include/linux/mtd/doc2000.h
@@ -2,7 +2,7 @@
/* Linux driver for Disk-On-Chip 2000 */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.h,v 1.8 2000/07/10 15:46:29 dwmw2 Exp $ */
+/* $Id: doc2000.h,v 1.12 2000/11/03 12:43:43 dwmw2 Exp $ */
#ifndef __MTD_DOC2000_H__
#define __MTD_DOC2000_H__
@@ -44,16 +44,24 @@
* Others use readb/writeb
*/
#if defined(__arm__)
-#define ReadDOC(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+(DoC_##reg<<2))))
-#define WriteDOC(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+(DoC_##reg<<2)) = (__u32)d} while(0)
+#define ReadDOC_(adr, reg) ((unsigned char)(*(__u32 *)(((unsigned long)adr)+(reg<<2))))
+#define WriteDOC_(d, adr, reg) do{ *(__u32 *)(((unsigned long)adr)+(reg<<2)) = (__u32)d} while(0)
#elif defined(__ppc__)
-#define ReadDOC(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+(DoC_##reg<<1))))
-#define WriteDOC(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+(DoC_##reg<<1)) = (__u16)d} while(0)
+#define ReadDOC_(adr, reg) ((unsigned char)(*(__u16 *)(((unsigned long)adr)+(reg<<1))))
+#define WriteDOC_(d, adr, reg) do{ *(__u16 *)(((unsigned long)adr)+(reg<<1)) = (__u16)d} while(0)
#else
-#define ReadDOC(adr, reg) readb(((unsigned long)adr) + DoC_##reg)
-#define WriteDOC(d, adr, reg) writeb(d, ((unsigned long)adr) + DoC_##reg)
+#define ReadDOC_(adr, reg) readb(((unsigned long)adr) + reg)
+#define WriteDOC_(d, adr, reg) writeb(d, ((unsigned long)adr) + reg)
#endif
+#if defined(__i386__)
+#define USE_MEMCPY
+#endif
+
+/* These are provided to directly use the DoC_xxx defines */
+#define ReadDOC(adr, reg) ReadDOC_(adr,DoC_##reg)
+#define WriteDOC(d, adr, reg) WriteDOC_(d,adr,DoC_##reg)
+
#define DOC_MODE_RESET 0
#define DOC_MODE_NORMAL 1
#define DOC_MODE_RESERVED1 2
@@ -80,9 +88,10 @@
#define DOC_TOGGLE_BIT 0x04
#define DOC_ECC_RESV 0x02
#define DOC_ECC_IGNORE 0x01
+
/* We have to also set the reserved bit 1 for enable */
#define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV)
-#define DOC_ECC_DIS (DOC_ECC_IGNORE | DOC_ECC_RESV)
+#define DOC_ECC_DIS (DOC_ECC_RESV)
struct Nand {
char floor, chip;
@@ -97,15 +106,23 @@ struct Nand {
#define MAX_FLOORS_MIL 4
#define MAX_CHIPS_MIL 1
+#define ADDR_COLUMN 1
+#define ADDR_PAGE 2
+#define ADDR_COLUMN_PAGE 3
+
struct DiskOnChip {
unsigned long physadr;
unsigned long virtadr;
unsigned long totlen;
char ChipID; /* Type of DiskOnChip */
+ int ioreg;
unsigned long mfr; /* Flash IDs - only one type of flash per device */
unsigned long id;
int chipshift;
+ char page256;
+ char pageadrlen;
+ unsigned long erasesize;
int curfloor;
int curchip;
@@ -115,5 +132,6 @@ struct DiskOnChip {
struct mtd_info *nextdoc;
};
+int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);
#endif /* __MTD_DOC2000_H__ */
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index ebb41c973..705169800 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -1,6 +1,6 @@
/* Overhauled routines for dealing with different mmap regions of flash */
-/* $Id: map.h,v 1.5 2000/06/26 16:18:58 dwmw2 Exp $ */
+/* $Id: map.h,v 1.10 2000/12/04 13:18:33 dwmw2 Exp $ */
#ifndef __LINUX_MTD_MAP_H__
#define __LINUX_MTD_MAP_H__
@@ -42,6 +42,8 @@ struct map_info {
void (*write16)(struct map_info *, __u16, unsigned long);
void (*write32)(struct map_info *, __u32, unsigned long);
void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
+
+ void (*set_vpp)(int);
/* We put these two here rather than a single void *map_priv,
because we want mappers to be able to have quickly-accessible
cache for the 'currently-mapped page' without the _extra_
@@ -54,6 +56,7 @@ struct map_info {
const char *im_name;
};
+#ifdef CONFIG_MODULES
/*
* Probe for the contents of a map device and make an MTD structure
* if anything is recognised. Doesn't register it because the calling
@@ -78,6 +81,18 @@ static inline struct mtd_info *do_map_probe(struct map_info *map, const char *fu
#define do_jedec_probe(x) do_map_probe(x, "jedec_probe", "jedec_probe")
#define do_ram_probe(x) do_map_probe(x, "map_ram_probe", "map_ram")
#define do_rom_probe(x) do_map_probe(x, "map_rom_probe", "map_rom")
+#else
+ /* without module support, call probe function directly */
+extern struct mtd_info *cfi_probe(struct map_info *);
+extern struct mtd_info *jedec_probe(struct map_info *);
+extern struct mtd_info *map_ram_probe(struct map_info *);
+extern struct mtd_info *map_rom_probe(struct map_info *);
+
+#define do_cfi_probe(x) cfi_probe(x)
+#define do_jedec_probe(x) jedec_probe(x)
+#define do_ram_probe(x) map_ram_probe(x)
+#define do_rom_probe(x) map_rom_probe(x)
+#endif
/*
* Destroy an MTD device which was created for a map device.
@@ -92,5 +107,7 @@ static inline void map_destroy(struct mtd_info *mtd)
kfree(mtd);
}
+#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(1); } while(0)
+#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(0); } while(0)
#endif /* __LINUX_MTD_MAP_H__ */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index a7bc521c2..708f4f203 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -1,5 +1,5 @@
-/* $Id: mtd.h,v 1.17 2000/07/04 07:24:49 jgg Exp $ */
+/* $Id: mtd.h,v 1.26 2000/10/30 17:18:04 sjhill Exp $ */
#ifndef __MTD_MTD_H__
#define __MTD_MTD_H__
@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/mtd/compatmac.h>
#include <linux/module.h>
+#include <linux/uio.h>
#endif /* __KERNEL__ */
@@ -61,7 +62,8 @@ struct mtd_oob_buf {
// Types of automatic ECC/Checksum available
#define MTD_ECC_NONE 0 // No automatic ECC available
-#define MTD_ECC_RS_DiskOnChip 1 // Automatic ECC on DiskOnChip
+#define MTD_ECC_RS_DiskOnChip 1 // Automatic ECC on DiskOnChip
+#define MTD_ECC_SW 2 // SW ECC for Toshiba & Samsung devices
struct mtd_info_user {
u_char type;
@@ -78,6 +80,8 @@ struct mtd_info_user {
#define MEMERASE _IOW('M', 2, struct erase_info_user)
#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
+#define MEMLOCK _IOW('M', 5, struct erase_info_user)
+#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
#ifndef __KERNEL__
@@ -123,6 +127,7 @@ struct mtd_info {
// Kernel-only stuff starts here.
char *name;
+ int index;
u_long bank_size;
@@ -144,9 +149,22 @@ struct mtd_info {
int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-
+
+ /* iovec-based read/write methods. We need these especially for NAND flash,
+ with its limited number of write cycles per erase.
+ NB: The 'count' parameter is the number of _vectors_, each of
+ which contains an (ofs, len) tuple.
+ */
+ int (*readv) (struct mtd_info *mtd, struct iovec *vecs, unsigned long count, loff_t from, size_t *retlen);
+ int (*writev) (struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen);
+
+ /* Sync */
void (*sync) (struct mtd_info *mtd);
+ /* Chip-supported device locking */
+ int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
+ int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
+
/* Power Management functions */
int (*suspend) (struct mtd_info *mtd);
void (*resume) (struct mtd_info *mtd);
@@ -198,20 +216,32 @@ extern int unregister_mtd_user (struct mtd_notifier *old);
#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
+#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
+#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
+#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
+#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0)
#endif /* MTDC */
-/* Debugging macros */
-
-#ifdef DEBUGLVL
-#define DEBUG(n, args...) if (DEBUGLVL>(n)) printk(KERN_DEBUG args)
-#else
+/*
+ * Debugging macro and defines
+ */
+#define MTD_DEBUG_LEVEL0 (0) /* Quiet */
+#define MTD_DEBUG_LEVEL1 (1) /* Audible */
+#define MTD_DEBUG_LEVEL2 (2) /* Loud */
+#define MTD_DEBUG_LEVEL3 (3) /* Noisy */
+
+#ifdef CONFIG_MTD_DEBUG
+#define DEBUG(n, args...) \
+ if (n <= CONFIG_MTD_DEBUG_VERBOSE) { \
+ printk(KERN_INFO args); \
+ }
+#else /* CONFIG_MTD_DEBUG */
#define DEBUG(n, args...)
-#endif
+#endif /* CONFIG_MTD_DEBUG */
#endif /* __KERNEL__ */
-
#endif /* __MTD_MTD_H__ */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 79ca1843c..8c678ab97 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -1,31 +1,154 @@
+/*
+ * linux/include/linux/mtd/nand.h
+ *
+ * Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
+ * Steven J. Hill <sjhill@cotw.com>
+ *
+ * $Id: nand.h,v 1.8 2000/10/30 17:16:17 sjhill 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.
+ *
+ * Info:
+ * Contains standard defines and IDs for NAND flash devices
+ *
+ * Changelog:
+ * 01-31-2000 DMW Created
+ * 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers
+ * so it can be used by other NAND flash device
+ * drivers. I also changed the copyright since none
+ * of the original contents of this file are specific
+ * to DoC devices. David can whack me with a baseball
+ * bat later if I did something naughty.
+ * 10-11-2000 SJH Added private NAND flash structure for driver
+ * 10-24-2000 SJH Added prototype for 'nand_scan' function
+ */
+#ifndef __LINUX_MTD_NAND_H
+#define __LINUX_MTD_NAND_H
-/* Defines for NAND flash devices */
-/* (c) 1999 Machine Vision Holdings, Inc. */
-/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: nand.h,v 1.2 1999/08/17 22:57:08 dwmw2 Exp $ */
+#include <linux/config.h>
+#include <linux/sched.h>
-#ifndef __MTD_NAND_H__
-#define __MTD_NAND_H__
-
-#define NAND_CMD_READ0 0
-#define NAND_CMD_READ1 1
-#define NAND_CMD_PAGEPROG 0x10
-#define NAND_CMD_READOOB 0x50
-#define NAND_CMD_ERASE1 0x60
-#define NAND_CMD_STATUS 0x70
-#define NAND_CMD_SEQIN 0x80
-#define NAND_CMD_READID 0x90
-#define NAND_CMD_ERASE2 0xd0
-#define NAND_CMD_RESET 0xff
-
-#define NAND_MFR_TOSHIBA 0x98
-#define NAND_MFR_SAMSUNG 0xec
-
-
-#endif /* __MTD_NAND_H__ */
+/*
+ * Searches for a NAND device
+ */
+extern int nand_scan (struct mtd_info *mtd);
+/*
+ * Standard NAND flash commands
+ */
+#define NAND_CMD_READ0 0
+#define NAND_CMD_READ1 1
+#define NAND_CMD_PAGEPROG 0x10
+#define NAND_CMD_READOOB 0x50
+#define NAND_CMD_ERASE1 0x60
+#define NAND_CMD_STATUS 0x70
+#define NAND_CMD_SEQIN 0x80
+#define NAND_CMD_READID 0x90
+#define NAND_CMD_ERASE2 0xd0
+#define NAND_CMD_RESET 0xff
+/*
+ * Enumeration for NAND flash chip state
+ */
+typedef enum {
+ FL_READY,
+ FL_READING,
+ FL_WRITING,
+ FL_ERASING,
+ FL_SYNCING
+} nand_state_t;
+/*
+ * NAND Private Flash Chip Data
+ *
+ * Structure overview:
+ *
+ * IO_ADDR - address to access the 8 I/O lines to the flash device
+ *
+ * CTRL_ADDR - address where ALE, CLE and CE control bits are accessed
+ *
+ * CLE - location in control word for Command Latch Enable bit
+ *
+ * ALE - location in control word for Address Latch Enable bit
+ *
+ * NCE - location in control word for nChip Enable bit
+ *
+ * chip_lock - spinlock used to protect access to this structure
+ *
+ * wq - wait queue to sleep on if a NAND operation is in progress
+ *
+ * state - give the current state of the NAND device
+ *
+ * page_shift - number of address bits in a page (column address bits)
+ *
+ * data_buf - data buffer passed to/from MTD user modules
+ *
+ * ecc_code_buf - used only for holding calculated or read ECCs for
+ * a page read or written when ECC is in use
+ *
+ * reserved - padding to make structure fall on word boundary if
+ * when ECC is in use
+ */
+struct nand_chip {
+ unsigned long IO_ADDR;
+ unsigned long CTRL_ADDR;
+ unsigned int CLE;
+ unsigned int ALE;
+ unsigned int NCE;
+ spinlock_t chip_lock;
+ wait_queue_head_t wq;
+ nand_state_t state;
+ int page_shift;
+ u_char *data_buf;
+#ifdef CONFIG_MTD_NAND_ECC
+ u_char ecc_code_buf[6];
+ u_char reserved[2];
+#endif
+};
+/*
+ * NAND Flash Manufacturer ID Codes
+ */
+#define NAND_MFR_TOSHIBA 0x98
+#define NAND_MFR_SAMSUNG 0xec
+/*
+ * NAND Flash Device ID Structure
+ *
+ * Structure overview:
+ *
+ * name - Complete name of device
+ *
+ * manufacture_id - manufacturer ID code of device.
+ *
+ * model_id - model ID code of device.
+ *
+ * chipshift - total number of address bits for the device which
+ * is used to calculate address offsets and the total
+ * number of bytes the device is capable of.
+ *
+ * page256 - denotes if flash device has 256 byte pages or not.
+ *
+ * pageadrlen - number of bytes minus one needed to hold the
+ * complete address into the flash array. Keep in
+ * mind that when a read or write is done to a
+ * specific address, the address is input serially
+ * 8 bits at a time. This structure member is used
+ * by the read/write routines as a loop index for
+ * shifting the address out 8 bits at a time.
+ *
+ * erasesize - size of an erase block in the flash device.
+ */
+struct nand_flash_dev {
+ char * name;
+ int manufacture_id;
+ int model_id;
+ int chipshift;
+ char page256;
+ char pageadrlen;
+ unsigned long erasesize;
+};
+#endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/nand_ids.h b/include/linux/mtd/nand_ids.h
new file mode 100644
index 000000000..0918b8c1e
--- /dev/null
+++ b/include/linux/mtd/nand_ids.h
@@ -0,0 +1,52 @@
+/*
+ * linux/include/linux/mtd/nand_ids.h
+ *
+ * Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
+ * Steven J. Hill <sjhill@cotw.com>
+ *
+ * $Id: nand_ids.h,v 1.1 2000/10/13 16:16:26 mdeans 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.
+ *
+ * Info:
+ * Contains standard defines and IDs for NAND flash devices
+ *
+ * Changelog:
+ * 01-31-2000 DMW Created
+ * 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers
+ * so it can be used by other NAND flash device
+ * drivers. I also changed the copyright since none
+ * of the original contents of this file are specific
+ * to DoC devices. David can whack me with a baseball
+ * bat later if I did something naughty.
+ * 10-11-2000 SJH Added private NAND flash structure for driver
+ * 2000-10-13 BE Moved out of 'nand.h' - avoids duplication.
+ */
+
+#ifndef __LINUX_MTD_NAND_IDS_H
+#define __LINUX_MTD_NAND_IDS_H
+
+static struct nand_flash_dev nand_flash_ids[] = {
+ {"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000},
+ {"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000},
+ {"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000},
+ {"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000},
+ {"Toshiba TH58512FT", NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000},
+ {"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000},
+ {"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000},
+ {"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000},
+ {"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000},
+ {"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000},
+ {"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000},
+ {"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000},
+ {"Samsung unknown 64Mb", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000},
+ {"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000},
+ {"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000},
+ {"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000},
+ {"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000},
+ {NULL,}
+};
+
+#endif /* __LINUX_MTD_NAND_IDS_H */
diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h
index 153fa5c6a..ae00ceb0b 100644
--- a/include/linux/mtd/nftl.h
+++ b/include/linux/mtd/nftl.h
@@ -2,18 +2,21 @@
/* Defines for NAND Flash Translation Layer */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: nftl.h,v 1.6 2000/03/31 15:12:20 dwmw2 Exp $ */
+/* $Id: nftl.h,v 1.9 2000/11/07 05:48:49 ollie Exp $ */
#ifndef __MTD_NFTL_H__
#define __MTD_NFTL_H__
+#ifndef __BOOT__
#include <linux/mtd/mtd.h>
+#endif
/* Block Control Information */
struct nftl_bci {
unsigned char ECCSig[6];
- __u16 Status;
+ __u8 Status;
+ __u8 Status1;
}__attribute__((packed));
/* Unit Control Information */
@@ -32,7 +35,8 @@ struct nftl_uci1 {
} __attribute__((packed));
struct nftl_uci2 {
- __u32 WriteInh;
+ __u16 FoldMark;
+ __u16 FoldMark1;
__u32 unused;
} __attribute__((packed));
@@ -60,10 +64,12 @@ struct NFTLMediaHeader {
#define MAX_ERASE_ZONES (8192 - 512)
#define ERASE_MARK 0x3c69
-#define BLOCK_FREE 0xffff
-#define BLOCK_USED 0x5555
-#define BLOCK_IGNORE 0x1111
-#define BLOCK_DELETED 0x0000
+#define SECTOR_FREE 0xff
+#define SECTOR_USED 0x55
+#define SECTOR_IGNORE 0x11
+#define SECTOR_DELETED 0x00
+
+#define FOLD_MARK_IN_PROGRESS 0x5555
#define ZONE_GOOD 0xff
#define ZONE_BAD_ORIGINAL 0
@@ -71,6 +77,11 @@ struct NFTLMediaHeader {
#ifdef __KERNEL__
+/* these info are used in ReplUnitTable */
+#define BLOCK_NIL 0xffff /* last block of a chain */
+#define BLOCK_FREE 0xfffe /* free block */
+#define BLOCK_NOTEXPLORED 0xfffd /* non explored block, only used during mounting */
+#define BLOCK_RESERVED 0xfffc /* bios block or bad block */
struct NFTLrecord {
struct mtd_info *mtd;
@@ -83,18 +94,27 @@ struct NFTLrecord {
unsigned char sectors;
unsigned short cylinders;
__u16 numvunits;
- __u16 lastEUN;
+ __u16 lastEUN; /* should be suppressed */
__u16 numfreeEUNs;
- __u16 LastFreeEUN; /* To speed up finding a free EUN */
+ __u16 LastFreeEUN; /* To speed up finding a free EUN */
__u32 long nr_sects;
int head,sect,cyl;
- __u16 *EUNtable; /* [numvunits]: First EUN for each virtual unit */
- __u16 *VirtualUnitTable; /* [numEUNs]: VirtualUnitNumber for each */
- __u16 *ReplUnitTable; /* [numEUNs]: ReplUnitNumber for each */
+ __u16 *EUNtable; /* [numvunits]: First EUN for each virtual unit */
+ __u16 *ReplUnitTable; /* [numEUNs]: ReplUnitNumber for each */
+ unsigned int nb_blocks; /* number of physical blocks */
+ unsigned int nb_boot_blocks; /* number of blocks used by the bios */
+ struct erase_info instr;
};
+int NFTL_mount(struct NFTLrecord *s);
+int NFTL_formatblock(struct NFTLrecord *s, int block);
+
+#ifndef NFTL_MAJOR
#define NFTL_MAJOR 93
+#endif
+
#define MAX_NFTLS 16
+#define MAX_SECTORS_PER_UNIT 32
#endif /* __KERNEL__ */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
new file mode 100644
index 000000000..a92023886
--- /dev/null
+++ b/include/linux/mtd/partitions.h
@@ -0,0 +1,50 @@
+/*
+ * MTD partitioning layer definitions
+ *
+ * (C) 2000 Nicolas Pitre <nico@cam.org>
+ *
+ * This code is GPL
+ *
+ * $Id: partitions.h,v 1.3 2000/11/10 23:35:12 nico Exp $
+ */
+
+#ifndef MTD_PARTITIONS_H
+#define MTD_PARTITIONS_H
+
+#include <linux/types.h>
+
+
+/*
+ * Partition definition structure:
+ *
+ * An array of struct partition is passed along with a MTD object to
+ * add_mtd_partitions() to create them.
+ *
+ * For each partition, these fields are available:
+ * name: string that will be used to label the partition's MTD device.
+ * size: the partition size; if 0, the partition will extend to the end of the
+ * master MTD device.
+ * offset: absolute starting position within the master MTD device; if 0,
+ * partition will start where the previous one ended.
+ * mask_flags: contains flags that have to be masked (removed) from the
+ * master MTD flag set for the corresponding MTD partition.
+ * For example, to force a read-only partition, simply adding
+ * MTD_WRITEABLE to the mask_flags will do the trick.
+ *
+ * Note: writeable partitions require their size and offset be
+ * erasesize aligned.
+ */
+
+struct mtd_partition {
+ char *name; /* identifier string */
+ u_long size; /* partition size */
+ u_long offset; /* offset within the master MTD space */
+ u_long mask_flags; /* master MTD flags to mask out for this partition */
+};
+
+
+int add_mtd_partitions(struct mtd_info *, struct mtd_partition *, int);
+int del_mtd_partitions(struct mtd_info *);
+
+#endif
+
diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h
index 05c506516..144eb922a 100644
--- a/include/linux/mtd/pmc551.h
+++ b/include/linux/mtd/pmc551.h
@@ -1,5 +1,5 @@
/*
- * $Id: pmc551.h,v 1.2 2000/03/31 14:40:42 dwmw2 Exp $
+ * $Id: pmc551.h,v 1.3 2000/10/30 20:03:23 major Exp $
*
* PMC551 PCI Mezzanine Ram Device
*
@@ -17,6 +17,9 @@
#include <linux/mtd/mtd.h>
+#define PMC551_VERSION "$Id: pmc551.h,v 1.3 2000/10/30 20:03:23 major Exp $\n"\
+ "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
+
/*
* Our personal and private information
*/
@@ -54,68 +57,25 @@ static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_cha
#define PMC551_PCI_MEM_MAP1 0x54
#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000
#define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0
-#define PMC551_PCI_MEM_MAP_1MB_APERTURE 0x00000000
-#define PMC551_PCI_MEM_MAP_2MB_APERTURE 0x00000010
-#define PMC551_PCI_MEM_MAP_REG_EN 0x00000002
-#define PMC551_PCI_MEM_MAP_ENABLE 0x00000001
-
-#define PMC551_SDRAM_MA 0x60
-#define PMC551_SDRAM_CMD 0x62
-#define PMC551_DRAM_CFG 0x64
-
-#define PMC551_DRAM_BLK0 0x68
-#define PMC551_DRAM_BLK1 0x6c
-#define PMC551_DRAM_BLK2 0x70
-#define PMC551_DRAM_BLK3 0x74
-#define PMC551_DRAM_BLK_GET_SIZE(x) ((512 * 1024) << ((x >> 4) & 0xf))
-#define PMC551_DRAM_BLK_SET_COL_MUX(x,v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
-#define PMC551_DRAM_BLK_SET_ROW_MUX(x,v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
-
-
-/* Use a 1MB apeture into the card. */
-#define PMC551_APERTURE_SIZE 0x00100000
-#define PMC551_ADDR_HIGH_MASK 0x3ff00000
-#define PMC551_ADDR_LOW_MASK 0x000fffff
-#define PMC551_APERTURE_VAL PMC551_PCI_MEM_MAP_1MB_APERTURE
-/*
- * Define the PCI ID's if the kernel doesn't define them for us
- */
-#ifndef PCI_VENDOR_ID_V3_SEMI
-#define PCI_VENDOR_ID_V3_SEMI 0x11b0
-#endif
-
-#ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC
-#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
-#endif
-
-
-#define PMC551_PCI_MEM_MAP0 0x50
-#define PMC551_PCI_MEM_MAP1 0x54
-#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000
-#define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0
-#define PMC551_PCI_MEM_MAP_1MB_APERTURE 0x00000000
-#define PMC551_PCI_MEM_MAP_2MB_APERTURE 0x00000010
#define PMC551_PCI_MEM_MAP_REG_EN 0x00000002
#define PMC551_PCI_MEM_MAP_ENABLE 0x00000001
#define PMC551_SDRAM_MA 0x60
#define PMC551_SDRAM_CMD 0x62
#define PMC551_DRAM_CFG 0x64
+#define PMC551_SYS_CTRL_REG 0x78
#define PMC551_DRAM_BLK0 0x68
#define PMC551_DRAM_BLK1 0x6c
#define PMC551_DRAM_BLK2 0x70
#define PMC551_DRAM_BLK3 0x74
-#define PMC551_DRAM_BLK_GET_SIZE(x) ((512 * 1024) << ((x >> 4) & 0xf))
+#define PMC551_DRAM_BLK_GET_SIZE(x) (524288<<((x>>4)&0x0f))
#define PMC551_DRAM_BLK_SET_COL_MUX(x,v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
#define PMC551_DRAM_BLK_SET_ROW_MUX(x,v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
-/* Use a 1MB apeture into the card. */
-#define PMC551_APERTURE_SIZE 0x00100000
#define PMC551_ADDR_HIGH_MASK 0x3ff00000
#define PMC551_ADDR_LOW_MASK 0x000fffff
-#define PMC551_APERTURE_VAL PMC551_PCI_MEM_MAP_1MB_APERTURE
#endif /* __MTD_PMC551_H__ */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2c2bfd4d5..462091674 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -51,11 +51,11 @@ struct divert_blk;
/* Backlog congestion levels */
#define NET_RX_SUCCESS 0 /* keep 'em coming, baby */
-#define NET_RX_CN_LOW 1 /* storm alert, just in case */
-#define NET_RX_CN_MOD 2 /* Storm on its way! */
-#define NET_RX_CN_HIGH 5 /* The storm is here */
-#define NET_RX_DROP -1 /* packet dropped */
-#define NET_RX_BAD -2 /* packet dropped due to kernel error */
+#define NET_RX_DROP 1 /* packet dropped */
+#define NET_RX_CN_LOW 2 /* storm alert, just in case */
+#define NET_RX_CN_MOD 3 /* Storm on its way! */
+#define NET_RX_CN_HIGH 4 /* The storm is here */
+#define NET_RX_BAD 5 /* packet dropped due to kernel error */
#define net_xmit_errno(e) ((e) != NET_XMIT_CN ? -ENOBUFS : 0)
@@ -333,11 +333,17 @@ struct net_device
atomic_t refcnt;
/* The flag marking that device is unregistered, but held by an user */
int deadbeaf;
- /* New style devices allow asynchronous destruction;
- netdevice_unregister for old style devices blocks until
- the last user will dereference this device.
- */
- int new_style;
+
+ /* Net device features */
+ int features;
+#define NETIF_F_SG 1 /* Scatter/gather IO. */
+#define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */
+#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
+#define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */
+#define NETIF_F_DYNALLOC 16 /* Self-dectructable device. */
+#define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */
+#define NETIF_F_FRAGLIST 1 /* Scatter/gather IO. */
+
/* Called after device is detached from network. */
void (*uninit)(struct net_device *dev);
/* Called after last user reference disappears. */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index b61722b15..cc8abab1f 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -63,8 +63,7 @@
*/
#define NFS_SUPER_MAGIC 0x6969
-#define NFS_FH(dentry) ((struct nfs_fh *) ((dentry)->d_fsdata))
-#define NFS_DSERVER(dentry) (&(dentry)->d_sb->u.nfs_sb.s_server)
+#define NFS_FH(inode) (&(inode)->u.nfs_i.fh)
#define NFS_SERVER(inode) (&(inode)->i_sb->u.nfs_sb.s_server)
#define NFS_CLIENT(inode) (NFS_SERVER(inode)->client)
#define NFS_PROTO(inode) (NFS_SERVER(inode)->rpc_ops)
@@ -93,6 +92,7 @@ do { \
#define NFS_FLAGS(inode) ((inode)->u.nfs_i.flags)
#define NFS_REVALIDATING(inode) (NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
+#define NFS_STALE(inode) (NFS_FLAGS(inode) & NFS_INO_STALE)
#define NFS_FILEID(inode) ((inode)->u.nfs_i.fileid)
#define NFS_FSID(inode) ((inode)->u.nfs_i.fsid)
@@ -139,13 +139,16 @@ unsigned long page_index(struct page *page)
extern struct super_block *nfs_read_super(struct super_block *, void *, int);
extern int init_nfs_fs(void);
extern void nfs_zap_caches(struct inode *);
+extern int nfs_inode_is_stale(struct inode *, struct nfs_fh *,
+ struct nfs_fattr *);
extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
struct nfs_fattr *);
extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_revalidate(struct dentry *);
+extern int nfs_permission(struct inode *, int);
extern int nfs_open(struct inode *, struct file *);
extern int nfs_release(struct inode *, struct file *);
-extern int __nfs_revalidate_inode(struct nfs_server *, struct dentry *);
+extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
extern int nfs_notify_change(struct dentry *, struct iattr *);
/*
@@ -192,7 +195,7 @@ extern void nfs_complete_unlink(struct dentry *);
/*
* linux/fs/nfs/write.c
*/
-extern int nfs_writepage(struct file *file, struct page *);
+extern int nfs_writepage(struct page *);
extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
/*
@@ -264,12 +267,11 @@ extern int nfs3_mount(struct sockaddr_in *, char *, struct nfs_fh *);
* inline functions
*/
static inline int
-nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
+nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
{
- struct inode *inode = dentry->d_inode;
if (time_before(jiffies, NFS_READTIME(inode)+NFS_ATTRTIMEO(inode)))
- return 0;
- return __nfs_revalidate_inode(server, dentry);
+ return NFS_STALE(inode) ? -ESTALE : 0;
+ return __nfs_revalidate_inode(server, inode);
}
static inline loff_t
diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h
index 2e10b1963..f14f3d8d9 100644
--- a/include/linux/nfs_fs_i.h
+++ b/include/linux/nfs_fs_i.h
@@ -3,6 +3,7 @@
#include <asm/types.h>
#include <linux/list.h>
+#include <linux/nfs.h>
/*
* nfs fs inode data in memory
@@ -15,6 +16,11 @@ struct nfs_inode_info {
__u64 fileid;
/*
+ * NFS file handle
+ */
+ struct nfs_fh fh;
+
+ /*
* Various flags
*/
unsigned short flags;
@@ -72,6 +78,7 @@ struct nfs_inode_info {
/*
* Legal inode flag values
*/
+#define NFS_INO_STALE 0x0001 /* possible stale inode */
#define NFS_INO_ADVISE_RDPLUS 0x0002 /* advise readdirplus */
#define NFS_INO_REVALIDATING 0x0004 /* revalidating attrs */
#define NFS_IS_SNAPSHOT 0x0010 /* a snapshot file */
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index f6c35dc01..2f37a4b19 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -26,7 +26,7 @@ struct nfs_page {
wb_list, /* Defines state of page: */
*wb_list_head; /* read/write/commit */
struct file *wb_file;
- struct dentry *wb_dentry;
+ struct inode *wb_inode;
struct rpc_cred *wb_cred;
struct page *wb_page; /* page to read in/write out */
wait_queue_head_t wb_wait; /* wait queue */
@@ -41,6 +41,7 @@ struct nfs_page {
#define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags))
extern struct nfs_page *nfs_create_request(struct file *file,
+ struct inode *inode,
struct page *page,
unsigned int offset,
unsigned int count);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9863c06af..1ee4dd616 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -316,39 +316,41 @@ struct nfs_rpc_ops {
int (*getroot) (struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *);
- int (*getattr) (struct dentry *, struct nfs_fattr *);
- int (*setattr) (struct dentry *, struct nfs_fattr *,
+ int (*getattr) (struct inode *, struct nfs_fattr *);
+ int (*setattr) (struct inode *, struct nfs_fattr *,
struct iattr *);
- int (*lookup) (struct dentry *, struct qstr *,
+ int (*lookup) (struct inode *, struct qstr *,
struct nfs_fh *, struct nfs_fattr *);
- int (*access) (struct dentry *, int , int);
- int (*readlink)(struct dentry *, void *, unsigned int);
- int (*read) (struct file *, struct nfs_fattr *,
+ int (*access) (struct inode *, int , int);
+ int (*readlink)(struct inode *, void *, unsigned int);
+ int (*read) (struct inode *, struct rpc_cred *,
+ struct nfs_fattr *,
int, loff_t, unsigned int,
void *buffer, int *eofp);
- int (*write) (struct file *, struct nfs_fattr *,
+ int (*write) (struct inode *, struct rpc_cred *,
+ struct nfs_fattr *,
int, loff_t, unsigned int,
void *buffer, struct nfs_writeverf *verfp);
- int (*commit) (struct dentry *, struct nfs_fattr *,
+ int (*commit) (struct inode *, struct nfs_fattr *,
unsigned long, unsigned int);
- int (*create) (struct dentry *, struct qstr *, struct iattr *,
+ int (*create) (struct inode *, struct qstr *, struct iattr *,
int, struct nfs_fh *, struct nfs_fattr *);
- int (*remove) (struct dentry *, struct qstr *);
+ int (*remove) (struct inode *, struct qstr *);
int (*unlink_setup) (struct rpc_message *,
struct dentry *, struct qstr *);
void (*unlink_done) (struct dentry *, struct rpc_message *);
- int (*rename) (struct dentry *, struct qstr *,
- struct dentry *, struct qstr *);
- int (*link) (struct dentry *, struct dentry *, struct qstr *);
- int (*symlink) (struct dentry *, struct qstr *, struct qstr *,
+ int (*rename) (struct inode *, struct qstr *,
+ struct inode *, struct qstr *);
+ int (*link) (struct inode *, struct inode *, struct qstr *);
+ int (*symlink) (struct inode *, struct qstr *, struct qstr *,
struct iattr *, struct nfs_fh *,
struct nfs_fattr *);
- int (*mkdir) (struct dentry *, struct qstr *, struct iattr *,
+ int (*mkdir) (struct inode *, struct qstr *, struct iattr *,
struct nfs_fh *, struct nfs_fattr *);
- int (*rmdir) (struct dentry *, struct qstr *);
- int (*readdir) (struct file *, u64 cookie, void *, unsigned int,
- int);
- int (*mknod) (struct dentry *, struct qstr *, struct iattr *,
+ int (*rmdir) (struct inode *, struct qstr *);
+ int (*readdir) (struct inode *, struct rpc_cred *,
+ u64, void *, unsigned int, int);
+ int (*mknod) (struct inode *, struct qstr *, struct iattr *,
dev_t, struct nfs_fh *, struct nfs_fattr *);
int (*statfs) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsinfo *);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0c2dc46ae..d98a3a01a 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -530,12 +530,13 @@ void pci_set_master(struct pci_dev *dev);
int pci_set_power_state(struct pci_dev *dev, int state);
int pci_assign_resource(struct pci_dev *dev, int i);
-/* Helper functions for low-level code (drivers/pci/setup.c) */
+/* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void);
-void pdev_assign_unassigned_resources(struct pci_dev *dev);
-void pci_set_bus_ranges(void);
+void pdev_enable_device(struct pci_dev *);
+void pdev_sort_resources(struct pci_dev *, struct resource_list *, u32);
+unsigned long pci_bridge_check_io(struct pci_dev *);
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
int (*)(struct pci_dev *, u8, u8));
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 7a89c6525..60aef94ee 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -119,6 +119,15 @@
/* Vendors and devices. Sort key: vendor first, device next. */
+#define PCI_VENDOR_ID_DYNALINK 0x0675
+#define PCI_DEVICE_ID_DYNALINK_IS64PH 0x1702
+
+#define PCI_VENDOR_ID_BERKOM 0x0871
+#define PCI_DEVICE_ID_BERKOM_A1T 0xffa1
+#define PCI_DEVICE_ID_BERKOM_T_CONCEPT 0xffa2
+#define PCI_DEVICE_ID_BERKOM_A4T 0xffa4
+#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO 0xffa8
+
#define PCI_VENDOR_ID_COMPAQ 0x0e11
#define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508
#define PCI_DEVICE_ID_COMPAQ_1280 0x3033
@@ -191,8 +200,8 @@
#define PCI_VENDOR_ID_NS 0x100b
#define PCI_DEVICE_ID_NS_87415 0x0002
-#define PCI_DEVICE_ID_NS_87560_LIO 0x000e
-#define PCI_DEVICE_ID_NS_87560_USB 0x0012
+#define PCI_DEVICE_ID_NS_87560_LIO 0x000e
+#define PCI_DEVICE_ID_NS_87560_USB 0x0012
#define PCI_DEVICE_ID_NS_87410 0xd001
#define PCI_VENDOR_ID_TSENG 0x100c
@@ -254,9 +263,17 @@
#define PCI_DEVICE_ID_IBM_405GP 0x0156
#define PCI_DEVICE_ID_IBM_MPIC_2 0xffff
+#define PCI_VENDOR_ID_COMPEX2 0x101a // pci.ids says "AT&T GIS (NCR)"
+#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005
+
#define PCI_VENDOR_ID_WD 0x101c
#define PCI_DEVICE_ID_WD_7197 0x3296
+#define PCI_VENDOR_ID_AMI 0x101e
+#define PCI_DEVICE_ID_AMI_MEGARAID3 0x1960
+#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010
+#define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060
+
#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_DEVICE_ID_AMD_LANCE 0x2000
#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001
@@ -272,6 +289,8 @@
#define PCI_DEVICE_ID_AMD_VIPER_740C 0x740C
#define PCI_VENDOR_ID_TRIDENT 0x1023
+#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000
+#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001
#define PCI_DEVICE_ID_TRIDENT_9320 0x9320
#define PCI_DEVICE_ID_TRIDENT_9388 0x9388
#define PCI_DEVICE_ID_TRIDENT_9397 0x9397
@@ -298,10 +317,10 @@
#define PCI_DEVICE_ID_MATROX_MIL_2 0x051b
#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f
#define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10
-#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000
-#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001
-#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520
-#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
+#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000
+#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001
+#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520
+#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
#define PCI_DEVICE_ID_MATROX_G400 0x0525
#define PCI_DEVICE_ID_MATROX_VIA 0x4536
@@ -366,8 +385,11 @@
#define PCI_DEVICE_ID_PCTECH_SAMURAI_1 0x3010
#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
-#define PCI_VENDOR_ID_DPT 0x1044
-#define PCI_DEVICE_ID_DPT 0xa400
+#define PCI_VENDOR_ID_ASUSTEK 0x1043
+#define PCI_DEVICE_ID_ASUSTEK_0675 0x0675
+
+#define PCI_VENDOR_ID_DPT 0x1044
+#define PCI_DEVICE_ID_DPT 0xa400
#define PCI_VENDOR_ID_OPTI 0x1045
#define PCI_DEVICE_ID_OPTI_92C178 0xc178
@@ -381,6 +403,10 @@
#define PCI_DEVICE_ID_OPTI_82C861 0xc861
#define PCI_DEVICE_ID_OPTI_82C825 0xd568
+#define PCI_VENDOR_ID_ELSA 0x1048
+#define PCI_DEVICE_ID_ELSA_MICROLINK 0x1000
+#define PCI_DEVICE_ID_ELSA_QS3000 0x3000
+
#define PCI_VENDOR_ID_SGS 0x104a
#define PCI_DEVICE_ID_SGS_2000 0x0008
#define PCI_DEVICE_ID_SGS_1764 0x0009
@@ -407,6 +433,8 @@
#define PCI_DEVICE_ID_TI_1251B 0xac1f
#define PCI_DEVICE_ID_TI_1420 0xac51
+#define PCI_VENDOR_ID_SONY 0x104d
+#define PCI_DEVICE_ID_SONY_CXD3222 0x8039
#define PCI_VENDOR_ID_OAK 0x104e
#define PCI_DEVICE_ID_OAK_OTI107 0x0107
@@ -415,7 +443,11 @@
#define PCI_VENDOR_ID_WINBOND2 0x1050
#define PCI_DEVICE_ID_WINBOND2_89C940 0x0940
#define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a
+#define PCI_DEVICE_ID_WINBOND2_6692 0x6692
+#define PCI_VENDOR_ID_ANIGMA 0x1051
+#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100
+
#define PCI_VENDOR_ID_EFAR 0x1055
#define PCI_DEVICE_ID_EFAR_SLC90E66_1 0x9130
#define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460
@@ -504,9 +536,10 @@
#define PCI_VENDOR_ID_LEADTEK 0x107d
#define PCI_DEVICE_ID_LEADTEK_805 0x0000
-#define PCI_VENDOR_ID_INTERPHASE 0x107e
+#define PCI_VENDOR_ID_INTERPHASE 0x107e
#define PCI_DEVICE_ID_INTERPHASE_5526 0x0004
#define PCI_DEVICE_ID_INTERPHASE_55x6 0x0005
+#define PCI_DEVICE_ID_INTERPHASE_5575 0x0008
#define PCI_VENDOR_ID_CONTAQ 0x1080
#define PCI_DEVICE_ID_CONTAQ_82C599 0x0600
@@ -545,8 +578,8 @@
#define PCI_VENDOR_ID_BROOKTREE 0x109e
#define PCI_DEVICE_ID_BROOKTREE_848 0x0350
#define PCI_DEVICE_ID_BROOKTREE_849A 0x0351
-#define PCI_DEVICE_ID_BROOKTREE_878_1 0x036e
-#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
+#define PCI_DEVICE_ID_BROOKTREE_878_1 0x036e
+#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
#define PCI_DEVICE_ID_BROOKTREE_8474 0x8474
#define PCI_VENDOR_ID_SIERRA 0x10a8
@@ -567,10 +600,13 @@
#define PCI_DEVICE_ID_DATABOOK_87144 0xb106
#define PCI_VENDOR_ID_PLX 0x10b5
-#define PCI_VENDOR_ID_PLX_ROMULUS 0x106a
+#define PCI_DEVICE_ID_PLX_R685 0x1030
+#define PCI_DEVICE_ID_PLX_ROMULUS 0x106a
#define PCI_DEVICE_ID_PLX_SPCOM800 0x1076
#define PCI_DEVICE_ID_PLX_1077 0x1077
#define PCI_DEVICE_ID_PLX_SPCOM200 0x1103
+#define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151
+#define PCI_DEVICE_ID_PLX_R753 0x1152
#define PCI_DEVICE_ID_PLX_9050 0x9050
#define PCI_DEVICE_ID_PLX_9060 0x9060
#define PCI_DEVICE_ID_PLX_9060ES 0x906E
@@ -618,6 +654,7 @@
#define PCI_DEVICE_ID_AL_M5229 0x5229
#define PCI_DEVICE_ID_AL_M5237 0x5237
#define PCI_DEVICE_ID_AL_M5243 0x5243
+#define PCI_DEVICE_ID_AL_M5451 0x5451
#define PCI_DEVICE_ID_AL_M7101 0x7101
#define PCI_VENDOR_ID_MITSUBISHI 0x10ba
@@ -625,7 +662,7 @@
#define PCI_VENDOR_ID_SURECOM 0x10bd
#define PCI_DEVICE_ID_SURECOM_NE34 0x0e34
-#define PCI_VENDOR_ID_NEOMAGIC 0x10c8
+#define PCI_VENDOR_ID_NEOMAGIC 0x10c8
#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2070 0x0001
#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128V 0x0002
#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZV 0x0003
@@ -693,6 +730,12 @@
#define PCI_DEVICE_ID_INIT_320P 0x9100
#define PCI_DEVICE_ID_INIT_360P 0x9500
+#define PCI_VENDOR_ID_CREATIVE 0x1102 // duplicate: ECTIVA
+#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
+
+#define PCI_VENDOR_ID_ECTIVA 0x1102 // duplicate: CREATIVE
+#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938
+
#define PCI_VENDOR_ID_TTI 0x1103
#define PCI_DEVICE_ID_TTI_HPT343 0x0003
#define PCI_DEVICE_ID_TTI_HPT366 0x0004
@@ -747,8 +790,8 @@
#define PCI_DEVICE_ID_VIA_8633_1 0xB091
#define PCI_DEVICE_ID_VIA_8367_1 0xB099
-#define PCI_VENDOR_ID_SMC2 0x1113
-#define PCI_DEVICE_ID_SMC2_1211TX 0x1211
+#define PCI_VENDOR_ID_SMC2 0x1113
+#define PCI_DEVICE_ID_SMC2_1211TX 0x1211
#define PCI_VENDOR_ID_VORTEX 0x1119
#define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000
@@ -788,6 +831,9 @@
#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000
#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002
+#define PCI_VENDOR_ID_IDT 0x111d
+#define PCI_DEVICE_ID_IDT_IDT77201 0x0001
+
#define PCI_VENDOR_ID_FORE 0x1127
#define PCI_DEVICE_ID_FORE_PCA200PC 0x0210
#define PCI_DEVICE_ID_FORE_PCA200E 0x0300
@@ -800,6 +846,17 @@
#define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146
#define PCI_DEVICE_ID_PHILIPS_SAA9730 0x9730
+#define PCI_VENDOR_ID_EICON 0x1133
+#define PCI_DEVICE_ID_EICON_DIVA20PRO 0xe001
+#define PCI_DEVICE_ID_EICON_DIVA20 0xe002
+#define PCI_DEVICE_ID_EICON_DIVA20PRO_U 0xe003
+#define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004
+#define PCI_DEVICE_ID_EICON_DIVA201 0xe005
+#define PCI_DEVICE_ID_EICON_MAESTRA 0xe010
+#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012
+#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
+#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014
+
#define PCI_VENDOR_ID_CYCLONE 0x113c
#define PCI_DEVICE_ID_CYCLONE_SDK 0x0001
@@ -826,6 +883,10 @@
#define PCI_DEVICE_ID_DIGI_XRJ 0x0009
#define PCI_DEVICE_ID_DIGI_EPCJ 0x000a
#define PCI_DEVICE_ID_DIGI_XR_920 0x0027
+#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
+#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071
+#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
+#define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073
#define PCI_VENDOR_ID_MUTECH 0x1159
#define PCI_DEVICE_ID_MUTECH_MV1000 0x0001
@@ -839,8 +900,8 @@
#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009
#define PCI_DEVICE_ID_SERVERWORKS_CIOB30 0x0010
#define PCI_DEVICE_ID_SERVERWORKS_CMIC_HE 0x0011
-#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201
-#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200
+#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201
+#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200
#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211
#define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
@@ -866,6 +927,13 @@
#define PCI_DEVICE_ID_ARTOP_ATP850UF 0x0005
#define PCI_DEVICE_ID_ARTOP_ATP860 0x0006
#define PCI_DEVICE_ID_ARTOP_ATP860R 0x0007
+#define PCI_DEVICE_ID_ARTOP_AEC7610 0x8002
+#define PCI_DEVICE_ID_ARTOP_AEC7612UW 0x8010
+#define PCI_DEVICE_ID_ARTOP_AEC7612U 0x8020
+#define PCI_DEVICE_ID_ARTOP_AEC7612S 0x8030
+#define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040
+#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050
+#define PCI_DEVICE_ID_ARTOP_8060 0x8060
#define PCI_VENDOR_ID_ZEITNET 0x1193
#define PCI_DEVICE_ID_ZEITNET_1221 0x0001
@@ -920,16 +988,16 @@
#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112
#define PCI_DEVICE_ID_COMPEX_RL2000 0x1401
-#define PCI_VENDOR_ID_RP 0x11fe
-#define PCI_DEVICE_ID_RP32INTF 0x0001
-#define PCI_DEVICE_ID_RP8INTF 0x0002
-#define PCI_DEVICE_ID_RP16INTF 0x0003
-#define PCI_DEVICE_ID_RP4QUAD 0x0004
-#define PCI_DEVICE_ID_RP8OCTA 0x0005
-#define PCI_DEVICE_ID_RP8J 0x0006
-#define PCI_DEVICE_ID_RPP4 0x000A
-#define PCI_DEVICE_ID_RPP8 0x000B
-#define PCI_DEVICE_ID_RP8M 0x000C
+#define PCI_VENDOR_ID_RP 0x11fe
+#define PCI_DEVICE_ID_RP32INTF 0x0001
+#define PCI_DEVICE_ID_RP8INTF 0x0002
+#define PCI_DEVICE_ID_RP16INTF 0x0003
+#define PCI_DEVICE_ID_RP4QUAD 0x0004
+#define PCI_DEVICE_ID_RP8OCTA 0x0005
+#define PCI_DEVICE_ID_RP8J 0x0006
+#define PCI_DEVICE_ID_RPP4 0x000A
+#define PCI_DEVICE_ID_RPP8 0x000B
+#define PCI_DEVICE_ID_RP8M 0x000C
#define PCI_VENDOR_ID_CYCLADES 0x120e
#define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100
@@ -957,7 +1025,7 @@
#define PCI_VENDOR_ID_3DFX 0x121a
#define PCI_DEVICE_ID_3DFX_VOODOO 0x0001
#define PCI_DEVICE_ID_3DFX_VOODOO2 0x0002
-#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003
+#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003
#define PCI_DEVICE_ID_3DFX_VOODOO3 0x0005
#define PCI_VENDOR_ID_SIGMADES 0x1236
@@ -966,7 +1034,10 @@
#define PCI_VENDOR_ID_CCUBE 0x123f
#define PCI_VENDOR_ID_AVM 0x1244
+#define PCI_DEVICE_ID_AVM_B1 0x0700
+#define PCI_DEVICE_ID_AVM_C4 0x0800
#define PCI_DEVICE_ID_AVM_A1 0x0a00
+#define PCI_DEVICE_ID_AVM_T1 0x1200
#define PCI_VENDOR_ID_DIPIX 0x1246
@@ -983,9 +1054,12 @@
#define PCI_DEVICE_ID_OPTIBASE_VQUEST 0x2130
#define PCI_VENDOR_ID_ESS 0x125d
+#define PCI_DEVICE_ID_ESS_ESS1968 0x1968
#define PCI_DEVICE_ID_ESS_AUDIOPCI 0x1969
+#define PCI_DEVICE_ID_ESS_ESS1978 0x1978
#define PCI_VENDOR_ID_SATSAGEM 0x1267
+#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016
#define PCI_DEVICE_ID_SATSAGEM_PCR2101 0x5352
#define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
@@ -994,10 +1068,14 @@
#define PCI_VENDOR_ID_ENSONIQ 0x1274
#define PCI_DEVICE_ID_ENSONIQ_AUDIOPCI 0x5000
-#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
+#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
#define PCI_VENDOR_ID_ROCKWELL 0x127A
+/* formerly Platform Tech */
+#define PCI_VENDOR_ID_ESS_OLD 0x1285
+#define PCI_DEVICE_ID_ESS_ESS0100 0x0100
+
#define PCI_VENDOR_ID_ALTEON 0x12ae
#define PCI_DEVICE_ID_ALTEON_ACENIC 0x0001
@@ -1031,6 +1109,10 @@
#define PCI_SUBDEVICE_ID_CHASE_PCIRAS4 0xF001
#define PCI_SUBDEVICE_ID_CHASE_PCIRAS8 0xF010
+#define PCI_VENDOR_ID_AUREAL 0x12eb
+#define PCI_DEVICE_ID_AUREAL_VORTEX_1 0x0001
+#define PCI_DEVICE_ID_AUREAL_VORTEX_2 0x0002
+
#define PCI_VENDOR_ID_CBOARDS 0x1307
#define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
@@ -1073,6 +1155,9 @@
#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061
#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062
+#define PCI_VENDOR_ID_DOMEX 0x134a
+#define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001
+
#define PCI_VENDOR_ID_QUATECH 0x135C
#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010
#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020
@@ -1089,12 +1174,56 @@
#define PCI_DEVICE_ID_SEALEVEL_COMM4 0x7401
#define PCI_DEVICE_ID_SEALEVEL_COMM8 0x7801
+#define PCI_VENDOR_ID_HYPERCOPE 0x1365
+#define PCI_DEVICE_ID_HYPERCOPE_PLX 0x9050
+#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO 0x0104
+#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO 0x0106
+#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO 0x0107
+#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2 0x0108
+#define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS 0x0109
+
+#define PCI_VENDOR_ID_LMC 0x1376
+#define PCI_DEVICE_ID_LMC_HSSI 0x0003
+#define PCI_DEVICE_ID_LMC_DS3 0x0004
+#define PCI_DEVICE_ID_LMC_SSI 0x0005
+#define PCI_DEVICE_ID_LMC_T1 0x0006
+
#define PCI_VENDOR_ID_NETGEAR 0x1385
#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a
+#define PCI_VENDOR_ID_APPLICOM 0x1389
+#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
+#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
+#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
+
+#define PCI_VENDOR_ID_MOXA 0x1393
+#define PCI_DEVICE_ID_MOXA_C104 0x1040
+#define PCI_DEVICE_ID_MOXA_C168 0x1680
+#define PCI_DEVICE_ID_MOXA_CP204J 0x2040
+#define PCI_DEVICE_ID_MOXA_C218 0x2180
+#define PCI_DEVICE_ID_MOXA_C320 0x3200
+
+#define PCI_VENDOR_ID_CCD 0x1397
+#define PCI_DEVICE_ID_CCD_2BD0 0x2bd0
+#define PCI_DEVICE_ID_CCD_B000 0xb000
+#define PCI_DEVICE_ID_CCD_B006 0xb006
+#define PCI_DEVICE_ID_CCD_B007 0xb007
+#define PCI_DEVICE_ID_CCD_B008 0xb008
+#define PCI_DEVICE_ID_CCD_B009 0xb009
+#define PCI_DEVICE_ID_CCD_B00A 0xb00a
+#define PCI_DEVICE_ID_CCD_B00B 0xb00b
+#define PCI_DEVICE_ID_CCD_B00C 0xb00c
+#define PCI_DEVICE_ID_CCD_B100 0xb100
+
#define PCI_VENDOR_ID_3WARE 0x13C1
#define PCI_DEVICE_ID_3WARE_1000 0x1000
+#define PCI_VENDOR_ID_CMEDIA 0x13f6
+#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100
+#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101
+#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111
+#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112
+
#define PCI_VENDOR_ID_LAVA 0x1407
#define PCI_DEVICE_ID_LAVA_DSERIAL 0x0100 /* 2x 16550 */
#define PCI_DEVICE_ID_LAVA_QUATRO_A 0x0101 /* 2x 16550, half of 4 port */
@@ -1112,11 +1241,16 @@
#define PCI_VENDOR_ID_TIMEDIA 0x1409
#define PCI_DEVICE_ID_TIMEDIA_1889 0x7168
-#define PCI_VENDOR_ID_OXSEMI 0x1415
-#define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501
+#define PCI_VENDOR_ID_OXSEMI 0x1415
+#define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501
#define PCI_DEVICE_ID_OXSEMI_16PCI952 0x950A
#define PCI_DEVICE_ID_OXSEMI_16PCI95N 0x9511
+#define PCI_VENDOR_ID_AIRONET 0x14b9
+#define PCI_DEVICE_ID_AIRONET_4800_1 0x0001
+#define PCI_DEVICE_ID_AIRONET_4800 0x4500 // values switched? see
+#define PCI_DEVICE_ID_AIRONET_4500 0x4800 // drivers/net/aironet4500_card.c
+
#define PCI_VENDOR_ID_TITAN 0x14D2
#define PCI_DEVICE_ID_TITAN_100 0xA001
#define PCI_DEVICE_ID_TITAN_200 0xA005
@@ -1137,6 +1271,9 @@
#define PCI_VENDOR_ID_MORETON 0x15aa
#define PCI_DEVICE_ID_RASTEL_2PORT 0x2000
+#define PCI_VENDOR_ID_ZOLTRIX 0x15b0
+#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2bd0
+
#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
#define PCI_DEVICE_ID_SYMPHONY_101 0x0001
@@ -1212,6 +1349,7 @@
#define PCI_DEVICE_ID_INTEL_82441 0x1237
#define PCI_DEVICE_ID_INTEL_82380FB 0x124b
#define PCI_DEVICE_ID_INTEL_82439 0x1250
+#define PCI_DEVICE_ID_INTEL_80960_RP 0x1960
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020
@@ -1330,6 +1468,7 @@
#define PCI_VENDOR_ID_TIGERJET 0xe159
#define PCI_DEVICE_ID_TIGERJET_300 0x0001
+#define PCI_DEVICE_ID_TIGERJET_100 0x0002
#define PCI_VENDOR_ID_ARK 0xedd8
#define PCI_DEVICE_ID_ARK_STING 0xa091
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 41d729e16..8c260c63d 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -59,7 +59,6 @@ typedef struct mdk_rdev_s mdk_rdev_t;
#error MD doesnt handle bigger kdev yet
#endif
-#define MAX_REAL 12 /* Max number of disks per md dev */
#define MAX_MD_DEVS (1<<MINORBITS) /* Max number of md dev */
/*
@@ -166,8 +165,7 @@ struct mdk_rdev_s
mddev_t *mddev; /* RAID array if running */
unsigned long last_events; /* IO event timestamp */
- struct inode *inode; /* Lock inode */
- struct file filp; /* Lock file */
+ struct block_device *bdev; /* block device handle */
mdp_super_t *sb;
unsigned long sb_offset;
@@ -207,6 +205,7 @@ struct mddev_s
struct semaphore reconfig_sem;
struct semaphore recovery_sem;
struct semaphore resync_sem;
+ atomic_t active;
atomic_t recovery_active; /* blocks scheduled, but not written */
md_wait_queue_head_t recovery_wait;
diff --git a/include/linux/raid/raid0.h b/include/linux/raid/raid0.h
index a27234f67..0b9372957 100644
--- a/include/linux/raid/raid0.h
+++ b/include/linux/raid/raid0.h
@@ -9,7 +9,7 @@ struct strip_zone
unsigned long dev_offset; /* Zone offset in real dev */
unsigned long size; /* Zone size */
int nb_dev; /* # of devices attached to the zone */
- mdk_rdev_t *dev[MAX_REAL]; /* Devices attached to the zone */
+ mdk_rdev_t *dev[MD_SB_DISKS]; /* Devices attached to the zone */
};
struct raid0_hash
diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
index aa17b8472..a9a9d3e8e 100644
--- a/include/linux/raid/raid1.h
+++ b/include/linux/raid/raid1.h
@@ -7,7 +7,6 @@ struct mirror_info {
int number;
int raid_disk;
kdev_t dev;
- int next;
int sect_limit;
int head_position;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index a58b23c86..0622510fc 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -149,7 +149,10 @@ extern void update_one_process(struct task_struct *p, unsigned long user,
extern signed long FASTCALL(schedule_timeout(signed long timeout));
asmlinkage void schedule(void);
-extern void schedule_task(struct tq_struct *task);
+extern int schedule_task(struct tq_struct *task);
+extern void flush_scheduled_tasks(void);
+extern int start_context_thread(void);
+extern int current_is_keventd(void);
/*
* The default fd array needs to be at least BITS_PER_LONG,
@@ -174,18 +177,19 @@ struct files_struct {
struct file * fd_array[NR_OPEN_DEFAULT];
};
-#define INIT_FILES { \
- ATOMIC_INIT(1), \
- RW_LOCK_UNLOCKED, \
- NR_OPEN_DEFAULT, \
- __FD_SETSIZE, \
- 0, \
- &init_files.fd_array[0], \
- &init_files.close_on_exec_init, \
- &init_files.open_fds_init, \
- { { 0, } }, \
- { { 0, } }, \
- { NULL, } \
+#define INIT_FILES \
+{ \
+ count: ATOMIC_INIT(1), \
+ file_lock: RW_LOCK_UNLOCKED, \
+ max_fds: NR_OPEN_DEFAULT, \
+ max_fdset: __FD_SETSIZE, \
+ next_fd: 0, \
+ fd: &init_files.fd_array[0], \
+ close_on_exec: &init_files.close_on_exec_init, \
+ open_fds: &init_files.open_fds_init, \
+ close_on_exec_init: { { 0, } }, \
+ open_fds_init: { { 0, } }, \
+ fd_array: { NULL, } \
}
/* Maximum number of active map areas.. This is a random (large) number */
@@ -220,18 +224,19 @@ struct mm_struct {
void * segments;
};
-#define INIT_MM(name) { \
- &init_mmap, NULL, NULL, \
- swapper_pg_dir, \
- ATOMIC_INIT(2), ATOMIC_INIT(1), 1, \
- __MUTEX_INITIALIZER(name.mmap_sem), \
- SPIN_LOCK_UNLOCKED, \
- 0, \
- 0, 0, 0, 0, \
- 0, 0, 0, \
- 0, 0, 0, 0, \
- 0, 0, 0, \
- 0, 0, 0, 0, NULL }
+#define INIT_MM(name) \
+{ \
+ mmap: &init_mmap, \
+ mmap_avl: NULL, \
+ mmap_cache: NULL, \
+ pgd: swapper_pg_dir, \
+ mm_users: ATOMIC_INIT(2), \
+ mm_count: ATOMIC_INIT(1), \
+ map_count: 1, \
+ mmap_sem: __MUTEX_INITIALIZER(name.mmap_sem), \
+ page_table_lock: SPIN_LOCK_UNLOCKED, \
+ segments: NULL \
+}
struct signal_struct {
atomic_t count;
@@ -240,10 +245,11 @@ struct signal_struct {
};
-#define INIT_SIGNALS { \
- ATOMIC_INIT(1), \
- { {{0,}}, }, \
- SPIN_LOCK_UNLOCKED }
+#define INIT_SIGNALS { \
+ count: ATOMIC_INIT(1), \
+ action: { {{0,}}, }, \
+ siglock: SPIN_LOCK_UNLOCKED \
+}
/*
* Some day this will be a full-fledged user tracking system..
diff --git a/include/linux/signal.h b/include/linux/signal.h
index f2d0766ef..c4e6eb3bd 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -193,7 +193,7 @@ static inline void siginitset(sigset_t *set, unsigned long mask)
memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1));
break;
case 2: set->sig[1] = 0;
- case 1:
+ case 1: ;
}
}
@@ -205,7 +205,7 @@ static inline void siginitsetinv(sigset_t *set, unsigned long mask)
memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1));
break;
case 2: set->sig[1] = -1;
- case 1:
+ case 1: ;
}
}
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c67f8c85a..17e48d0e9 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -65,8 +65,7 @@ struct sk_buff {
struct sk_buff_head * list; /* List we are on */
struct sock *sk; /* Socket we are owned by */
struct timeval stamp; /* Time we arrived */
- struct net_device *dev; /* Device we arrived on/are leaving by */
- struct net_device *rx_dev;
+ struct net_device *dev; /* Device we arrived on/are leaving by */
/* Transport layer header */
union
@@ -110,8 +109,7 @@ struct sk_buff {
unsigned int len; /* Length of actual data */
unsigned int csum; /* Checksum */
volatile char used; /* Data moved to user and not MSG_PEEK */
- unsigned char is_clone, /* We are a clone */
- cloned, /* head may be cloned (check refcnt to be sure). */
+ unsigned char cloned, /* head may be cloned (check refcnt to be sure). */
pkt_type, /* Packet class */
ip_summed; /* Driver fed us an IP checksum */
__u32 priority; /* Packet queueing priority */
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h
index e475057fc..501ea4b96 100644
--- a/include/linux/smb_fs.h
+++ b/include/linux/smb_fs.h
@@ -126,8 +126,8 @@ int smb_errno(struct smb_sb_info *);
int smb_close(struct inode *);
int smb_close_fileid(struct dentry *, __u16);
int smb_open(struct dentry *, int);
-int smb_proc_read(struct dentry *, off_t, int, char *);
-int smb_proc_write(struct dentry *, off_t, int, const char *);
+int smb_proc_read(struct inode *, off_t, int, char *);
+int smb_proc_write(struct inode *, off_t, int, const char *);
int smb_proc_create(struct dentry *, __u16, time_t, __u16 *);
int smb_proc_mv(struct dentry *, struct dentry *);
int smb_proc_mkdir(struct dentry *);
diff --git a/include/linux/smb_fs_sb.h b/include/linux/smb_fs_sb.h
index 4bad7e928..0d14b83ae 100644
--- a/include/linux/smb_fs_sb.h
+++ b/include/linux/smb_fs_sb.h
@@ -14,8 +14,9 @@
#include <linux/types.h>
#include <linux/smb.h>
-/* Get the server for the specified dentry */
-#define server_from_dentry(dentry) &dentry->d_sb->u.smbfs_sb
+/* structure access macros */
+#define server_from_inode(inode) (&(inode)->i_sb->u.smbfs_sb)
+#define server_from_dentry(dentry) (&(dentry)->d_sb->u.smbfs_sb)
#define SB_of(server) ((struct super_block *) ((char *)(server) - \
(unsigned long)(&((struct super_block *)0)->u.smbfs_sb)))
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 8ba581f5b..8bb2d1c5d 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -65,7 +65,7 @@
#elif (DEBUG_SPINLOCKS < 2)
typedef struct {
- volatile unsigned int lock;
+ volatile unsigned long lock;
} spinlock_t;
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
@@ -80,7 +80,7 @@ typedef struct {
#else /* (DEBUG_SPINLOCKS >= 2) */
typedef struct {
- volatile unsigned int lock;
+ volatile unsigned long lock;
volatile unsigned int babble;
const char *module;
} spinlock_t;
diff --git a/include/linux/stallion.h b/include/linux/stallion.h
index a4f6e2278..072f89508 100644
--- a/include/linux/stallion.h
+++ b/include/linux/stallion.h
@@ -75,7 +75,7 @@ typedef struct stlport {
int ioaddr;
int uartaddr;
int pagenr;
- int istate;
+ long istate;
int flags;
int baud_base;
int custom_divisor;
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index f3e9ad2be..c6e6e40e0 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -43,7 +43,7 @@ struct rpc_task {
struct rpc_task * tk_prev_task; /* global list of tasks */
struct rpc_clnt * tk_client; /* RPC client */
struct rpc_rqst * tk_rqstp; /* RPC request */
- volatile int tk_status; /* result of last operation */
+ int tk_status; /* result of last operation */
struct rpc_wait_queue * tk_rpcwait; /* RPC wait queue we're on */
/*
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index dd27162ff..b204387c5 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -138,8 +138,7 @@ struct rpc_xprt {
struct rpc_wait_queue reconn; /* waiting for reconnect */
struct rpc_rqst * free; /* free slots */
struct rpc_rqst slot[RPC_MAXREQS];
- volatile unsigned char connected : 1, /* TCP: connected */
- write_space: 1; /* TCP: can send */
+ unsigned int sockstate; /* Socket state */
unsigned char shutdown : 1, /* being shut down */
nocong : 1, /* no congestion control */
stream : 1, /* TCP */
@@ -190,6 +189,18 @@ void __rpciod_tcp_dispatcher(void);
extern struct list_head rpc_xprt_pending;
+#define XPRT_WSPACE 0
+#define XPRT_CONNECT 1
+
+#define xprt_wspace(xp) (test_bit(XPRT_WSPACE, &(xp)->sockstate))
+#define xprt_test_and_set_wspace(xp) (test_and_set_bit(XPRT_WSPACE, &(xp)->sockstate))
+#define xprt_clear_wspace(xp) (clear_bit(XPRT_WSPACE, &(xp)->sockstate))
+
+#define xprt_connected(xp) (!(xp)->stream || test_bit(XPRT_CONNECT, &(xp)->sockstate))
+#define xprt_set_connected(xp) (set_bit(XPRT_CONNECT, &(xp)->sockstate))
+#define xprt_test_and_set_connected(xp) (test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate))
+#define xprt_clear_connected(xp) (clear_bit(XPRT_CONNECT, &(xp)->sockstate))
+
static inline
int xprt_tcp_pending(void)
{
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 87364f298..1390490f9 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -82,8 +82,6 @@ struct vm_area_struct;
struct sysinfo;
struct zone_t;
-/* linux/ipc/shm.c */
-extern int shm_swap(int, int);
/* linux/mm/swap.c */
extern int memory_pressure;
diff --git a/include/linux/tqueue.h b/include/linux/tqueue.h
index 3eb8f14ae..a0363ffa6 100644
--- a/include/linux/tqueue.h
+++ b/include/linux/tqueue.h
@@ -14,6 +14,7 @@
#define _LINUX_TQUEUE_H
#include <linux/spinlock.h>
+#include <linux/list.h>
#include <asm/bitops.h>
#include <asm/system.h>
@@ -29,37 +30,33 @@
* used as a bottom half handler. This is for example useful for bottom
* halfs, which want to be delayed until the next clock tick.
*
- * Problems:
- * - The queue_task_irq() inline function is only atomic with respect to itself.
- * Problems can occur, when queue_task_irq() is called from a normal system
- * call, and an interrupt comes in. No problems occur, when queue_task_irq()
- * is called from an interrupt or bottom half, and interrupted, as run_task_queue()
- * will not be executed/continued before the last interrupt returns. If in
- * doubt, use queue_task(), not queue_task_irq().
+ * Notes:
* - Bottom halfs are called in the reverse order that they were linked into
* the list.
*/
struct tq_struct {
- struct tq_struct *next; /* linked list of active bh's */
+ struct list_head list; /* linked list of active bh's */
unsigned long sync; /* must be initialized to zero */
void (*routine)(void *); /* function to call */
void *data; /* argument to function */
};
-typedef struct tq_struct * task_queue;
+typedef struct list_head task_queue;
-#define DECLARE_TASK_QUEUE(q) task_queue q = NULL
+#define DECLARE_TASK_QUEUE(q) LIST_HEAD(q)
+#define TQ_ACTIVE(q) (!list_empty(&q))
-extern task_queue tq_timer, tq_immediate, tq_scheduler, tq_disk;
+extern task_queue tq_timer, tq_immediate, tq_disk;
/*
* To implement your own list of active bottom halfs, use the following
* two definitions:
*
- * struct tq_struct *my_bh = NULL;
+ * DECLARE_TASK_QUEUE(my_bh);
* struct tq_struct run_my_bh = {
- * 0, 0, (void (*)(void *)) run_task_queue, &my_bh
+ * routine: (void (*)(void *)) run_task_queue,
+ * data: &my_bh
* };
*
* To activate a bottom half on your list, use:
@@ -78,18 +75,21 @@ extern task_queue tq_timer, tq_immediate, tq_scheduler, tq_disk;
extern spinlock_t tqueue_lock;
/*
- * queue_task
+ * Queue a task on a tq. Return non-zero if it was successfully
+ * added.
*/
-static inline void queue_task(struct tq_struct *bh_pointer,
+static inline int queue_task(struct tq_struct *bh_pointer,
task_queue *bh_list)
{
+ int ret = 0;
if (!test_and_set_bit(0,&bh_pointer->sync)) {
unsigned long flags;
spin_lock_irqsave(&tqueue_lock, flags);
- bh_pointer->next = *bh_list;
- *bh_list = bh_pointer;
+ list_add_tail(&bh_pointer->list, bh_list);
spin_unlock_irqrestore(&tqueue_lock, flags);
+ ret = 1;
}
+ return ret;
}
/*
@@ -97,28 +97,29 @@ static inline void queue_task(struct tq_struct *bh_pointer,
*/
static inline void run_task_queue(task_queue *list)
{
- if (*list) {
+ while (!list_empty(list)) {
unsigned long flags;
- struct tq_struct *p;
+ struct list_head *next;
spin_lock_irqsave(&tqueue_lock, flags);
- p = *list;
- *list = NULL;
- spin_unlock_irqrestore(&tqueue_lock, flags);
-
- while (p) {
+ next = list->next;
+ if (next != list) {
void *arg;
void (*f) (void *);
- struct tq_struct *save_p;
- arg = p -> data;
- f = p -> routine;
- save_p = p;
- p = p -> next;
- smp_mb();
- save_p -> sync = 0;
+ struct tq_struct *p;
+
+ list_del(next);
+ p = list_entry(next, struct tq_struct, list);
+ arg = p->data;
+ f = p->routine;
+ p->sync = 0;
+ spin_unlock_irqrestore(&tqueue_lock, flags);
+
if (f)
- (*f)(arg);
+ f(arg);
+ continue;
}
+ spin_unlock_irqrestore(&tqueue_lock, flags);
}
}
diff --git a/include/linux/tty.h b/include/linux/tty.h
index bb5bebde0..642c8bd7e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -360,7 +360,6 @@ extern int rp_init(void);
extern int cy_init(void);
extern int stl_init(void);
extern int stli_init(void);
-extern int riscom8_init(void);
extern int specialix_init(void);
extern int espserial_init(void);
extern int macserial_init(void);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 2828238ac..39e9f2eed 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -412,7 +412,7 @@ typedef struct urb
struct usb_device *dev; // pointer to associated USB device
unsigned int pipe; // pipe information
int status; // returned status
- unsigned int transfer_flags; // USB_DISABLE_SPD | USB_ISO_ASAP | USB_URB_EARLY_COMPLETE
+ unsigned int transfer_flags; // USB_DISABLE_SPD | USB_ISO_ASAP | etc.
void *transfer_buffer; // associated data buffer
int transfer_buffer_length; // data buffer length
int actual_length; // actual data buffer length
@@ -428,7 +428,7 @@ typedef struct urb
void *context; // context for completion routine
usb_complete_t complete; // pointer to completion routine
//
- iso_packet_descriptor_t iso_frame_desc[0];
+ iso_packet_descriptor_t iso_frame_desc[0];
} urb_t, *purb_t;
#define FILL_CONTROL_URB(a,aa,b,c,d,e,f,g) \
@@ -545,7 +545,7 @@ struct usb_bus {
struct list_head inodes;
};
-#define USB_MAXCHILDREN (8) /* This is arbitrary */
+#define USB_MAXCHILDREN (16) /* This is arbitrary */
struct usb_device {
int devnum; /* Device number on USB bus */
diff --git a/include/linux/wanrouter.h b/include/linux/wanrouter.h
index 736493d1d..415454f5f 100644
--- a/include/linux/wanrouter.h
+++ b/include/linux/wanrouter.h
@@ -442,7 +442,7 @@ typedef struct wan_device
char api_status; /* device api status */
struct net_device_stats stats; /* interface statistics */
unsigned reserved[16]; /* reserved for future use */
- unsigned critical; /* critical section flag */
+ unsigned long critical; /* critical section flag */
/****** device management methods ***/
int (*setup) (struct wan_device *wandev, wandev_conf_t *conf);
int (*shutdown) (struct wan_device *wandev);
diff --git a/include/net/checksum.h b/include/net/checksum.h
index 76cf27e77..6a16809c9 100644
--- a/include/net/checksum.h
+++ b/include/net/checksum.h
@@ -124,10 +124,31 @@ static __inline__ unsigned int csum_and_copy_to_user
}
#endif
-static inline unsigned int csum_chain(unsigned int csum, unsigned int addend)
+static inline unsigned int csum_add(unsigned int csum, unsigned int addend)
{
csum += addend;
return csum + (csum < addend);
}
+static inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
+{
+ return csum_add(csum, ~addend);
+}
+
+static inline unsigned int
+csum_block_add(unsigned int csum, unsigned int csum2, int offset)
+{
+ if (offset&1)
+ csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF);
+ return csum_add(csum, csum2);
+}
+
+static inline unsigned int
+csum_block_sub(unsigned int csum, unsigned int csum2, int offset)
+{
+ if (offset&1)
+ csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF);
+ return csum_sub(csum, csum2);
+}
+
#endif
diff --git a/include/net/icmp.h b/include/net/icmp.h
index e7ff46a05..dc4d6f524 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -24,6 +24,11 @@
#include <net/sock.h>
#include <net/protocol.h>
+struct icmp_err {
+ int errno;
+ unsigned fatal:1;
+};
+
extern struct icmp_err icmp_err_convert[];
extern struct icmp_mib icmp_statistics[NR_CPUS*2];
#define ICMP_INC_STATS(field) SNMP_INC_STATS(icmp_statistics, field)
diff --git a/include/net/ipx.h b/include/net/ipx.h
index 84e7cdb1d..bc023a662 100644
--- a/include/net/ipx.h
+++ b/include/net/ipx.h
@@ -45,6 +45,7 @@ typedef struct ipx_interface {
/* IPX address */
__u32 if_netnum;
unsigned char if_node[IPX_NODE_LEN];
+ atomic_t refcnt;
/* physical device info */
struct net_device *if_dev;
@@ -54,6 +55,7 @@ typedef struct ipx_interface {
/* socket support */
unsigned short if_sknum;
struct sock *if_sklist;
+ spinlock_t if_sklist_lock;
/* administrative overhead */
int if_ipx_offset;
diff --git a/include/net/sock.h b/include/net/sock.h
index 75aae4d1b..8550282cb 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -383,7 +383,8 @@ struct tcp_opt {
__u32 urg_seq; /* Seq of received urgent pointer */
__u16 urg_data; /* Saved octet of OOB data and control flags */
__u8 pending; /* Scheduled timer event */
- __u8 __empty;
+ __u8 urg_mode; /* In urgent mode */
+ __u32 snd_up; /* Urgent pointer */
/* The syn_wait_lock is necessary only to avoid tcp_get_info having
* to grab the main lock sock while browsing the listening hash
@@ -402,7 +403,7 @@ struct tcp_opt {
struct open_request *accept_queue;
struct open_request *accept_queue_tail;
- int write_pending; /* A write to socket waits to start. */
+ int write_pending; /* A write to socket waits to start. */
unsigned int keepalive_time; /* time before keep alive takes place */
unsigned int keepalive_intvl; /* time interval between keep alive probes */
@@ -1168,6 +1169,7 @@ static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
}
#endif /* CONFIG_FILTER */
+ skb->dev = NULL;
skb_set_owner_r(skb, sk);
skb_queue_tail(&sk->receive_queue, skb);
if (!sk->dead)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index dd8e74ca1..ccdff5aaa 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -328,9 +328,13 @@ static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
*/
#define TCP_DELACK_MAX (HZ/5) /* maximal time to delay before sending an ACK */
-#define TCP_DELACK_MIN (2) /* minimal time to delay before sending an ACK,
- * 2 scheduler ticks, not depending on HZ. */
-#define TCP_ATO_MIN 2
+#if HZ >= 100
+#define TCP_DELACK_MIN (HZ/25) /* minimal time to delay before sending an ACK */
+#define TCP_ATO_MIN (HZ/25)
+#else
+#define TCP_DELACK_MIN 4
+#define TCP_ATO_MIN 4
+#endif
#define TCP_RTO_MAX (120*HZ)
#define TCP_RTO_MIN (HZ/5)
#define TCP_TIMEOUT_INIT (3*HZ) /* RFC 1122 initial RTO value */
@@ -688,6 +692,10 @@ static __inline__ void tcp_delack_init(struct tcp_opt *tp)
memset(&tp->ack, 0, sizeof(tp->ack));
}
+static inline void tcp_clear_options(struct tcp_opt *tp)
+{
+ tp->tstamp_ok = tp->sack_ok = tp->wscale_ok = tp->snd_wscale = 0;
+}
enum tcp_tw_status
{
@@ -734,7 +742,8 @@ extern int tcp_recvmsg(struct sock *sk,
extern int tcp_listen_start(struct sock *sk);
extern void tcp_parse_options(struct sk_buff *skb,
- struct tcp_opt *tp);
+ struct tcp_opt *tp,
+ int estab);
/*
* TCP v4 functions exported for the inet6 API
@@ -997,6 +1006,9 @@ struct tcp_skb_cb {
#define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */
#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS)
+#define TCPCB_URG 0x20 /* Urgent pointer advenced here */
+
+#define TCPCB_AT_TAIL (TCPCB_URG)
__u16 urg_ptr; /* Valid w/URG flags is set. */
__u32 ack_seq; /* Sequence number ACK'd */
@@ -1134,18 +1146,19 @@ static __inline__ void tcp_minshall_update(struct tcp_opt *tp, int mss, struct s
/* Return 0, if packet can be sent now without violation Nagle's rules:
1. It is full sized.
- 2. Or it contains FIN or URG.
+ 2. Or it contains FIN.
3. Or TCP_NODELAY was set.
4. Or TCP_CORK is not set, and all sent packets are ACKed.
With Minshall's modification: all sent small packets are ACKed.
*/
-static __inline__ int tcp_nagle_check(struct tcp_opt *tp, struct sk_buff *skb, unsigned mss_now)
+static __inline__ int
+tcp_nagle_check(struct tcp_opt *tp, struct sk_buff *skb, unsigned mss_now, int nonagle)
{
return (skb->len < mss_now &&
- !(TCP_SKB_CB(skb)->flags & (TCPCB_FLAG_URG|TCPCB_FLAG_FIN)) &&
- (tp->nonagle == 2 ||
- (!tp->nonagle &&
+ !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+ (nonagle == 2 ||
+ (!nonagle &&
tp->packets_out &&
tcp_minshall_check(tp))));
}
@@ -1154,7 +1167,7 @@ static __inline__ int tcp_nagle_check(struct tcp_opt *tp, struct sk_buff *skb, u
* should be put on the wire right now.
*/
static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
- unsigned cur_mss, int tail)
+ unsigned cur_mss, int nonagle)
{
/* RFC 1122 - section 4.2.3.4
*
@@ -1180,8 +1193,8 @@ static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
/* Don't be strict about the congestion window for the
* final FIN frame. -DaveM
*/
- return ((!tail || !tcp_nagle_check(tp, skb, cur_mss) ||
- skb_tailroom(skb) < 32) &&
+ return ((nonagle==1 || tp->urg_mode
+ || !tcp_nagle_check(tp, skb, cur_mss, nonagle)) &&
((tcp_packets_in_flight(tp) < tp->snd_cwnd) ||
(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd));
@@ -1204,12 +1217,15 @@ static __inline__ int tcp_skb_is_last(struct sock *sk, struct sk_buff *skb)
*/
static __inline__ void __tcp_push_pending_frames(struct sock *sk,
struct tcp_opt *tp,
- unsigned cur_mss)
+ unsigned cur_mss,
+ int nonagle)
{
struct sk_buff *skb = tp->send_head;
if (skb) {
- if (!tcp_snd_test(tp, skb, cur_mss, tcp_skb_is_last(sk, skb)) ||
+ if (!tcp_skb_is_last(sk, skb))
+ nonagle = 1;
+ if (!tcp_snd_test(tp, skb, cur_mss, nonagle) ||
tcp_write_xmit(sk))
tcp_check_probe_timer(sk, tp);
}
@@ -1219,7 +1235,7 @@ static __inline__ void __tcp_push_pending_frames(struct sock *sk,
static __inline__ void tcp_push_pending_frames(struct sock *sk,
struct tcp_opt *tp)
{
- __tcp_push_pending_frames(sk, tp, tcp_current_mss(sk));
+ __tcp_push_pending_frames(sk, tp, tcp_current_mss(sk), tp->nonagle);
}
static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_opt *tp)
@@ -1227,7 +1243,8 @@ static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_opt *tp)
struct sk_buff *skb = tp->send_head;
return (skb &&
- tcp_snd_test(tp, skb, tcp_current_mss(sk), tcp_skb_is_last(sk, skb)));
+ tcp_snd_test(tp, skb, tcp_current_mss(sk),
+ tcp_skb_is_last(sk, skb) ? 1 : tp->nonagle));
}
static __inline__ void tcp_init_wl(struct tcp_opt *tp, u32 ack, u32 seq)
diff --git a/include/video/fbcon.h b/include/video/fbcon.h
index 332cabf7e..3dfb64435 100644
--- a/include/video/fbcon.h
+++ b/include/video/fbcon.h
@@ -290,13 +290,19 @@ static __inline__ void *fb_memclear_small(void *s, size_t count)
"1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
- "1: subql #1,%1 ; jcs 3f\n\t"
- "2: moveml %2/%3/%4/%5,%0@-\n\t"
+ "1:"
+ : "=a" (s), "=d" (count)
+ : "d" (0), "0" ((char *)s+count), "1" (count)
+ );
+ __asm__ __volatile__(
+ "subql #1,%1 ; jcs 3f\n\t"
+ "movel %2,%%d4; movel %2,%%d5; movel %2,%%d6\n\t"
+ "2: moveml %2/%%d4/%%d5/%%d6,%0@-\n\t"
"dbra %1,2b\n\t"
"3:"
: "=a" (s), "=d" (count)
- : "d" (0), "d" (0), "d" (0), "d" (0),
- "0" ((char *)s+count), "1" (count)
+ : "d" (0), "0" (s), "1" (count)
+ : "d4", "d5", "d6"
);
return(0);
@@ -355,13 +361,19 @@ static __inline__ void *fb_memset255(void *s, size_t count)
"1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
- "1: subql #1,%1 ; jcs 3f\n\t"
- "2: moveml %2/%3/%4/%5,%0@-\n\t"
+ "1:"
+ : "=a" (s), "=d" (count)
+ : "d" (-1), "0" ((char *)s+count), "1" (count)
+ );
+ __asm__ __volatile__(
+ "subql #1,%1 ; jcs 3f\n\t"
+ "movel %2,%%d4; movel %2,%%d5; movel %2,%%d6\n\t"
+ "2: moveml %2/%%d4/%%d5/%%d6,%0@-\n\t"
"dbra %1,2b\n\t"
"3:"
: "=a" (s), "=d" (count)
- : "d" (-1), "d" (-1), "d" (-1), "d" (-1),
- "0" ((char *) s + count), "1" (count)
+ : "d" (-1), "0" (s), "1" (count)
+ : "d4", "d5", "d6"
);
return(0);
diff --git a/init/main.c b/init/main.c
index 6d8d413f4..96bd23e60 100644
--- a/init/main.c
+++ b/init/main.c
@@ -51,8 +51,8 @@
extern int con3215_activate(void);
#endif
-#ifdef CONFIG_MAC
-extern void nubus_init(void);
+#ifdef CONFIG_NUBUS
+#include <linux/nubus.h>
#endif
#ifdef CONFIG_ISAPNP
@@ -80,8 +80,6 @@ extern void nubus_init(void);
extern char _stext, _etext;
extern char *linux_banner;
-extern int console_loglevel;
-
static int init(void *);
extern void init_IRQ(void);
@@ -255,7 +253,9 @@ static struct dev_name_struct {
{ "ida/c0d14p",0x48E0 },
{ "ida/c0d15p",0x48F0 },
#endif
-
+#ifdef CONFIG_NFTL
+ { "nftla", 0x5d00 },
+#endif
{ NULL, 0 }
};
@@ -684,7 +684,7 @@ static void __init do_basic_setup(void)
#ifdef CONFIG_DIO
dio_init();
#endif
-#ifdef CONFIG_MAC
+#ifdef CONFIG_NUBUS
nubus_init();
#endif
#ifdef CONFIG_ISAPNP
@@ -704,6 +704,7 @@ static void __init do_basic_setup(void)
else mount_initrd =0;
#endif
+ start_context_thread();
do_initcalls();
/* .. filesystems .. */
@@ -716,14 +717,6 @@ static void __init do_basic_setup(void)
init_pcmcia_ds(); /* Do this last */
#endif
-#ifdef CONFIG_HOTPLUG
- /* do this after other 'do this last' stuff, because we want
- * to minimize spurious executions of /sbin/hotplug
- * during boot-up
- */
- net_notifier_init();
-#endif
-
/* Mount the root filesystem.. */
mount_root();
diff --git a/ipc/shm.c b/ipc/shm.c
index c4607fd5e..195e9116c 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -129,7 +129,6 @@ static int shm_swapout(struct page *, struct file *);
static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
#endif
-static void zshm_swap (int prio, int gfp_mask);
static void zmap_unuse(swp_entry_t entry, struct page *page);
static void shmzero_open(struct vm_area_struct *shmd);
static void shmzero_close(struct vm_area_struct *shmd);
@@ -1374,13 +1373,39 @@ asmlinkage long sys_shmdt (char *shmaddr)
/*
* Enter the shm page into the SHM data structures.
*
- * The way "nopage" is done, we don't actually have to
- * do anything here: nopage will have filled in the shm
- * data structures already, and shm_swap_out() will just
- * work off them..
+ * This turns the physical page into a swap cache entry.
*/
static int shm_swapout(struct page * page, struct file *file)
{
+ struct shmid_kernel *shp;
+ struct inode * inode = file->f_dentry->d_inode;
+ swp_entry_t entry;
+ unsigned int idx;
+
+ idx = page->index;
+ entry = get_swap_page();
+ if (!entry.val)
+ return -ENOMEM;
+
+ /* Add it to the swap cache */
+ add_to_swap_cache(page, entry);
+ SetPageDirty(page);
+
+ /* Add it to the shm data structures */
+ swap_duplicate(entry); /* swap-cache and SHM_ENTRY */
+ shp = shm_lock(inode->i_ino);
+ SHM_ENTRY (shp, idx) = swp_entry_to_pte(entry);
+ shm_unlock(inode->i_ino);
+
+ /*
+ * We had one extra page count for the SHM_ENTRY.
+ * We just overwrote it, so we should free that
+ * count too (the VM layer will do an additional
+ * free that free's the page table count that
+ * it got rid of itself).
+ */
+ page_cache_free(page);
+
return 0;
}
@@ -1395,47 +1420,58 @@ static struct page * shm_nopage_core(struct shmid_kernel *shp, unsigned int idx,
if (idx >= shp->shm_npages)
return NOPAGE_SIGBUS;
+repeat:
+ /* Do we already have the page in memory? */
pte = SHM_ENTRY(shp,idx);
- if (!pte_present(pte)) {
- /* page not present so shm_swap can't race with us
- and the semaphore protects us by other tasks that
- could potentially fault on our pte under us */
- if (pte_none(pte)) {
- shm_unlock(shp->id);
- page = page_cache_alloc();
+ if (pte_present(pte)) {
+ /* Yes - just increment the page count */
+ page = pte_page(pte);
+ page_cache_get(page);
+ return page;
+ }
+
+ /* No, but maybe we ahve a page cache entry for it? */
+ if (!pte_none(pte)) {
+ swp_entry_t entry = pte_to_swp_entry(pte);
+
+ shm_unlock(shp->id);
+
+ /* Look it up or read it in.. */
+ page = lookup_swap_cache(entry);
+ if (!page) {
+ lock_kernel();
+ swapin_readahead(entry);
+ page = read_swap_cache(entry);
+ unlock_kernel();
if (!page)
goto oom;
- clear_user_highpage(page, address);
- if ((shp != shm_lock(shp->id)) && (shp->id != zero_id))
- BUG();
- } else {
- swp_entry_t entry = pte_to_swp_entry(pte);
-
- shm_unlock(shp->id);
- page = lookup_swap_cache(entry);
- if (!page) {
- lock_kernel();
- swapin_readahead(entry);
- page = read_swap_cache(entry);
- unlock_kernel();
- if (!page)
- goto oom;
- }
- delete_from_swap_cache(page);
- page = replace_with_highmem(page);
- swap_free(entry);
- if ((shp != shm_lock(shp->id)) && (shp->id != zero_id))
- BUG();
- (*swp)--;
}
- (*rss)++;
- pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
- SHM_ENTRY(shp, idx) = pte;
+ if ((shp != shm_lock(shp->id)) && (shp->id != zero_id))
+ BUG();
+ (*swp)--;
+ return page;
+ }
+
+ /* Ok, get a new page */
+ shm_unlock(shp->id);
+ page = page_cache_alloc();
+ if (!page)
+ goto oom;
+ clear_user_highpage(page, address);
+ if ((shp != shm_lock(shp->id)) && (shp->id != zero_id))
+ BUG();
+
+ page->index = idx;
+ /* Did somebody else allocate it while we slept? */
+ if (!pte_none(SHM_ENTRY(shp, idx))) {
+ page_cache_free(page);
+ goto repeat;
}
- /* pte_val(pte) == SHM_ENTRY (shp, idx) */
- page_cache_get(pte_page(pte));
- return pte_page(pte);
+ pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
+ SHM_ENTRY(shp, idx) = pte;
+ page_cache_get(page); /* one for the page table, once more for SHM_ENTRY */
+ return page;
oom:
shm_lock(shp->id);
@@ -1461,131 +1497,6 @@ static struct page * shm_nopage(struct vm_area_struct * shmd, unsigned long addr
return(page);
}
-#define OKAY 0
-#define RETRY 1
-#define FAILED 2
-
-static int shm_swap_core(struct shmid_kernel *shp, unsigned long idx, swp_entry_t swap_entry, int *counter, struct page **outpage)
-{
- pte_t page;
- struct page *page_map;
-
- page = SHM_ENTRY(shp, idx);
- if (!pte_present(page))
- return RETRY;
- page_map = pte_page(page);
- if (page_map->zone->free_pages > page_map->zone->pages_high)
- return RETRY;
- if (shp->id != zero_id) swap_attempts++;
-
- if (--*counter < 0) /* failed */
- return FAILED;
- if (page_count(page_map) != 1)
- return RETRY;
-
- lock_page(page_map);
- if (!(page_map = prepare_highmem_swapout(page_map)))
- return FAILED;
- SHM_ENTRY (shp, idx) = swp_entry_to_pte(swap_entry);
-
- /* add the locked page to the swap cache before allowing
- the swapin path to run lookup_swap_cache(). This avoids
- reading a not yet uptodate block from disk.
- NOTE: we just accounted the swap space reference for this
- swap cache page at __get_swap_page() time. */
- add_to_swap_cache(*outpage = page_map, swap_entry);
- return OKAY;
-}
-
-static void shm_swap_postop(struct page *page)
-{
- lock_kernel();
- rw_swap_page(WRITE, page, 0);
- unlock_kernel();
- page_cache_release(page);
-}
-
-static int shm_swap_preop(swp_entry_t *swap_entry)
-{
- lock_kernel();
- /* subtle: preload the swap count for the swap cache. We can't
- increase the count inside the critical section as we can't release
- the shm_lock there. And we can't acquire the big lock with the
- shm_lock held (otherwise we would deadlock too easily). */
- *swap_entry = __get_swap_page(2);
- if (!(*swap_entry).val) {
- unlock_kernel();
- return 1;
- }
- unlock_kernel();
- return 0;
-}
-
-/*
- * Goes through counter = (shm_rss >> prio) present shm pages.
- */
-static unsigned long swap_id; /* currently being swapped */
-static unsigned long swap_idx; /* next to swap */
-
-int shm_swap (int prio, int gfp_mask)
-{
- struct shmid_kernel *shp;
- swp_entry_t swap_entry;
- unsigned long id, idx;
- int loop = 0;
- int counter;
- struct page * page_map;
-
- /*
- * Push this inside:
- */
- if (!(gfp_mask & __GFP_IO))
- return 0;
-
- zshm_swap(prio, gfp_mask);
- counter = shm_rss >> prio;
- if (!counter)
- return 0;
- if (shm_swap_preop(&swap_entry))
- return 0;
-
- shm_lockall();
-check_id:
- shp = shm_get(swap_id);
- if(shp==NULL || shp->shm_flags & PRV_LOCKED) {
-next_id:
- swap_idx = 0;
- if (++swap_id > shm_ids.max_id) {
- swap_id = 0;
- if (loop) {
-failed:
- shm_unlockall();
- __swap_free(swap_entry, 2);
- return 0;
- }
- loop = 1;
- }
- goto check_id;
- }
- id = swap_id;
-
-check_table:
- idx = swap_idx++;
- if (idx >= shp->shm_npages)
- goto next_id;
-
- switch (shm_swap_core(shp, idx, swap_entry, &counter, &page_map)) {
- case RETRY: goto check_table;
- case FAILED: goto failed;
- }
- swap_successes++;
- shm_swp++;
- shm_rss--;
- shm_unlockall();
-
- shm_swap_postop(page_map);
- return 1;
-}
/*
* Free the swap entry and set the new pte for the shm page.
@@ -1712,7 +1623,6 @@ done:
#define VMA_TO_SHP(vma) ((vma)->vm_file->private_data)
static spinlock_t zmap_list_lock = SPIN_LOCK_UNLOCKED;
-static unsigned long zswap_idx; /* next to swap */
static struct shmid_kernel *zswap_shp = &zshmid_kernel;
static int zshm_rss;
@@ -1859,62 +1769,3 @@ static void zmap_unuse(swp_entry_t entry, struct page *page)
shm_unlock(zero_id);
spin_unlock(&zmap_list_lock);
}
-
-static void zshm_swap (int prio, int gfp_mask)
-{
- struct shmid_kernel *shp;
- swp_entry_t swap_entry;
- unsigned long idx;
- int loop = 0;
- int counter;
- struct page * page_map;
-
- counter = zshm_rss >> prio;
- if (!counter)
- return;
-next:
- if (shm_swap_preop(&swap_entry))
- return;
-
- spin_lock(&zmap_list_lock);
- shm_lock(zero_id);
- if (zshmid_kernel.zero_list.next == 0)
- goto failed;
-next_id:
- if (zswap_shp == &zshmid_kernel) {
- if (loop) {
-failed:
- shm_unlock(zero_id);
- spin_unlock(&zmap_list_lock);
- __swap_free(swap_entry, 2);
- return;
- }
- zswap_shp = list_entry(zshmid_kernel.zero_list.next,
- struct shmid_kernel, zero_list);
- zswap_idx = 0;
- loop = 1;
- }
- shp = zswap_shp;
-
-check_table:
- idx = zswap_idx++;
- if (idx >= shp->shm_npages) {
- zswap_shp = list_entry(zswap_shp->zero_list.next,
- struct shmid_kernel, zero_list);
- zswap_idx = 0;
- goto next_id;
- }
-
- switch (shm_swap_core(shp, idx, swap_entry, &counter, &page_map)) {
- case RETRY: goto check_table;
- case FAILED: goto failed;
- }
- shm_unlock(zero_id);
- spin_unlock(&zmap_list_lock);
-
- shm_swap_postop(page_map);
- if (counter)
- goto next;
- return;
-}
-
diff --git a/kernel/Makefile b/kernel/Makefile
index 8f4c218f3..311d66cb8 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -26,6 +26,13 @@ ifeq ($(CONFIG_PM),y)
OX_OBJS += pm.o
endif
+ifneq ($(CONFIG_IA64),y)
+# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
+# needed for x86 only. Why this used to be enabled for all architectures is beyond
+# me. I suspect most platforms don't need this, but until we know that for sure
+# I turn this off for IA-64 only. Andreas Schwab says it's also needed on m68k
+# to get a correct value for the wait-channel (WCHAN in ps). --davidm
CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
+endif
include $(TOPDIR)/Rules.make
diff --git a/kernel/context.c b/kernel/context.c
index b5219786a..864a70131 100644
--- a/kernel/context.c
+++ b/kernel/context.c
@@ -3,58 +3,155 @@
*
* Mechanism for running arbitrary tasks in process context
*
- * dwmw2@redhat.com
+ * dwmw2@redhat.com: Genesis
+ *
+ * andrewm@uow.edu.au: 2.4.0-test12
+ * - Child reaping
+ * - Support for tasks which re-add themselves
+ * - flush_scheduled_tasks.
*/
+#define __KERNEL_SYSCALLS__
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/unistd.h>
+#include <linux/signal.h>
static DECLARE_TASK_QUEUE(tq_context);
static DECLARE_WAIT_QUEUE_HEAD(context_task_wq);
+static DECLARE_WAIT_QUEUE_HEAD(context_task_done);
+static int keventd_running;
+static struct task_struct *keventd_task;
-void schedule_task(struct tq_struct *task)
+static int need_keventd(const char *who)
{
- queue_task(task, &tq_context);
- wake_up(&context_task_wq);
+ if (keventd_running == 0)
+ printk(KERN_ERR "%s(): keventd has not started\n", who);
+ return keventd_running;
+}
+
+int current_is_keventd(void)
+{
+ int ret = 0;
+ if (need_keventd(__FUNCTION__))
+ ret = (current == keventd_task);
+ return ret;
}
-EXPORT_SYMBOL(schedule_task);
+/**
+ * schedule_task - schedule a function for subsequent execution in process context.
+ * @task: pointer to a &tq_struct which defines the function to be scheduled.
+ *
+ * May be called from interrupt context. The scheduled function is run at some
+ * time in the near future by the keventd kernel thread. If it can sleep, it
+ * should be designed to do so for the minimum possible time, as it will be
+ * stalling all other scheduled tasks.
+ *
+ * schedule_task() returns non-zero if the task was successfully scheduled.
+ * If @task is already residing on a task queue then schedule_task() fails
+ * to schedule your task and returns zero.
+ */
+int schedule_task(struct tq_struct *task)
+{
+ int ret;
+ need_keventd(__FUNCTION__);
+ ret = queue_task(task, &tq_context);
+ wake_up(&context_task_wq);
+ return ret;
+}
static int context_thread(void *dummy)
{
- DECLARE_WAITQUEUE(wait, current);
+ struct task_struct *curtask = current;
+ DECLARE_WAITQUEUE(wait, curtask);
+ struct k_sigaction sa;
daemonize();
- strcpy(current->comm, "eventd");
+ strcpy(curtask->comm, "keventd");
+ keventd_running = 1;
+ keventd_task = curtask;
+
+ spin_lock_irq(&curtask->sigmask_lock);
+ siginitsetinv(&curtask->blocked, sigmask(SIGCHLD));
+ recalc_sigpending(curtask);
+ spin_unlock_irq(&curtask->sigmask_lock);
- spin_lock_irq(&current->sigmask_lock);
- sigfillset(&current->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(&current->sigmask_lock);
+ /* Install a handler so SIGCLD is delivered */
+ sa.sa.sa_handler = SIG_IGN;
+ sa.sa.sa_flags = 0;
+ siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
+ do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
+ /*
+ * If one of the functions on a task queue re-adds itself
+ * to the task queue we call schedule() in state TASK_RUNNING
+ */
for (;;) {
- current->state = TASK_INTERRUPTIBLE;
+ set_task_state(curtask, TASK_INTERRUPTIBLE);
add_wait_queue(&context_task_wq, &wait);
-
- /*
- * Careful: we depend on the wait-queue modifications
- * to also act as memory barriers.
- */
- if (!tq_context)
- schedule();
-
+ if (TQ_ACTIVE(tq_context))
+ set_task_state(curtask, TASK_RUNNING);
+ schedule();
remove_wait_queue(&context_task_wq, &wait);
- current->state = TASK_RUNNING;
run_task_queue(&tq_context);
+ wake_up(&context_task_done);
+ if (signal_pending(curtask)) {
+ while (waitpid(-1, (unsigned int *)0, __WALL|WNOHANG) > 0)
+ ;
+ flush_signals(curtask);
+ recalc_sigpending(curtask);
+ }
}
}
-static int __init start_context_thread(void)
+/**
+ * flush_scheduled_tasks - ensure that any scheduled tasks have run to completion.
+ *
+ * Forces execution of the schedule_task() queue and blocks until its completion.
+ *
+ * If a kernel subsystem uses schedule_task() and wishes to flush any pending
+ * tasks, it should use this function. This is typically used in driver shutdown
+ * handlers.
+ *
+ * The caller should hold no spinlocks and should hold no semaphores which could
+ * cause the scheduled tasks to block.
+ */
+static struct tq_struct dummy_task;
+
+void flush_scheduled_tasks(void)
+{
+ int count;
+ DECLARE_WAITQUEUE(wait, current);
+
+ /*
+ * Do it twice. It's possible, albeit highly unlikely, that
+ * the caller queued a task immediately before calling us,
+ * and that the eventd thread was already past the run_task_queue()
+ * but not yet into wake_up(), so it woke us up before completing
+ * the caller's queued task or our new dummy task.
+ */
+ add_wait_queue(&context_task_done, &wait);
+ for (count = 0; count < 2; count++) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+
+ /* Queue a dummy task to make sure we get kicked */
+ schedule_task(&dummy_task);
+
+ /* Wait for it to complete */
+ schedule();
+ }
+ remove_wait_queue(&context_task_done, &wait);
+}
+
+int start_context_thread(void)
{
kernel_thread(context_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
return 0;
}
-module_init(start_context_thread);
+EXPORT_SYMBOL(schedule_task);
+EXPORT_SYMBOL(flush_scheduled_tasks);
+
diff --git a/kernel/dma.c b/kernel/dma.c
index 983dedb60..3ee09759f 100644
--- a/kernel/dma.c
+++ b/kernel/dma.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <asm/dma.h>
#include <asm/system.h>
diff --git a/kernel/exit.c b/kernel/exit.c
index 33b68980b..99d4f6770 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -22,7 +22,7 @@ extern struct task_struct *child_reaper;
int getrusage(struct task_struct *, int, struct rusage *);
-void release(struct task_struct * p)
+void release_task(struct task_struct * p)
{
if (p != current) {
#ifdef CONFIG_SMP
@@ -31,15 +31,15 @@ void release(struct task_struct * p)
* runqueue (active on some other CPU still)
*/
for (;;) {
- spin_lock_irq(&runqueue_lock);
+ task_lock(p);
if (!p->has_cpu)
break;
- spin_unlock_irq(&runqueue_lock);
+ task_unlock(p);
do {
barrier();
} while (p->has_cpu);
}
- spin_unlock_irq(&runqueue_lock);
+ task_unlock(p);
#endif
atomic_dec(&p->user->processes);
free_uid(p->user);
@@ -302,9 +302,9 @@ static inline void __exit_mm(struct task_struct * tsk)
{
struct mm_struct * mm = tsk->mm;
+ mm_release();
if (mm) {
atomic_inc(&mm->mm_count);
- mm_release();
if (mm != tsk->active_mm) BUG();
/* more a memory barrier than a real lock */
task_lock(tsk);
@@ -550,7 +550,7 @@ repeat:
do_notify_parent(p, SIGCHLD);
write_unlock_irq(&tasklist_lock);
} else
- release(p);
+ release_task(p);
goto end_wait4;
default:
continue;
diff --git a/kernel/fork.c b/kernel/fork.c
index d85c3494a..bf3e36cfb 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -196,6 +196,7 @@ fail_nomem:
}
#define allocate_mm() (kmem_cache_alloc(mm_cachep, SLAB_KERNEL))
+#define free_mm(mm) (kmem_cache_free(mm_cachep, (mm)))
static struct mm_struct * mm_init(struct mm_struct * mm)
{
@@ -206,7 +207,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
mm->pgd = pgd_alloc();
if (mm->pgd)
return mm;
- kmem_cache_free(mm_cachep, mm);
+ free_mm(mm);
return NULL;
}
@@ -236,7 +237,7 @@ inline void __mmdrop(struct mm_struct *mm)
if (mm == &init_mm) BUG();
pgd_free(mm->pgd);
destroy_context(mm);
- kmem_cache_free(mm_cachep, mm);
+ free_mm(mm);
}
/*
@@ -541,7 +542,7 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
* arch/ia64/kernel/process.c.
*/
int do_fork(unsigned long clone_flags, unsigned long stack_start,
- struct pt_regs *regs, unsigned long stack_top)
+ struct pt_regs *regs, unsigned long stack_size)
{
int retval = -ENOMEM;
struct task_struct *p;
@@ -636,7 +637,7 @@ 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;
- retval = copy_thread(0, clone_flags, stack_start, stack_top, p, regs);
+ retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
if (retval)
goto bad_fork_cleanup_sighand;
p->semundo = NULL;
diff --git a/kernel/kmod.c b/kernel/kmod.c
index a21507eec..b68392685 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/unistd.h>
+#include <linux/kmod.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
@@ -165,7 +166,7 @@ static int exec_modprobe(void * module_name)
int request_module(const char * module_name)
{
- int pid;
+ pid_t pid;
int waitpid_result;
sigset_t tmpsig;
int i;
@@ -256,43 +257,105 @@ EXPORT_SYMBOL(hotplug_path);
#endif /* CONFIG_HOTPLUG */
+struct subprocess_info {
+ struct semaphore *sem;
+ char *path;
+ char **argv;
+ char **envp;
+ pid_t retval;
+};
-static int exec_helper (void *arg)
+/*
+ * This is the task which runs the usermode application
+ */
+static int ____call_usermodehelper(void *data)
{
- void **params = (void **) arg;
- char *path = (char *) params [0];
- char **argv = (char **) params [1];
- char **envp = (char **) params [2];
- return exec_usermodehelper (path, argv, envp);
-}
+ struct subprocess_info *sub_info = data;
+ int retval;
+ retval = -EPERM;
+ if (current->fs->root)
+ retval = exec_usermodehelper(sub_info->path, sub_info->argv, sub_info->envp);
-int call_usermodehelper (char *path, char **argv, char **envp)
+ /* Exec failed? */
+ sub_info->retval = (pid_t)retval;
+ do_exit(0);
+}
+
+/*
+ * This is run by keventd.
+ */
+static void __call_usermodehelper(void *data)
{
- void *params [3] = { path, argv, envp };
- int pid, pid2, retval;
- mm_segment_t fs;
+ struct subprocess_info *sub_info = data;
+ pid_t pid;
- if ( ! current->fs->root ) {
- printk(KERN_ERR "call_usermodehelper[%s]: no root fs\n",
- path);
- return -EPERM;
- }
- if ((pid = kernel_thread (exec_helper, (void *) params, 0)) < 0) {
- printk(KERN_ERR "failed fork %s, errno = %d", argv [0], -pid);
- return -1;
+ /*
+ * CLONE_VFORK: wait until the usermode helper has execve'd successfully
+ * We need the data structures to stay around until that is done.
+ */
+ pid = kernel_thread(____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD);
+ if (pid < 0)
+ sub_info->retval = pid;
+ up(sub_info->sem);
+}
+
+/**
+ * call_usermodehelper - start a usermode application
+ * @path: pathname for the application
+ * @argv: null-terminated argument list
+ * @envp: null-terminated environment list
+ *
+ * Runs a user-space application. The application is started asynchronously. It
+ * runs as a child of keventd. It runs with full root capabilities. keventd silently
+ * reaps the child when it exits.
+ *
+ * Must be called from process context. Returns zero on success, else a negative
+ * error code.
+ */
+int call_usermodehelper(char *path, char **argv, char **envp)
+{
+ DECLARE_MUTEX_LOCKED(sem);
+ struct subprocess_info sub_info = {
+ sem: &sem,
+ path: path,
+ argv: argv,
+ envp: envp,
+ retval: 0,
+ };
+ struct tq_struct tqs = {
+ routine: __call_usermodehelper,
+ data: &sub_info,
+ };
+
+ if (path[0] == '\0')
+ goto out;
+
+ if (current_is_keventd()) {
+ /* We can't wait on keventd! */
+ __call_usermodehelper(&sub_info);
+ } else {
+ schedule_task(&tqs);
+ down(&sem); /* Wait until keventd has started the subprocess */
}
+out:
+ return sub_info.retval;
+}
- fs = get_fs ();
- set_fs (KERNEL_DS);
- pid2 = waitpid (pid, &retval, __WCLONE);
- set_fs (fs);
+/*
+ * This is for the serialisation of device probe() functions
+ * against device open() functions
+ */
+static DECLARE_MUTEX(dev_probe_sem);
- if (pid2 != pid) {
- printk(KERN_ERR "waitpid(%d) failed, %d\n", pid, pid2);
- return -1;
- }
- return retval;
+void dev_probe_lock(void)
+{
+ down(&dev_probe_sem);
+}
+
+void dev_probe_unlock(void)
+{
+ up(&dev_probe_sem);
}
EXPORT_SYMBOL(exec_usermodehelper);
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index 100adaeb3..4ed94117e 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -53,7 +53,6 @@
#include <linux/kmod.h>
#endif
-extern int console_loglevel;
extern void set_device_ro(kdev_t dev,int flag);
extern void *sys_call_table;
@@ -175,6 +174,7 @@ EXPORT_SYMBOL(invalidate_inode_pages);
EXPORT_SYMBOL(truncate_inode_pages);
EXPORT_SYMBOL(fsync_dev);
EXPORT_SYMBOL(permission);
+EXPORT_SYMBOL(vfs_permission);
EXPORT_SYMBOL(inode_setattr);
EXPORT_SYMBOL(inode_change_ok);
EXPORT_SYMBOL(write_inode_now);
@@ -185,7 +185,6 @@ EXPORT_SYMBOL(getblk);
EXPORT_SYMBOL(bdget);
EXPORT_SYMBOL(bdput);
EXPORT_SYMBOL(bread);
-EXPORT_SYMBOL(breada);
EXPORT_SYMBOL(__brelse);
EXPORT_SYMBOL(__bforget);
EXPORT_SYMBOL(ll_rw_block);
@@ -369,7 +368,6 @@ EXPORT_SYMBOL(del_timer_sync);
EXPORT_SYMBOL(mod_timer);
EXPORT_SYMBOL(tq_timer);
EXPORT_SYMBOL(tq_immediate);
-EXPORT_SYMBOL(tq_scheduler);
#ifdef CONFIG_SMP
/* Various random spinlocks we want to export */
diff --git a/kernel/module.c b/kernel/module.c
index e89149de9..dd02b40cd 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -100,7 +100,8 @@ void inter_module_register(const char *im_name, struct module *owner, const void
spin_unlock(&ime_lock);
kfree(ime_new);
/* Program logic error, fatal */
- panic("inter_module_register: duplicate im_name '%s'", im_name);
+ printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);
+ BUG();
}
}
list_add(&(ime_new->list), &ime_list);
@@ -140,7 +141,8 @@ void inter_module_unregister(const char *im_name)
}
else {
/* Program logic error, fatal */
- panic("inter_module_unregister: no entry for '%s'", im_name);
+ printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);
+ BUG();
}
}
@@ -211,7 +213,8 @@ void inter_module_put(const char *im_name)
}
}
spin_unlock(&ime_lock);
- panic("inter_module_put: no entry for '%s'", im_name);
+ printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);
+ BUG();
}
@@ -480,7 +483,9 @@ sys_init_module(const char *name_user, struct module *mod_user)
/* Ok, that's about all the sanity we can stomach; copy the rest. */
- if (copy_from_user(mod+1, mod_user+1, mod->size-sizeof(*mod))) {
+ if (copy_from_user((char *)mod+mod_user_size,
+ (char *)mod_user+mod_user_size,
+ mod->size-mod_user_size)) {
error = -EFAULT;
goto err3;
}
diff --git a/kernel/sched.c b/kernel/sched.c
index 119edeb81..1299c8365 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -197,7 +197,7 @@ static inline int preemption_goodness(struct task_struct * prev, struct task_str
/*
* This is ugly, but reschedule_idle() is very timing-critical.
- * We `are called with the runqueue spinlock held and we must
+ * We are called with the runqueue spinlock held and we must
* not claim the tasklist_lock.
*/
static FASTCALL(void reschedule_idle(struct task_struct * p));
@@ -272,8 +272,10 @@ send_now_idle:
}
tsk = target_tsk;
if (tsk) {
- if (oldest_idle != -1ULL)
+ if (oldest_idle != -1ULL) {
+ best_cpu = tsk->processor;
goto send_now_idle;
+ }
tsk->need_resched = 1;
if (tsk->processor != this_cpu)
smp_send_reschedule(tsk->processor);
@@ -452,7 +454,7 @@ static inline void __schedule_tail(struct task_struct *prev)
goto needs_resched;
out_unlock:
- task_unlock(prev);
+ task_unlock(prev); /* Synchronise here with release_task() if prev is TASK_ZOMBIE */
return;
/*
@@ -511,10 +513,7 @@ asmlinkage void schedule(void)
int this_cpu, c;
if (!current->active_mm) BUG();
- if (tq_scheduler)
- goto handle_tq_scheduler;
-tq_scheduler_back:
-
+need_resched_back:
prev = current;
this_cpu = prev->processor;
@@ -652,7 +651,7 @@ still_running_back:
same_process:
reacquire_kernel_lock(current);
if (current->need_resched)
- goto tq_scheduler_back;
+ goto need_resched_back;
return;
@@ -677,15 +676,6 @@ handle_softirq:
do_softirq();
goto handle_softirq_back;
-handle_tq_scheduler:
- /*
- * do not run the task queue with disabled interrupts,
- * cli() wouldn't work on SMP
- */
- sti();
- run_task_queue(&tq_scheduler);
- goto tq_scheduler_back;
-
move_rr_last:
if (!prev->counter) {
prev->counter = NICE_TO_TICKS(prev->nice);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 5591ee2bc..3fdf03c34 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -41,7 +41,7 @@
/* External variables not in a header file. */
extern int panic_timeout;
-extern int console_loglevel, C_A_D;
+extern int C_A_D;
extern int bdf_prm[], bdflush_min[], bdflush_max[];
extern int sysctl_overcommit_memory;
extern int max_threads;
diff --git a/kernel/timer.c b/kernel/timer.c
index e67783a30..579b065f3 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -39,7 +39,6 @@ int tickadj = 500/HZ ? : 1; /* microsecs */
DECLARE_TASK_QUEUE(tq_timer);
DECLARE_TASK_QUEUE(tq_immediate);
-DECLARE_TASK_QUEUE(tq_scheduler);
/*
* phase-lock loop variables
@@ -681,7 +680,7 @@ void do_timer(struct pt_regs *regs)
update_process_times(user_mode(regs));
#endif
mark_bh(TIMER_BH);
- if (tq_timer)
+ if (TQ_ACTIVE(tq_timer))
mark_bh(TQUEUE_BH);
}
diff --git a/kernel/user.c b/kernel/user.c
index d033c9659..be99b110e 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -8,7 +8,6 @@
* able to have per-user limits for system resources.
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -74,29 +73,12 @@ static inline struct user_struct *uid_hash_find(uid_t uid, struct user_struct **
}
}
-/*
- * For SMP, we need to re-test the user struct counter
- * after having acquired the spinlock. This allows us to do
- * the common case (not freeing anything) without having
- * any locking.
- */
-#ifdef CONFIG_SMP
- #define uid_hash_free(up) (!atomic_read(&(up)->__count))
-#else
- #define uid_hash_free(up) (1)
-#endif
-
void free_uid(struct user_struct *up)
{
- if (up) {
- if (atomic_dec_and_test(&up->__count)) {
- spin_lock(&uidhash_lock);
- if (uid_hash_free(up)) {
- uid_hash_remove(up);
- kmem_cache_free(uid_cachep, up);
- }
- spin_unlock(&uidhash_lock);
- }
+ if (up && atomic_dec_and_lock(&up->__count, &uidhash_lock)) {
+ uid_hash_remove(up);
+ kmem_cache_free(uid_cachep, up);
+ spin_unlock(&uidhash_lock);
}
}
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 3367fc3e1..0c3a29536 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -48,6 +48,38 @@ long simple_strtol(const char *cp,char **endp,unsigned int base)
return simple_strtoul(cp,endp,base);
}
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper(*cp) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+long long simple_strtoll(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoull(cp+1,endp,base);
+ return simple_strtoull(cp,endp,base);
+}
+
static int skip_atoi(const char **s)
{
int i=0;
diff --git a/mm/filemap.c b/mm/filemap.c
index a191cc2f4..ec8ff8ac7 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1469,15 +1469,15 @@ page_not_uptodate:
* The "mapping" test takes care of somebody having truncated the
* page and thus made this write-page a no-op..
*/
-static int filemap_write_page(struct file *file,
- struct page * page,
- int wait)
+static int filemap_write_page(struct page * page, int wait)
{
struct address_space * mapping = page->mapping;
int error = 0;
- if (mapping)
- error = mapping->a_ops->writepage(file, page);
+ if (mapping && mapping->a_ops->writepage) {
+ ClearPageDirty(page);
+ error = mapping->a_ops->writepage(page);
+ }
return error;
}
@@ -1488,11 +1488,10 @@ static int filemap_write_page(struct file *file,
* at the same time..
*/
extern void wakeup_bdflush(int);
-int filemap_swapout(struct page * page, struct file * file)
+int filemap_swapout(struct page * page, struct file *file)
{
- int retval = filemap_write_page(file, page, 0);
- wakeup_bdflush(0);
- return retval;
+ SetPageDirty(page);
+ return 0;
}
/* Called with mm->page_table_lock held to protect against other
@@ -1501,56 +1500,26 @@ int filemap_swapout(struct page * page, struct file * file)
static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
unsigned long address, unsigned int flags)
{
- unsigned long pgoff;
pte_t pte;
struct page *page;
int error;
pte = *ptep;
- if (!(flags & MS_INVALIDATE)) {
- if (!pte_present(pte))
- goto out;
- if (!ptep_test_and_clear_dirty(ptep))
- goto out;
- flush_page_to_ram(pte_page(pte));
- flush_cache_page(vma, address);
- flush_tlb_page(vma, address);
- page = pte_page(pte);
- page_cache_get(page);
- } else {
- if (pte_none(pte))
- goto out;
- flush_cache_page(vma, address);
-
- pte = ptep_get_and_clear(ptep);
- flush_tlb_page(vma, address);
-
- if (!pte_present(pte)) {
- spin_unlock(&vma->vm_mm->page_table_lock);
- swap_free(pte_to_swp_entry(pte));
- spin_lock(&vma->vm_mm->page_table_lock);
- goto out;
- }
- page = pte_page(pte);
- if (!pte_dirty(pte) || flags == MS_INVALIDATE) {
- page_cache_free(page);
- goto out;
- }
- }
- pgoff = (address - vma->vm_start) >> PAGE_CACHE_SHIFT;
- pgoff += vma->vm_pgoff;
- if (page->index != pgoff) {
- printk("weirdness: pgoff=%lu index=%lu address=%lu vm_start=%lu vm_pgoff=%lu\n",
- pgoff, page->index, address, vma->vm_start, vma->vm_pgoff);
- }
+ if (!pte_present(pte))
+ goto out;
+ if (!ptep_test_and_clear_dirty(ptep))
+ goto out;
+ flush_page_to_ram(pte_page(pte));
+ flush_cache_page(vma, address);
+ flush_tlb_page(vma, address);
+ page = pte_page(pte);
+ page_cache_get(page);
spin_unlock(&vma->vm_mm->page_table_lock);
- lock_page(page);
-
- error = filemap_write_page(vma->vm_file, page, 1);
- UnlockPage(page);
+ lock_page(page);
+ error = filemap_write_page(page, 1);
page_cache_free(page);
spin_lock(&vma->vm_mm->page_table_lock);
@@ -1649,20 +1618,11 @@ int filemap_sync(struct vm_area_struct * vma, unsigned long address,
}
/*
- * This handles (potentially partial) area unmaps..
- */
-static void filemap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
-{
- filemap_sync(vma, start, len, MS_ASYNC);
-}
-
-/*
* Shared mappings need to be able to do the right thing at
* close/unmap/sync. They will also use the private file as
* backing-store for swapping..
*/
static struct vm_operations_struct file_shared_mmap = {
- unmap: filemap_unmap, /* unmap - we need to sync the pages */
sync: filemap_sync,
nopage: filemap_nopage,
swapout: filemap_swapout,
@@ -2462,7 +2422,7 @@ generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
if (count) {
remove_suid(inode);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- mark_inode_dirty(inode);
+ mark_inode_dirty_sync(inode);
}
while (count) {
@@ -2521,8 +2481,14 @@ unlock:
if (cached_page)
page_cache_free(cached_page);
+ /* For now, when the user asks for O_SYNC, we'll actually
+ * provide O_DSYNC. */
+ if ((status >= 0) && (file->f_flags & O_SYNC))
+ status = generic_osync_inode(inode, 1); /* 1 means datasync */
+
err = written ? written : status;
out:
+
up(&inode->i_sem);
return err;
fail_write:
diff --git a/mm/highmem.c b/mm/highmem.c
index 5e8ebde4b..7935d1280 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -23,77 +23,6 @@
#include <linux/slab.h>
/*
- * Take one locked page, return another low-memory locked page.
- */
-struct page * prepare_highmem_swapout(struct page * page)
-{
- struct page *new_page;
- unsigned long regular_page;
-
- /*
- * If this is a highmem page so it can't be swapped out directly
- * otherwise the b_data buffer addresses will break
- * the lowlevel device drivers.
- */
- if (!PageHighMem(page))
- return page;
-
- /*
- * Here we break the page lock, and we split the
- * dirty page into two. We can unlock the old page,
- * and we'll now have two of them. Too bad, it would
- * have been nice to continue to potentially share
- * across a fork().
- */
- UnlockPage(page);
- regular_page = __get_free_page(GFP_ATOMIC);
- if (!regular_page)
- return NULL;
-
- copy_page((void *)regular_page, kmap(page));
- kunmap(page);
-
- /*
- * ok, we can just forget about our highmem page since
- * we stored its data into the new regular_page.
- */
- page_cache_release(page);
- new_page = virt_to_page(regular_page);
- LockPage(new_page);
- return new_page;
-}
-
-struct page * replace_with_highmem(struct page * page)
-{
- struct page *highpage;
-
- if (PageHighMem(page) || !nr_free_highpages())
- return page;
-
- highpage = alloc_page(GFP_ATOMIC|__GFP_HIGHMEM);
- if (!highpage)
- return page;
- if (!PageHighMem(highpage)) {
- page_cache_release(highpage);
- return page;
- }
-
- copy_page(kmap(highpage), page_address(page));
- kunmap(highpage);
-
- if (page->mapping)
- BUG();
-
- /*
- * We can just forget the old page since
- * we stored its data into the new highmem-page.
- */
- page_cache_release(page);
-
- return highpage;
-}
-
-/*
* Virtual_count is not a pure "count".
* 0 means that it is not mapped, and has not been mapped
* since a TLB flush - it is usable.
diff --git a/mm/memory.c b/mm/memory.c
index d6b8f6371..13dad21a0 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -227,7 +227,7 @@ skip_copy_pte_range: address = (address + PMD_SIZE) & PMD_MASK;
/* If it's a COW mapping, write protect it both in the parent and the child */
if (cow) {
- ptep_clear_wrprotect(src_pte);
+ ptep_set_wrprotect(src_pte);
pte = *src_pte;
}
@@ -269,6 +269,8 @@ static inline int free_pte(pte_t page)
* free_page() used to be able to clear swap cache
* entries. We may now have to do it manually.
*/
+ if (pte_dirty(page))
+ SetPageDirty(ptpage);
free_page_and_swap_cache(ptpage);
return 1;
}
@@ -829,8 +831,9 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
* - we're the only user (count == 1)
* - the only other user is the swap cache,
* and the only swap cache user is itself,
- * in which case we can remove the page
- * from the swap cache.
+ * in which case we can just continue to
+ * use the same swap cache (it will be
+ * marked dirty).
*/
switch (page_count(old_page)) {
case 2:
@@ -845,7 +848,6 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
UnlockPage(old_page);
break;
}
- delete_from_swap_cache_nolock(old_page);
UnlockPage(old_page);
/* FallThrough */
case 1:
@@ -885,45 +887,6 @@ bad_wp_page:
return -1;
}
-/*
- * This function zeroes out partial mmap'ed pages at truncation time..
- */
-static void partial_clear(struct vm_area_struct *vma, unsigned long address)
-{
- unsigned int offset;
- struct page *page;
- pgd_t *page_dir;
- pmd_t *page_middle;
- pte_t *page_table, pte;
-
- page_dir = pgd_offset(vma->vm_mm, address);
- if (pgd_none(*page_dir))
- return;
- if (pgd_bad(*page_dir)) {
- pgd_ERROR(*page_dir);
- pgd_clear(page_dir);
- return;
- }
- page_middle = pmd_offset(page_dir, address);
- if (pmd_none(*page_middle))
- return;
- if (pmd_bad(*page_middle)) {
- pmd_ERROR(*page_middle);
- pmd_clear(page_middle);
- return;
- }
- page_table = pte_offset(page_middle, address);
- pte = *page_table;
- if (!pte_present(pte))
- return;
- flush_cache_page(vma, address);
- page = pte_page(pte);
- if ((!VALID_PAGE(page)) || PageReserved(page))
- return;
- offset = address & ~PAGE_MASK;
- memclear_highpage_flush(page, offset, PAGE_SIZE - offset);
-}
-
static void vmtruncate_list(struct vm_area_struct *mpnt,
unsigned long pgoff, unsigned long partial)
{
@@ -951,10 +914,6 @@ static void vmtruncate_list(struct vm_area_struct *mpnt,
/* Ok, partially affected.. */
start += diff << PAGE_SHIFT;
len = (len - diff) << PAGE_SHIFT;
- if (start & ~PAGE_MASK) {
- partial_clear(mpnt, start);
- start = (start + ~PAGE_MASK) & PAGE_MASK;
- }
flush_cache_range(mm, start, end);
zap_page_range(mm, start, len);
flush_tlb_range(mm, start, end);
@@ -1085,14 +1044,9 @@ static int do_swap_page(struct mm_struct * mm,
*/
lock_page(page);
swap_free(entry);
- if (write_access && !is_page_shared(page)) {
- delete_from_swap_cache_nolock(page);
- UnlockPage(page);
- page = replace_with_highmem(page);
- pte = mk_pte(page, vma->vm_page_prot);
+ if (write_access && !is_page_shared(page))
pte = pte_mkwrite(pte_mkdirty(pte));
- } else
- UnlockPage(page);
+ UnlockPage(page);
set_pte(page_table, pte);
/* No need to invalidate - it was non-present before */
diff --git a/mm/mmap.c b/mm/mmap.c
index da649f2a2..648cc5208 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -354,11 +354,11 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned lon
lock_vma_mappings(vma);
spin_lock(&mm->page_table_lock);
__insert_vm_struct(mm, vma);
+ unlock_vma_mappings(vma);
if (correct_wcount)
atomic_inc(&file->f_dentry->d_inode->i_writecount);
merge_segments(mm, vma->vm_start, vma->vm_end);
spin_unlock(&mm->page_table_lock);
- unlock_vma_mappings(vma);
mm->total_vm += len >> PAGE_SHIFT;
if (flags & VM_LOCKED) {
@@ -858,9 +858,9 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
lock_vma_mappings(vma);
spin_lock(&mm->page_table_lock);
__insert_vm_struct(mm, vma);
+ unlock_vma_mappings(vma);
merge_segments(mm, vma->vm_start, vma->vm_end);
spin_unlock(&mm->page_table_lock);
- unlock_vma_mappings(vma);
mm->total_vm += len >> PAGE_SHIFT;
if (flags & VM_LOCKED) {
@@ -1034,20 +1034,23 @@ void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned l
avl_remove(mpnt, &mm->mmap_avl);
prev->vm_end = mpnt->vm_end;
prev->vm_next = mpnt->vm_next;
+ mm->map_count--;
if (mpnt->vm_ops && mpnt->vm_ops->close) {
mpnt->vm_pgoff += (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
mpnt->vm_start = mpnt->vm_end;
spin_unlock(&mm->page_table_lock);
- unlock_vma_mappings(mpnt);
mpnt->vm_ops->close(mpnt);
- lock_vma_mappings(mpnt);
- spin_lock(&mm->page_table_lock);
- }
- mm->map_count--;
+ } else
+ spin_unlock(&mm->page_table_lock);
+
+ lock_vma_mappings(mpnt);
__remove_shared_vm_struct(mpnt);
+ unlock_vma_mappings(mpnt);
if (mpnt->vm_file)
fput(mpnt->vm_file);
kmem_cache_free(vm_area_cachep, mpnt);
mpnt = prev;
+
+ spin_lock(&mm->page_table_lock);
}
}
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 64c178b31..e47987f1e 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -10,6 +10,7 @@
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
static inline void change_pte_range(pmd_t * pmd, unsigned long address,
unsigned long size, pgprot_t newprot)
diff --git a/mm/mremap.c b/mm/mremap.c
index 764cfabb8..bdbcf4841 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -144,9 +144,9 @@ static inline unsigned long move_vma(struct vm_area_struct * vma,
lock_vma_mappings(vma);
spin_lock(&current->mm->page_table_lock);
__insert_vm_struct(current->mm, new_vma);
+ unlock_vma_mappings(vma);
merge_segments(current->mm, new_vma->vm_start, new_vma->vm_end);
spin_unlock(&current->mm->page_table_lock);
- unlock_vma_mappings(vma);
do_munmap(current->mm, addr, old_len);
current->mm->total_vm += new_len >> PAGE_SHIFT;
if (new_vma->vm_flags & VM_LOCKED) {
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 90c077439..dca35de59 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -90,8 +90,6 @@ static void __free_pages_ok (struct page *page, unsigned long order)
BUG();
if (PageDecrAfter(page))
BUG();
- if (PageDirty(page))
- BUG();
if (PageActive(page))
BUG();
if (PageInactiveDirty(page))
@@ -99,7 +97,7 @@ static void __free_pages_ok (struct page *page, unsigned long order)
if (PageInactiveClean(page))
BUG();
- page->flags &= ~(1<<PG_referenced);
+ page->flags &= ~((1<<PG_referenced) | (1<<PG_dirty));
page->age = PAGE_AGE_START;
zone = page->zone;
diff --git a/mm/swap.c b/mm/swap.c
index b4b9f76be..693773ccd 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -180,33 +180,9 @@ void deactivate_page_nolock(struct page * page)
* Don't touch it if it's not on the active list.
* (some pages aren't on any list at all)
*/
- if (PageActive(page) && page_count(page) <= maxcount &&
- !page_ramdisk(page)) {
-
- /*
- * We can move the page to the inactive_dirty list
- * if we have the strong suspicion that they might
- * become freeable in the near future.
- *
- * That is, the page has buffer heads attached (that
- * need to be cleared away) and/or the function calling
- * us has an extra reference count on the page.
- */
- if (page->buffers || page_count(page) == 2) {
- del_page_from_active_list(page);
- add_page_to_inactive_dirty_list(page);
- /*
- * Only if we are SURE the page is clean and immediately
- * reusable, we move it to the inactive_clean list.
- */
- } else if (page->mapping && !PageDirty(page) &&
- !PageLocked(page)) {
- del_page_from_active_list(page);
- add_page_to_inactive_clean_list(page);
- }
- /*
- * OK, we cannot free the page. Leave it alone.
- */
+ if (PageActive(page) && page_count(page) <= maxcount && !page_ramdisk(page)) {
+ del_page_from_active_list(page);
+ add_page_to_inactive_dirty_list(page);
}
}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 3a91d955e..df45b34af 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -17,8 +17,15 @@
#include <asm/pgtable.h>
+static int swap_writepage(struct page *page)
+{
+ rw_swap_page(WRITE, page, 0);
+ return 0;
+}
+
static struct address_space_operations swap_aops = {
- sync_page: block_sync_page
+ writepage: swap_writepage,
+ sync_page: block_sync_page,
};
struct address_space swapper_space = {
@@ -106,6 +113,7 @@ void delete_from_swap_cache_nolock(struct page *page)
lru_cache_del(page);
spin_lock(&pagecache_lock);
+ ClearPageDirty(page);
__delete_from_swap_cache(page);
spin_unlock(&pagecache_lock);
page_cache_release(page);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 339cffb5b..62ce5f1ff 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -215,8 +215,8 @@ void vfree(void * addr)
if (tmp->addr == addr) {
*p = tmp->next;
vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
- kfree(tmp);
write_unlock(&vmlist_lock);
+ kfree(tmp);
return;
}
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index dd92afecc..46eb771af 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -91,6 +91,9 @@ static int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, un
*/
if (PageSwapCache(page)) {
entry.val = page->index;
+ if (pte_dirty(pte))
+ SetPageDirty(page);
+set_swap_pte:
swap_duplicate(entry);
set_pte(page_table, swp_entry_to_pte(entry));
drop_pte:
@@ -99,7 +102,8 @@ drop_pte:
flush_tlb_page(vma, address);
deactivate_page(page);
page_cache_release(page);
- goto out_failed;
+out_failed:
+ return 0;
}
/*
@@ -166,13 +170,13 @@ drop_pte:
flush_tlb_page(vma, address);
spin_unlock(&mm->page_table_lock);
error = swapout(page, file);
- UnlockPage(page);
if (file) fput(file);
- if (!error)
- goto out_free_success;
+ if (error < 0)
+ goto out_unlock_restore;
+ UnlockPage(page);
deactivate_page(page);
page_cache_release(page);
- return error;
+ return 1; /* We released page_table_lock */
}
/*
@@ -185,33 +189,11 @@ drop_pte:
if (!entry.val)
goto out_unlock_restore; /* No swap space left */
- /* Make sure to flush the TLB _before_ we start copying things.. */
- flush_tlb_page(vma, address);
- if (!(page = prepare_highmem_swapout(page)))
- goto out_swap_free;
-
- swap_duplicate(entry); /* One for the process, one for the swap cache */
-
- /* Add it to the swap cache */
+ /* Add it to the swap cache and mark it dirty */
add_to_swap_cache(page, entry);
+ SetPageDirty(page);
+ goto set_swap_pte;
- /* Put the swap entry into the pte after the page is in swapcache */
- mm->rss--;
- set_pte(page_table, swp_entry_to_pte(entry));
- spin_unlock(&mm->page_table_lock);
-
- /* OK, do a physical asynchronous write to swap. */
- rw_swap_page(WRITE, page, 0);
- deactivate_page(page);
-
-out_free_success:
- page_cache_release(page);
- return 1;
-out_swap_free:
- set_pte(page_table, pte);
- swap_free(entry);
-out_failed:
- return 0;
out_unlock_restore:
set_pte(page_table, pte);
UnlockPage(page);
@@ -501,7 +483,7 @@ struct page * reclaim_page(zone_t * zone)
continue;
}
- /* The page is dirty, or locked, move to inactive_diry list. */
+ /* The page is dirty, or locked, move to inactive_dirty list. */
if (page->buffers || TryLockPage(page)) {
del_page_from_inactive_clean_list(page);
add_page_to_inactive_dirty_list(page);
@@ -616,6 +598,36 @@ dirty_page_rescan:
}
/*
+ * Dirty swap-cache page? Write it out if
+ * last copy..
+ */
+ if (PageDirty(page)) {
+ int (*writepage)(struct page *) = page->mapping->a_ops->writepage;
+ if (!writepage)
+ goto page_active;
+
+ /* Can't start IO? Move it to the back of the list */
+ if (!can_get_io_locks) {
+ list_del(page_lru);
+ list_add(page_lru, &inactive_dirty_list);
+ UnlockPage(page);
+ continue;
+ }
+
+ /* OK, do a physical asynchronous write to swap. */
+ ClearPageDirty(page);
+ page_cache_get(page);
+ spin_unlock(&pagemap_lru_lock);
+
+ writepage(page);
+ page_cache_release(page);
+
+ /* And re-start the thing.. */
+ spin_lock(&pagemap_lru_lock);
+ continue;
+ }
+
+ /*
* If the page has buffers, try to free the buffer mappings
* associated with this page. If we succeed we either free
* the page (in case it was a buffercache only page) or we
@@ -701,6 +713,7 @@ dirty_page_rescan:
UnlockPage(page);
cleaned_pages++;
} else {
+page_active:
/*
* OK, we don't know what to do with the page.
* It's no use keeping it here, so we move it to
@@ -925,13 +938,6 @@ static int refill_inactive(unsigned int gfp_mask, int user)
shrink_dcache_memory(priority, gfp_mask);
shrink_icache_memory(priority, gfp_mask);
- /* Try to get rid of some shared memory pages.. */
- while (shm_swap(priority, gfp_mask)) {
- made_progress = 1;
- if (--count <= 0)
- goto done;
- }
-
/*
* Then, try to page stuff out..
*/
diff --git a/net/802/fddi.c b/net/802/fddi.c
index 4dccc3a9e..7edee2bef 100644
--- a/net/802/fddi.c
+++ b/net/802/fddi.c
@@ -22,7 +22,8 @@
* 2 of the License, or (at your option) any later version.
*
* Changes
- * Alan Cox : New arp/rebuild header
+ * Alan Cox : New arp/rebuild header
+ * Maciej W. Rozycki : IPv6 support
*/
#include <linux/config.h>
@@ -57,11 +58,11 @@ int fddi_header(struct sk_buff *skb, struct net_device *dev, unsigned short type
int hl = FDDI_K_SNAP_HLEN;
struct fddihdr *fddi;
- if(type != ETH_P_IP && type != ETH_P_ARP)
+ if(type != ETH_P_IP && type != ETH_P_IPV6 && type != ETH_P_ARP)
hl=FDDI_K_8022_HLEN-3;
fddi = (struct fddihdr *)skb_push(skb, hl);
fddi->fc = FDDI_FC_K_ASYNC_LLC_DEF;
- if(type == ETH_P_IP || type == ETH_P_ARP)
+ if(type == ETH_P_IP || type == ETH_P_IPV6 || type == ETH_P_ARP)
{
fddi->hdr.llc_snap.dsap = FDDI_EXTENDED_SAP;
fddi->hdr.llc_snap.ssap = FDDI_EXTENDED_SAP;
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 4a016d08b..e8d3170be 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -220,7 +220,7 @@ static void vc_info(struct atm_vcc *vcc,char *buf)
default:
here += sprintf(here,"%3d",vcc->family);
}
- here += sprintf(here," %04x %5d %7d/%7d %7d/%7d\n",vcc->flags.bits,
+ here += sprintf(here," %04x %5ld %7d/%7d %7d/%7d\n",vcc->flags.bits,
vcc->reply,
atomic_read(&vcc->tx_inuse),vcc->sk->sndbuf,
atomic_read(&vcc->rx_inuse),vcc->sk->rcvbuf);
diff --git a/net/core/dev.c b/net/core/dev.c
index 1e5b59c3d..cf4dcf8cd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -154,6 +154,12 @@ static void sample_queue(unsigned long dummy);
static struct timer_list samp_timer = { function: sample_queue };
#endif
+#ifdef CONFIG_HOTPLUG
+static int net_run_sbin_hotplug(struct net_device *dev, char *action);
+#else
+#define net_run_sbin_hotplug(dev, action) ({ 0; })
+#endif
+
/*
* Our notifier list
*/
@@ -617,7 +623,7 @@ void netdev_state_change(struct net_device *dev)
void dev_load(const char *name)
{
- if (!__dev_get_by_name(name) && capable(CAP_SYS_MODULE))
+ if (!dev_get(name) && capable(CAP_SYS_MODULE))
request_module(name);
}
@@ -875,8 +881,6 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
skb2->h.raw = skb2->nh.raw;
skb2->pkt_type = PACKET_OUTGOING;
- skb2->rx_dev = skb->dev;
- dev_hold(skb2->rx_dev);
ptype->func(skb2, skb->dev, ptype);
}
}
@@ -1129,10 +1133,7 @@ int netif_rx(struct sk_buff *skb)
goto drop;
enqueue:
- if (skb->rx_dev)
- dev_put(skb->rx_dev);
- skb->rx_dev = skb->dev;
- dev_hold(skb->rx_dev);
+ dev_hold(skb->dev);
__skb_queue_tail(&queue->input_pkt_queue,skb);
__cpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ);
local_irq_restore(flags);
@@ -1206,11 +1207,11 @@ static int deliver_to_old_ones(struct packet_type *pt, struct sk_buff *skb, int
*/
static __inline__ void skb_bond(struct sk_buff *skb)
{
- struct net_device *dev = skb->rx_dev;
+ struct net_device *dev = skb->dev;
if (dev->master) {
dev_hold(dev->master);
- skb->dev = skb->rx_dev = dev->master;
+ skb->dev = dev->master;
dev_put(dev);
}
}
@@ -1320,6 +1321,7 @@ static void net_rx_action(struct softirq_action *h)
for (;;) {
struct sk_buff *skb;
+ struct net_device *rx_dev;
local_irq_disable();
skb = __skb_dequeue(&queue->input_pkt_queue);
@@ -1330,10 +1332,13 @@ static void net_rx_action(struct softirq_action *h)
skb_bond(skb);
+ rx_dev = skb->dev;
+
#ifdef CONFIG_NET_FASTROUTE
if (skb->pkt_type == PACKET_FASTROUTE) {
netdev_rx_stat[this_cpu].fastroute_deferred_out++;
dev_queue_xmit(skb);
+ dev_put(rx_dev);
continue;
}
#endif
@@ -1369,6 +1374,7 @@ static void net_rx_action(struct softirq_action *h)
if (skb->dev->br_port != NULL &&
br_handle_frame_hook != NULL) {
handle_bridge(skb, pt_prev);
+ dev_put(rx_dev);
continue;
}
#endif
@@ -1399,6 +1405,8 @@ static void net_rx_action(struct softirq_action *h)
kfree_skb(skb);
}
+ dev_put(rx_dev);
+
if (bugdet-- < 0 || jiffies - start_time > 1)
goto softnet_break;
@@ -2196,9 +2204,11 @@ int dev_ioctl(unsigned int cmd, void *arg)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
dev_load(ifr.ifr_name);
+ dev_probe_lock();
rtnl_lock();
ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock();
+ dev_probe_unlock();
return ret;
case SIOCGIFMEM:
@@ -2217,9 +2227,11 @@ int dev_ioctl(unsigned int cmd, void *arg)
if (cmd >= SIOCDEVPRIVATE &&
cmd <= SIOCDEVPRIVATE + 15) {
dev_load(ifr.ifr_name);
+ dev_probe_lock();
rtnl_lock();
ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock();
+ dev_probe_unlock();
if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
return -EFAULT;
return ret;
@@ -2303,6 +2315,12 @@ int register_netdevice(struct net_device *dev)
#endif
if (dev_boot_phase) {
+#ifdef CONFIG_NET_DIVERT
+ ret = alloc_divert_blk(dev);
+ if (ret)
+ return ret;
+#endif /* CONFIG_NET_DIVERT */
+
/* This is NOT bug, but I am not sure, that all the
devices, initialized before netdev module is started
are sane.
@@ -2328,12 +2346,6 @@ int register_netdevice(struct net_device *dev)
dev_hold(dev);
write_unlock_bh(&dev_base_lock);
-#ifdef CONFIG_NET_DIVERT
- ret = alloc_divert_blk(dev);
- if (ret)
- return ret;
-#endif /* CONFIG_NET_DIVERT */
-
/*
* Default initial state at registry is that the
* device is present.
@@ -2344,6 +2356,12 @@ int register_netdevice(struct net_device *dev)
return 0;
}
+#ifdef CONFIG_NET_DIVERT
+ ret = alloc_divert_blk(dev);
+ if (ret)
+ return ret;
+#endif /* CONFIG_NET_DIVERT */
+
dev->iflink = -1;
/* Init, if this function is available */
@@ -2383,15 +2401,11 @@ int register_netdevice(struct net_device *dev)
dev->deadbeaf = 0;
write_unlock_bh(&dev_base_lock);
-#ifdef CONFIG_NET_DIVERT
- ret = alloc_divert_blk(dev);
- if (ret)
- return ret;
-#endif /* CONFIG_NET_DIVERT */
-
/* Notify protocols, that a new device appeared. */
notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+ net_run_sbin_hotplug(dev, "register");
+
return 0;
}
@@ -2414,11 +2428,12 @@ int netdev_finish_unregister(struct net_device *dev)
return 0;
}
#ifdef NET_REFCNT_DEBUG
- printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name, dev->new_style?"":", old style");
+ printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name,
+ (dev->features & NETIF_F_DYNALLOC)?"":", old style");
#endif
if (dev->destructor)
dev->destructor(dev);
- if (dev->new_style)
+ if (dev->features & NETIF_F_DYNALLOC)
kfree(dev);
return 0;
}
@@ -2462,6 +2477,10 @@ int unregister_netdevice(struct net_device *dev)
return -ENODEV;
}
+ /* Synchronize to net_rx_action. */
+ br_write_lock_bh(BR_NETPROTO_LOCK);
+ br_write_unlock_bh(BR_NETPROTO_LOCK);
+
if (dev_boot_phase == 0) {
#ifdef CONFIG_NET_FASTROUTE
dev_clear_fastroute(dev);
@@ -2470,6 +2489,8 @@ int unregister_netdevice(struct net_device *dev)
/* Shutdown queueing discipline. */
dev_shutdown(dev);
+ net_run_sbin_hotplug(dev, "unregister");
+
/* Notify protocols, that we are about to destroy
this device. They should clean all the things.
*/
@@ -2491,7 +2512,7 @@ int unregister_netdevice(struct net_device *dev)
free_divert_blk(dev);
#endif
- if (dev->new_style) {
+ if (dev->features & NETIF_F_DYNALLOC) {
#ifdef NET_REFCNT_DEBUG
if (atomic_read(&dev->refcnt) != 1)
printk(KERN_DEBUG "unregister_netdevice: holding %s refcnt=%d\n", dev->name, atomic_read(&dev->refcnt)-1);
@@ -2709,29 +2730,15 @@ int __init net_dev_init(void)
/* Notify userspace when a netdevice event occurs,
* by running '/sbin/hotplug net' with certain
* environment variables set.
- *
- * Currently reported events are listed in netdev_event_names[].
*/
-/* /sbin/hotplug ONLY executes for events named here */
-static char *netdev_event_names[] = {
- [NETDEV_REGISTER] = "register",
- [NETDEV_UNREGISTER] = "unregister",
-};
-
-static int run_sbin_hotplug(struct notifier_block *this,
- unsigned long event, void *ptr)
+static int net_run_sbin_hotplug(struct net_device *dev, char *action)
{
- struct net_device *dev = (struct net_device *) ptr;
- char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action[32];
+ char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action_str[32];
int i;
- if ((event >= ARRAY_SIZE(netdev_event_names)) ||
- !netdev_event_names[event])
- return NOTIFY_DONE;
-
sprintf(ifname, "INTERFACE=%s", dev->name);
- sprintf(action, "ACTION=%s", netdev_event_names[event]);
+ sprintf(action_str, "ACTION=%s", action);
i = 0;
argv[i++] = hotplug_path;
@@ -2743,27 +2750,9 @@ static int run_sbin_hotplug(struct notifier_block *this,
envp [i++] = "HOME=/";
envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
envp [i++] = ifname;
- envp [i++] = action;
+ envp [i++] = action_str;
envp [i] = 0;
- call_usermodehelper (argv [0], argv, envp);
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block sbin_hotplug = {
- notifier_call: run_sbin_hotplug,
-};
-
-/*
- * called from init/main.c, -after- all the initcalls are complete.
- * Registers a hook that calls /sbin/hotplug on every netdev
- * addition and removal.
- */
-void __init net_notifier_init (void)
-{
- if (register_netdevice_notifier(&sbin_hotplug))
- printk (KERN_WARNING "unable to register netdev notifier\n"
- KERN_WARNING "/sbin/hotplug will not be run.\n");
+ return call_usermodehelper(argv [0], argv, envp);
}
#endif
diff --git a/net/core/dst.c b/net/core/dst.c
index 2b17d3782..0771c634b 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -179,7 +179,8 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
now. _It_ _is_ _explicit_ _deliberate_
_race_ _condition_.
*/
- if (event!=NETDEV_DOWN && !dev->new_style &&
+ if (event!=NETDEV_DOWN &&
+ !(dev->features & NETIF_F_DYNALLOC) &&
dst->output == dst_blackhole) {
dst->dev = &loopback_dev;
dev_put(dev);
diff --git a/net/core/dv.c b/net/core/dv.c
index 4df7747b8..0e5b3e671 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -62,7 +62,7 @@ int alloc_divert_blk(struct net_device *dev)
if (dev->divert == NULL) {
printk(KERN_DEBUG "divert: unable to allocate divert_blk for %s\n",
dev->name);
- return -EFAULT;
+ return -ENOMEM;
} else {
memset(dev->divert, 0, sizeof(struct divert_blk));
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index ecbea0425..2cb555071 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -165,6 +165,16 @@ static int neigh_del_timer(struct neighbour *n)
return 0;
}
+static void pneigh_queue_purge(struct sk_buff_head *list)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(list)) != NULL) {
+ dev_put(skb->dev);
+ kfree_skb(skb);
+ }
+}
+
int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
{
int i;
@@ -209,11 +219,11 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
}
}
- skb_queue_purge(&tbl->proxy_queue);
pneigh_ifdown(tbl, dev);
write_unlock_bh(&tbl->lock);
del_timer_sync(&tbl->proxy_timer);
+ pneigh_queue_purge(&tbl->proxy_queue);
return 0;
}
@@ -999,7 +1009,11 @@ static void neigh_proxy_process(unsigned long arg)
struct neigh_table *tbl = (struct neigh_table *)arg;
long sched_next = 0;
unsigned long now = jiffies;
- struct sk_buff *skb = tbl->proxy_queue.next;
+ struct sk_buff *skb;
+
+ spin_lock(&tbl->proxy_queue.lock);
+
+ skb = tbl->proxy_queue.next;
while (skb != (struct sk_buff*)&tbl->proxy_queue) {
struct sk_buff *back = skb;
@@ -1007,19 +1021,21 @@ static void neigh_proxy_process(unsigned long arg)
skb = skb->next;
if (tdif <= 0) {
+ struct net_device *dev = back->dev;
__skb_unlink(back, &tbl->proxy_queue);
- if (tbl->proxy_redo)
+ if (tbl->proxy_redo && netif_running(dev))
tbl->proxy_redo(back);
else
kfree_skb(back);
+
+ dev_put(dev);
} else if (!sched_next || tdif < sched_next)
sched_next = tdif;
}
del_timer(&tbl->proxy_timer);
- if (sched_next) {
- tbl->proxy_timer.expires = jiffies + sched_next;
- add_timer(&tbl->proxy_timer);
- }
+ if (sched_next)
+ mod_timer(&tbl->proxy_timer, jiffies + sched_next);
+ spin_unlock(&tbl->proxy_queue.lock);
}
void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
@@ -1034,16 +1050,19 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
}
skb->stamp.tv_sec = 0;
skb->stamp.tv_usec = now + sched_next;
+
+ spin_lock(&tbl->proxy_queue.lock);
if (del_timer(&tbl->proxy_timer)) {
long tval = tbl->proxy_timer.expires - now;
if (tval < sched_next)
sched_next = tval;
}
- tbl->proxy_timer.expires = now + sched_next;
dst_release(skb->dst);
skb->dst = NULL;
+ dev_hold(skb->dev);
__skb_queue_tail(&tbl->proxy_queue, skb);
- add_timer(&tbl->proxy_timer);
+ mod_timer(&tbl->proxy_timer, now + sched_next);
+ spin_unlock(&tbl->proxy_queue.lock);
}
@@ -1135,7 +1154,7 @@ int neigh_table_clear(struct neigh_table *tbl)
del_timer_sync(&tbl->gc_timer);
tasklet_kill(&tbl->gc_task);
del_timer_sync(&tbl->proxy_timer);
- skb_queue_purge(&tbl->proxy_queue);
+ pneigh_queue_purge(&tbl->proxy_queue);
neigh_ifdown(tbl, NULL);
if (tbl->entries)
printk(KERN_CRIT "neighbour leakage\n");
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 173506c3d..c5dcecfb3 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4,7 +4,7 @@
* Authors: Alan Cox <iiitac@pyr.swan.ac.uk>
* Florian La Roche <rzsfl@rz.uni-sb.de>
*
- * Version: $Id: skbuff.c,v 1.73 2000/05/22 07:29:44 davem Exp $
+ * Version: $Id: skbuff.c,v 1.75 2000/12/08 17:15:53 davem Exp $
*
* Fixes:
* Alan Cox : Fixed the worst of the load balancer bugs.
@@ -202,7 +202,6 @@ struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
/* Set up other state */
skb->len = 0;
- skb->is_clone = 0;
skb->cloned = 0;
atomic_set(&skb->users, 1);
@@ -233,7 +232,6 @@ static inline void skb_headerinit(void *p, kmem_cache_t *cache,
skb->ip_summed = 0;
skb->security = 0; /* By default packets are insecure */
skb->dst = NULL;
- skb->rx_dev = NULL;
#ifdef CONFIG_NETFILTER
skb->nfmark = skb->nfcache = 0;
skb->nfct = NULL;
@@ -287,10 +285,6 @@ void __kfree_skb(struct sk_buff *skb)
#ifdef CONFIG_NETFILTER
nf_conntrack_put(skb->nfct);
#endif
-#ifdef CONFIG_NET
- if(skb->rx_dev)
- dev_put(skb->rx_dev);
-#endif
skb_headerinit(skb, NULL, 0); /* clean state */
kfree_skbmem(skb);
}
@@ -325,12 +319,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
skb->cloned = 1;
dst_clone(n->dst);
- n->rx_dev = NULL;
n->cloned = 1;
n->next = n->prev = NULL;
n->list = NULL;
n->sk = NULL;
- n->is_clone = 1;
atomic_set(&n->users, 1);
n->destructor = NULL;
#ifdef CONFIG_NETFILTER
@@ -349,7 +341,6 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->list=NULL;
new->sk=NULL;
new->dev=old->dev;
- new->rx_dev=NULL;
new->priority=old->priority;
new->protocol=old->protocol;
new->dst=dst_clone(old->dst);
@@ -358,7 +349,6 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->mac.raw=old->mac.raw+offset;
memcpy(new->cb, old->cb, sizeof(old->cb));
new->used=old->used;
- new->is_clone=0;
atomic_set(&new->users, 1);
new->pkt_type=old->pkt_type;
new->stamp=old->stamp;
@@ -417,7 +407,7 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask)
}
/**
- * skb_copy - copy and expand sk_buff
+ * skb_copy_expand - copy and expand sk_buff
* @skb: buffer to copy
* @newheadroom: new free bytes at head
* @newtailroom: new free bytes at tail
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 4754cd850..361729458 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -78,9 +78,9 @@ extern int decnet_log_martians;
static void dn_log_martian(struct sk_buff *skb, const char *msg)
{
if (decnet_log_martians && net_ratelimit()) {
- char *devname = skb->rx_dev ? skb->rx_dev->name : "???";
+ char *devname = skb->dev ? skb->dev->name : "???";
struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
- printk(KERN_INFO "DECnet: Martian packet (%s) rx_dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, cb->src, cb->dst, cb->src_port, cb->dst_port);
+ printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, cb->src, cb->dst, cb->src_port, cb->dst_port);
}
}
@@ -782,7 +782,7 @@ free_out:
int dn_nsp_rx(struct sk_buff *skb)
{
- return NF_HOOK(PF_DECnet, NF_DN_LOCAL_IN, skb, skb->rx_dev, NULL, dn_nsp_rx_packet);
+ return NF_HOOK(PF_DECnet, NF_DN_LOCAL_IN, skb, skb->dev, NULL, dn_nsp_rx_packet);
}
/*
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 20ec07acc..70646fc11 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -526,6 +526,7 @@ static int dn_forward(struct sk_buff *skb)
{
struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
struct dst_entry *dst = skb->dst;
+ struct net_device *dev = skb->dev;
struct neighbour *neigh;
int err = -EINVAL;
@@ -551,7 +552,7 @@ static int dn_forward(struct sk_buff *skb)
else
cb->rt_flags &= ~DN_RT_F_IE;
- return NF_HOOK(PF_DECnet, NF_DN_FORWARD, skb, skb->rx_dev, skb->dev, neigh->output);
+ return NF_HOOK(PF_DECnet, NF_DN_FORWARD, skb, dev, skb->dev, neigh->output);
error:
@@ -985,7 +986,6 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
}
skb->protocol = __constant_htons(ETH_P_DNA_RT);
skb->dev = dev;
- skb->rx_dev = dev;
cb->src = src;
cb->dst = dst;
local_bh_disable();
@@ -1002,7 +1002,6 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
if (skb->dev)
dev_put(skb->dev);
skb->dev = NULL;
- skb->rx_dev = NULL;
if (err)
goto out_free;
skb->dst = &rt->u.dst;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7af589b75..6b980e3f3 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1,7 +1,7 @@
/*
* NET3 IP device support routines.
*
- * Version: $Id: devinet.c,v 1.38 2000/08/19 23:22:56 davem Exp $
+ * Version: $Id: devinet.c,v 1.39 2000/12/10 22:24:11 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -519,6 +519,7 @@ int devinet_ioctl(unsigned int cmd, void *arg)
return -EINVAL;
}
+ dev_probe_lock();
rtnl_lock();
if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL) {
@@ -649,10 +650,12 @@ int devinet_ioctl(unsigned int cmd, void *arg)
}
done:
rtnl_unlock();
+ dev_probe_unlock();
return ret;
rarok:
rtnl_unlock();
+ dev_probe_unlock();
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
return -EFAULT;
return 0;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 07041a3e5..7091bf82c 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -5,7 +5,7 @@
*
* The IP fragmentation functionality.
*
- * Version: $Id: ip_fragment.c,v 1.50 2000/07/07 22:29:42 davem Exp $
+ * Version: $Id: ip_fragment.c,v 1.53 2000/12/08 17:15:53 davem Exp $
*
* Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
* Alan Cox <Alan.Cox@linux.org>
@@ -51,6 +51,9 @@
int sysctl_ipfrag_high_thresh = 256*1024;
int sysctl_ipfrag_low_thresh = 192*1024;
+/* Important NOTE! Fragment queue must be destroyed before MSL expires.
+ * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
+ */
int sysctl_ipfrag_time = IP_FRAG_TIME;
struct ipfrag_skb_cb
@@ -80,7 +83,7 @@ struct ipq {
atomic_t refcnt;
struct timer_list timer; /* when will this queue expire? */
struct ipq **pprev;
- struct net_device *dev; /* Device - for icmp replies */
+ int iif; /* Device index - for icmp replies */
};
/* Hash table. */
@@ -252,8 +255,13 @@ static void ip_expire(unsigned long arg)
IP_INC_STATS_BH(IpReasmFails);
if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) {
+ struct sk_buff *head = qp->fragments;
+
/* Send an ICMP "Fragment Reassembly Timeout" message. */
- icmp_send(qp->fragments, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+ if ((head->dev = dev_get_by_index(qp->iif)) != NULL) {
+ icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+ dev_put(head->dev);
+ }
}
out:
spin_unlock(&qp->lock);
@@ -287,6 +295,9 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
#endif
qp = qp_in;
+ if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))
+ atomic_inc(&qp->refcnt);
+
atomic_inc(&qp->refcnt);
if((qp->next = ipq_hash[hash]) != NULL)
qp->next->pprev = &qp->next;
@@ -367,9 +378,6 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (qp->last_in & COMPLETE)
goto err;
- if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))
- atomic_inc(&qp->refcnt);
-
offset = ntohs(iph->frag_off);
flags = offset & ~IP_OFFSET;
offset &= IP_OFFSET;
@@ -477,7 +485,8 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
else
qp->fragments = skb;
- qp->dev = skb->dev;
+ qp->iif = skb->dev->ifindex;
+ skb->dev = NULL;
qp->meat += skb->len;
atomic_add(skb->truesize, &ip_frag_mem);
if (offset == 0)
@@ -496,7 +505,7 @@ err:
* of bits on input. Until the new skb data handling is in I'm not going
* to touch this with a bargepole.
*/
-static struct sk_buff *ip_frag_reasm(struct ipq *qp)
+static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
{
struct sk_buff *skb;
struct iphdr *iph;
@@ -537,13 +546,13 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp)
if (skb->ip_summed != fp->ip_summed)
skb->ip_summed = CHECKSUM_NONE;
else if (skb->ip_summed == CHECKSUM_HW)
- skb->csum = csum_chain(skb->csum, fp->csum);
+ skb->csum = csum_add(skb->csum, fp->csum);
}
skb->dst = dst_clone(head->dst);
skb->pkt_type = head->pkt_type;
skb->protocol = head->protocol;
- skb->dev = qp->dev;
+ skb->dev = dev;
/*
* Clearly bogus, because security markings of the individual
@@ -592,6 +601,7 @@ struct sk_buff *ip_defrag(struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
struct ipq *qp;
+ struct net_device *dev;
IP_INC_STATS_BH(IpReasmReqds);
@@ -599,6 +609,8 @@ struct sk_buff *ip_defrag(struct sk_buff *skb)
if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
ip_evictor();
+ dev = skb->dev;
+
/* Lookup (or create) queue header */
if ((qp = ip_find(iph)) != NULL) {
struct sk_buff *ret = NULL;
@@ -609,7 +621,7 @@ struct sk_buff *ip_defrag(struct sk_buff *skb)
if (qp->last_in == (FIRST_IN|LAST_IN) &&
qp->meat == qp->len)
- ret = ip_frag_reasm(qp);
+ ret = ip_frag_reasm(qp, dev);
spin_unlock(&qp->lock);
ipq_put(qp);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index f7b73adb8..0c924a793 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -271,7 +271,7 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
nt = (struct ip_tunnel*)dev->priv;
nt->dev = dev;
dev->init = ipgre_tunnel_init;
- dev->new_style = 1;
+ dev->features |= NETIF_F_DYNALLOC;
memcpy(&nt->parms, parms, sizeof(*parms));
strcpy(dev->name, nt->parms.name);
if (dev->name[0] == 0) {
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 873030d0a..be5df4c26 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -5,7 +5,7 @@
*
* The Internet Protocol (IP) module.
*
- * Version: $Id: ip_input.c,v 1.50 2000/10/24 22:54:26 davem Exp $
+ * Version: $Id: ip_input.c,v 1.51 2000/12/08 17:15:53 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -225,12 +225,6 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
nf_debug_ip_local_deliver(skb);
#endif /*CONFIG_NETFILTER_DEBUG*/
- /* Free rx_dev before enqueueing to sockets */
- if (skb->rx_dev) {
- dev_put(skb->rx_dev);
- skb->rx_dev = NULL;
- }
-
/* Point into the IP datagram, just past the header. */
skb->h.raw = skb->nh.raw + iph->ihl*4;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index f87921077..17cd81ee2 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -5,7 +5,7 @@
*
* The IP to API glue.
*
- * Version: $Id: ip_sockglue.c,v 1.53 2000/10/22 16:06:56 davem Exp $
+ * Version: $Id: ip_sockglue.c,v 1.54 2000/11/28 13:34:56 davem Exp $
*
* Authors: see ip.c
*
@@ -356,10 +356,14 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
err = copied;
/* Reset and regenerate socket error */
+ spin_lock_irq(&sk->error_queue.lock);
sk->err = 0;
if ((skb2 = skb_peek(&sk->error_queue)) != NULL) {
sk->err = SKB_EXT_ERR(skb2)->ee.ee_errno;
+ spin_unlock_irq(&sk->error_queue.lock);
sk->error_report(sk);
+ } else {
+ spin_unlock_irq(&sk->error_queue.lock);
}
out_free_skb:
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index a8cb239a8..5b896e7d8 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -1,7 +1,7 @@
/*
* Linux NET3: IP/IP protocol decoder.
*
- * Version: $Id: ipip.c,v 1.40 2000/10/28 17:19:25 davem Exp $
+ * Version: $Id: ipip.c,v 1.41 2000/11/28 13:13:27 davem Exp $
*
* Authors:
* Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
@@ -240,7 +240,7 @@ struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create)
nt = (struct ip_tunnel*)dev->priv;
nt->dev = dev;
dev->init = ipip_tunnel_init;
- dev->new_style = 1;
+ dev->features |= NETIF_F_DYNALLOC;
memcpy(&nt->parms, parms, sizeof(*parms));
strcpy(dev->name, nt->parms.name);
if (dev->name[0] == 0) {
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index dc946b97b..0be5d9307 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -9,7 +9,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Version: $Id: ipmr.c,v 1.54 2000/08/02 06:05:16 davem Exp $
+ * Version: $Id: ipmr.c,v 1.55 2000/11/28 13:13:27 davem Exp $
*
* Fixes:
* Michael Chastain : Incorrect size of copying.
@@ -205,7 +205,7 @@ struct net_device *ipmr_reg_vif(struct vifctl *v)
dev->flags = IFF_NOARP;
dev->hard_start_xmit = reg_vif_xmit;
dev->get_stats = reg_vif_get_stats;
- dev->new_style = 1;
+ dev->features |= NETIF_F_DYNALLOC;
if (register_netdevice(dev)) {
kfree(dev);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 73fd4eaf7..9c8d493b5 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -400,13 +400,6 @@ static struct sk_buff *netlink_build_message(ipq_queue_element_t *e, int *errp)
if (e->info->outdev) strcpy(pm->outdev_name, e->info->outdev->name);
else pm->outdev_name[0] = '\0';
pm->hw_protocol = e->skb->protocol;
- if (e->skb->rx_dev) {
- pm->hw_type = e->skb->rx_dev->type;
- if (e->skb->rx_dev->hard_header_parse)
- pm->hw_addrlen =
- e->skb->rx_dev->hard_header_parse(e->skb,
- pm->hw_addr);
- }
if (data_len)
memcpy(pm->payload, e->skb->data, data_len);
nlh->nlmsg_len = skb->tail - old_tail;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index cfc8ca6da..2e8201e78 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -89,10 +89,8 @@ struct ipt_table_info
unsigned int hook_entry[NF_IP_NUMHOOKS];
unsigned int underflow[NF_IP_NUMHOOKS];
- char padding[SMP_ALIGN((NF_IP_NUMHOOKS*2+2)*sizeof(unsigned int))];
-
/* ipt_entry tables: one per CPU */
- char entries[0];
+ char entries[0] __attribute__((aligned(SMP_CACHE_BYTES)));
};
static LIST_HEAD(ipt_target);
@@ -101,7 +99,7 @@ static LIST_HEAD(ipt_tables);
#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
#ifdef CONFIG_SMP
-#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*cpu_number_map(p))
+#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
#else
#define TABLE_OFFSET(t,p) 0
#endif
@@ -283,7 +281,8 @@ ipt_do_table(struct sk_buff **pskb,
read_lock_bh(&table->lock);
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
table_base = (void *)table->private->entries
- + TABLE_OFFSET(table->private, smp_processor_id());
+ + TABLE_OFFSET(table->private,
+ cpu_number_map(smp_processor_id()));
e = get_entry(table_base, table->private->hook_entry[hook]);
#ifdef CONFIG_NETFILTER_DEBUG
@@ -860,7 +859,7 @@ translate_table(const char *name,
/* And one copy for every other CPU */
for (i = 1; i < smp_num_cpus; i++) {
- memcpy(newinfo->entries + SMP_ALIGN(newinfo->size*i),
+ memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries,
SMP_ALIGN(newinfo->size));
}
@@ -1359,7 +1358,7 @@ int ipt_register_table(struct ipt_table *table)
int ret;
struct ipt_table_info *newinfo;
static struct ipt_table_info bootstrap
- = { 0, 0, { 0 }, { 0 }, { }, { } };
+ = { 0, 0, { 0 }, { 0 }, { } };
MOD_INC_USE_COUNT;
newinfo = vmalloc(sizeof(struct ipt_table_info)
diff --git a/net/ipv4/netfilter/ipt_MIRROR.c b/net/ipv4/netfilter/ipt_MIRROR.c
index cb5362dc2..9449c5128 100644
--- a/net/ipv4/netfilter/ipt_MIRROR.c
+++ b/net/ipv4/netfilter/ipt_MIRROR.c
@@ -50,7 +50,7 @@ static int route_mirror(struct sk_buff *skb)
/* check if the interface we are leaving by is the same as the
one we arrived on */
- if (skb->rx_dev == rt->u.dst.dev) {
+ if (skb->dev == rt->u.dst.dev) {
/* Drop old route. */
dst_release(skb->dst);
skb->dst = &rt->u.dst;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 675154d91..5db8dc8dd 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -5,7 +5,7 @@
*
* RAW - implementation of IP "raw" sockets.
*
- * Version: $Id: raw.c,v 1.55 2000/10/24 22:54:26 davem Exp $
+ * Version: $Id: raw.c,v 1.56 2000/11/28 13:38:38 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -614,20 +614,16 @@ static void get_raw_sock(struct sock *sp, char *tmpbuf, int i)
{
unsigned int dest, src;
__u16 destp, srcp;
- int timer_active;
- unsigned long timer_expires;
dest = sp->daddr;
src = sp->rcv_saddr;
destp = 0;
srcp = sp->num;
- timer_active = (timer_pending(&sp->timer)) ? 2 : 0;
- timer_expires = (timer_active == 2 ? sp->timer.expires : jiffies);
sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
i, src, srcp, dest, destp, sp->state,
atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
- timer_active, timer_expires-jiffies, 0,
+ 0, 0L, 0,
sock_i_uid(sp), 0,
sock_i_ino(sp),
atomic_read(&sp->refcnt), sp);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 6b254e2ad..b370fcdf9 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.179 2000/11/10 04:02:04 davem Exp $
+ * Version: $Id: tcp.c,v 1.180 2000/11/28 17:04:09 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -929,13 +929,13 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
iov = msg->msg_iov;
copied = 0;
- while(--iovlen >= 0) {
+ while (--iovlen >= 0) {
int seglen=iov->iov_len;
unsigned char * from=iov->iov_base;
iov++;
- while(seglen > 0) {
+ while (seglen > 0) {
int copy, tmp, queue_it;
if (err)
@@ -952,17 +952,11 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
/* Now we need to check if we have a half
* built packet we can tack some data onto.
*/
- if (tp->send_head && !(flags & MSG_OOB)) {
- skb = sk->write_queue.prev;
+ skb = sk->write_queue.prev;
+ if (tp->send_head &&
+ (mss_now - skb->len) > 0) {
copy = skb->len;
- /* If the remote does SWS avoidance we should
- * queue the best we can if not we should in
- * fact send multiple packets...
- * A method for detecting this would be most
- * welcome.
- */
- if (skb_tailroom(skb) > 0 &&
- (mss_now - copy) > 0) {
+ if (skb_tailroom(skb) > 0) {
int last_byte_was_odd = (copy % 4);
copy = mss_now - copy;
@@ -1004,7 +998,15 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
tp->pushed_seq = tp->write_seq;
}
+ if (flags&MSG_OOB) {
+ tp->urg_mode = 1;
+ tp->snd_up = tp->write_seq;
+ TCP_SKB_CB(skb)->sacked |= TCPCB_URG;
+ }
continue;
+ } else {
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+ tp->pushed_seq = tp->write_seq;
}
}
@@ -1032,6 +1034,8 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
set_bit(SOCK_NOSPACE, &sk->socket->flags);
+ __tcp_push_pending_frames(sk, tp, mss_now, 1);
+
if (!timeo) {
err = -EAGAIN;
goto do_interrupted;
@@ -1040,7 +1044,6 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
err = sock_intr_errno(timeo);
goto do_interrupted;
}
- __tcp_push_pending_frames(sk, tp, mss_now);
timeo = wait_for_tcp_memory(sk, timeo);
/* If SACK's were formed or PMTU events happened,
@@ -1053,7 +1056,6 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
seglen -= copy;
/* Prepare control bits for TCP header creation engine. */
- TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
if (PSH_NEEDED ||
after(tp->write_seq+copy, tp->pushed_seq+(tp->max_window>>1))) {
TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK|TCPCB_FLAG_PSH;
@@ -1063,12 +1065,10 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
}
TCP_SKB_CB(skb)->sacked = 0;
if (flags & MSG_OOB) {
- /* Funny. 8) This makes URG fully meaningless.
- * Well, OK. It does not contradict to anything yet. */
- TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_URG;
- TCP_SKB_CB(skb)->urg_ptr = copy;
- } else
- TCP_SKB_CB(skb)->urg_ptr = 0;
+ TCP_SKB_CB(skb)->sacked |= TCPCB_URG;
+ tp->urg_mode = 1;
+ tp->snd_up = tp->write_seq + copy;
+ }
/* TCP data bytes are SKB_PUT() on top, later
* TCP+IP+DEV headers are SKB_PUSH()'d beneath.
@@ -1093,20 +1093,20 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
}
err = copied;
out:
- __tcp_push_pending_frames(sk, tp, mss_now);
- TCP_CHECK_TIMER(sk);
+ __tcp_push_pending_frames(sk, tp, mss_now, tp->nonagle);
out_unlock:
+ TCP_CHECK_TIMER(sk);
release_sock(sk);
return err;
do_sock_err:
- if(copied)
+ if (copied)
err = copied;
else
err = sock_error(sk);
goto out;
do_shutdown:
- if(copied)
+ if (copied)
err = copied;
else {
if (!(flags&MSG_NOSIGNAL))
@@ -1115,13 +1115,16 @@ do_shutdown:
}
goto out;
do_interrupted:
- if(copied)
+ if (copied)
err = copied;
- goto out;
+ goto out_unlock;
do_fault:
__kfree_skb(skb);
do_fault2:
- err = -EFAULT;
+ if (copied)
+ err = copied;
+ else
+ err = -EFAULT;
goto out;
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ea9d18d97..15d087716 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.202 2000/09/21 01:05:38 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.203 2000/11/28 17:04:09 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -56,6 +56,10 @@
* Andi Kleen: Process packets with PSH set in the
* fast path.
* J Hadi Salim: ECN support
+ * Andrei Gurtov,
+ * Pasi Sarolahti,
+ * Panu Kuhlberg: Experimental audit of TCP (re)transmission
+ * engine. Lots of bugs are found.
*/
#include <linux/config.h>
@@ -1259,7 +1263,7 @@ static void tcp_cwnd_down(struct tcp_opt *tp)
static __inline__ int tcp_packet_delayed(struct tcp_opt *tp)
{
return !tp->retrans_stamp ||
- (tp->saw_tstamp &&
+ (tp->saw_tstamp && tp->rcv_tsecr &&
(__s32)(tp->rcv_tsecr - tp->retrans_stamp) < 0);
}
@@ -1378,10 +1382,8 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_opt *tp)
NET_INC_STATS_BH(TCPLossUndo);
tp->retransmits = 0;
tp->undo_marker = 0;
- if (!IsReno(tp)) {
+ if (!IsReno(tp))
tp->ca_state = TCP_CA_Open;
- tp->backoff = 0;
- }
return 1;
}
return 0;
@@ -1479,7 +1481,6 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
tp->retransmits = 0;
if (tcp_try_undo_recovery(sk, tp))
return;
- tp->backoff = 0;
break;
case TCP_CA_CWR:
@@ -1579,7 +1580,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
/* Read draft-ietf-tcplw-high-performance before mucking
* with this code. (Superceeds RFC1323)
*/
-static void tcp_ack_saw_tstamp(struct tcp_opt *tp)
+static void tcp_ack_saw_tstamp(struct tcp_opt *tp, int flag)
{
__u32 seq_rtt;
@@ -1594,7 +1595,12 @@ static void tcp_ack_saw_tstamp(struct tcp_opt *tp)
seq_rtt = tcp_time_stamp - tp->rcv_tsecr;
tcp_rtt_estimator(tp, seq_rtt);
tcp_set_rto(tp);
- tp->rto <<= tp->backoff;
+ if (tp->backoff) {
+ if (!tp->retransmits || !(flag & FLAG_RETRANS_DATA_ACKED))
+ tp->backoff = 0;
+ else
+ tp->rto <<= tp->backoff;
+ }
tcp_bound_rto(tp);
}
@@ -1609,20 +1615,27 @@ static void tcp_ack_no_tstamp(struct tcp_opt *tp, u32 seq_rtt, int flag)
* I.e. Karn's algorithm. (SIGCOMM '87, p5.)
*/
- if (!tp->retransmits && !(flag & FLAG_RETRANS_DATA_ACKED)) {
- tp->backoff = 0;
- tcp_rtt_estimator(tp, seq_rtt);
- tcp_set_rto(tp);
- tcp_bound_rto(tp);
+ tcp_rtt_estimator(tp, seq_rtt);
+ tcp_set_rto(tp);
+ if (tp->backoff) {
+ /* To relax it? We have valid sample as soon as we are
+ * here. Why not to clear backoff?
+ */
+ if (!tp->retransmits || !(flag & FLAG_RETRANS_DATA_ACKED))
+ tp->backoff = 0;
+ else
+ tp->rto <<= tp->backoff;
}
+ tcp_bound_rto(tp);
}
static __inline__ void
-tcp_ack_update_rtt(struct tcp_opt *tp, int flag, u32 seq_rtt)
+tcp_ack_update_rtt(struct tcp_opt *tp, int flag, s32 seq_rtt)
{
- if (tp->saw_tstamp)
- tcp_ack_saw_tstamp(tp);
- else
+ /* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */
+ if (tp->saw_tstamp && tp->rcv_tsecr)
+ tcp_ack_saw_tstamp(tp, flag);
+ else if (seq_rtt >= 0)
tcp_ack_no_tstamp(tp, seq_rtt, flag);
}
@@ -1669,7 +1682,7 @@ static int tcp_clean_rtx_queue(struct sock *sk)
struct sk_buff *skb;
__u32 now = tcp_time_stamp;
int acked = 0;
- __u32 seq_rtt = 0; /* F..g gcc... */
+ __s32 seq_rtt = -1;
while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head)) {
struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
@@ -1700,16 +1713,23 @@ static int tcp_clean_rtx_queue(struct sock *sk)
if(sacked & TCPCB_SACKED_RETRANS)
tp->retrans_out--;
acked |= FLAG_RETRANS_DATA_ACKED;
- }
+ seq_rtt = -1;
+ } else if (seq_rtt < 0)
+ seq_rtt = now - scb->when;
if(sacked & TCPCB_SACKED_ACKED)
tp->sacked_out--;
if(sacked & TCPCB_LOST)
tp->lost_out--;
- }
+ if(sacked & TCPCB_URG) {
+ if (tp->urg_mode &&
+ !before(scb->end_seq, tp->snd_up))
+ tp->urg_mode = 0;
+ }
+ } else if (seq_rtt < 0)
+ seq_rtt = now - scb->when;
if(tp->fackets_out)
tp->fackets_out--;
tp->packets_out--;
- seq_rtt = now - scb->when;
__skb_unlink(skb, skb->list);
tcp_free_skb(sk, skb);
}
@@ -1821,7 +1841,8 @@ static int tcp_ack_update_window(struct sock *sk, struct tcp_opt *tp,
#ifdef TCP_DEBUG
if (before(tp->snd_una + tp->snd_wnd, tp->snd_nxt)) {
- if (net_ratelimit())
+ if ((tp->snd_una + tp->snd_wnd)-tp->snd_nxt >= (1<<tp->snd_wscale)
+ && net_ratelimit())
printk(KERN_DEBUG "TCP: peer %u.%u.%u.%u:%u/%u shrinks window %u:%u:%u. Bad, what else can I say?\n",
NIPQUAD(sk->daddr), htons(sk->dport), sk->num,
tp->snd_una, tp->snd_wnd, tp->snd_nxt);
@@ -1929,7 +1950,7 @@ uninteresting_ack:
* But, this can also be called on packets in the established flow when
* the fast version below fails.
*/
-void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp)
+void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp, int estab)
{
unsigned char *ptr;
struct tcphdr *th = skb->h.th;
@@ -1956,7 +1977,7 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp)
return; /* don't parse partial options */
switch(opcode) {
case TCPOPT_MSS:
- if(opsize==TCPOLEN_MSS && th->syn) {
+ if(opsize==TCPOLEN_MSS && th->syn && !estab) {
u16 in_mss = ntohs(*(__u16 *)ptr);
if (in_mss) {
if (tp->user_mss && tp->user_mss < in_mss)
@@ -1966,7 +1987,7 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp)
}
break;
case TCPOPT_WINDOW:
- if(opsize==TCPOLEN_WINDOW && th->syn)
+ if(opsize==TCPOLEN_WINDOW && th->syn && !estab)
if (sysctl_tcp_window_scaling) {
tp->wscale_ok = 1;
tp->snd_wscale = *(__u8 *)ptr;
@@ -1981,8 +2002,8 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp)
break;
case TCPOPT_TIMESTAMP:
if(opsize==TCPOLEN_TIMESTAMP) {
- if (sysctl_tcp_timestamps) {
- tp->tstamp_ok = 1;
+ if ((estab && tp->tstamp_ok) ||
+ (!estab && sysctl_tcp_timestamps)) {
tp->saw_tstamp = 1;
tp->rcv_tsval = ntohl(*(__u32 *)ptr);
tp->rcv_tsecr = ntohl(*(__u32 *)(ptr+4));
@@ -1990,7 +2011,7 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp)
}
break;
case TCPOPT_SACK_PERM:
- if(opsize==TCPOLEN_SACK_PERM && th->syn) {
+ if(opsize==TCPOLEN_SACK_PERM && th->syn && !estab) {
if (sysctl_tcp_sack) {
tp->sack_ok = 1;
tcp_sack_reset(tp);
@@ -2019,7 +2040,8 @@ static __inline__ int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr
if (th->doff == sizeof(struct tcphdr)>>2) {
tp->saw_tstamp = 0;
return 0;
- } else if (th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
+ } else if (tp->tstamp_ok &&
+ th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
__u32 *ptr = (__u32 *)(th + 1);
if (*ptr == __constant_ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
| (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
@@ -2031,7 +2053,7 @@ static __inline__ int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr
return 1;
}
}
- tcp_parse_options(skb, tp);
+ tcp_parse_options(skb, tp, 1);
return 1;
}
@@ -3329,8 +3351,9 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
struct tcphdr *th, unsigned len)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int saved_clamp = tp->mss_clamp;
- tcp_parse_options(skb, tp);
+ tcp_parse_options(skb, tp, 0);
if (th->ack) {
/* rfc793:
@@ -3345,24 +3368,12 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
* test reduces to:
*/
if (TCP_SKB_CB(skb)->ack_seq != tp->snd_nxt)
- return 1;
+ goto reset_and_undo;
- if (tp->saw_tstamp) {
- if (tp->rcv_tsecr == 0) {
- /* Workaround for bug in linux-2.1 and early
- * 2.2 kernels. Let's pretend that we did not
- * see such timestamp to avoid bogus rtt value,
- * calculated by tcp_ack().
- */
- tp->saw_tstamp = 0;
-
- /* But do not forget to store peer's timestamp! */
- if (th->syn)
- tcp_store_ts_recent(tp);
- } else if (!between(tp->rcv_tsecr, tp->retrans_stamp, tcp_time_stamp)) {
- NET_INC_STATS_BH(PAWSActiveRejected);
- return 1;
- }
+ if (tp->saw_tstamp && tp->rcv_tsecr &&
+ !between(tp->rcv_tsecr, tp->retrans_stamp, tcp_time_stamp)) {
+ NET_INC_STATS_BH(PAWSActiveRejected);
+ goto reset_and_undo;
}
/* Now ACK is acceptable.
@@ -3386,7 +3397,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
* --ANK(990513)
*/
if (!th->syn)
- goto discard;
+ goto discard_and_undo;
/* rfc793:
* "If the SYN bit is on ...
@@ -3419,14 +3430,16 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tp->window_clamp = min(tp->window_clamp,65535);
}
- if (tp->tstamp_ok) {
+ if (tp->saw_tstamp) {
+ tp->tstamp_ok = 1;
tp->tcp_header_len =
sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
- } else
- tp->tcp_header_len = sizeof(struct tcphdr);
- if (tp->saw_tstamp)
tcp_store_ts_recent(tp);
+ } else {
+ tp->tcp_header_len = sizeof(struct tcphdr);
+ }
+
if (tp->sack_ok && sysctl_tcp_fack)
tp->sack_ok |= 2;
@@ -3467,7 +3480,10 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tp->ack.lrcvtime = tcp_time_stamp;
tcp_enter_quickack_mode(tp);
tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MAX);
- goto discard;
+
+discard:
+ __kfree_skb(skb);
+ return 0;
} else {
tcp_send_ack(sk);
}
@@ -3483,12 +3499,12 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
* Otherwise (no ACK) drop the segment and return."
*/
- goto discard;
+ goto discard_and_undo;
}
/* PAWS check. */
if (tp->ts_recent_stamp && tp->saw_tstamp && tcp_paws_check(tp, 0))
- goto discard;
+ goto discard_and_undo;
if (th->syn) {
/* We see SYN without ACK. It is attempt of
@@ -3496,8 +3512,15 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
* Particularly, it can be connect to self.
*/
tcp_set_state(sk, TCP_SYN_RECV);
- if (tp->saw_tstamp)
+
+ if (tp->saw_tstamp) {
+ tp->tstamp_ok = 1;
tcp_store_ts_recent(tp);
+ tp->tcp_header_len =
+ sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
+ } else {
+ tp->tcp_header_len = sizeof(struct tcphdr);
+ }
tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
@@ -3526,15 +3549,23 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
* Uncomment this return to process the data.
*/
return -1;
+#else
+ goto discard;
#endif
}
/* "fifth, if neither of the SYN or RST bits is set then
* drop the segment and return."
*/
-discard:
- __kfree_skb(skb);
- return 0;
+discard_and_undo:
+ tcp_clear_options(tp);
+ tp->mss_clamp = saved_clamp;
+ goto discard;
+
+reset_and_undo:
+ tcp_clear_options(tp);
+ tp->mss_clamp = saved_clamp;
+ return 1;
}
@@ -3671,8 +3702,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
* and does not calculate rtt.
* Fix it at least with timestamps.
*/
- if (tp->saw_tstamp && !tp->srtt)
- tcp_ack_saw_tstamp(tp);
+ if (tp->saw_tstamp && tp->rcv_tsecr && !tp->srtt)
+ tcp_ack_saw_tstamp(tp, 0);
if (tp->tstamp_ok)
tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 9f16a976c..c2cc4815b 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_ipv4.c,v 1.220 2000/11/14 07:26:02 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.222 2000/12/08 17:15:53 davem Exp $
*
* IPv4 specific functions
*
@@ -1320,17 +1320,14 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
if (req == NULL)
goto drop;
- tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
+ tcp_clear_options(&tp);
tp.mss_clamp = 536;
tp.user_mss = sk->tp_pinfo.af_tcp.user_mss;
- tcp_parse_options(skb, &tp);
+ tcp_parse_options(skb, &tp, 0);
if (want_cookie) {
- tp.sack_ok = 0;
- tp.wscale_ok = 0;
- tp.snd_wscale = 0;
- tp.tstamp_ok = 0;
+ tcp_clear_options(&tp);
tp.saw_tstamp = 0;
}
@@ -1343,6 +1340,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
tp.saw_tstamp = 0;
tp.tstamp_ok = 0;
}
+ tp.tstamp_ok = tp.saw_tstamp;
tcp_openreq_init(req, &tp, skb);
@@ -1651,6 +1649,8 @@ process:
if (sk->state == TCP_TIME_WAIT)
goto do_time_wait;
+ skb->dev = NULL;
+
bh_lock_sock(sk);
ret = 0;
if (!sk->lock.users) {
@@ -2016,7 +2016,8 @@ static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i)
tp->probes_out,
sock_i_ino(sp),
atomic_read(&sp->refcnt), sp,
- tp->rto, tp->ack.ato, tp->ack.quick, tp->ack.pingpong, sp->sndbuf
+ tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
+ tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
);
}
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index fea27faea..90074c84b 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_minisocks.c,v 1.4 2000/09/18 05:59:48 davem Exp $
+ * Version: $Id: tcp_minisocks.c,v 1.5 2000/11/28 17:04:10 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -134,7 +134,7 @@ tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
tp.saw_tstamp = 0;
if (th->doff > (sizeof(struct tcphdr)>>2) && tw->ts_recent_stamp) {
- tcp_parse_options(skb, &tp);
+ tcp_parse_options(skb, &tp, 0);
if (tp.saw_tstamp) {
tp.ts_recent = tw->ts_recent;
@@ -809,7 +809,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
ttp.saw_tstamp = 0;
if (th->doff > (sizeof(struct tcphdr)>>2)) {
- tcp_parse_options(skb, &ttp);
+ tcp_parse_options(skb, &ttp, 0);
if (ttp.saw_tstamp) {
ttp.ts_recent = req->ts_recent;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 7b6f45428..ca46db72c 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_output.c,v 1.128 2000/10/29 01:51:09 davem Exp $
+ * Version: $Id: tcp_output.c,v 1.129 2000/11/28 17:04:10 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -252,7 +252,13 @@ int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
th->window = htons(tcp_select_window(sk));
}
th->check = 0;
- th->urg_ptr = ntohs(tcb->urg_ptr);
+ th->urg_ptr = 0;
+
+ if (tp->urg_mode &&
+ between(tp->snd_up, tcb->seq+1, tcb->seq+0xFFFF)) {
+ th->urg_ptr = htons(tp->snd_up-tcb->seq);
+ th->urg = 1;
+ }
if (tcb->flags & TCPCB_FLAG_SYN) {
tcp_syn_build_options((__u32 *)(th + 1),
@@ -315,7 +321,7 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb, int force_queue, unsigne
__skb_queue_tail(&sk->write_queue, skb);
tcp_charge_skb(sk, skb);
- if (!force_queue && tp->send_head == NULL && tcp_snd_test(tp, skb, cur_mss, 1)) {
+ if (!force_queue && tp->send_head == NULL && tcp_snd_test(tp, skb, cur_mss, tp->nonagle)) {
/* Send it out now. */
TCP_SKB_CB(skb)->when = tcp_time_stamp;
if (tcp_transmit_skb(sk, skb_clone(skb, sk->allocation)) == 0) {
@@ -344,7 +350,7 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
u16 flags;
/* Get a new skb... force flag on. */
- buff = tcp_alloc_skb(sk, nsize + MAX_TCP_HEADER + 15, GFP_ATOMIC);
+ buff = tcp_alloc_skb(sk, nsize + MAX_TCP_HEADER, GFP_ATOMIC);
if (buff == NULL)
return -ENOMEM; /* We'll just try again later. */
tcp_charge_skb(sk, buff);
@@ -358,27 +364,14 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
/* PSH and FIN should only be set in the second packet. */
flags = TCP_SKB_CB(skb)->flags;
- TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN | TCPCB_FLAG_PSH);
- if(flags & TCPCB_FLAG_URG) {
- u16 old_urg_ptr = TCP_SKB_CB(skb)->urg_ptr;
-
- /* Urgent data is always a pain in the ass. */
- if(old_urg_ptr > len) {
- TCP_SKB_CB(skb)->flags &= ~(TCPCB_FLAG_URG);
- TCP_SKB_CB(skb)->urg_ptr = 0;
- TCP_SKB_CB(buff)->urg_ptr = old_urg_ptr - len;
- } else {
- flags &= ~(TCPCB_FLAG_URG);
- }
- }
- if(!(flags & TCPCB_FLAG_URG))
- TCP_SKB_CB(buff)->urg_ptr = 0;
+ TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
TCP_SKB_CB(buff)->flags = flags;
- TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_EVER_RETRANS);
+ TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) {
tp->lost_out++;
tp->left_out++;
}
+ TCP_SKB_CB(buff)->sacked &= ~TCPCB_AT_TAIL;
/* Copy and checksum data tail into the new buffer. */
buff->csum = csum_partial_copy_nocheck(skb->data + len, skb_put(buff, nsize),
@@ -489,7 +482,7 @@ int tcp_write_xmit(struct sock *sk)
mss_now = tcp_current_mss(sk);
while((skb = tp->send_head) &&
- tcp_snd_test(tp, skb, mss_now, tcp_skb_is_last(sk, skb))) {
+ tcp_snd_test(tp, skb, mss_now, tcp_skb_is_last(sk, skb) ? tp->nonagle : 1)) {
if (skb->len > mss_now) {
if (tcp_fragment(sk, skb, mss_now))
break;
@@ -544,6 +537,7 @@ int tcp_write_xmit(struct sock *sk)
* If the free space is less than the 1/4 of the maximum
* space available and the free space is less than 1/2 mss,
* then set the window to 0.
+ * [ Actually, bsd uses MSS and 1/4 of maximal _window_ ]
* Otherwise, just prevent the window from shrinking
* and from being larger than the largest representable value.
*
@@ -589,7 +583,7 @@ u32 __tcp_select_window(struct sock *sk)
if (tcp_memory_pressure)
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4*tp->advmss);
- if (free_space < ((int) (mss/2)))
+ if (free_space < ((int)mss))
return 0;
}
@@ -625,10 +619,6 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
int skb_size = skb->len, next_skb_size = next_skb->len;
u16 flags = TCP_SKB_CB(skb)->flags;
- /* Punt if the first SKB has URG set. */
- if(flags & TCPCB_FLAG_URG)
- return;
-
/* Also punt if next skb has been SACK'd. */
if(TCP_SKB_CB(next_skb)->sacked & TCPCB_SACKED_ACKED)
return;
@@ -666,16 +656,12 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
/* Merge over control information. */
flags |= TCP_SKB_CB(next_skb)->flags; /* This moves PSH/FIN etc. over */
- if(flags & TCPCB_FLAG_URG) {
- u16 urgptr = TCP_SKB_CB(next_skb)->urg_ptr;
- TCP_SKB_CB(skb)->urg_ptr = urgptr + skb_size;
- }
TCP_SKB_CB(skb)->flags = flags;
/* All done, get rid of second SKB and account for it so
* packet counting does not break.
*/
- TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked&TCPCB_EVER_RETRANS;
+ TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked&(TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
if (TCP_SKB_CB(next_skb)->sacked&TCPCB_SACKED_RETRANS)
tp->retrans_out--;
if (TCP_SKB_CB(next_skb)->sacked&TCPCB_LOST) {
@@ -687,6 +673,11 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
tp->sacked_out--;
tp->left_out--;
}
+ /* Not quite right: it can be > snd.fack, but
+ * it is better to underestimate fackets.
+ */
+ if (tp->fackets_out)
+ tp->fackets_out--;
tcp_free_skb(sk, next_skb);
tp->packets_out--;
}
@@ -946,7 +937,7 @@ void tcp_send_fin(struct sock *sk)
} else {
/* Socket is locked, keep trying until memory is available. */
for (;;) {
- skb = alloc_skb(MAX_TCP_HEADER + 15, GFP_KERNEL);
+ skb = alloc_skb(MAX_TCP_HEADER, GFP_KERNEL);
if (skb)
break;
current->policy |= SCHED_YIELD;
@@ -958,13 +949,12 @@ void tcp_send_fin(struct sock *sk)
skb->csum = 0;
TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
TCP_SKB_CB(skb)->sacked = 0;
- TCP_SKB_CB(skb)->urg_ptr = 0;
/* FIN eats a sequence byte, write_seq advanced by tcp_send_skb(). */
TCP_SKB_CB(skb)->seq = tp->write_seq;
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
tcp_send_skb(sk, skb, 0, mss_now);
- __tcp_push_pending_frames(sk, tp, mss_now);
+ __tcp_push_pending_frames(sk, tp, mss_now, 1);
}
}
@@ -979,7 +969,7 @@ void tcp_send_active_reset(struct sock *sk, int priority)
struct sk_buff *skb;
/* NOTE: No TCP options attached and we never retransmit this. */
- skb = alloc_skb(MAX_TCP_HEADER + 15, priority);
+ skb = alloc_skb(MAX_TCP_HEADER, priority);
if (!skb) {
NET_INC_STATS(TCPAbortFailed);
return;
@@ -990,7 +980,6 @@ void tcp_send_active_reset(struct sock *sk, int priority)
skb->csum = 0;
TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
TCP_SKB_CB(skb)->sacked = 0;
- TCP_SKB_CB(skb)->urg_ptr = 0;
/* Send it off. */
TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
@@ -1158,7 +1147,6 @@ int tcp_connect(struct sock *sk, struct sk_buff *buff)
TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
TCP_ECN_send_syn(tp, buff);
TCP_SKB_CB(buff)->sacked = 0;
- TCP_SKB_CB(buff)->urg_ptr = 0;
buff->csum = 0;
TCP_SKB_CB(buff)->seq = tp->write_seq++;
TCP_SKB_CB(buff)->end_seq = tp->write_seq;
@@ -1267,7 +1255,7 @@ void tcp_send_ack(struct sock *sk)
* tcp_transmit_skb() will set the ownership to this
* sock.
*/
- buff = alloc_skb(MAX_TCP_HEADER + 15, GFP_ATOMIC);
+ buff = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
if (buff == NULL) {
tcp_schedule_ack(tp);
tp->ack.ato = TCP_ATO_MIN;
@@ -1280,7 +1268,6 @@ void tcp_send_ack(struct sock *sk)
buff->csum = 0;
TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
TCP_SKB_CB(buff)->sacked = 0;
- TCP_SKB_CB(buff)->urg_ptr = 0;
/* Send it off, this clears delayed acks for us. */
TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
@@ -1291,14 +1278,22 @@ void tcp_send_ack(struct sock *sk)
/* This routine sends a packet with an out of date sequence
* number. It assumes the other end will try to ack it.
+ *
+ * Question: what should we make while urgent mode?
+ * 4.4BSD forces sending single byte of data. We cannot send
+ * out of window data, because we have SND.NXT==SND.MAX...
+ *
+ * Current solution: to send TWO zero-length segments in urgent mode:
+ * one is with SEG.SEQ=SND.UNA to deliver urgent pointer, another is
+ * out-of-date with SND.UNA-1 to probe window.
*/
-static int tcp_xmit_probe_skb(struct sock *sk)
+static int tcp_xmit_probe_skb(struct sock *sk, int urgent)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
struct sk_buff *skb;
/* We don't queue it, tcp_transmit_skb() sets ownership. */
- skb = alloc_skb(MAX_TCP_HEADER + 15, GFP_ATOMIC);
+ skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
if (skb == NULL)
return -1;
@@ -1306,14 +1301,13 @@ static int tcp_xmit_probe_skb(struct sock *sk)
skb_reserve(skb, MAX_TCP_HEADER);
skb->csum = 0;
TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
- TCP_SKB_CB(skb)->sacked = 0;
- TCP_SKB_CB(skb)->urg_ptr = 0;
+ TCP_SKB_CB(skb)->sacked = urgent;
/* Use a previous sequence. This should cause the other
* end to send an ack. Don't queue or clone SKB, just
* send it.
*/
- TCP_SKB_CB(skb)->seq = tp->snd_una - 1;
+ TCP_SKB_CB(skb)->seq = urgent ? tp->snd_una : tp->snd_una - 1;
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
TCP_SKB_CB(skb)->when = tcp_time_stamp;
return tcp_transmit_skb(sk, skb);
@@ -1353,7 +1347,10 @@ int tcp_write_wakeup(struct sock *sk)
}
return err;
} else {
- return tcp_xmit_probe_skb(sk);
+ if (tp->urg_mode &&
+ between(tp->snd_up, tp->snd_una+1, tp->snd_una+0xFFFF))
+ tcp_xmit_probe_skb(sk, TCPCB_URG);
+ return tcp_xmit_probe_skb(sk, 0);
}
}
return -1;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index e098b9ff2..5df184df5 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -5,7 +5,7 @@
*
* The User Datagram Protocol (UDP).
*
- * Version: $Id: udp.c,v 1.90 2000/10/18 18:04:22 davem Exp $
+ * Version: $Id: udp.c,v 1.91 2000/11/28 13:38:38 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -989,20 +989,16 @@ static void get_udp_sock(struct sock *sp, char *tmpbuf, int i)
{
unsigned int dest, src;
__u16 destp, srcp;
- int timer_active;
- unsigned long timer_expires;
dest = sp->daddr;
src = sp->rcv_saddr;
destp = ntohs(sp->dport);
srcp = ntohs(sp->sport);
- timer_active = timer_pending(&sp->timer) ? 2 : 0;
- timer_expires = (timer_active == 2 ? sp->timer.expires : jiffies);
sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
i, src, srcp, dest, destp, sp->state,
atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
- timer_active, timer_expires-jiffies, 0,
+ 0, 0L, 0,
sock_i_uid(sp), 0,
sock_i_ino(sp),
atomic_read(&sp->refcnt), sp);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4f3113872..d342d5642 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -6,7 +6,7 @@
* Pedro Roque <roque@di.fc.ul.pt>
* Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
*
- * $Id: addrconf.c,v 1.58 2000/05/03 06:37:07 davem Exp $
+ * $Id: addrconf.c,v 1.59 2000/11/28 11:39:43 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,6 +21,7 @@
* <chexum@bankinf.banki.hu>
* Andi Kleen : kill doube kfree on module
* unload.
+ * Maciej W. Rozycki : FDDI support
*/
#include <linux/config.h>
@@ -667,6 +668,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
{
switch (dev->type) {
case ARPHRD_ETHER:
+ case ARPHRD_FDDI:
case ARPHRD_IEEE802_TR:
if (dev->addr_len != ETH_ALEN)
return -1;
@@ -1207,7 +1209,8 @@ static void addrconf_dev_config(struct net_device *dev)
ASSERT_RTNL();
- if ((dev->type != ARPHRD_ETHER) &&
+ if ((dev->type != ARPHRD_ETHER) &&
+ (dev->type != ARPHRD_FDDI) &&
(dev->type != ARPHRD_IEEE802_TR)) {
/* Alas, we support only Ethernet autoconfiguration. */
return;
@@ -2008,6 +2011,7 @@ void __init addrconf_init(void)
init_loopback(dev);
break;
case ARPHRD_ETHER:
+ case ARPHRD_FDDI:
case ARPHRD_IEEE802_TR:
addrconf_dev_config(dev);
break;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 986cd023f..8e6865366 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: datagram.c,v 1.20 2000/07/08 00:20:43 davem Exp $
+ * $Id: datagram.c,v 1.21 2000/11/28 13:42:08 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -183,10 +183,14 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
err = copied;
/* Reset and regenerate socket error */
+ spin_lock_irq(&sk->error_queue.lock);
sk->err = 0;
if ((skb2 = skb_peek(&sk->error_queue)) != NULL) {
sk->err = SKB_EXT_ERR(skb2)->ee.ee_errno;
+ spin_unlock_irq(&sk->error_queue.lock);
sk->error_report(sk);
+ } else {
+ spin_unlock_irq(&sk->error_queue.lock);
}
out_free_skb:
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 6c6ae227f..c4e3f6f1a 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -6,7 +6,7 @@
* Pedro Roque <roque@di.fc.ul.pt>
* Ian P. Morris <I.P.Morris@soton.ac.uk>
*
- * $Id: ip6_input.c,v 1.17 2000/02/27 19:42:53 davem Exp $
+ * $Id: ip6_input.c,v 1.18 2000/12/08 17:15:54 davem Exp $
*
* Based in linux/net/ipv4/ip_input.c
*
@@ -146,11 +146,6 @@ static inline int ip6_input_finish(struct sk_buff *skb)
}
len = skb->tail - skb->h.raw;
- if (skb->rx_dev) {
- dev_put(skb->rx_dev);
- skb->rx_dev = NULL;
- }
-
raw_sk = raw_v6_htable[nexthdr&(MAX_INET_PROTOS-1)];
if (raw_sk)
raw_sk = ipv6_raw_deliver(skb, nexthdr, len);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 87c9f1eb4..e93799a37 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -7,7 +7,7 @@
*
* Based on linux/net/ipv4/ip_sockglue.c
*
- * $Id: ipv6_sockglue.c,v 1.33 2000/02/27 19:42:54 davem Exp $
+ * $Id: ipv6_sockglue.c,v 1.34 2000/11/28 13:44:28 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -443,7 +443,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, char *optval,
len -= msg.msg_controllen;
return put_user(len, optlen);
}
- case IP_MTU:
+ case IPV6_MTU:
{
struct dst_entry *dst;
val = 0;
@@ -458,6 +458,63 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, char *optval,
return -ENOTCONN;
break;
}
+
+ case IPV6_PKTINFO:
+ val = np->rxopt.bits.rxinfo;
+ break;
+
+ case IPV6_HOPLIMIT:
+ val = np->rxopt.bits.rxhlim;
+ break;
+
+ case IPV6_RTHDR:
+ val = np->rxopt.bits.srcrt;
+ break;
+
+ case IPV6_HOPOPTS:
+ val = np->rxopt.bits.hopopts;
+ break;
+
+ case IPV6_AUTHHDR:
+ val = np->rxopt.bits.authhdr;
+ break;
+
+ case IPV6_DSTOPTS:
+ val = np->rxopt.bits.dstopts;
+ break;
+
+ case IPV6_FLOWINFO:
+ val = np->rxopt.bits.rxflow;
+ break;
+
+ case IPV6_UNICAST_HOPS:
+ val = np->hop_limit;
+ break;
+
+ case IPV6_MULTICAST_HOPS:
+ val = np->mcast_hops;
+ break;
+
+ case IPV6_MULTICAST_LOOP:
+ val = np->mc_loop;
+ break;
+
+ case IPV6_MULTICAST_IF:
+ val = np->mcast_oif;
+ break;
+
+ case IPV6_MTU_DISCOVER:
+ val = np->pmtudisc;
+ break;
+
+ case IPV6_RECVERR:
+ val = np->recverr;
+ break;
+
+ case IPV6_FLOWINFO_SEND:
+ val = np->sndflow;
+ break;
+
default:
#ifdef CONFIG_NETFILTER
lock_sock(sk);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 520a3b6c1..7c3bfca37 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -654,14 +654,23 @@ static void ndisc_router_discovery(struct sk_buff *skb)
*/
if (in6_dev->nd_parms) {
- if (ra_msg->retrans_timer)
- in6_dev->nd_parms->retrans_time = (ntohl(ra_msg->retrans_timer)*HZ)/1000;
+ __u32 rtime = ntohl(ra_msg->retrans_timer);
- if (ra_msg->reachable_time) {
- __u32 rtime = (ntohl(ra_msg->reachable_time)*HZ)/1000;
+ if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/HZ) {
+ rtime = (rtime*HZ)/1000;
+ if (rtime < HZ/10)
+ rtime = HZ/10;
+ in6_dev->nd_parms->retrans_time = rtime;
+ }
+
+ rtime = ntohl(ra_msg->reachable_time);
+ if (rtime && rtime/1000 < MAX_SCHEDULE_TIMEOUT/(3*HZ)) {
+ rtime = (rtime*HZ)/1000;
- if (rtime &&
- rtime != in6_dev->nd_parms->base_reachable_time) {
+ if (rtime < HZ/10)
+ rtime = HZ/10;
+
+ if (rtime != in6_dev->nd_parms->base_reachable_time) {
in6_dev->nd_parms->base_reachable_time = rtime;
in6_dev->nd_parms->gc_staletime = 3 * rtime;
in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
@@ -1050,11 +1059,9 @@ int ndisc_rcv(struct sk_buff *skb, unsigned long len)
neigh_release(neigh);
}
} else {
- /* Hack. It will be freed upon exit from
- ndisc_rcv
- */
- atomic_inc(&skb->users);
- pneigh_enqueue(&nd_tbl, in6_dev->nd_parms, skb);
+ struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
+ if (n)
+ pneigh_enqueue(&nd_tbl, in6_dev->nd_parms, n);
in6_dev_put(in6_dev);
return 0;
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 43ef2e87d..e934897ec 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -7,7 +7,7 @@
*
* Adapted from linux/net/ipv4/raw.c
*
- * $Id: raw.c,v 1.41 2000/10/18 18:04:23 davem Exp $
+ * $Id: raw.c,v 1.42 2000/11/28 13:38:38 davem Exp $
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
@@ -743,15 +743,11 @@ static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i)
{
struct in6_addr *dest, *src;
__u16 destp, srcp;
- int sock_timer_active;
- unsigned long timer_expires;
dest = &sp->net_pinfo.af_inet6.daddr;
src = &sp->net_pinfo.af_inet6.rcv_saddr;
destp = 0;
srcp = sp->num;
- sock_timer_active = timer_pending(&sp->timer) ? 2 : 0;
- timer_expires = (sock_timer_active == 2 ? sp->timer.expires : jiffies);
sprintf(tmpbuf,
"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
"%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
@@ -762,7 +758,7 @@ static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i)
dest->s6_addr32[2], dest->s6_addr32[3], destp,
sp->state,
atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
- sock_timer_active, timer_expires-jiffies, 0,
+ 0, 0L, 0,
sock_i_uid(sp), 0,
sock_i_ino(sp),
atomic_read(&sp->refcnt), sp);
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 01000f862..0529aa480 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: reassembly.c,v 1.19 2000/07/11 22:35:24 davem Exp $
+ * $Id: reassembly.c,v 1.22 2000/12/08 17:41:54 davem Exp $
*
* Based on: net/ipv4/ip_fragment.c
*
@@ -78,7 +78,6 @@ struct frag_queue
struct sk_buff *fragments;
int len;
int meat;
- struct net_device *dev;
int iif;
__u8 last_in; /* has first/last segment arrived? */
#define COMPLETE 4
@@ -287,6 +286,9 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash,
#endif
fq = fq_in;
+ if (!mod_timer(&fq->timer, jiffies + sysctl_ip6frag_time))
+ atomic_inc(&fq->refcnt);
+
atomic_inc(&fq->refcnt);
if((fq->next = ip6_frag_hash[hash]) != NULL)
fq->next->pprev = &fq->next;
@@ -356,9 +358,6 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
if (fq->last_in & COMPLETE)
goto err;
- if (!mod_timer(&fq->timer, jiffies + sysctl_ip6frag_time))
- atomic_inc(&fq->refcnt);
-
offset = ntohs(fhdr->frag_off) & ~0x7;
end = offset + (ntohs(skb->nh.ipv6h->payload_len) -
((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1)));
@@ -476,8 +475,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
else
fq->fragments = skb;
- fq->dev = skb->dev;
fq->iif = skb->dev->ifindex;
+ skb->dev = NULL;
fq->meat += skb->len;
atomic_add(skb->truesize, &ip6_frag_mem);
@@ -507,7 +506,8 @@ err:
* queue is eligible for reassembly i.e. it is not COMPLETE,
* the last and the first frames arrived and all the bits are here.
*/
-static u8* ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in)
+static u8 *ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
+ struct net_device *dev)
{
struct sk_buff *fp, *head = fq->fragments;
struct sk_buff *skb;
@@ -541,7 +541,7 @@ static u8* ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in)
skb->mac.raw = skb->data;
skb->nh.ipv6h = (struct ipv6hdr *) skb->data;
- skb->dev = fq->dev;
+ skb->dev = dev;
skb->protocol = __constant_htons(ETH_P_IPV6);
skb->pkt_type = head->pkt_type;
FRAG6_CB(skb)->h = FRAG6_CB(head)->h;
@@ -579,6 +579,7 @@ u8* ipv6_reassembly(struct sk_buff **skbp, __u8 *nhptr)
{
struct sk_buff *skb = *skbp;
struct frag_hdr *fhdr = (struct frag_hdr *) (skb->h.raw);
+ struct net_device *dev = skb->dev;
struct frag_queue *fq;
struct ipv6hdr *hdr;
@@ -616,7 +617,7 @@ u8* ipv6_reassembly(struct sk_buff **skbp, __u8 *nhptr)
if (fq->last_in == (FIRST_IN|LAST_IN) &&
fq->meat == fq->len)
- ret = ip6_frag_reasm(fq, skbp);
+ ret = ip6_frag_reasm(fq, skbp, dev);
spin_unlock(&fq->lock);
fq_put(fq);
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index f263a3197..d77890b26 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -6,12 +6,16 @@
* Pedro Roque <roque@di.fc.ul.pt>
* Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
*
- * $Id: sit.c,v 1.45 2000/10/28 17:19:25 davem Exp $
+ * $Id: sit.c,v 1.47 2000/11/28 13:49:22 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * Changes:
+ * Roger Venning <r.venning@telstra.com>: 6to4 support
+ * Nate Thompson <nate@thebog.net>: 6to4 support
*/
#define __NO_VERSION__
@@ -176,7 +180,7 @@ struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create)
nt = (struct ip_tunnel*)dev->priv;
nt->dev = dev;
dev->init = ipip6_tunnel_init;
- dev->new_style = 1;
+ dev->features |= NETIF_F_DYNALLOC;
memcpy(&nt->parms, parms, sizeof(*parms));
strcpy(dev->name, nt->parms.name);
if (dev->name[0] == 0) {
@@ -423,6 +427,21 @@ static inline int do_ip_send(struct sk_buff *skb)
return ip_send(skb);
}
+
+/* Returns the embedded IPv4 address if the IPv6 address
+ comes from 6to4 (draft-ietf-ngtrans-6to4-04) addr space */
+
+static inline u32 try_6to4(struct in6_addr *v6dst)
+{
+ u32 dst = 0;
+
+ if (v6dst->s6_addr16[0] == htons(0x2002)) {
+ /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
+ memcpy(&dst, &v6dst->s6_addr16[1], 4);
+ }
+ return dst;
+}
+
/*
* This function assumes it is being called from dev_queue_xmit()
* and that skb is filled properly by that function.
@@ -452,6 +471,9 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->protocol != __constant_htons(ETH_P_IPV6))
goto tx_error;
+ if (!dst)
+ dst = try_6to4(&iph6->daddr);
+
if (!dst) {
struct neighbour *neigh = NULL;
@@ -481,6 +503,10 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
tunnel->stat.tx_carrier_errors++;
goto tx_error_icmp;
}
+ if (rt->rt_type != RTN_UNICAST) {
+ tunnel->stat.tx_carrier_errors++;
+ goto tx_error_icmp;
+ }
tdev = rt->u.dst.dev;
if (tdev == dev) {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b830884e8..1b0684987 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: tcp_ipv6.c,v 1.126 2000/10/18 18:04:23 davem Exp $
+ * $Id: tcp_ipv6.c,v 1.128 2000/12/08 17:15:54 davem Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
@@ -1157,11 +1157,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (req == NULL)
goto drop;
- tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
+ tcp_clear_options(&tp);
tp.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
tp.user_mss = sk->tp_pinfo.af_tcp.user_mss;
- tcp_parse_options(skb, &tp);
+ tcp_parse_options(skb, &tp, 0);
tcp_openreq_init(req, &tp, skb);
@@ -1576,6 +1576,8 @@ process:
if(sk->state == TCP_TIME_WAIT)
goto do_time_wait;
+ skb->dev = NULL;
+
bh_lock_sock(sk);
ret = 0;
if (!sk->lock.users) {
@@ -1924,7 +1926,8 @@ static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i)
tp->probes_out,
sock_i_ino(sp),
atomic_read(&sp->refcnt), sp,
- tp->rto, tp->ack.ato, tp->ack.quick, tp->ack.pingpong, sp->sndbuf
+ tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
+ tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
);
}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 187db4414..fbf0c31f6 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -7,7 +7,7 @@
*
* Based on linux/ipv4/udp.c
*
- * $Id: udp.c,v 1.58 2000/10/18 18:04:23 davem Exp $
+ * $Id: udp.c,v 1.59 2000/11/28 13:38:38 davem Exp $
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
@@ -906,15 +906,11 @@ static void get_udp6_sock(struct sock *sp, char *tmpbuf, int i)
{
struct in6_addr *dest, *src;
__u16 destp, srcp;
- int sock_timer_active;
- unsigned long timer_expires;
dest = &sp->net_pinfo.af_inet6.daddr;
src = &sp->net_pinfo.af_inet6.rcv_saddr;
destp = ntohs(sp->dport);
srcp = ntohs(sp->sport);
- sock_timer_active = timer_pending(&sp->timer) ? 2 : 0;
- timer_expires = (sock_timer_active == 2 ? sp->timer.expires : jiffies);
sprintf(tmpbuf,
"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
"%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
@@ -925,7 +921,7 @@ static void get_udp6_sock(struct sock *sp, char *tmpbuf, int i)
dest->s6_addr32[2], dest->s6_addr32[3], destp,
sp->state,
atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
- sock_timer_active, timer_expires-jiffies, 0,
+ 0, 0L, 0,
sock_i_uid(sp), 0,
sock_i_ino(sp),
atomic_read(&sp->refcnt), sp);
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 2fc3ea46c..26cc63348 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -53,6 +53,14 @@
* Fixed connecting to primary net,
* Automatic binding on send & receive,
* Martijn van Oosterhout <kleptogimp@geocities.com>
+ * Revision 042: Multithreading - use spinlocks and refcounting to
+ * protect some structures: ipx_interface sock list, list
+ * of ipx interfaces, etc.
+ * Bugfixes - do refcounting on net_devices, check function
+ * results, etc. Thanks to davem and freitag for
+ * suggestions and guidance.
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>,
+ * November, 2000
*
* Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
* pair. Also, now usage count is managed this way
@@ -104,24 +112,33 @@ static void ipx_proto_finito(void);
#endif /* def MODULE */
/* Configuration Variables */
-static unsigned char ipxcfg_max_hops = 16;
-static char ipxcfg_auto_select_primary = 0;
-static char ipxcfg_auto_create_interfaces = 0;
+static unsigned char ipxcfg_max_hops = 16;
+static char ipxcfg_auto_select_primary;
+static char ipxcfg_auto_create_interfaces;
/* Global Variables */
-static struct datalink_proto *p8022_datalink = NULL;
-static struct datalink_proto *pEII_datalink = NULL;
-static struct datalink_proto *p8023_datalink = NULL;
-static struct datalink_proto *pSNAP_datalink = NULL;
+static struct datalink_proto *p8022_datalink;
+static struct datalink_proto *pEII_datalink;
+static struct datalink_proto *p8023_datalink;
+static struct datalink_proto *pSNAP_datalink;
static struct proto_ops ipx_dgram_ops;
static struct net_proto_family *spx_family_ops;
-static ipx_route *ipx_routes = NULL;
-static ipx_interface *ipx_interfaces = NULL;
-static ipx_interface *ipx_primary_net = NULL;
-static ipx_interface *ipx_internal_net = NULL;
+static ipx_route *ipx_routes;
+static rwlock_t ipx_routes_lock = RW_LOCK_UNLOCKED;
+
+static ipx_interface *ipx_interfaces;
+static spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED;
+
+static ipx_interface *ipx_primary_net;
+static ipx_interface *ipx_internal_net;
+
+#undef IPX_REFCNT_DEBUG
+#ifdef IPX_REFCNT_DEBUG
+atomic_t ipx_sock_nr;
+#endif
static int ipxcfg_set_auto_create(char val)
{
@@ -163,6 +180,26 @@ static int ipxcfg_get_config_data(ipx_config_data *arg)
* *
\**************************************************************************/
+static inline void ipxitf_hold(ipx_interface *intrfc)
+{
+ atomic_inc(&intrfc->refcnt);
+}
+
+static void ipxitf_down(ipx_interface *intrfc);
+
+static inline void ipxitf_put(ipx_interface *intrfc)
+{
+ if (atomic_dec_and_test(&intrfc->refcnt))
+ ipxitf_down(intrfc);
+}
+
+static void __ipxitf_down(ipx_interface *intrfc);
+
+static inline void __ipxitf_put(ipx_interface *intrfc)
+{
+ if (atomic_dec_and_test(&intrfc->refcnt))
+ __ipxitf_down(intrfc);
+}
/*
* Note: Sockets may not be removed _during_ an interrupt or inet_bh
* handler using this technique. They can be added although we do not
@@ -173,25 +210,19 @@ void ipx_remove_socket(struct sock *sk)
{
struct sock *s;
ipx_interface *intrfc;
- unsigned long flags;
-
- save_flags(flags);
- cli();
/* Determine interface with which socket is associated */
intrfc = sk->protinfo.af_ipx.intrfc;
if(intrfc == NULL)
- {
- restore_flags(flags);
return;
- }
+ ipxitf_hold(intrfc);
+ spin_lock_bh(&intrfc->if_sklist_lock);
s = intrfc->if_sklist;
if(s == sk)
{
intrfc->if_sklist = s->next;
- restore_flags(flags);
- return;
+ goto out;
}
while(s && s->next)
@@ -199,29 +230,28 @@ void ipx_remove_socket(struct sock *sk)
if(s->next == sk)
{
s->next = sk->next;
- restore_flags(flags);
- return;
+ goto out;
}
s = s->next;
}
- restore_flags(flags);
+out: spin_unlock_bh(&intrfc->if_sklist_lock);
+ sock_put(sk);
+ ipxitf_put(intrfc);
}
-/*
- * This is only called from user mode. Thus it protects itself against
- * interrupt users but doesn't worry about being called during work.
- * Once it is removed from the queue no interrupt or bottom half will
- * touch it and we are (fairly 8-) ) safe.
- */
static void ipx_destroy_socket(struct sock *sk)
{
- struct sk_buff *skb;
-
ipx_remove_socket(sk);
- while((skb = skb_dequeue(&sk->receive_queue)) != NULL)
- kfree_skb(skb);
-
- sk_free(sk);
+ skb_queue_purge(&sk->receive_queue);
+#ifdef IPX_REFCNT_DEBUG
+ atomic_dec(&ipx_sock_nr);
+ printk(KERN_DEBUG "IPX socket %p released, %d are still alive\n", sk,
+ atomic_read(&ipx_sock_nr));
+ if (atomic_read(&sk->refcnt) != 1)
+ printk(KERN_DEBUG "Destruction sock ipx %p delayed, cnt=%d\n",
+ sk, atomic_read(&sk->refcnt));
+#endif
+ sock_put(sk);
}
/*
@@ -230,6 +260,8 @@ static void ipx_destroy_socket(struct sock *sk)
*/
static ipx_route * ipxrtr_lookup(__u32);
+/* ipxitf_clear_primary_net has to be called with ipx_interfaces_lock held */
+
static void ipxitf_clear_primary_net(void)
{
if(ipxcfg_auto_select_primary && (ipx_interfaces != NULL))
@@ -238,7 +270,8 @@ static void ipxitf_clear_primary_net(void)
ipx_primary_net = NULL;
}
-static ipx_interface *ipxitf_find_using_phys(struct net_device *dev, unsigned short datalink)
+static ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
+ unsigned short datalink)
{
ipx_interface *i;
@@ -250,15 +283,33 @@ static ipx_interface *ipxitf_find_using_phys(struct net_device *dev, unsigned sh
return (i);
}
+static ipx_interface *ipxitf_find_using_phys(struct net_device *dev,
+ unsigned short datalink)
+{
+ ipx_interface *i;
+
+ spin_lock_bh(&ipx_interfaces_lock);
+ i = __ipxitf_find_using_phys(dev, datalink);
+ if (i)
+ ipxitf_hold(i);
+ spin_unlock_bh(&ipx_interfaces_lock);
+ return i;
+}
+
static ipx_interface *ipxitf_find_using_net(__u32 net)
{
ipx_interface *i;
- if(!net)
- return (ipx_primary_net);
-
- for(i = ipx_interfaces; i && (i->if_netnum != net); i = i->if_next)
+ spin_lock_bh(&ipx_interfaces_lock);
+ if(net)
+ for(i = ipx_interfaces; i && (i->if_netnum != net);
+ i = i->if_next)
;
+ else
+ i = ipx_primary_net;
+ if (i)
+ ipxitf_hold(i);
+ spin_unlock_bh(&ipx_interfaces_lock);
return (i);
}
@@ -268,6 +319,9 @@ static void ipxitf_insert_socket(ipx_interface *intrfc, struct sock *sk)
{
struct sock *s;
+ ipxitf_hold(intrfc);
+ sock_hold(sk);
+ spin_lock_bh(&intrfc->if_sklist_lock);
sk->protinfo.af_ipx.intrfc = intrfc;
sk->next = NULL;
if(intrfc->if_sklist == NULL)
@@ -278,9 +332,12 @@ static void ipxitf_insert_socket(ipx_interface *intrfc, struct sock *sk)
;
s->next = sk;
}
+ spin_unlock_bh(&intrfc->if_sklist_lock);
+ ipxitf_put(intrfc);
}
-static struct sock *ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
+/* caller must hold intrfc->if_sklist_lock */
+static struct sock *__ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
{
struct sock *s;
@@ -288,6 +345,19 @@ static struct sock *ipxitf_find_socket(ipx_interface *intrfc, unsigned short por
(s != NULL) && (s->protinfo.af_ipx.port != port);
s = s->next)
;
+ return s;
+}
+
+/* caller must hold a reference to intrfc */
+static struct sock *ipxitf_find_socket(ipx_interface *intrfc, unsigned short port)
+{
+ struct sock *s;
+
+ spin_lock_bh(&intrfc->if_sklist_lock);
+ s = __ipxitf_find_socket(intrfc, port);
+ if (s)
+ sock_hold(s);
+ spin_unlock_bh(&intrfc->if_sklist_lock);
return (s);
}
@@ -297,7 +367,11 @@ static struct sock *ipxitf_find_socket(ipx_interface *intrfc, unsigned short por
static struct sock *ipxitf_find_internal_socket(ipx_interface *intrfc,
unsigned char *node, unsigned short port)
{
- struct sock *s = intrfc->if_sklist;
+ struct sock *s;
+
+ ipxitf_hold(intrfc);
+ spin_lock_bh(&intrfc->if_sklist_lock);
+ s = intrfc->if_sklist;
while(s != NULL)
{
@@ -308,6 +382,8 @@ static struct sock *ipxitf_find_internal_socket(ipx_interface *intrfc,
}
s = s->next;
}
+ spin_unlock_bh(&intrfc->if_sklist_lock);
+ ipxitf_put(intrfc);
return (s);
}
@@ -315,7 +391,7 @@ static struct sock *ipxitf_find_internal_socket(ipx_interface *intrfc,
static void ipxrtr_del_routes(ipx_interface *);
-static void ipxitf_down(ipx_interface *intrfc)
+static void __ipxitf_down(ipx_interface *intrfc)
{
ipx_interface *i;
struct sock *s, *t;
@@ -323,6 +399,7 @@ static void ipxitf_down(ipx_interface *intrfc)
/* Delete all routes associated with this interface */
ipxrtr_del_routes(intrfc);
+ spin_lock_bh(&intrfc->if_sklist_lock);
/* error sockets */
for(s = intrfc->if_sklist; s != NULL; )
{
@@ -336,6 +413,7 @@ static void ipxitf_down(ipx_interface *intrfc)
t->next = NULL;
}
intrfc->if_sklist = NULL;
+ spin_unlock_bh(&intrfc->if_sklist_lock);
/* remove this interface from list */
if(intrfc == ipx_interfaces)
@@ -356,12 +434,21 @@ static void ipxitf_down(ipx_interface *intrfc)
if(intrfc == ipx_internal_net)
ipx_internal_net = NULL;
+ if (intrfc->if_dev)
+ dev_put(intrfc->if_dev);
kfree(intrfc);
MOD_DEC_USE_COUNT;
return;
}
+static void ipxitf_down(ipx_interface *intrfc)
+{
+ spin_lock_bh(&ipx_interfaces_lock);
+ __ipxitf_down(intrfc);
+ spin_unlock_bh(&ipx_interfaces_lock);
+}
+
static int ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
@@ -370,14 +457,16 @@ static int ipxitf_device_event(struct notifier_block *notifier, unsigned long ev
if(event != NETDEV_DOWN)
return NOTIFY_DONE;
+ spin_lock_bh(&ipx_interfaces_lock);
for(i = ipx_interfaces; i != NULL;)
{
tmp = i->if_next;
if(i->if_dev == dev)
- ipxitf_down(i);
+ __ipxitf_put(i);
i = tmp;
}
+ spin_unlock_bh(&ipx_interfaces_lock);
return (NOTIFY_DONE);
}
@@ -396,15 +485,19 @@ static int ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
* On input skb->sk is NULL. Nobody is charged for the memory.
*/
+/* caller must hold a reference to intrfc */
+
#ifdef CONFIG_IPX_INTERN
static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
{
struct ipxhdr *ipx = skb->nh.ipxh;
struct sock *s;
+ int ret;
int is_broadcast = (memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
IPX_NODE_LEN) == 0);
+ spin_lock_bh(&intrfc->if_sklist_lock);
s = intrfc->if_sklist;
while(s != NULL)
@@ -420,8 +513,9 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c
if(copy != 0)
{
skb1 = skb_clone(skb, GFP_ATOMIC);
+ ret = -ENOMEM;
if (skb1 == NULL)
- return -ENOMEM;
+ goto out;
}
else
{
@@ -441,7 +535,9 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c
if(copy == 0)
kfree_skb(skb);
- return (0);
+ ret = 0;
+out: spin_unlock_bh(&intrfc->if_sklist_lock);
+ return ret;
}
#else
@@ -451,6 +547,7 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c
struct ipxhdr *ipx = skb->nh.ipxh;
struct sock *sock1 = NULL, *sock2 = NULL;
struct sk_buff *skb1 = NULL, *skb2 = NULL;
+ int ret;
if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451)
{
@@ -490,10 +587,14 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c
* socket. Only these sockets have ipx_ncp_conn != 0, set
* by SIOCIPXNCPCONN.
*/
+ spin_lock_bh(&intrfc->if_sklist_lock);
for (sock1=intrfc->if_sklist;
(sock1 != NULL) &&
(sock1->protinfo.af_ipx.ipx_ncp_conn != connection);
sock1=sock1->next);
+ if (sock1)
+ sock_hold(sock1);
+ spin_unlock_bh(&intrfc->if_sklist_lock);
}
}
if (sock1 == NULL)
@@ -556,8 +657,9 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c
else
skb1 = skb;
+ ret = -ENOMEM;
if(skb1 == NULL)
- return (-ENOMEM);
+ goto out;
/* Do we need 2 SKBs? */
if(sock1 && sock2)
@@ -568,13 +670,19 @@ static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int c
if(sock1)
(void) ipxitf_def_skb_handler(sock1, skb1);
+ ret = -ENOMEM;
if(skb2 == NULL)
- return (-ENOMEM);
+ goto out;
if(sock2)
(void) ipxitf_def_skb_handler(sock2, skb2);
- return (0);
+ ret = 0;
+out: if (sock1)
+ sock_put(sock1);
+ if (sock2)
+ sock_put(sock2);
+ return ret;
}
#endif /* CONFIG_IPX_INTERN */
@@ -603,6 +711,8 @@ static struct sk_buff *ipxitf_adjust_skbuff(ipx_interface *intrfc, struct sk_buf
return (skb2);
}
+/* caller must hold a reference to intrfc */
+
static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
{
struct ipxhdr *ipx = skb->nh.ipxh;
@@ -715,6 +825,9 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
{
struct ipxhdr *ipx = skb->nh.ipxh;
ipx_interface *i;
+ int ret = 0;
+
+ ipxitf_hold(intrfc);
/* See if we should update our network number */
if(!intrfc->if_netnum /* net number of intrfc not known yet (== 0) */
@@ -738,6 +851,7 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
ipx_frame_name(i->if_dlink_type),
ipx_device_name(intrfc),
ipx_frame_name(intrfc->if_dlink_type));
+ ipxitf_put(i);
}
}
@@ -770,6 +884,7 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
*l = intrfc->if_netnum; /* insert recvd netnum into list */
ipx->ipx_tctrl++;
/* xmit on all other interfaces... */
+ spin_lock_bh(&ipx_interfaces_lock);
for(ifcs = ipx_interfaces; ifcs != NULL; ifcs = ifcs->if_next)
{
/* Except unconfigured interfaces */
@@ -785,9 +900,11 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
{
ipx->ipx_dest.net = ifcs->if_netnum;
skb2=skb_clone(skb, GFP_ATOMIC);
- ipxrtr_route_skb(skb2);
+ if (skb2)
+ ipxrtr_route_skb(skb2);
}
}
+ spin_unlock_bh(&ipx_interfaces_lock);
/* Reset network number in packet */
ipx->ipx_dest.net = intrfc->if_netnum;
@@ -806,25 +923,27 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
{
skb=skb_unshare(skb, GFP_ATOMIC);
if(skb)
- return (ipxrtr_route_skb(skb));
- else
- return (0);
+ ret = ipxrtr_route_skb(skb);
+ goto out_intrfc;
}
- kfree_skb(skb);
- return (0);
+ goto out_free_skb;
}
/* see if we should keep it */
if((memcmp(ipx_broadcast_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0)
|| (memcmp(intrfc->if_node, ipx->ipx_dest.node, IPX_NODE_LEN) == 0))
{
- return (ipxitf_demux_socket(intrfc, skb, 0));
+ ret = ipxitf_demux_socket(intrfc, skb, 0);
+ goto out_intrfc;
}
/* we couldn't pawn it off so unload it */
+out_free_skb:
kfree_skb(skb);
- return (0);
+out_intrfc:
+ ipxitf_put(intrfc);
+ return ret;
}
static void ipxitf_insert(ipx_interface *intrfc)
@@ -832,6 +951,7 @@ static void ipxitf_insert(ipx_interface *intrfc)
ipx_interface *i;
intrfc->if_next = NULL;
+ spin_lock_bh(&ipx_interfaces_lock);
if(ipx_interfaces == NULL)
ipx_interfaces = intrfc;
else
@@ -840,18 +960,18 @@ static void ipxitf_insert(ipx_interface *intrfc)
;
i->if_next = intrfc;
}
+ spin_unlock_bh(&ipx_interfaces_lock);
if(ipxcfg_auto_select_primary && (ipx_primary_net == NULL))
ipx_primary_net = intrfc;
- MOD_INC_USE_COUNT;
-
return;
}
static int ipxitf_create_internal(ipx_interface_definition *idef)
{
ipx_interface *intrfc;
+ int ret;
/* Only one primary network allowed */
if(ipx_primary_net != NULL)
@@ -860,8 +980,11 @@ static int ipxitf_create_internal(ipx_interface_definition *idef)
/* Must have a valid network number */
if(!idef->ipx_network)
return (-EADDRNOTAVAIL);
- if(ipxitf_find_using_net(idef->ipx_network) != NULL)
+ intrfc = ipxitf_find_using_net(idef->ipx_network);
+ if(intrfc != NULL) {
+ ipxitf_put(intrfc);
return (-EADDRINUSE);
+ }
intrfc = (ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
if(intrfc == NULL)
@@ -877,9 +1000,15 @@ static int ipxitf_create_internal(ipx_interface_definition *idef)
memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN);
ipx_internal_net = intrfc;
ipx_primary_net = intrfc;
+ spin_lock_init(&intrfc->if_sklist_lock);
+ atomic_set(&intrfc->refcnt, 1);
+ MOD_INC_USE_COUNT;
+ ipxitf_hold(intrfc);
ipxitf_insert(intrfc);
- return (ipxitf_add_local_route(intrfc));
+ ret = ipxitf_add_local_route(intrfc);
+ ipxitf_put(intrfc);
+ return ret;
}
static int ipx_map_frame_type(unsigned char type)
@@ -908,6 +1037,7 @@ static int ipxitf_create(ipx_interface_definition *idef)
unsigned short dlink_type = 0;
struct datalink_proto *datalink = NULL;
ipx_interface *intrfc;
+ int err;
if(idef->ipx_special == IPX_INTERNAL)
return (ipxitf_create_internal(idef));
@@ -915,11 +1045,16 @@ static int ipxitf_create(ipx_interface_definition *idef)
if((idef->ipx_special == IPX_PRIMARY) && (ipx_primary_net != NULL))
return (-EEXIST);
- if(idef->ipx_network
- && (ipxitf_find_using_net(idef->ipx_network) != NULL))
+ intrfc = ipxitf_find_using_net(idef->ipx_network);
+ if(idef->ipx_network && intrfc != NULL) {
+ ipxitf_put(intrfc);
return (-EADDRINUSE);
+ }
- dev = __dev_get_by_name(idef->ipx_device);
+ if (intrfc)
+ ipxitf_put(intrfc);
+
+ dev = dev_get_by_name(idef->ipx_device);
if(dev == NULL)
return (-ENODEV);
@@ -960,22 +1095,26 @@ static int ipxitf_create(ipx_interface_definition *idef)
break;
}
+ err = -ENETDOWN;
if(!(dev->flags & IFF_UP))
- return (-ENETDOWN);
+ goto out_dev;
/* Check addresses are suitable */
+ err = -EINVAL;
if(dev->addr_len > IPX_NODE_LEN)
- return (-EINVAL);
+ goto out_dev;
+ err = -EPROTONOSUPPORT;
if(datalink == NULL)
- return (-EPROTONOSUPPORT);
+ goto out_dev;
if((intrfc = ipxitf_find_using_phys(dev, dlink_type)) == NULL)
{
/* Ok now create */
intrfc = (ipx_interface *)kmalloc(sizeof(ipx_interface),GFP_ATOMIC);
+ err = -EAGAIN;
if(intrfc == NULL)
- return (-EAGAIN);
+ goto out_dev;
intrfc->if_dev = dev;
intrfc->if_netnum = idef->ipx_network;
intrfc->if_dlink_type = dlink_type;
@@ -995,14 +1134,26 @@ static int ipxitf_create(ipx_interface_definition *idef)
}
else
memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN);
+ spin_lock_init(&intrfc->if_sklist_lock);
+ atomic_set(&intrfc->refcnt, 1);
+ MOD_INC_USE_COUNT;
+ ipxitf_hold(intrfc);
ipxitf_insert(intrfc);
}
+
/* If the network number is known, add a route */
+ err = 0;
if(!intrfc->if_netnum)
- return (0);
-
- return (ipxitf_add_local_route(intrfc));
+ goto out_intrfc;
+
+ err = ipxitf_add_local_route(intrfc);
+out_intrfc:
+ ipxitf_put(intrfc);
+ return err;
+out_dev:
+ dev_put(dev);
+ return err;
}
static int ipxitf_delete(ipx_interface_definition *idef)
@@ -1010,33 +1161,40 @@ static int ipxitf_delete(ipx_interface_definition *idef)
struct net_device *dev = NULL;
unsigned short dlink_type = 0;
ipx_interface *intrfc;
+ int ret = 0;
+ spin_lock_bh(&ipx_interfaces_lock);
if(idef->ipx_special == IPX_INTERNAL)
{
if(ipx_internal_net != NULL)
{
- ipxitf_down(ipx_internal_net);
- return (0);
+ __ipxitf_put(ipx_internal_net);
+ goto out;
}
- return (-ENOENT);
+ ret = -ENOENT;
+ goto out;
}
dlink_type = ipx_map_frame_type(idef->ipx_dlink_type);
- if(dlink_type == 0)
- return (-EPROTONOSUPPORT);
+ if(dlink_type == 0) {
+ ret = -EPROTONOSUPPORT;
+ goto out;
+ }
dev = __dev_get_by_name(idef->ipx_device);
- if(dev == NULL)
- return (-ENODEV);
+ if(dev == NULL) {
+ ret = -ENODEV;
+ goto out;
+ }
- intrfc = ipxitf_find_using_phys(dev, dlink_type);
+ intrfc = __ipxitf_find_using_phys(dev, dlink_type);
if(intrfc != NULL)
- {
- ipxitf_down(intrfc);
- return (0);
- }
+ __ipxitf_put(intrfc);
+ else
+ ret = -EINVAL;
- return (-EINVAL);
+out: spin_unlock_bh(&ipx_interfaces_lock);
+ return ret;
}
static ipx_interface *ipxitf_auto_create(struct net_device *dev,
@@ -1089,6 +1247,9 @@ static ipx_interface *ipxitf_auto_create(struct net_device *dev,
memset(intrfc->if_node, 0, IPX_NODE_LEN);
memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
dev->dev_addr, dev->addr_len);
+ spin_lock_init(&intrfc->if_sklist_lock);
+ atomic_set(&intrfc->refcnt, 1);
+ MOD_INC_USE_COUNT;
ipxitf_insert(intrfc);
}
@@ -1151,6 +1312,7 @@ static int ipxitf_ioctl(unsigned int cmd, void *arg)
if(!copy_to_user(arg, &ifr, sizeof(ifr)))
err = 0;
+ ipxitf_put(ipxif);
return (err);
}
@@ -1187,12 +1349,16 @@ static ipx_route *ipxrtr_lookup(__u32 net)
{
ipx_route *r;
+ read_lock_bh(&ipx_routes_lock);
for(r = ipx_routes; (r != NULL) && (r->ir_net != net); r = r->ir_next)
;
+ read_unlock_bh(&ipx_routes_lock);
return (r);
}
+/* caller must hold a reference to intrfc */
+
static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc, unsigned char *node)
{
ipx_route *rt;
@@ -1204,8 +1370,11 @@ static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc, unsigned char
rt = (ipx_route *)kmalloc(sizeof(ipx_route),GFP_ATOMIC);
if(rt == NULL)
return (-EAGAIN);
+
+ write_lock_bh(&ipx_routes_lock);
rt->ir_next = ipx_routes;
ipx_routes = rt;
+ write_unlock_bh(&ipx_routes_lock);
}
else if(intrfc == ipx_internal_net)
return (-EEXIST);
@@ -1230,6 +1399,7 @@ static void ipxrtr_del_routes(ipx_interface *intrfc)
{
ipx_route **r, *tmp;
+ write_lock_bh(&ipx_routes_lock);
for(r = &ipx_routes; (tmp = *r) != NULL;)
{
if(tmp->ir_intrfc == intrfc)
@@ -1240,42 +1410,50 @@ static void ipxrtr_del_routes(ipx_interface *intrfc)
else
r = &(tmp->ir_next);
}
+ write_unlock_bh(&ipx_routes_lock);
}
static int ipxrtr_create(ipx_route_definition *rd)
{
ipx_interface *intrfc;
+ int ret;
/* Find the appropriate interface */
intrfc = ipxitf_find_using_net(rd->ipx_router_network);
if(intrfc == NULL)
return (-ENETUNREACH);
-
- return (ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node));
+ ret = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node);
+ ipxitf_put(intrfc);
+ return ret;
}
static int ipxrtr_delete(long net)
{
ipx_route **r;
ipx_route *tmp;
+ int err;
+ write_lock_bh(&ipx_routes_lock);
for(r = &ipx_routes; (tmp = *r) != NULL;)
{
if(tmp->ir_net == net)
{
/* Directly connected; can't lose route */
+ err = -EPERM;
if(!(tmp->ir_routed))
- return (-EPERM);
+ goto out;
*r = tmp->ir_next;
kfree(tmp);
- return (0);
+ err = 0;
+ goto out;
}
r = &(tmp->ir_next);
}
-
- return (-ENOENT);
+ err = -ENOENT;
+out: write_unlock_bh(&ipx_routes_lock);
+ return err;
}
/*
@@ -1352,13 +1530,14 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, stru
intrfc = rt->ir_intrfc;
}
+ ipxitf_hold(intrfc);
ipx_offset = intrfc->if_ipx_offset;
size = sizeof(struct ipxhdr) + len;
size += ipx_offset;
skb = sock_alloc_send_skb(sk, size, 0, noblock, &err);
if(skb == NULL)
- return (err);
+ goto out;
skb_reserve(skb,ipx_offset);
skb->sk = sk;
@@ -1397,7 +1576,7 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, stru
if(err)
{
kfree_skb(skb);
- return (-EFAULT);
+ goto out;
}
/* Apply checksum. Not allowed on 802.3 links. */
@@ -1406,14 +1585,15 @@ static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, stru
else
ipx->ipx_checksum = ipx_set_checksum(ipx, len + sizeof(struct ipxhdr));
- return (ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
- rt->ir_router_node : ipx->ipx_dest.node));
+ err = ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
+ rt->ir_router_node : ipx->ipx_dest.node);
+out: ipxitf_put(intrfc);
+ return err;
}
int ipxrtr_route_skb(struct sk_buff *skb)
{
struct ipxhdr *ipx = skb->nh.ipxh;
- ipx_interface *i;
ipx_route *r;
r = ipxrtr_lookup(ipx->ipx_dest.net);
@@ -1423,9 +1603,10 @@ int ipxrtr_route_skb(struct sk_buff *skb)
return (0);
}
- i = r->ir_intrfc;
- (void)ipxitf_send(i, skb, (r->ir_routed) ?
+ ipxitf_hold(r->ir_intrfc);
+ (void)ipxitf_send(r->ir_intrfc, skb, (r->ir_routed) ?
r->ir_router_node : ipx->ipx_dest.node);
+ ipxitf_put(r->ir_intrfc);
return (0);
}
@@ -1512,8 +1693,13 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset,
/* Theory.. Keep printing in the same place until we pass offset */
- len += sprintf(buffer,"%-11s%-15s%-9s%-11s%s\n", "Network",
+ len += sprintf(buffer,"%-11s%-15s%-9s%-11s%s", "Network",
"Node_Address", "Primary", "Device", "Frame_Type");
+#ifdef IPX_REFCNT_DEBUG
+ len += sprintf(buffer + len, " refcnt");
+#endif
+ strcat(buffer+len++, "\n");
+ spin_lock_bh(&ipx_interfaces_lock);
for(i = ipx_interfaces; i != NULL; i = i->if_next)
{
len += sprintf(buffer+len, "%08lX ", (long unsigned int)ntohl(i->if_netnum));
@@ -1523,9 +1709,12 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset,
len += sprintf(buffer+len, "%-9s", (i == ipx_primary_net) ?
"Yes" : "No");
len += sprintf(buffer+len, "%-11s", ipx_device_name(i));
- len += sprintf(buffer+len, "%s\n",
+ len += sprintf(buffer+len, "%-9s",
ipx_frame_name(i->if_dlink_type));
-
+#ifdef IPX_REFCNT_DEBUG
+ len += sprintf(buffer+len,"%6d",atomic_read(&i->refcnt));
+#endif
+ strcat(buffer+len++, "\n");
/* Are we still dumping unwanted data then discard the record */
pos = begin + len;
@@ -1537,6 +1726,7 @@ static int ipx_interface_get_info(char *buffer, char **start, off_t offset,
if(pos > offset + length) /* We have dumped enough */
break;
}
+ spin_unlock_bh(&ipx_interfaces_lock);
/* The data in question runs from begin to begin+len */
*start = buffer + (offset - begin); /* Start of wanted data */
@@ -1564,8 +1754,11 @@ static int ipx_get_info(char *buffer, char **start, off_t offset, int length)
"Remote_Address", "Tx_Queue", "Rx_Queue",
"State", "Uid");
+ spin_lock_bh(&ipx_interfaces_lock);
for(i = ipx_interfaces; i != NULL; i = i->if_next)
{
+ ipxitf_hold(i);
+ spin_lock_bh(&i->if_sklist_lock);
for(s = i->if_sklist; s != NULL; s = s->next)
{
#ifdef CONFIG_IPX_INTERN
@@ -1617,7 +1810,10 @@ static int ipx_get_info(char *buffer, char **start, off_t offset, int length)
if(pos > offset + length) /* We have dumped enough */
break;
}
+ spin_unlock_bh(&i->if_sklist_lock);
+ ipxitf_put(i);
}
+ spin_unlock_bh(&ipx_interfaces_lock);
/* The data in question runs from begin to begin+len */
*start = buffer + (offset-begin);
@@ -1636,6 +1832,7 @@ static int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length)
len += sprintf(buffer,"%-11s%-13s%s\n",
"Network", "Router_Net", "Router_Node");
+ read_lock_bh(&ipx_routes_lock);
for(rt = ipx_routes; rt != NULL; rt = rt->ir_next)
{
len += sprintf(buffer+len,"%08lX ", (long unsigned int) ntohl(rt->ir_net));
@@ -1663,6 +1860,7 @@ static int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length)
if(pos > offset + length)
break;
}
+ read_unlock_bh(&ipx_routes_lock);
*start = buffer + (offset - begin);
len -= (offset - begin);
@@ -1777,7 +1975,11 @@ static int ipx_create(struct socket *sock, int protocol)
default:
return (-ESOCKTNOSUPPORT);
}
-
+#ifdef IPX_REFCNT_DEBUG
+ atomic_inc(&ipx_sock_nr);
+ printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk,
+ atomic_read(&ipx_sock_nr));
+#endif
sock_init_data(sock, sk);
sk->destruct = NULL;
sk->no_check = 1; /* Checksum off by default */
@@ -1807,14 +2009,18 @@ static int ipx_release(struct socket *sock)
return (0);
}
+/* caller must hold a referente to intrfc */
+
static unsigned short ipx_first_free_socketnum(ipx_interface *intrfc)
{
unsigned short socketNum = intrfc->if_sknum;
+ spin_lock_bh(&intrfc->if_sklist_lock);
+
if(socketNum < IPX_MIN_EPHEMERAL_SOCKET)
socketNum = IPX_MIN_EPHEMERAL_SOCKET;
- while(ipxitf_find_socket(intrfc, ntohs(socketNum)) != NULL)
+ while(__ipxitf_find_socket(intrfc, ntohs(socketNum)) != NULL)
{
if(socketNum > IPX_MAX_EPHEMERAL_SOCKET)
socketNum = IPX_MIN_EPHEMERAL_SOCKET;
@@ -1822,6 +2028,7 @@ static unsigned short ipx_first_free_socketnum(ipx_interface *intrfc)
socketNum++;
}
+ spin_unlock_bh(&intrfc->if_sklist_lock);
intrfc->if_sknum = socketNum;
return (ntohs(socketNum));
@@ -1832,6 +2039,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sock *sk;
ipx_interface *intrfc;
struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;
+ int ret;
sk = sock->sk;
@@ -1848,13 +2056,15 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if(addr->sipx_port == 0)
{
addr->sipx_port = ipx_first_free_socketnum(intrfc);
+ ret = -EINVAL;
if(addr->sipx_port == 0)
- return (-EINVAL);
+ goto out;
}
/* protect IPX system stuff like routing/sap */
+ ret = -EACCES;
if(ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET && !capable(CAP_NET_ADMIN))
- return (-EACCES);
+ goto out;
sk->protinfo.af_ipx.port = addr->sipx_port;
@@ -1866,8 +2076,9 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
* node number 0 was specified, the default is used.
*/
+ ret = -EINVAL;
if(memcmp(addr->sipx_node,ipx_broadcast_node,IPX_NODE_LEN) == 0)
- return (-EINVAL);
+ goto out;
if(memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN) == 0)
{
memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,
@@ -1878,6 +2089,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
memcpy(sk->protinfo.af_ipx.node, addr->sipx_node, IPX_NODE_LEN);
}
+ ret = -EADDRINUSE;
if(ipxitf_find_internal_socket(intrfc,
sk->protinfo.af_ipx.node,
sk->protinfo.af_ipx.port) != NULL)
@@ -1885,7 +2097,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
SOCK_DEBUG(sk,
"IPX: bind failed because port %X in use.\n",
ntohs((int)addr->sipx_port));
- return (-EADDRINUSE);
+ goto out;
}
}
else
@@ -1898,12 +2110,13 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,
IPX_NODE_LEN);
+ ret = -EADDRINUSE;
if(ipxitf_find_socket(intrfc, addr->sipx_port) != NULL)
{
SOCK_DEBUG(sk,
"IPX: bind failed because port %X in use.\n",
ntohs((int)addr->sipx_port));
- return (-EADDRINUSE);
+ goto out;
}
}
@@ -1912,11 +2125,12 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
/* Source addresses are easy. It must be our network:node pair for
an interface routed to IPX with the ipx routing ioctl() */
+ ret = -EADDRINUSE;
if(ipxitf_find_socket(intrfc, addr->sipx_port) != NULL)
{
SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n",
ntohs((int)addr->sipx_port));
- return (-EADDRINUSE);
+ goto out;
}
#endif /* CONFIG_IPX_INTERN */
@@ -1925,7 +2139,9 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
sk->zapped = 0;
SOCK_DEBUG(sk, "IPX: bound socket 0x%04X.\n", ntohs(addr->sipx_port) );
- return (0);
+ ret = 0;
+out: ipxitf_put(intrfc);
+ return ret;
}
static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
@@ -2037,6 +2253,7 @@ int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
/* NULL here for pt means the packet was looped back */
ipx_interface *intrfc;
struct ipxhdr *ipx;
+ int ret;
ipx = skb->nh.ipxh;
@@ -2066,14 +2283,16 @@ int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
&& ntohl(ipx->ipx_dest.net) != 0L)
{
intrfc = ipxitf_auto_create(dev, pt->type);
+ ipxitf_hold(intrfc);
}
if(intrfc == NULL) /* Not one of ours */
goto drop;
}
- return (ipxitf_rcv(intrfc, skb));
-
+ ret = ipxitf_rcv(intrfc, skb);
+ ipxitf_put(intrfc);
+ return ret;
drop:
kfree_skb(skb);
return (0);
@@ -2412,8 +2631,9 @@ static int __init ipx_init(void)
proc_net_create("ipx_route", 0, ipx_rt_get_info);
#endif
- printk(KERN_INFO "NET4: Linux IPX 0.38 for NET4.0\n");
+ printk(KERN_INFO "NET4: Linux IPX 0.42v4 for NET4.0\n");
printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
+ printk(KERN_INFO "IPX Portions Copyright (c) 2000 Conectiva, Inc.\n");
return 0;
}
module_init(ipx_init);
@@ -2451,21 +2671,14 @@ EXPORT_SYMBOL(ipx_unregister_spx);
#ifdef MODULE
static void ipx_proto_finito(void)
{
- ipx_interface *ifc;
+ /* no need to worry about having anything on the ipx_interfaces
+ * list, when a interface is created we increment the module
+ * usage count, so the module will only be unloaded when there
+ * are no more interfaces */
- while(ipx_interfaces)
- {
- ifc = ipx_interfaces;
- ipx_interfaces = ifc->if_next;
- ifc->if_next = NULL;
- ipxitf_down(ifc);
- }
-
-#ifdef CONFIG_PROC_FS
proc_net_remove("ipx_route");
proc_net_remove("ipx_interface");
proc_net_remove("ipx");
-#endif
unregister_netdevice_notifier(&ipx_dev_notifier);
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index ae626e08b..7ae03b0a6 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -512,7 +512,7 @@ int ircomm_proc_read(char *buf, char **start, off_t offset, int len)
#endif /* CONFIG_PROC_FS */
#ifdef MODULE
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_AUTHOR("Dag Brattli <dag@brattli.net>");
MODULE_DESCRIPTION("IrCOMM protocol");
int init_module(void)
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 67925c5b5..b88cc3d53 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -100,7 +100,11 @@ int __init ircomm_tty_init(void)
memset(&driver, 0, sizeof(struct tty_driver));
driver.magic = TTY_DRIVER_MAGIC;
driver.driver_name = "ircomm";
+#ifdef CONFIG_DEVFS_FS
+ driver.name = "ircomm%d";
+#else
driver.name = "ircomm";
+#endif
driver.major = IRCOMM_TTY_MAJOR;
driver.minor_start = IRCOMM_TTY_MINOR;
driver.num = IRCOMM_TTY_PORTS;
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index c77ca6268..714f66d02 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -421,7 +421,7 @@ int irda_device_setup(struct net_device *dev)
dev->hard_header_len = 0;
dev->addr_len = 0;
- dev->new_style = 1;
+ dev->features |= NETIF_F_DYNALLOC;
/* dev->destructor = irda_device_destructor; */
dev->type = ARPHRD_IRDA;
diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c
index a06b18582..56c3604f6 100644
--- a/net/irda/irlan/irlan_client_event.c
+++ b/net/irda/irlan/irlan_client_event.c
@@ -108,11 +108,10 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
irlan_client_get_value_confirm);
/* Get some values from peer IAS */
+ irlan_next_client_state(self, IRLAN_QUERY);
iriap_getvaluebyclass_request(self->client.iriap,
self->saddr, self->daddr,
"IrLAN", "IrDA:TinyTP:LsapSel");
-
- irlan_next_client_state(self, IRLAN_QUERY);
break;
case IRLAN_WATCHDOG_TIMEOUT:
IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index ec5f6611c..e5454d3a4 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -4,10 +4,10 @@
* Version: 0.9
* Description: IrLAP state machine implementation
* Status: Experimental.
- * Author: Dag Brattli <dagb@cs.uit.no>
+ * Author: Dag Brattli <dag@brattli.net>
* Created at: Sat Aug 16 00:59:29 1997
* Modified at: Sat Dec 25 21:07:57 1999
- * Modified by: Dag Brattli <dagb@cs.uit.no>
+ * Modified by: Dag Brattli <dag@brattli.net>
*
* Copyright (c) 1998-2000 Dag Brattli <dag@brattli.net>,
* Copyright (c) 1998 Thomas Davis <ratbert@radiks.net>
@@ -551,13 +551,15 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
* since we want to work even with devices that violate the
* timing requirements.
*/
- if (irda_device_is_receiving(self->netdev)) {
- IRDA_DEBUG(1, __FUNCTION__
+ if (irda_device_is_receiving(self->netdev) && !self->add_wait) {
+ IRDA_DEBUG(2, __FUNCTION__
"(), device is slow to answer, "
"waiting some more!\n");
irlap_start_slot_timer(self, MSECS_TO_JIFFIES(10));
+ self->add_wait = TRUE;
return ret;
}
+ self->add_wait = FALSE;
if (self->s < self->S) {
irlap_send_discovery_xid_frame(self, self->S,
@@ -1324,9 +1326,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
* of receiving a frame (page 45, IrLAP). Check that
* we only do this once for each frame.
*/
- if (irda_device_is_receiving(self->netdev) &&
- !self->add_wait)
- {
+ if (irda_device_is_receiving(self->netdev) && !self->add_wait) {
IRDA_DEBUG(1, "FINAL_TIMER_EXPIRED when receiving a "
"frame! Waiting a little bit more!\n");
irlap_start_final_timer(self, MSECS_TO_JIFFIES(300));
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 6b4c77854..576d6400e 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -5,7 +5,7 @@
*
* PACKET - implements raw packet sockets.
*
- * Version: $Id: af_packet.c,v 1.46 2000/10/24 21:26:19 davem Exp $
+ * Version: $Id: af_packet.c,v 1.47 2000/12/08 17:15:54 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -264,11 +264,6 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct
strncpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
spkt->spkt_protocol = skb->protocol;
- if (skb->rx_dev) {
- dev_put(skb->rx_dev);
- skb->rx_dev = NULL;
- }
-
/*
* Charge the memory to the socket. This is done specifically
* to prevent sockets using all the memory up.
@@ -482,17 +477,13 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
if (dev->hard_header_parse)
sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
- if (skb->rx_dev) {
- dev_put(skb->rx_dev);
- skb->rx_dev = NULL;
- }
-
#ifdef CONFIG_FILTER
if (skb->len > snaplen)
__skb_trim(skb, snaplen);
#endif
skb_set_owner_r(skb, sk);
+ skb->dev = NULL;
spin_lock(&sk->receive_queue.lock);
po->stats.tp_packets++;
__skb_queue_tail(&sk->receive_queue, skb);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index b384b754c..92a531fe0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -510,7 +510,7 @@ call_bind(struct rpc_task *task)
struct rpc_clnt *clnt = task->tk_client;
struct rpc_xprt *xprt = clnt->cl_xprt;
- task->tk_action = (xprt->connected) ? call_transmit : call_reconnect;
+ task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_reconnect;
if (!clnt->cl_port) {
task->tk_action = call_reconnect;
@@ -663,7 +663,7 @@ minor_timeout:
else if (!clnt->cl_port) {
task->tk_action = call_bind;
clnt->cl_stats->rpcretrans++;
- } else if (clnt->cl_xprt->stream && !clnt->cl_xprt->connected) {
+ } else if (!xprt_connected(clnt->cl_xprt)) {
task->tk_action = call_reconnect;
clnt->cl_stats->rpcretrans++;
} else {
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 9eee6afe2..b229ee3e1 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -82,7 +82,7 @@ spinlock_t rpc_sched_lock = SPIN_LOCK_UNLOCKED;
* This is the last-ditch buffer for NFS swap requests
*/
static u32 swap_buffer[PAGE_SIZE >> 2];
-static int swap_buffer_used;
+static long swap_buffer_used;
/*
* Make allocation of the swap_buffer SMP-safe
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index b614a1f14..dfc437522 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -392,10 +392,7 @@ static void
xprt_disconnect(struct rpc_xprt *xprt)
{
dprintk("RPC: disconnected transport %p\n", xprt);
- xprt->connected = 0;
- xprt->tcp_offset = 0;
- xprt->tcp_copied = 0;
- xprt->tcp_more = 0;
+ xprt_clear_connected(xprt);
xprt_remove_pending(xprt);
rpc_wake_up_status(&xprt->pending, -ENOTCONN);
}
@@ -412,7 +409,7 @@ xprt_reconnect(struct rpc_task *task)
int status;
dprintk("RPC: %4d xprt_reconnect %p connected %d\n",
- task->tk_pid, xprt, xprt->connected);
+ task->tk_pid, xprt, xprt_connected(xprt));
if (xprt->shutdown)
return;
@@ -445,6 +442,11 @@ xprt_reconnect(struct rpc_task *task)
xprt_disconnect(xprt);
+ /* Reset TCP record info */
+ xprt->tcp_offset = 0;
+ xprt->tcp_copied = 0;
+ xprt->tcp_more = 0;
+
/* Now connect it asynchronously. */
dprintk("RPC: %4d connecting new socket\n", task->tk_pid);
status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
@@ -468,10 +470,10 @@ xprt_reconnect(struct rpc_task *task)
}
dprintk("RPC: %4d connect status %d connected %d\n",
- task->tk_pid, status, xprt->connected);
+ task->tk_pid, status, xprt_connected(xprt));
spin_lock_bh(&xprt_sock_lock);
- if (!xprt->connected) {
+ if (!xprt_connected(xprt)) {
task->tk_timeout = xprt->timeout.to_maxval;
rpc_sleep_on(&xprt->reconn, task, xprt_reconn_status, NULL);
spin_unlock_bh(&xprt_sock_lock);
@@ -841,7 +843,7 @@ tcp_input_record(struct rpc_xprt *xprt)
if (xprt->shutdown)
return -EIO;
- if (!xprt->connected)
+ if (!xprt_connected(xprt))
return -ENOTCONN;
/* Read in a new fragment marker if necessary */
@@ -982,7 +984,7 @@ static void tcp_data_ready(struct sock *sk, int len)
dprintk("RPC: tcp_data_ready client %p\n", xprt);
dprintk("RPC: state %x conn %d dead %d zapped %d\n",
- sk->state, xprt->connected,
+ sk->state, xprt_connected(xprt),
sk->dead, sk->zapped);
out:
if (sk->sleep && waitqueue_active(sk->sleep))
@@ -999,23 +1001,26 @@ tcp_state_change(struct sock *sk)
goto out;
dprintk("RPC: tcp_state_change client %p...\n", xprt);
dprintk("RPC: state %x conn %d dead %d zapped %d\n",
- sk->state, xprt->connected,
+ sk->state, xprt_connected(xprt),
sk->dead, sk->zapped);
- spin_lock_bh(&xprt_sock_lock);
switch (sk->state) {
case TCP_ESTABLISHED:
- xprt->connected = 1;
+ if (xprt_test_and_set_connected(xprt))
+ break;
+ spin_lock_bh(&xprt_sock_lock);
if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->sending)
rpc_wake_up_task(xprt->snd_task);
rpc_wake_up(&xprt->reconn);
+ spin_unlock_bh(&xprt_sock_lock);
+ break;
+ case TCP_SYN_SENT:
+ case TCP_SYN_RECV:
break;
default:
- xprt->connected = 0;
- rpc_wake_up_status(&xprt->pending, -ENOTCONN);
+ xprt_disconnect(xprt);
break;
}
- spin_unlock_bh(&xprt_sock_lock);
out:
if (sk->sleep && waitqueue_active(sk->sleep))
wake_up_interruptible_all(sk->sleep);
@@ -1040,16 +1045,13 @@ tcp_write_space(struct sock *sk)
if (!sock_writeable(sk))
return;
- spin_lock_bh(&xprt_sock_lock);
- if (xprt->write_space)
- goto out_unlock;
-
- xprt->write_space = 1;
+ if (!xprt_test_and_set_wspace(xprt)) {
+ spin_lock_bh(&xprt_sock_lock);
+ if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->sending)
+ rpc_wake_up_task(xprt->snd_task);
+ spin_unlock_bh(&xprt_sock_lock);
+ }
- if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->sending)
- rpc_wake_up_task(xprt->snd_task);
- out_unlock:
- spin_unlock_bh(&xprt_sock_lock);
if (test_bit(SOCK_NOSPACE, &sock->flags)) {
if (sk->sleep && waitqueue_active(sk->sleep)) {
clear_bit(SOCK_NOSPACE, &sock->flags);
@@ -1073,16 +1075,13 @@ udp_write_space(struct sock *sk)
if (sock_wspace(sk) < min(sk->sndbuf,XPRT_MIN_WRITE_SPACE))
return;
- spin_lock_bh(&xprt_sock_lock);
- if (xprt->write_space)
- goto out_unlock;
-
- xprt->write_space = 1;
+ if (!xprt_test_and_set_wspace(xprt)) {
+ spin_lock_bh(&xprt_sock_lock);
+ if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->sending)
+ rpc_wake_up_task(xprt->snd_task);
+ spin_unlock_bh(&xprt_sock_lock);
+ }
- if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->sending)
- rpc_wake_up_task(xprt->snd_task);
- out_unlock:
- spin_unlock_bh(&xprt_sock_lock);
if (sk->sleep && waitqueue_active(sk->sleep))
wake_up_interruptible(sk->sleep);
}
@@ -1167,7 +1166,7 @@ xprt_transmit(struct rpc_task *task)
if (xprt->shutdown)
task->tk_status = -EIO;
- if (!xprt->connected)
+ if (!xprt_connected(xprt))
task->tk_status = -ENOTCONN;
if (task->tk_status < 0)
@@ -1211,7 +1210,7 @@ do_xprt_transmit(struct rpc_task *task)
* called xprt_sendmsg().
*/
while (1) {
- xprt->write_space = 0;
+ xprt_clear_wspace(xprt);
status = xprt_sendmsg(xprt, req);
if (status < 0)
@@ -1255,7 +1254,7 @@ do_xprt_transmit(struct rpc_task *task)
case -ENOMEM:
/* Protect against (udp|tcp)_write_space */
spin_lock_bh(&xprt_sock_lock);
- if (!xprt->write_space) {
+ if (!xprt_wspace(xprt)) {
task->tk_timeout = req->rq_timeout.to_current;
rpc_sleep_on(&xprt->sending, task, NULL, NULL);
}
@@ -1547,12 +1546,12 @@ xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
sk->data_ready = udp_data_ready;
sk->write_space = udp_write_space;
sk->no_check = UDP_CSUM_NORCV;
- xprt->connected = 1;
+ xprt_set_connected(xprt);
} else {
sk->data_ready = tcp_data_ready;
sk->state_change = tcp_state_change;
sk->write_space = tcp_write_space;
- xprt->connected = 0;
+ xprt_clear_connected(xprt);
}
/* Reset to new socket */
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 0242b12e5..8d42109d8 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -520,6 +520,7 @@ static struct sock *x25_make_new(struct sock *osk)
sk->state = TCP_ESTABLISHED;
sk->sleep = osk->sleep;
sk->zapped = osk->zapped;
+ sk->backlog_rcv = osk->backlog_rcv;
x25->t21 = osk->protinfo.x25->t21;
x25->t22 = osk->protinfo.x25->t22;
@@ -867,7 +868,7 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
return -EINVAL;
/* we currently don't support segmented records at the user interface */
- if (!(msg->msg_flags & MSG_EOR))
+ if (!(msg->msg_flags & (MSG_EOR|MSG_OOB)))
return -EINVAL;
if (sk->zapped)
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index d5aac6238..77dba8e22 100644
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -2,10 +2,15 @@
## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
## Copyright (C) 2000 Tim Waugh <twaugh@redhat.com> ##
+## ##
+## #define enhancements by Armin Kuster <akuster@mvista.com> ##
+## Copyright (c) 2000 MontaVista Software, Inc. ##
## ##
## This software falls under the GNU General Public License. ##
## Please read the COPYING file for more information ##
+# w.o. 03-11-2000: added the '-filelist' option.
+
#
# This will read a 'c' file and scan for embedded comments in the
# style of gnome comments (+minor extensions - see below).
@@ -85,7 +90,7 @@
$type_constant = "\\\%([-_\\w]+)";
$type_func = "(\\w+)\\(\\)";
$type_param = "\\\@(\\w+)";
-$type_struct = "\\\&((struct\\s*)?\\w+)";
+$type_struct = "\\\&((struct\\s*)?[_\\w]+)";
$type_env = "(\\\$\\w+)";
@@ -150,6 +155,8 @@ $output_mode = "man";
$blankline = $blankline_man;
$modulename = "API Documentation";
$function_only = 0;
+$filelist = '';
+
while ($ARGV[0] =~ m/^-(.*)/) {
$cmd = shift @ARGV;
if ($cmd eq "-html") {
@@ -186,6 +193,8 @@ while ($ARGV[0] =~ m/^-(.*)/) {
$verbose = 1;
} elsif (($cmd eq "-h") || ($cmd eq "--help")) {
usage();
+ } elsif ($cmd eq '-filelist') {
+ $filelist = shift @ARGV;
}
}
@@ -326,7 +335,8 @@ sub output_sgml {
print "<refnamediv>\n";
print " <refname>".$args{'function'}."</refname>\n";
print " <refpurpose>\n";
- print " ".$args{'purpose'}."\n";
+ print " ";
+ output_highlight ($args{'purpose'});
print " </refpurpose>\n";
print "</refnamediv>\n";
@@ -662,8 +672,14 @@ sub dump_function {
$prototype =~ s/^extern+ //;
$prototype =~ s/^inline+ //;
$prototype =~ s/^__inline__+ //;
-
- if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ s/^#define+ //; #ak added
+
+ if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
@@ -780,13 +796,28 @@ $section_default = "Description"; # default section
$section_intro = "Introduction";
$section = $section_default;
-$lineno = 0;
+if( $filelist ne '' ) {
+ open(FLIST,"<$filelist") or die "Can't open file list $filelist";
+ while(<FLIST>) {
+ chop;
+ process_file($_);
+ }
+}
+
foreach $file (@ARGV) {
chomp($file);
+ process_file($file);
+}
+
+sub process_file($) {
+ my ($file) = @_;
+
if (!open(IN,"<$file")) {
print STDERR "Error: Cannot open file $file\n";
- next;
+ return;
}
+
+ $lineno = 0;
while (<IN>) {
$lineno++;
@@ -876,7 +907,7 @@ foreach $file (@ARGV) {
elsif (/([^\{]*)/) {
$prototype .= $1;
}
- if (/\{/) {
+ if (/\{/ || /\#/) { # added for #define AK
$prototype =~ s@/\*.*?\*/@@gos; # strip comments.
$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
$prototype =~ s@^ +@@gos; # strip leading spaces