Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@penguin.transmeta.com>2002-03-07 00:59:10 -0800
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-03-07 00:59:10 -0800
commit6cfda12a768e95117898e731014c7d412c08840f (patch)
treeab77cf687901d623cb8f60c9167f1f5b84f005de
parent4c7fefc3a448c3021ffa6b2eb4ba340b4168653a (diff)
parente6adbbcd677d6ae3d99fe7906b58a8c8b5ee2692 (diff)
Merge bk://are.twiddle.net:8080/axp-2.5
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
-rw-r--r--COPYING4
-rw-r--r--Documentation/DocBook/kernel-locking.tmpl14
-rw-r--r--Documentation/filesystems/cramfs.txt34
-rw-r--r--Documentation/networking/arcnet-hardware.txt2
-rw-r--r--Documentation/networking/bonding.txt2
-rw-r--r--Documentation/networking/driver.txt84
-rw-r--r--Documentation/networking/generic-hdlc.txt115
-rw-r--r--Documentation/pci.txt7
-rw-r--r--Documentation/power/pci.txt12
-rw-r--r--Documentation/sound/alsa/CMIPCI.txt228
-rw-r--r--Documentation/sound/alsa/SB-Live-mixer.txt356
-rw-r--r--Documentation/sound/alsa/seq_oss.html409
-rw-r--r--Documentation/sound/oss/AD1816 (renamed from Documentation/sound/AD1816)0
-rw-r--r--Documentation/sound/oss/ALS (renamed from Documentation/sound/ALS)0
-rw-r--r--Documentation/sound/oss/AWE32 (renamed from Documentation/sound/AWE32)0
-rw-r--r--Documentation/sound/oss/AudioExcelDSP16 (renamed from Documentation/sound/AudioExcelDSP16)0
-rw-r--r--Documentation/sound/oss/CMI8330 (renamed from Documentation/sound/CMI8330)0
-rw-r--r--Documentation/sound/oss/CMI8338 (renamed from Documentation/sound/CMI8338)0
-rw-r--r--Documentation/sound/oss/CS4232 (renamed from Documentation/sound/CS4232)0
-rw-r--r--Documentation/sound/oss/ChangeLog.awe (renamed from Documentation/sound/ChangeLog.awe)0
-rw-r--r--Documentation/sound/oss/ChangeLog.multisound (renamed from Documentation/sound/ChangeLog.multisound)0
-rw-r--r--Documentation/sound/oss/ESS (renamed from Documentation/sound/ESS)0
-rw-r--r--Documentation/sound/oss/ESS1868 (renamed from Documentation/sound/ESS1868)0
-rw-r--r--Documentation/sound/oss/INSTALL.awe (renamed from Documentation/sound/INSTALL.awe)0
-rw-r--r--Documentation/sound/oss/Introduction (renamed from Documentation/sound/Introduction)0
-rw-r--r--Documentation/sound/oss/MAD16 (renamed from Documentation/sound/MAD16)0
-rw-r--r--Documentation/sound/oss/Maestro (renamed from Documentation/sound/Maestro)0
-rw-r--r--Documentation/sound/oss/Maestro3 (renamed from Documentation/sound/Maestro3)0
-rw-r--r--Documentation/sound/oss/MultiSound (renamed from Documentation/sound/MultiSound)0
-rw-r--r--Documentation/sound/oss/NEWS (renamed from Documentation/sound/NEWS)0
-rw-r--r--Documentation/sound/oss/NM256 (renamed from Documentation/sound/NM256)0
-rw-r--r--Documentation/sound/oss/OPL3 (renamed from Documentation/sound/OPL3)0
-rw-r--r--Documentation/sound/oss/OPL3-SA (renamed from Documentation/sound/OPL3-SA)0
-rw-r--r--Documentation/sound/oss/OPL3-SA2 (renamed from Documentation/sound/OPL3-SA2)2
-rw-r--r--Documentation/sound/oss/Opti (renamed from Documentation/sound/Opti)0
-rw-r--r--Documentation/sound/oss/PAS16 (renamed from Documentation/sound/PAS16)0
-rw-r--r--Documentation/sound/oss/PSS (renamed from Documentation/sound/PSS)0
-rw-r--r--Documentation/sound/oss/PSS-updates (renamed from Documentation/sound/PSS-updates)0
-rw-r--r--Documentation/sound/oss/README.OSS (renamed from Documentation/sound/README.OSS)2
-rw-r--r--Documentation/sound/oss/README.awe (renamed from Documentation/sound/README.awe)0
-rw-r--r--Documentation/sound/oss/README.modules (renamed from Documentation/sound/README.modules)0
-rw-r--r--Documentation/sound/oss/README.ymfsb (renamed from Documentation/sound/README.ymfsb)0
-rw-r--r--Documentation/sound/oss/SoundPro (renamed from Documentation/sound/SoundPro)0
-rw-r--r--Documentation/sound/oss/Soundblaster (renamed from Documentation/sound/Soundblaster)0
-rw-r--r--Documentation/sound/oss/Tropez+ (renamed from Documentation/sound/Tropez+)0
-rw-r--r--Documentation/sound/oss/VIA-chipset (renamed from Documentation/sound/VIA-chipset)0
-rw-r--r--Documentation/sound/oss/VIBRA16 (renamed from Documentation/sound/VIBRA16)0
-rw-r--r--Documentation/sound/oss/WaveArtist (renamed from Documentation/sound/WaveArtist)0
-rw-r--r--Documentation/sound/oss/Wavefront (renamed from Documentation/sound/Wavefront)0
-rw-r--r--Documentation/sound/oss/btaudio (renamed from Documentation/sound/btaudio)0
-rw-r--r--Documentation/sound/oss/cs46xx (renamed from Documentation/sound/cs46xx)0
-rw-r--r--Documentation/sound/oss/es1370 (renamed from Documentation/sound/es1370)0
-rw-r--r--Documentation/sound/oss/es1371 (renamed from Documentation/sound/es1371)0
-rw-r--r--Documentation/sound/oss/mwave (renamed from Documentation/sound/mwave)0
-rw-r--r--Documentation/sound/oss/solo1 (renamed from Documentation/sound/solo1)0
-rw-r--r--Documentation/sound/oss/sonicvibes (renamed from Documentation/sound/sonicvibes)0
-rw-r--r--Documentation/sound/oss/ultrasound (renamed from Documentation/sound/ultrasound)0
-rw-r--r--Documentation/sound/oss/vwsnd (renamed from Documentation/sound/vwsnd)0
-rw-r--r--Documentation/usb/ov511.txt6
-rw-r--r--MAINTAINERS12
-rw-r--r--Makefile3
-rw-r--r--arch/alpha/defconfig2
-rw-r--r--arch/alpha/kernel/entry.S2
-rw-r--r--arch/arm/config.in1
-rw-r--r--arch/arm/def-configs/shannon1
-rw-r--r--arch/arm/kernel/armksyms.c4
-rw-r--r--arch/arm/kernel/process.c3
-rw-r--r--arch/arm/mach-adifcc/mm.c2
-rw-r--r--arch/arm/mach-anakin/mm.c2
-rw-r--r--arch/arm/mach-arc/mm.c7
-rw-r--r--arch/arm/mach-clps711x/autcpu12.c2
-rw-r--r--arch/arm/mach-clps711x/edb7211-mm.c8
-rw-r--r--arch/arm/mach-sa1100/adsbitsy.c2
-rw-r--r--arch/arm/mach-sa1100/assabet.c4
-rw-r--r--arch/arm/mach-sa1100/cerf.c8
-rw-r--r--arch/arm/mach-sa1100/empeg.c2
-rw-r--r--arch/arm/mach-sa1100/flexanet.c8
-rw-r--r--arch/arm/mach-sa1100/freebird.c4
-rw-r--r--arch/arm/mach-sa1100/graphicsclient.c177
-rw-r--r--arch/arm/mach-sa1100/graphicsmaster.c81
-rw-r--r--arch/arm/mach-sa1100/h3600.c6
-rw-r--r--arch/arm/mach-sa1100/huw_webpanel.c2
-rw-r--r--arch/arm/mach-sa1100/itsy.c4
-rw-r--r--arch/arm/mach-sa1100/jornada720.c6
-rw-r--r--arch/arm/mach-sa1100/lart.c4
-rw-r--r--arch/arm/mach-sa1100/nanoengine.c6
-rw-r--r--arch/arm/mach-sa1100/neponset.c4
-rw-r--r--arch/arm/mach-sa1100/omnimeter.c2
-rw-r--r--arch/arm/mach-sa1100/pangolin.c2
-rw-r--r--arch/arm/mach-sa1100/pfs168.c28
-rw-r--r--arch/arm/mach-sa1100/pleb.c4
-rw-r--r--arch/arm/mach-sa1100/simpad.c2
-rw-r--r--arch/arm/mach-sa1100/stork.c8
-rw-r--r--arch/arm/mach-sa1100/system3.c136
-rw-r--r--arch/arm/mach-sa1100/victor.c2
-rw-r--r--arch/arm/mach-sa1100/xp860.c6
-rw-r--r--arch/arm/mach-sa1100/yopy.c6
-rw-r--r--arch/arm/mm/fault-armv.c3
-rw-r--r--arch/arm/mm/fault-common.c6
-rw-r--r--arch/arm/mm/init.c35
-rw-r--r--arch/arm/mm/minicache.c2
-rw-r--r--arch/arm/mm/mm-armv.c26
-rw-r--r--arch/arm/mm/proc-xscale.S19
-rw-r--r--arch/cris/drivers/ide.c2
-rw-r--r--arch/i386/defconfig8
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/i386/kernel/apm.c2
-rw-r--r--arch/i386/kernel/entry.S3
-rw-r--r--arch/i386/kernel/io_apic.c26
-rw-r--r--arch/i386/kernel/mpparse.c19
-rw-r--r--arch/i386/kernel/pci-pc.c94
-rw-r--r--arch/i386/kernel/smpboot.c15
-rw-r--r--arch/i386/kernel/time.c1
-rw-r--r--arch/i386/kernel/traps.c2
-rw-r--r--arch/i386/vmlinux.lds4
-rw-r--r--arch/ia64/sn/io/pci_bus_cvlink.c4
-rw-r--r--arch/mips64/sgi-ip27/ip27-rtc.c3
-rw-r--r--arch/ppc/boot/ld.script1
-rw-r--r--arch/ppc/boot/simple/misc-embedded.c4
-rw-r--r--arch/ppc/config.in3
-rw-r--r--arch/ppc/iSeries/rtc.c3
-rw-r--r--arch/ppc/kernel/entry.S21
-rw-r--r--arch/ppc/kernel/iSeries_head.S2
-rw-r--r--arch/ppc/kernel/iSeries_misc.S2
-rw-r--r--arch/ppc/kernel/idle.c147
-rw-r--r--arch/ppc/kernel/misc.S93
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c16
-rw-r--r--arch/ppc/kernel/qspan_pci.c2
-rw-r--r--arch/ppc/kernel/smp.c20
-rw-r--r--arch/ppc/lib/locks.c2
-rw-r--r--arch/ppc/mm/cachemap.c4
-rw-r--r--arch/ppc/mm/fault.c29
-rw-r--r--arch/ppc/mm/hashtable.S225
-rw-r--r--arch/ppc/mm/iSeries_hashtable.c16
-rw-r--r--arch/ppc/mm/iSeries_mmu.c7
-rw-r--r--arch/ppc/mm/init.c31
-rw-r--r--arch/ppc/mm/mmu_decl.h5
-rw-r--r--arch/ppc/mm/pgtable.c15
-rw-r--r--arch/ppc/mm/ppc_mmu.c8
-rw-r--r--arch/ppc/mm/tlb.c36
-rw-r--r--arch/ppc/vmlinux.lds4
-rw-r--r--arch/ppc64/kernel/entry.S2
-rw-r--r--arch/s390/kernel/entry.S4
-rw-r--r--arch/s390x/kernel/entry.S2
-rw-r--r--arch/sparc64/defconfig2
-rw-r--r--arch/x86_64/defconfig1
-rw-r--r--arch/x86_64/kernel/entry.S2
-rw-r--r--drivers/acorn/block/mfmhd.c2
-rw-r--r--drivers/acorn/char/mouse_ps2.c3
-rw-r--r--drivers/acorn/scsi/ecoscsi.c6
-rw-r--r--drivers/acpi/executer/exresnte.c2
-rw-r--r--drivers/block/DAC960.c2
-rw-r--r--drivers/block/acsi.c2
-rw-r--r--drivers/block/ataflop.c2
-rw-r--r--drivers/block/blkpg.c40
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/cpqarray.c2
-rw-r--r--drivers/block/floppy.c2
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/paride/pd.c2
-rw-r--r--drivers/block/paride/pf.c2
-rw-r--r--drivers/block/ps2esdi.c2
-rw-r--r--drivers/block/rd.c2
-rw-r--r--drivers/block/xd.c2
-rw-r--r--drivers/cdrom/cdrom.c6
-rw-r--r--drivers/char/acquirewdt.c3
-rw-r--r--drivers/char/agp/agpgart_be.c40
-rw-r--r--drivers/char/drm/i810_dma.c9
-rw-r--r--drivers/char/synclink.c2
-rw-r--r--drivers/ide/Config.help20
-rw-r--r--drivers/ide/Config.in6
-rw-r--r--drivers/ide/ali14xx.c4
-rw-r--r--drivers/ide/cmd640.c5
-rw-r--r--drivers/ide/cmd64x.c2
-rw-r--r--drivers/ide/dtc2278.c4
-rw-r--r--drivers/ide/hd.c2
-rw-r--r--drivers/ide/hpt366.c10
-rw-r--r--drivers/ide/hptraid.c2
-rw-r--r--drivers/ide/ht6560b.c7
-rw-r--r--drivers/ide/ide-cd.c49
-rw-r--r--drivers/ide/ide-disk.c102
-rw-r--r--drivers/ide/ide-dma.c98
-rw-r--r--drivers/ide/ide-floppy.c53
-rw-r--r--drivers/ide/ide-geometry.c8
-rw-r--r--drivers/ide/ide-pci.c197
-rw-r--r--drivers/ide/ide-probe.c128
-rw-r--r--drivers/ide/ide-proc.c9
-rw-r--r--drivers/ide/ide-tape.c57
-rw-r--r--drivers/ide/ide-taskfile.c1153
-rw-r--r--drivers/ide/ide.c919
-rw-r--r--drivers/ide/opti621.c13
-rw-r--r--drivers/ide/pdcraid.c2
-rw-r--r--drivers/ide/piix.c2
-rw-r--r--drivers/ide/qd65xx.c14
-rw-r--r--drivers/ide/rz1000.c8
-rw-r--r--drivers/ide/serverworks.c2
-rw-r--r--drivers/isdn/act2000/act2000_isa.c3
-rw-r--r--drivers/md/md.c20
-rw-r--r--drivers/message/i2o/i2o_block.c2
-rw-r--r--drivers/mtd/devices/pmc551.c2
-rw-r--r--drivers/mtd/ftl.c2
-rw-r--r--drivers/mtd/nand/spia.c2
-rw-r--r--drivers/mtd/nftlcore.c2
-rw-r--r--drivers/net/3c503.c9
-rw-r--r--drivers/net/3c505.c81
-rw-r--r--drivers/net/3c509.c11
-rw-r--r--drivers/net/8139cp.c122
-rw-r--r--drivers/net/Config.help91
-rw-r--r--drivers/net/Config.in18
-rw-r--r--drivers/net/Makefile16
-rw-r--r--drivers/net/ac3200.c9
-rw-r--r--drivers/net/e100/Makefile16
-rw-r--r--drivers/net/e100/e100.h1033
-rw-r--r--drivers/net/e100/e100_config.c596
-rw-r--r--drivers/net/e100/e100_config.h206
-rw-r--r--drivers/net/e100/e100_eeprom.c614
-rw-r--r--drivers/net/e100/e100_main.c3797
-rw-r--r--drivers/net/e100/e100_phy.c1133
-rw-r--r--drivers/net/e100/e100_phy.h183
-rw-r--r--drivers/net/e100/e100_proc.c925
-rw-r--r--drivers/net/e100/e100_ucode.h411
-rw-r--r--drivers/net/e100/e100_vendor.h348
-rw-r--r--drivers/net/e1000/e1000_main.c19
-rw-r--r--drivers/net/e2100.c11
-rw-r--r--drivers/net/eepro100.c22
-rw-r--r--drivers/net/es3210.c9
-rw-r--r--drivers/net/hamradio/6pack.c1
-rw-r--r--drivers/net/hamradio/baycom_epp.c1
-rw-r--r--drivers/net/hamradio/bpqether.c1
-rw-r--r--drivers/net/hamradio/hdlcdrv.c1
-rw-r--r--drivers/net/hamradio/mkiss.c1
-rw-r--r--drivers/net/hamradio/scc.c1
-rw-r--r--drivers/net/hamradio/yam.c1
-rw-r--r--drivers/net/hp-plus.c7
-rw-r--r--drivers/net/hp.c7
-rw-r--r--drivers/net/irda/ali-ircc.c1
-rw-r--r--drivers/net/irda/irda-usb.c88
-rw-r--r--drivers/net/irda/nsc-ircc.c1
-rw-r--r--drivers/net/irda/sa1100_ir.c2
-rw-r--r--drivers/net/irda/smc-ircc.c1
-rw-r--r--drivers/net/irda/toshoboe.c4
-rw-r--r--drivers/net/irda/vlsi_ir.c1
-rw-r--r--drivers/net/irda/w83977af_ir.c1
-rw-r--r--drivers/net/lne390.c7
-rw-r--r--drivers/net/lp486e.c1
-rw-r--r--drivers/net/ne.c9
-rw-r--r--drivers/net/ne2k-pci.c6
-rw-r--r--drivers/net/ne3210.c9
-rw-r--r--drivers/net/pcmcia/Config.in5
-rw-r--r--drivers/net/pcmcia/Makefile5
-rw-r--r--drivers/net/pcnet32.c411
-rw-r--r--drivers/net/ppp_deflate.c44
-rw-r--r--drivers/net/saa9730.c1
-rw-r--r--drivers/net/sk98lin/skge.c42
-rw-r--r--drivers/net/smc-ultra.c7
-rw-r--r--drivers/net/smc-ultra32.c4
-rw-r--r--drivers/net/starfire.c66
-rw-r--r--drivers/net/tg3.c5925
-rw-r--r--drivers/net/tg3.h1851
-rw-r--r--drivers/net/tokenring/lanstreamer.c230
-rw-r--r--drivers/net/tokenring/lanstreamer.h34
-rw-r--r--drivers/net/tulip/ChangeLog7
-rw-r--r--drivers/net/tulip/Config.help110
-rw-r--r--drivers/net/tulip/Config.in27
-rw-r--r--drivers/net/tulip/Makefile39
-rw-r--r--drivers/net/tulip/de2104x.c (renamed from drivers/net/de2104x.c)0
-rw-r--r--drivers/net/tulip/de4x5.c (renamed from drivers/net/de4x5.c)34
-rw-r--r--drivers/net/tulip/de4x5.h (renamed from drivers/net/de4x5.h)0
-rw-r--r--drivers/net/tulip/dmfe.c (renamed from drivers/net/dmfe.c)2
-rw-r--r--drivers/net/tulip/tulip_core.c65
-rw-r--r--drivers/net/tulip/winbond-840.c (renamed from drivers/net/winbond-840.c)0
-rw-r--r--drivers/net/tulip/xircom_cb.c (renamed from drivers/net/pcmcia/xircom_cb.c)660
-rw-r--r--drivers/net/tulip/xircom_tulip_cb.c (renamed from drivers/net/pcmcia/xircom_tulip_cb.c)0
-rw-r--r--drivers/net/wan/Config.help5
-rw-r--r--drivers/net/wan/Config.in15
-rw-r--r--drivers/net/wan/Makefile14
-rw-r--r--drivers/net/wan/c101.c117
-rw-r--r--drivers/net/wan/dscc4.c127
-rw-r--r--drivers/net/wan/farsync.c548
-rw-r--r--drivers/net/wan/farsync.h5
-rw-r--r--drivers/net/wan/hd64570.h8
-rw-r--r--drivers/net/wan/hd6457x.c250
-rw-r--r--drivers/net/wan/hdlc.c1453
-rw-r--r--drivers/net/wan/hdlc_cisco.c293
-rw-r--r--drivers/net/wan/hdlc_fr.c842
-rw-r--r--drivers/net/wan/hdlc_generic.c188
-rw-r--r--drivers/net/wan/hdlc_ppp.c119
-rw-r--r--drivers/net/wan/hdlc_raw.c84
-rw-r--r--drivers/net/wan/hdlc_x25.c219
-rw-r--r--drivers/net/wan/n2.c118
-rw-r--r--drivers/net/wan/sdla_x25.c4
-rw-r--r--drivers/net/wd.c9
-rw-r--r--drivers/net/wireless/orinoco.c1
-rw-r--r--drivers/pci/pci.c112
-rw-r--r--drivers/pci/pci.ids18
-rw-r--r--drivers/pcmcia/Config.in1
-rw-r--r--drivers/pcmcia/Makefile25
-rw-r--r--drivers/pcmcia/sa1100.h94
-rw-r--r--drivers/pcmcia/sa1100_adsbitsy.c223
-rw-r--r--drivers/pcmcia/sa1100_assabet.c257
-rw-r--r--drivers/pcmcia/sa1100_badge4.c186
-rw-r--r--drivers/pcmcia/sa1100_cerf.c153
-rw-r--r--drivers/pcmcia/sa1100_flexanet.c194
-rw-r--r--drivers/pcmcia/sa1100_freebird.c106
-rw-r--r--drivers/pcmcia/sa1100_generic.c1349
-rw-r--r--drivers/pcmcia/sa1100_generic.h77
-rw-r--r--drivers/pcmcia/sa1100_graphicsclient.c56
-rw-r--r--drivers/pcmcia/sa1100_graphicsmaster.c223
-rw-r--r--drivers/pcmcia/sa1100_h3600.c272
-rw-r--r--drivers/pcmcia/sa1100_jornada720.c225
-rw-r--r--drivers/pcmcia/sa1100_neponset.c346
-rw-r--r--drivers/pcmcia/sa1100_pangolin.c87
-rw-r--r--drivers/pcmcia/sa1100_pfs168.c227
-rw-r--r--drivers/pcmcia/sa1100_shannon.c177
-rw-r--r--drivers/pcmcia/sa1100_simpad.c62
-rw-r--r--drivers/pcmcia/sa1100_stork.c120
-rw-r--r--drivers/pcmcia/sa1100_system3.c131
-rw-r--r--drivers/pcmcia/sa1100_xp860.c257
-rw-r--r--drivers/pcmcia/sa1100_yopy.c110
-rw-r--r--drivers/pcmcia/sa1111_generic.c180
-rw-r--r--drivers/pcmcia/sa1111_generic.h7
-rw-r--r--drivers/pnp/pnpbios_core.c5
-rw-r--r--drivers/pnp/quirks.c6
-rw-r--r--drivers/s390/block/dasd.c4
-rw-r--r--drivers/s390/char/tape34xx.c4
-rw-r--r--drivers/s390/misc/chandev.c2
-rw-r--r--drivers/s390/net/ctctty.c2
-rw-r--r--drivers/sbus/char/jsflash.c2
-rw-r--r--drivers/scsi/3w-xxxx.c868
-rw-r--r--drivers/scsi/3w-xxxx.h56
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.c2
-rw-r--r--drivers/scsi/ide-scsi.c33
-rw-r--r--drivers/scsi/scsi.c93
-rw-r--r--drivers/scsi/scsi.h10
-rw-r--r--drivers/scsi/scsi_error.c63
-rw-r--r--drivers/scsi/scsi_syms.c5
-rw-r--r--drivers/scsi/sd.c2
-rw-r--r--drivers/scsi/sr.c236
-rw-r--r--drivers/scsi/sr.h2
-rw-r--r--drivers/scsi/sr_ioctl.c91
-rw-r--r--drivers/scsi/sr_vendor.c70
-rw-r--r--drivers/telephony/Config.help5
-rw-r--r--drivers/telephony/ixj.c2
-rw-r--r--drivers/usb/hid-core.c2
-rw-r--r--drivers/usb/ov511.c1973
-rw-r--r--drivers/usb/ov511.h82
-rw-r--r--drivers/usb/storage/isd200.c2
-rw-r--r--drivers/usb/storage/transport.c4
-rw-r--r--drivers/video/vesafb.c2
-rw-r--r--fs/block_dev.c21
-rw-r--r--fs/coda/cache.c4
-rw-r--r--fs/coda/cnode.c22
-rw-r--r--fs/coda/coda_linux.c27
-rw-r--r--fs/coda/dir.c354
-rw-r--r--fs/coda/file.c14
-rw-r--r--fs/coda/inode.c7
-rw-r--r--fs/coda/pioctl.c9
-rw-r--r--fs/coda/psdev.c20
-rw-r--r--fs/coda/sysctl.c62
-rw-r--r--fs/coda/upcall.c71
-rw-r--r--fs/cramfs/README22
-rw-r--r--fs/cramfs/inode.c7
-rw-r--r--fs/exec.c63
-rw-r--r--fs/ext2/ext2.h1
-rw-r--r--fs/ext2/fsync.c5
-rw-r--r--fs/hpfs/ea.c4
-rw-r--r--fs/inode.c6
-rw-r--r--fs/intermezzo/kml_reint.c3
-rw-r--r--fs/intermezzo/presto.c10
-rw-r--r--fs/intermezzo/vfs.c108
-rw-r--r--fs/jffs2/compr_zlib.c110
-rw-r--r--fs/jffs2/nodelist.h5
-rw-r--r--fs/jffs2/super.c7
-rw-r--r--fs/jfs/jfs_dtree.c50
-rw-r--r--fs/jfs/jfs_dtree.h4
-rw-r--r--fs/namei.c119
-rw-r--r--fs/namespace.c38
-rw-r--r--fs/nfsd/export.c7
-rw-r--r--fs/open.c26
-rw-r--r--fs/partitions/Config.in2
-rw-r--r--fs/partitions/check.c25
-rw-r--r--fs/partitions/check.h6
-rw-r--r--fs/partitions/msdos.c56
-rw-r--r--fs/reiserfs/fix_node.c2
-rw-r--r--fs/reiserfs/inode.c2
-rw-r--r--fs/reiserfs/journal.c69
-rw-r--r--fs/reiserfs/super.c10
-rw-r--r--fs/smbfs/ChangeLog13
-rw-r--r--fs/smbfs/cache.c2
-rw-r--r--fs/smbfs/dir.c2
-rw-r--r--fs/smbfs/file.c25
-rw-r--r--fs/smbfs/inode.c38
-rw-r--r--fs/smbfs/proc.c647
-rw-r--r--fs/smbfs/proto.h6
-rw-r--r--fs/super.c33
-rw-r--r--include/asm-arm/arch-sa1100/graphicsclient.h9
-rw-r--r--include/asm-arm/arch-sa1100/irqs.h3
-rw-r--r--include/asm-arm/arch-sa1100/system3.h18
-rw-r--r--include/asm-arm/pgalloc.h120
-rw-r--r--include/asm-arm/pgtable.h13
-rw-r--r--include/asm-arm/proc-armv/pgalloc.h39
-rw-r--r--include/asm-arm/proc-armv/pgtable.h2
-rw-r--r--include/asm-cris/ide.h3
-rw-r--r--include/asm-i386/io.h62
-rw-r--r--include/asm-i386/mpspec.h3
-rw-r--r--include/asm-i386/siginfo.h1
-rw-r--r--include/asm-i386/unistd.h1
-rw-r--r--include/asm-ia64/sn/pci/pcibr.h2
-rw-r--r--include/asm-ppc/highmem.h2
-rw-r--r--include/asm-ppc/kmap_types.h4
-rw-r--r--include/asm-ppc/pgalloc.h131
-rw-r--r--include/asm-ppc/pgtable.h35
-rw-r--r--include/asm-x86_64/rwsem.h8
-rw-r--r--include/linux/blk.h12
-rw-r--r--include/linux/blkpg.h2
-rw-r--r--include/linux/cache.h4
-rw-r--r--include/linux/coda_fs_i.h1
-rw-r--r--include/linux/coda_linux.h45
-rw-r--r--include/linux/coda_proc.h18
-rw-r--r--include/linux/compiler.h6
-rw-r--r--include/linux/cramfs_fs.h25
-rw-r--r--include/linux/fs.h25
-rw-r--r--include/linux/hdlc.h299
-rw-r--r--include/linux/hdlc/ioctl.h55
-rw-r--r--include/linux/hdreg.h3
-rw-r--r--include/linux/ide.h220
-rw-r--r--include/linux/if.h39
-rw-r--r--include/linux/if_ether.h1
-rw-r--r--include/linux/jbd.h4
-rw-r--r--include/linux/mm.h5
-rw-r--r--include/linux/pci.h6
-rw-r--r--include/linux/pci_ids.h7
-rw-r--r--include/linux/pnpbios.h2
-rw-r--r--include/linux/reiserfs_fs_sb.h1
-rw-r--r--include/linux/smb.h2
-rw-r--r--include/linux/smb_fs.h25
-rw-r--r--include/linux/smb_fs_sb.h3
-rw-r--r--include/linux/smb_mount.h1
-rw-r--r--include/linux/smbno.h47
-rw-r--r--include/linux/smp.h16
-rw-r--r--include/linux/sockios.h2
-rw-r--r--include/linux/swap.h2
-rw-r--r--include/linux/telephony.h4
-rw-r--r--include/net/irda/irda-usb.h6
-rw-r--r--include/net/irda/irda.h4
-rw-r--r--include/net/irda/irlap.h5
-rw-r--r--include/net/irda/irlap_event.h1
-rw-r--r--include/net/irda/irqueue.h8
-rw-r--r--include/sound/core.h4
-rw-r--r--include/sound/driver.h8
-rw-r--r--include/sound/info.h6
-rw-r--r--include/sound/pcm.h1
-rw-r--r--include/sound/pcm_params.h2
-rw-r--r--include/sound/version.h2
-rw-r--r--init/do_mounts.c4
-rw-r--r--init/main.c29
-rw-r--r--kernel/kmod.c11
-rw-r--r--kernel/ksyms.c3
-rw-r--r--kernel/sched.c5
-rw-r--r--kernel/signal.c2
-rw-r--r--lib/zlib_inflate/inflate.c8
-rw-r--r--mm/filemap.c61
-rw-r--r--mm/page_alloc.c2
-rw-r--r--mm/slab.c4
-rw-r--r--mm/swapfile.c75
-rw-r--r--net/core/dev.c10
-rw-r--r--net/irda/af_irda.c18
-rw-r--r--net/irda/irda_device.c2
-rw-r--r--net/irda/irlap.c49
-rw-r--r--net/irda/irlap_event.c40
-rw-r--r--net/irda/irlap_frame.c35
-rw-r--r--net/irda/irnet/irnet.h5
-rw-r--r--net/irda/irnet/irnet_irda.c5
-rw-r--r--net/unix/af_unix.c7
-rw-r--r--net/wanrouter/af_wanpipe.c8
-rw-r--r--scripts/cramfs/GNUmakefile12
-rw-r--r--scripts/cramfs/cramfsck.c588
-rw-r--r--scripts/cramfs/mkcramfs.c776
-rw-r--r--scripts/tkgen.c8
-rw-r--r--sound/Config.help7
-rw-r--r--sound/core/Config.help40
-rw-r--r--sound/core/Config.in9
-rw-r--r--sound/core/Makefile15
-rw-r--r--sound/core/info.c31
-rw-r--r--sound/core/info_oss.c2
-rw-r--r--sound/core/ioctl32/Makefile17
-rw-r--r--sound/core/ioctl32/hwdep32.c37
-rw-r--r--sound/core/ioctl32/ioctl32.c357
-rw-r--r--sound/core/ioctl32/ioctl32.h79
-rw-r--r--sound/core/ioctl32/pcm32.c296
-rw-r--r--sound/core/ioctl32/rawmidi32.c86
-rw-r--r--sound/core/ioctl32/timer32.c93
-rw-r--r--sound/core/oss/pcm_oss.c42
-rw-r--r--sound/core/rtctimer.c60
-rw-r--r--sound/core/seq/Makefile1
-rw-r--r--sound/core/seq/seq_midi_event.c13
-rw-r--r--sound/core/seq/seq_virmidi.c3
-rw-r--r--sound/core/sound_oss.c2
-rw-r--r--sound/drivers/Config.help18
-rw-r--r--sound/drivers/mpu401/Makefile1
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c1
-rw-r--r--sound/drivers/mtpav.c1
-rw-r--r--sound/drivers/opl3/Makefile4
-rw-r--r--sound/drivers/opl3/opl3_lib.c1
-rw-r--r--sound/drivers/serial-u16550.c7
-rw-r--r--sound/i2c/Makefile2
-rw-r--r--sound/isa/Config.help99
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c1
-rw-r--r--sound/isa/ad1848/ad1848_lib.c1
-rw-r--r--sound/isa/azt2320.c2
-rw-r--r--sound/isa/cs423x/cs4231_lib.c1
-rw-r--r--sound/isa/es1688/es1688_lib.c1
-rw-r--r--sound/isa/gus/gus_main.c1
-rw-r--r--sound/isa/opl3sa2.c2
-rw-r--r--sound/isa/sb/Makefile4
-rw-r--r--sound/isa/sb/emu8000.c1
-rw-r--r--sound/isa/sb/sb16_main.c6
-rw-r--r--sound/isa/sb/sb8.c1
-rw-r--r--sound/isa/sb/sb_common.c1
-rw-r--r--sound/isa/sgalaxy.c2
-rw-r--r--sound/isa/wavefront/wavefront_synth.c45
-rw-r--r--sound/oss/via82cxxx_audio.c2
-rw-r--r--sound/pci/Config.help75
-rw-r--r--sound/pci/ymfpci/ymfpci.c2
-rw-r--r--sound/synth/Makefile2
525 files changed, 31988 insertions, 13376 deletions
diff --git a/COPYING b/COPYING
index ae401538ebb7..2a7e338ec2fc 100644
--- a/COPYING
+++ b/COPYING
@@ -307,7 +307,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
- Copyright (C) 19yy <name of author>
+ Copyright (C) <year> <name of author>
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
@@ -329,7 +329,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
- Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index 3acdf3bc7377..bd1582a3412a 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
+++ b/Documentation/DocBook/kernel-locking.tmpl
@@ -788,8 +788,18 @@
</para>
<para>
- Note that the atomic operations are defined to act as both
- read and write barriers on all platforms.
+ Note that the atomic operations do in general not act as memory
+ barriers. Instead you can insert a memory barrier before or
+ after <function>atomic_inc()</function> or
+ <function>atomic_dec()</function> by inserting
+ <function>smp_mb__before_atomic_inc()</function>,
+ <function>smp_mb__after_atomic_inc()</function>,
+ <function>smp_mb__before_atomic_dec()</function> or
+ <function>smp_mb__after_atomic_dec()</function>
+ respectively. The advantage of using those macros instead of
+ <function>smp_mb()</function> is, that they are cheaper on some
+ platforms.
+ <!-- Sebastian Wilhelmi <seppi@seppi.de> 2002-03-04 -->
</para>
</sect1>
diff --git a/Documentation/filesystems/cramfs.txt b/Documentation/filesystems/cramfs.txt
index 3346fb68da26..31f53f0ab957 100644
--- a/Documentation/filesystems/cramfs.txt
+++ b/Documentation/filesystems/cramfs.txt
@@ -10,7 +10,7 @@ diskspace than traditional filesystems.
You can't write to a cramfs filesystem (making it compressible and
compact also makes it _very_ hard to update on-the-fly), so you have to
-create the disk image with the "mkcramfs" utility in scripts/cramfs.
+create the disk image with the "mkcramfs" utility.
Usage Notes
@@ -19,9 +19,7 @@ Usage Notes
File sizes are limited to less than 16MB.
Maximum filesystem size is a little over 256MB. (The last file on the
-filesystem is allowed to extend past 256MB.) (Comments in mkcramfs.c
-suggest that ROM sizes may be limited to 64MB, though that's not a
-limitation in cramfs code.)
+filesystem is allowed to extend past 256MB.)
Only the low 8 bits of gid are stored. The current version of
mkcramfs simply truncates to 8 bits, which is a potential security
@@ -48,18 +46,28 @@ mind the filesystem becoming unreadable to future kernels.
For /usr/share/magic
-------------------
+--------------------
-0 long 0x28cd3d45 Linux cramfs
->4 long x size %d
->8 long x flags 0x%x
->12 long x future 0x%x
+0 ulelong 0x28cd3d45 Linux cramfs offset 0
+>4 ulelong x size %d
+>8 ulelong x flags 0x%x
+>12 ulelong x future 0x%x
>16 string >\0 signature "%.16s"
->32 long x fsid.crc 0x%x
->36 long x fsid.edition %d
->40 long x fsid.blocks %d
->44 long x fsid.files %d
+>32 ulelong x fsid.crc 0x%x
+>36 ulelong x fsid.edition %d
+>40 ulelong x fsid.blocks %d
+>44 ulelong x fsid.files %d
>48 string >\0 name "%.16s"
+512 ulelong 0x28cd3d45 Linux cramfs offset 512
+>516 ulelong x size %d
+>520 ulelong x flags 0x%x
+>524 ulelong x future 0x%x
+>528 string >\0 signature "%.16s"
+>544 ulelong x fsid.crc 0x%x
+>548 ulelong x fsid.edition %d
+>552 ulelong x fsid.blocks %d
+>556 ulelong x fsid.files %d
+>560 string >\0 name "%.16s"
Hacker Notes
diff --git a/Documentation/networking/arcnet-hardware.txt b/Documentation/networking/arcnet-hardware.txt
index 5072e63ff9ba..30a5f01403d3 100644
--- a/Documentation/networking/arcnet-hardware.txt
+++ b/Documentation/networking/arcnet-hardware.txt
@@ -2256,7 +2256,7 @@ function, and the 8th switch is used to select "compatible" or "enhanced".
When I got my two cards, one of them had this switch set to "enhanced". That
card didn't work at all, it wasn't even recognized by the driver. The other
card had this switch set to "compatible" and it behaved absolutely normally. I
-guess that the switch on one of the cards, must have been changed accidently
+guess that the switch on one of the cards, must have been changed accidentally
when the card was taken out of its former host. The question remains
unanswered, what is the purpose of the "enhanced" position?
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index ef4bc599ed47..517e53a35a8d 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -503,7 +503,7 @@ The main limitations are :
Resources and links
===================
-Current developement on this driver is posted to:
+Current development on this driver is posted to:
- http://www.sourceforge.net/projects/bonding/
Donald Becker's Ethernet Drivers and diag programs may be found at :
diff --git a/Documentation/networking/driver.txt b/Documentation/networking/driver.txt
new file mode 100644
index 000000000000..ffdd2f2d5944
--- /dev/null
+++ b/Documentation/networking/driver.txt
@@ -0,0 +1,84 @@
+Documents about softnet driver issues in general can be found
+at:
+
+ http://www.firstfloor.org/~andi/softnet/
+
+Transmit path guidelines:
+
+1) The hard_start_xmit method must never return '1' under any
+ normal circumstances. It is considered a hard error unless
+ there is no way your device can tell ahead of time when it's
+ transmit function will become busy.
+
+ Instead it must maintain the queue properly. For example,
+ for a driver implementing scatter-gather this means:
+
+ static int drv_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+ {
+ struct drv *dp = dev->priv;
+
+ lock_tx(dp);
+ ...
+ /* This is a hard error log it. */
+ if (TX_BUFFS_AVAIL(dp) <= (skb_shinfo(skb)->nr_frags + 1)) {
+ netif_stop_queue(dev);
+ unlock_tx(dp);
+ printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
+ dev->name);
+ return 1;
+ }
+
+ ... queue packet to card ...
+ ... update tx consumer index ...
+
+ if (TX_BUFFS_AVAIL(dp) <= (MAX_SKB_FRAGS + 1))
+ netif_stop_queue(dev);
+
+ ...
+ unlock_tx(dp);
+ ...
+ }
+
+ And then at the end of your TX reclaimation event handling:
+
+ if (netif_queue_stopped(dp->dev) &&
+ TX_BUFFS_AVAIL(dp) > (MAX_SKB_FRAGS + 1))
+ netif_wake_queue(dp->dev);
+
+ For a non-scatter-gather supporting card, the three tests simply become:
+
+ /* This is a hard error log it. */
+ if (TX_BUFFS_AVAIL(dp) <= 0)
+
+ and:
+
+ if (TX_BUFFS_AVAIL(dp) == 0)
+
+ and:
+
+ if (netif_queue_stopped(dp->dev) &&
+ TX_BUFFS_AVAIL(dp) > 0)
+ netif_wake_queue(dp->dev);
+
+2) Do not forget to update netdev->trans_start to jiffies after
+ each new tx packet is given to the hardware.
+
+3) Do not forget that once you return 0 from your hard_start_xmit
+ method, it is your driver's responsibility to free up the SKB
+ and in some finite amount of time.
+
+ For example, this means that it is not allowed for your TX
+ mitigation scheme to let TX packets "hang out" in the TX
+ ring unreclaimed forever if no new TX packets are sent.
+ This error can deadlock sockets waiting for send buffer room
+ to be freed up.
+
+ If you return 1 from the hard_start_xmit method, you must not keep
+ any reference to that SKB and you must not attempt to free it up.
+
+Probing guidelines:
+
+1) Any hardware layer address you obtain for your device should
+ be verified. For example, for ethernet check it with
+ linux/etherdevice.h:is_valid_ether_addr()
diff --git a/Documentation/networking/generic-hdlc.txt b/Documentation/networking/generic-hdlc.txt
new file mode 100644
index 000000000000..37631c95b90a
--- /dev/null
+++ b/Documentation/networking/generic-hdlc.txt
@@ -0,0 +1,115 @@
+Generic HDLC layer for Linux kernel 2.4/2.5
+Krzysztof Halasa <khc@pm.waw.pl>
+May, 2001
+
+
+Generic HDLC layer currently supports:
+- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP),
+- raw HDLC (IPv4 only),
+- Cisco HDLC,
+- PPP (uses syncppp.c),
+- X.25 (uses X.25 routines).
+
+There are hardware drivers for the following cards:
+- C101 by Moxa Technologies Co., Ltd.
+- RISCom/N2 by SDL Communications Inc.
+- and others, some not in the official kernel.
+
+Make sure the hdlc.o and the hardware driver are loaded. It should
+create a number of "hdlc" (hdlc0 etc) network devices, one for each
+WAN port. You'll need the "sethdlc" utility, get it from:
+ http://hq.pm.waw.pl/hdlc/
+
+Compile sethdlc.c utility:
+ gcc -O2 -Wall -o sethdlc sethdlc.c
+Make sure you're using a correct version of sethdlc for your kernel.
+
+Use sethdlc to set physical interface, clock rate, HDLC mode used,
+and add any required PVCs if using Frame Relay.
+Usually you want something like:
+
+ sethdlc hdlc0 clock int rate 128000
+ sethdlc hdlc0 cisco interval 10 timeout 25
+or
+ sethdlc hdlc0 rs232 clock ext
+ sethdlc fr lmi ansi
+ sethdlc create 99
+
+In Frame Relay mode, ifconfig master hdlc device up (without assigning
+any IP address to it) before using pvc devices.
+
+
+Setting interface:
+
+* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
+ if the card has software-selectable interfaces
+ loopback - activate hardware loopback (for testing only)
+* clock ext - external clock (uses DTE RX and TX clock)
+* clock int - internal clock (provides clock signal on DCE clock output)
+* clock txint - TX internal, RX external (provides TX clock on DCE output)
+* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output)
+* rate - sets clock rate in bps (not required for external clock or
+ for txfromrx)
+
+Setting protocol:
+
+* hdlc - sets raw HDLC (IP-only) mode
+ nrz / nrzi / fm-mark / fm-space / manchester - sets transmission code
+ no-parity / crc16 / crc16-pr0 (CRC16 with preset zeros) / crc32-itu
+ crc16-itu (CRC16 with ITU-T polynomial) / crc16-itu-pr0 - sets parity
+
+* cisco - sets Cisco HDLC mode (IP, IPv6 and IPX supported)
+ interval - time in seconds between keepalive packets
+ timeout - time in seconds after last received keepalive packet before
+ we assume the link is down
+
+* ppp - sets synchronous PPP mode
+
+* x25 - sets X.25 mode
+
+* fr - Frame Relay mode
+ lmi ansi / ccitt / none - LMI (link management) type
+ dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
+ It has nothing to do with clocks!
+ t391 - link integrity verification polling timer (in seconds) - user
+ t392 - polling verification timer (in seconds) - network
+ n391 - full status polling counter - user
+ n392 - error threshold - both user and network
+ n393 - monitored events count - both user and network
+
+* create | delete n - FR only - adds / deletes PVC interface with DLCI #n.
+
+
+
+
+Board-specific issues
+---------------------
+
+n2.o and c101.o need parameters to work (note double quotes):
+
+ insmod n2 hw='"io,irq,ram,ports[:io,irq,...]"'
+example:
+ insmod n2 hw='"0x300,10,0xD0000,01"'
+
+or
+ insmod c101 hw='"irq,ram[:irq,...]"
+example:
+ insmod c101 hw='"9,0xdc000"'
+
+If built into the kernel, these drivers need kernel (command line) parameters:
+ n2=io,irq,ram,ports:...
+or
+ c101=irq,ram:...
+
+
+
+If you have a problem with N2 or C101 card, you can issue the "private"
+command to see port's packet descriptor rings:
+
+ sethdlc hdlc0 private
+
+The hardware driver have to be build with CONFIG_HDLC_DEBUG_RINGS.
+Attaching this info to bug reports would be helpful. Anyway, let me know
+if you have problems using this.
+
+For patches and other info look at http://hq.pm.waw.pl/hdlc/
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 5ac05854aa89..496abe268ad4 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -156,6 +156,11 @@ if it was in suspended state. Please note that this function can fail.
which enables the bus master bit in PCI_COMMAND register and also fixes
the latency timer value if it's set to something bogus by the BIOS.
+ If you want to use the PCI Memory-Write-Invalidate transaction,
+call pci_set_mwi(). This enables bit PCI_COMMAND bit for Mem-Wr-Inval
+and also ensures that the cache line size register is set correctly.
+Make sure to check the return value of pci_set_mwi(), not all architectures
+may support Memory-Write-Invalidate.
4. How to access PCI config space
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -202,6 +207,8 @@ pci_resource_end() Returns bus end address for a given PCI region
pci_resource_len() Returns the byte length of a PCI region
pci_set_drvdata() Set private driver data pointer for a pci_dev
pci_get_drvdata() Return private driver data pointer for a pci_dev
+pci_set_mwi() Enable Memory-Write-Invalidate transactions.
+pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
7. Miscellaneous hints
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index 931cdd1aacd8..2050df6a4b15 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -63,7 +63,7 @@ Upon entering a suspend state, the PM layer iterates through all of its register
callbacks. This currently takes place only during APM state transitions.
Upon going to sleep, the PCI subsystem walks its device tree twice. Both times, it does
-a depth first walk of the device tree. The first walk saves each of the device's state
+a depth first walk of the device tree. The first walk saves each of the device's state
and checks for devices that will prevent the system from entering a global power state.
The next walk then places the devices in a low power state.
@@ -104,7 +104,7 @@ pci_restore_state
-----------------
Usage:
- pci_restore_state(dev,buffer);
+ pci_restore_state(dev, buffer);
Description:
Restore previously saved config space. (First 64 bytes only);
@@ -117,7 +117,7 @@ pci_set_power_state
-------------------
Usage:
- pci_set_power_state(dev,state);
+ pci_set_power_state(dev, state);
Description:
Transition device to low power state using PCI PM Capabilities registers.
@@ -132,7 +132,7 @@ pci_enable_wake
---------------
Usage:
- pci_enable_wake(dev,state,enable);
+ pci_enable_wake(dev, state, enable);
Description:
Enable device to generate PME# during low power state using PCI PM
@@ -155,7 +155,7 @@ These functions are intended for use by individual drivers, and are defined in
struct pci_driver:
int (*save_state) (struct pci_dev *dev, u32 state);
- int (*suspend)(struct pci_dev *dev, u32 state);
+ int (*suspend) (struct pci_dev *dev, u32 state);
int (*resume) (struct pci_dev *dev);
int (*enable_wake) (struct pci_dev *dev, u32 state, int enable);
@@ -178,7 +178,7 @@ is preserved when entering D1, but the screen is placed into a low power state
The driver can also interpret this function as a notification that it may be entering
a sleep state in the near future. If it knows that the device cannot enter the
-requested state, either because of lack of support for it, or because the devices is
+requested state, either because of lack of support for it, or because the device is
middle of some critical operation, then it should fail.
This function should not be used to set any state in the device or the driver because
diff --git a/Documentation/sound/alsa/CMIPCI.txt b/Documentation/sound/alsa/CMIPCI.txt
new file mode 100644
index 000000000000..582781b64b13
--- /dev/null
+++ b/Documentation/sound/alsa/CMIPCI.txt
@@ -0,0 +1,228 @@
+ Brief Notes on C-Media 8738/8338 Driver
+ =======================================
+
+ Takashi Iwai <tiwai@suse.de>
+
+
+Front/Rear Multi-channel Playback
+---------------------------------
+
+CM8x38 chip can use ADC as the second DAC so that two different stereo
+channels can be used for front/rear playbacks. Since there are two
+DACs, both streams are handled independently unlike the 4/6ch multi-
+channel playbacks in the section below.
+
+As default, ALSA driver assigns the first PCM device (i.e. hw:0,0 for
+card#0) for front and 4/6ch playbacks, while the second PCM device
+(hw:0,1) is assigned to the second DAC for rear playback.
+
+There are slight difference between two DACs.
+
+- The first DAC supports U8 and S16LE formats, while the second DAC
+ supports only S16LE.
+- The second DAC supports only two channel stereo.
+
+Please note that the CM8x38 DAC doesn't support continuous playback
+rate but only fixed rates: 5512, 8000, 11025, 16000, 22050, 32000,
+44100 and 48000 Hz.
+
+The rear output can be heard only when "Four Channel Mode" switch is
+disabled. Otherwise no signal will be routed to the rear speakers.
+As default it's turned on.
+
+*** WARNING ***
+When "Four Channel Mode" switch is off, the output from rear speakers
+will be FULL VOLUME regardless of Master and PCM volumes.
+This might damage your audio equipment. Please disconnect speakers
+before your turn off this switch.
+*** WARNING ***
+
+[ Well.. I once got the output with correct volume (i.e. same with the
+ front one) and was so excited. It was even with "Four Channel" bit
+ on and "double DAC" mode. Actually I could hear separate 4 channels
+ from front and rear speakers! But.. after reboot, all was gone.
+ It's a very pity that I didn't save the register dump at that
+ time.. Maybe there is an unknown register to achieve this... ]
+
+If your card has an extra output jack for the rear output, the rear
+playback should be routed there as default. If not, there is a
+control switch in the driver "Line-In As Rear", which you can change
+via alsamixer or somewhat else. When this switch is on, line-in jack
+is used as rear output.
+
+There are two more controls regarding to the rear output.
+The "Exchange DAC" switch is used to exchange front and rear playback
+routes, i.e. the 2nd DAC is output from front output.
+
+
+4/6 Multi-Channel Playback
+--------------------------
+
+The recent CM8738 chips support for the 4/6 multi-channel playback
+function. This is useful especially for AC3 decoding.
+
+When the multi-channel is supported, the driver name has a suffix
+"-MC" such like "CMI8738-MC6". You can check this name from
+/proc/asound/cards.
+
+When the 4/6-ch output is enabled, the front DAC accepts up to 6 (or
+4) channels. This is different from the dual DACs described in the
+previous section. While the dual DAC supports two different rates or
+formats, the 4/6-ch playback supports only the same condition for all
+channels.
+
+For using 4/6 channel playback, you need to specify the PCM channels
+as you like and set the format S16LE. For example, for playback with
+4 channels,
+
+ snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
+ // or mmap if you like
+ snd_pcm_hw_params_set_format(pcm, hw, SND_PCM_FORMAT_S16_LE);
+ snd_pcm_hw_params_set_channels(pcm, hw, 4);
+
+and use the interleaved 4 channel data.
+
+There is a control switch, "Line-In As Bass". As you can imagine from
+its name, the line-in jack is used for the bass (5th and 6th channels)
+output.
+
+
+Digital I/O
+-----------
+
+The CM8x38 provides the excellent SPDIF capability with very chip
+price (yes, that's the reason I bought the card :)
+
+The SPDIF playback and capture are done via the third PCM device
+(hw:0,2). Usually this is assigned to the PCM device "spdif".
+The available rates are 44100 and 48000 Hz.
+For playback with aplay, you can run like below:
+
+ % aplay -Dhw:0,2 foo.wav
+
+or
+
+ % aplay -Dspdif foo.wav
+
+So far, only S16LE format is supported. Still no 24bit. Sorry, not
+enough info for this.
+
+The playback and capture over SPDIF use normal DAC and ADC,
+respectively, so you cannot playback both analog and digital streams
+simultaneously.
+
+To enable SPDIF output, you need to turn on "IEC958 Output Switch"
+control via mixer or alsactl. Then you'll see the red light on from
+the card so you know that's working obviously :)
+The SPDIF input is always enabled, so you can hear SPDIF input data
+from line-out with "IEC958 In Monitor" switch at any time (see
+below).
+
+You can play via SPDIF even with the first device (hw:0,0),
+but SPDIF is enabled only when the proper format (S16LE), sample rate
+(441100 or 48000) and channels (2) are used. Otherwise it's turned
+off. (Also don't forget to turn on "IEC958 Output Switch", too.)
+
+
+Additionally there are relevant control switches:
+
+"IEC958 Mix Analog" - Mix analog PCM playback and FM-OPL/3 streams and
+ output through SPDIF. This switch appears only on old chip
+ models (CM8738 033 and 037).
+ Note: without this control you can output PCM to SPDIF.
+ This is "mixing" of streams, so e.g. it's not for AC3 output
+ (see the next section).
+
+"IEC958 In Select" - Select SPDIF input, the internal CD-in (false)
+ and the external input (true). This switch appears only on
+ the chip models 039 or later.
+
+"IEC958 Loop" - SPDIF input data is loop back into SPDIF
+ output (aka bypass)
+
+"IEC958 Copyright" - Set the copyright bit.
+
+"IEC958 5V" - Select 0.5V (coax) or 5V (optical) interface.
+ On some cards this doesn't work and you need to change the
+ configuration with hardware dip-switch.
+
+"IEC958 In Monitor" - SPDIF input is routed to DAC.
+
+"IEC958 In Phase Inverse" - Set SPDIF input format as inverse.
+ [FIXME: this doesn't work on all chips..]
+
+"IEC958 In Valid" - Set input validity flag detection.
+
+Note: When "PCM Playback Switch" is on, you'll hear the digital output
+stream through analog line-out.
+
+
+The AC3 (RAW DIGITAL) OUTPUT
+----------------------------
+
+The driver supports raw digital (typically AC3) i/o over SPDIF. This
+can be toggled via IEC958 playback control, but usually you need to
+access it via alsa-lib. See alsa-lib documents for more details.
+
+On the raw digital mode, the "PCM Playback Switch" is automatically
+turned off so that non-audio data is heard from the analog line-out.
+Similarly the following switches are off: "IEC958 Mix Analog" and
+"IEC958 Loop". The switches are resumed after closing the SPDIF PCM
+device automatically to the previous state.
+
+
+ANALOG MIXER INTERFACE
+----------------------
+
+The mixer interface on CM8x38 is similar to SB16.
+There are Master, PCM, Synth, CD, Line, Mic and PC Speaker playback
+volumes. Synth, CD, Line and Mic have playback and capture switches,
+too, as well as SB16.
+
+In addition to the standard SB mixer, CM8x38 provides more functions.
+- PCM playback switch
+- PCM capture switch (to capture the data sent to DAC)
+- Mic Boost switch
+- Mic capture volume
+- Aux playback volume/switch and capture switch
+- 3D control switch
+
+
+MIDI CONTROLLER
+---------------
+
+The MPU401-UART interface is enabled as default only for the first
+(CMIPCI) card. You need to set module option "snd_midi_port" properly
+for the 2nd (CMIPCI) card.
+
+There is _no_ hardware wavetable function on this chip (except for
+OPL3 synth below).
+What's said as MIDI synth on Windows is a software synthesizer
+emulation. On Linux use TiMidity or other softsynth program for
+playing MIDI music.
+
+
+FM OPL/3 Synth
+--------------
+
+The FM OPL/3 is also enabled as default only for the first card.
+Set "snd_fm_port" module option for more cards.
+
+The output quality of FM OPL/3 is, however, very weird.
+I don't know why..
+
+
+Joystick and Modem
+------------------
+
+The joystick and modem should be available by enabling the control
+switch "Joystick" and "Modem" respectively. But I myself have never
+tested them yet.
+
+
+Debugging Information
+---------------------
+
+The registers are shown in /proc/asound/cardX/cmipci. If you have any
+problem (especially unexpected behavior of mixer), please attach the
+output of this proc file together with the bug report.
diff --git a/Documentation/sound/alsa/SB-Live-mixer.txt b/Documentation/sound/alsa/SB-Live-mixer.txt
new file mode 100644
index 000000000000..d37b0e646e2f
--- /dev/null
+++ b/Documentation/sound/alsa/SB-Live-mixer.txt
@@ -0,0 +1,356 @@
+
+ Sound Blaster Live mixer / default DSP code
+ ===========================================
+
+
+The EMU10K1 chips have a DSP part which can be programmed to support
+various ways of sample processing, which is described here.
+(This acticle does not deal with the overall functionality of the
+EMU10K1 chips. See the manuals section for further details.)
+
+The ALSA driver programs this portion of chip by default code
+(can be altered later) which offers the following functionality:
+
+
+1) IEC958 (S/PDIF) raw PCM
+--------------------------
+
+This PCM device (it's the 4th PCM device (index 3!) and first subdevice
+(index 0) for a given card) allows to forward 48kHz, stereo, 16-bit
+little endian streams without any modifications to the digital output
+(coaxial or optical). The universal interface allows the creation of up
+to 8 raw PCM devices operating at 48kHz, 16-bit little endian. It would
+be easy to add support for multichannel devices to the current code,
+but the conversion routines exist only for stereo (2-channel streams)
+at the time.
+
+Look to tram_poke routines in lowlevel/emu10k1/emufx.c for more details.
+
+
+2) Digital mixer controls
+-------------------------
+
+These controls are built using the DSP instructions. They offer extended
+functionality. Only the default build-in code in the ALSA driver is described
+here. Note that the controls work as attenuators: the maximum value is the
+neutral position leaving the signal unchanged. Note that if the same destination
+is mentioned in multiple controls, the signal is accumulated and can be wrapped
+(set to maximal or minimal value without checking of overflow).
+
+
+Explanation of used abbreviations:
+
+DAC - digital to analog converter
+ADC - analog to digital converter
+I2S - one-way three wire serial bus for digital sound by Philips Semiconductors
+ (this standard is used for connecting standalone DAC and ADC converters)
+LFE - low frequency effects (subwoofer signal)
+AC97 - a chip containing an analog mixer, DAC and ADC converters
+IEC958 - S/PDIF
+FX-bus - the EMU10K1 chip has an effect bus containing 16 accumulators.
+ Each of the synthesizer voices can feed its output to these accumulators
+ and the DSP microcontroller can operate with the resulting sum.
+
+
+name='Wave Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='Wave Surround Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result samples are forwarded to the rear I2S DACs. These DACs operates
+separately (they are not inside the AC97 codec).
+
+name='Wave Center Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result is mixed to mono signal (single channel) and forwarded to
+the ??rear?? right DAC PCM slot of the AC97 codec.
+
+name='Wave LFE Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM.
+The result is mixed to mono signal (single channel) and forwarded to
+the ??rear?? left DAC PCM slot of the AC97 codec.
+
+name='Wave Capture Volume',index=0
+name='Wave Capture Switch',index=0
+
+These controls are used to attenuate samples for left and right PCM FX-bus
+accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Music Playback Volume',index=0
+
+This control is used to attenuate samples for left and right MIDI FX-bus
+accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
+The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='Music Capture Volume',index=0
+name='Music Capture Switch',index=0
+
+These controls are used to attenuate samples for left and right MIDI FX-bus
+accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Surround Digital Playback Volume',index=0
+
+This control is used to attenuate samples for left and right rear PCM FX-bus
+accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
+The result samples are forwarded to the rear I2S DACs. These DACs operate
+separately (they are not inside the AC97 codec).
+
+name='Surround Digital Capture Volume',index=0
+name='Surround Digital Capture Switch',index=0
+
+These controls are used to attenuate samples for left and right rear PCM FX-bus
+accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Center Playback Volume',index=0
+
+This control is used to attenuate sample for center PCM FX-bus accumulator.
+ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
+to the ??rear?? right DAC PCM slot of the AC97 codec.
+
+name='LFE Playback Volume',index=0
+
+This control is used to attenuate sample for center PCM FX-bus accumulator.
+ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
+to the ??rear?? left DAC PCM slot of the AC97 codec.
+
+name='AC97 Playback Volume',index=0
+
+This control is used to attenuate samples for left and right front ADC PCM slots
+of the AC97 codec. The result samples are forwarded to the front DAC PCM
+slots of the AC97 codec.
+********************************************************************************
+*** Note: This control should be zero for the standard operations, otherwise ***
+*** a digital loopback is activated. ***
+********************************************************************************
+
+name='AC97 Capture Volume',index=0
+
+This control is used to attenuate samples for left and right front ADC PCM slots
+of the AC97 codec. The result is forwarded to the ADC capture FIFO (thus to
+the standard capture PCM device).
+********************************************************************************
+*** Note: This control should be 100 (maximal value), otherwise no analog ***
+*** inputs of the AC97 codec can be captured (recorded). ***
+********************************************************************************
+
+name='IEC958 TTL Playback Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='IEC958 TTL Capture Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
+
+name='Zoom Video Playback Volume',index=0
+
+This control is used to attenuate samples from left and right zoom video
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='Zoom Video Capture Volume',index=0
+
+This control is used to attenuate samples from left and right zoom video
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
+
+name='IEC958 Optical Playback Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 optical
+digital input. The result samples are forwarded to the front DAC PCM slots
+of the AC97 codec.
+
+name='IEC958 Optical Capture Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 optical
+digital inputs. The result samples are forwarded to the ADC capture FIFO
+(thus to the standard capture PCM device).
+
+name='IEC958 Coaxial Playback Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 coaxial
+digital inputs. The result samples are forwarded to the front DAC PCM slots
+of the AC97 codec.
+
+name='IEC958 Coaxial Capture Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 coaxial
+digital inputs. The result samples are forwarded to the ADC capture FIFO
+(thus to the standard capture PCM device).
+
+name='Line LiveDrive Playback Volume',index=0
+name='Line LiveDrive Playback Volume',index=1
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the LiveDrive). The result samples are forwarded to the front
+DAC PCM slots of the AC97 codec.
+
+name='Line LiveDrive Capture Volume',index=1
+name='Line LiveDrive Capture Volume',index=1
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the LiveDrive). The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+name='Tone Control - Switch',index=0
+
+This control turns the tone control on or off. The samples for front, rear
+and center / LFE outputs are affected.
+
+name='Tone Control - Bass',index=0
+
+This control sets the bass intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+name='Tone Control - Treble',index=0
+
+This control sets the treble intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+name='IEC958 Optical Raw Playback Switch',index=0
+
+If this switch is on, then the samples for the IEC958 (S/PDIF) digital
+output are taken only from the raw FX8010 PCM, otherwise standard front
+PCM samples are taken.
+
+name='Headphone Playback Volume',index=1
+
+This control attenuates the samples for the headphone output.
+
+name='Headphone Center Playback Switch',index=1
+
+If this switch is on, then the sample for the center PCM is put to the
+left headphone output (useful for SB Live cards without separate center/LFE
+output).
+
+name='Headphone LFE Playback Switch',index=1
+
+If this switch is on, then the sample for the center PCM is put to the
+right headphone output (useful for SB Live cards without separate center/LFE
+output).
+
+
+3) PCM stream related controls
+------------------------------
+
+name='EMU10K1 PCM Volume',index 0-31
+
+Channel volume attenuation in range 0-0xffff. The maximum value (no
+attenuation) is default. The channel mapping for three values is
+as follows:
+
+ 0 - mono, default 0xffff (no attenuation)
+ 1 - left, default 0xffff (no attenuation)
+ 2 - right, default 0xffff (no attenuation)
+
+name='EMU10K1 PCM Send Routing',index 0-31
+
+This control specifies the destination - FX-bus accumulators. There are
+twelve values with this mapping:
+
+ 0 - mono, A destination (FX-bus 0-15), default 0
+ 1 - mono, B destination (FX-bus 0-15), default 1
+ 2 - mono, C destination (FX-bus 0-15), default 2
+ 3 - mono, D destination (FX-bus 0-15), default 3
+ 4 - left, A destination (FX-bus 0-15), default 0
+ 5 - left, B destination (FX-bus 0-15), default 1
+ 6 - left, C destination (FX-bus 0-15), default 2
+ 7 - left, D destination (FX-bus 0-15), default 3
+ 8 - right, A destination (FX-bus 0-15), default 0
+ 9 - right, B destination (FX-bus 0-15), default 1
+ 10 - right, C destination (FX-bus 0-15), default 2
+ 11 - right, D destination (FX-bus 0-15), default 3
+
+Don't forget that it's illegal to assign a channel to the same FX-bus accumulator
+more than once (it means 0=0 && 1=0 is an invalid combination).
+
+name='EMU10K1 PCM Send Volume',index 0-31
+
+It specifies the attenuation (amount) for given destination in range 0-255.
+The channel mapping is following:
+
+ 0 - mono, A destination attn, default 255 (no attenuation)
+ 1 - mono, B destination attn, default 255 (no attenuation)
+ 2 - mono, C destination attn, default 0 (mute)
+ 3 - mono, D destination attn, default 0 (mute)
+ 4 - left, A destination attn, default 255 (no attenuation)
+ 5 - left, B destination attn, default 0 (mute)
+ 6 - left, C destination attn, default 0 (mute)
+ 7 - left, D destination attn, default 0 (mute)
+ 8 - right, A destination attn, default 0 (mute)
+ 9 - right, B destination attn, default 255 (no attenuation)
+ 10 - right, C destination attn, default 0 (mute)
+ 11 - right, D destination attn, default 0 (mute)
+
+
+
+4) MANUALS/PATENTS:
+-------------------
+
+ftp://opensource.creative.com/pub/doc
+-------------------------------------
+
+ Files:
+ LM4545.pdf AC97 Codec
+
+ m2049.pdf The EMU10K1 Digital Audio Processor
+
+ hog63.ps FX8010 - A DSP Chip Architecture for Audio Effects
+
+
+WIPO Patents
+------------
+ Patent numbers:
+ WO 9901813 (A1) Audio Effects Processor with multiple asynchronous (Jan. 14, 1999)
+ streams
+
+ WO 9901814 (A1) Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
+
+ WO 9901953 (A1) Audio Effects Processor having Decoupled Instruction
+ Execution and Audio Data Sequencing (Jan. 14, 1999)
+
+
+US Patents (http://www.uspto.gov/)
+----------------------------------
+
+ US 5925841 Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
+
+ US 5928342 Audio Effects Processor integrated on a single chip (Jul. 27, 1999)
+ with a multiport memory onto which multiple asynchronous
+ digital sound samples can be concurrently loaded
+
+ US 5930158 Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
+
+ US 6032235 Memory initialization circuit (Tram) (Feb. 29, 2000)
+
+ US 6138207 Interpolation looping of audio samples in cache connected to (Oct. 24, 2000)
+ system bus with prioritization and modification of bus transfers
+ in accordance with loop ends and minimum block sizes
+
+ US 6151670 Method for conserving memory storage using a (Nov. 21, 2000)
+ pool of short term memory registers
+
+ US 6195715 Interrupt control for multiple programs communicating with (Feb. 27, 2001)
+ a common interrupt by associating programs to GP registers,
+ defining interrupt register, polling GP registers, and invoking
+ callback routine associated with defined interrupt register
diff --git a/Documentation/sound/alsa/seq_oss.html b/Documentation/sound/alsa/seq_oss.html
new file mode 100644
index 000000000000..d9776cf60c07
--- /dev/null
+++ b/Documentation/sound/alsa/seq_oss.html
@@ -0,0 +1,409 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+ <TITLE>OSS Sequencer Emulation on ALSA</TITLE>
+</HEAD>
+<BODY>
+
+<CENTER>
+<H1>
+
+<HR WIDTH="100%"></H1></CENTER>
+
+<CENTER>
+<H1>
+OSS Sequencer Emulation on ALSA</H1></CENTER>
+
+<HR WIDTH="100%">
+<P>Copyright (c) 1998,1999 by Takashi Iwai
+<TT><A HREF="mailto:iwai@ww.uni-erlangen.de">&lt;iwai@ww.uni-erlangen.de></A></TT>
+<P>ver.0.1.8; Nov. 16, 1999
+<H2>
+
+<HR WIDTH="100%"></H2>
+
+<H2>
+1. Description</H2>
+This directory contains the OSS sequencer emulation driver on ALSA. Note
+that this program is still in the development state.
+<P>What this does - it provides the emulation of the OSS sequencer, access
+via
+<TT>/dev/sequencer</TT> and <TT>/dev/music</TT> devices.
+The most of applications using OSS can run if the appropriate ALSA
+sequencer is prepared.
+<P>The following features are emulated by this driver:
+<UL>
+<LI>
+Normal sequencer and MIDI events:</LI>
+
+<BR>They are converted to the ALSA sequencer events, and sent to the corresponding
+port.
+<LI>
+Timer events:</LI>
+
+<BR>The timer is not selectable by ioctl. The control rate is fixed to
+100 regardless of HZ. That is, even on Alpha system, a tick is always
+1/100 second. The base rate and tempo can be changed in <TT>/dev/music</TT>.
+
+<LI>
+Patch loading:</LI>
+
+<BR>It purely depends on the synth drivers whether it's supported since
+the patch loading is realized by callback to the synth driver.
+<LI>
+I/O controls:</LI>
+
+<BR>Most of controls are accepted. Some controls
+are dependent on the synth driver, as well as even on original OSS.</UL>
+Furthermore, you can find the following advanced features:
+<UL>
+<LI>
+Better queue mechanism:</LI>
+
+<BR>The events are queued before processing them.
+<LI>
+Multiple applications:</LI>
+
+<BR>You can run two or more applications simultaneously (even for OSS sequencer)!
+However, each MIDI device is exclusive - that is, if a MIDI device is opened
+once by some application, other applications can't use it. No such a restriction
+in synth devices.
+<LI>
+Real-time event processing:</LI>
+
+<BR>The events can be processed in real time without using out of bound
+ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
+events will be processed in real-time without queued. To switch off the
+real-time mode, send RELTIME 0 event.
+<LI>
+<TT>/proc</TT> interface:</LI>
+
+<BR>The status of applications and devices can be shown via <TT>/proc/asound/seq/oss</TT>
+at any time. In the later version, configuration will be changed via <TT>/proc</TT>
+interface, too.</UL>
+
+<H2>
+2. Installation</H2>
+Run configure script with both sequencer support (<TT>--with-sequencer=yes</TT>)
+and OSS emulation (<TT>--with-oss=yes</TT>) options. A module <TT>snd-seq-oss.o</TT>
+will be created. If the synth module of your sound card supports for OSS
+emulation (so far, only Emu8000 driver), this module will be loaded automatically.
+Otherwise, you need to load this module manually.
+<P>At beginning, this module probes all the MIDI ports which have been
+already connected to the sequencer. Once after that, the creation and deletion
+of ports are watched by announcement mechanism of ALSA sequencer.
+<P>The available synth and MIDI devices can be found in proc interface.
+Run "<TT>cat /proc/asound/seq/oss</TT>", and check the devices. For example,
+if you use an AWE64 card, you'll see like the following:
+<PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OSS sequencer emulation version 0.1.8
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ALSA client number 63
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ALSA receiver port 0
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of applications: 0
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of synth devices: 1
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synth 0: [EMU8000]
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type 0x1 : subtype 0x20 : voices 32
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capabilties : ioctl enabled / load_patch enabled
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of MIDI devices: 3
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 0: [Emu8000 Port-0] ALSA port 65:0
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability write / opened none
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 1: [Emu8000 Port-1] ALSA port 65:1
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability write / opened none
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 2: [0: MPU-401 (UART)] ALSA port 64:0
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability read/write / opened none</PRE>
+Note that the device number may be different from the information of
+<TT>/proc/asound/oss-devices</TT>
+or ones of the original OSS driver. Use the device number listed in <TT>/proc/asound/seq/oss</TT>
+to play via OSS sequencer emulation.
+<H2>
+3. Using Synthesizer Devices</H2>
+Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
+and xmp-1.1.5. You can load samples via <TT>/dev/sequencer</TT> like sfxload,
+too.
+<P>If the lowlevel driver supports multiple access to synth devices (like
+Emu8000 driver), two or more applications are allowed to run at the same
+time.
+<H2>
+4. Using MIDI Devices</H2>
+So far, only MIDI output was tested. MIDI input was not checked at all,
+but hopefully it will work. Use the device number listed in <TT>/proc/asound/seq/oss</TT>.
+Be aware that these numbers are mostly different from the list in
+<TT>/proc/asound/oss-devices</TT>.
+<H2>
+5. Module Options</H2>
+The following module options are available:
+<UL>
+<LI>
+<TT>maxqlen</TT></LI>
+
+<BR>specifies the maximum read/write queue length. This queue is private
+for OSS sequencer, so that it is independent from the queue length of ALSA
+sequencer. Default value is 1024.
+<LI>
+<TT>seq_oss_debug</TT></LI>
+
+<BR>specifies the debug level and accepts zero (= no debug message) or
+positive integer. Default value is 0.</UL>
+
+<H2>
+6. Queue Mechanism</H2>
+OSS sequencer emulation uses an ALSA priority queue. The
+events from <TT>/dev/sequencer</TT> are processed and put onto the queue
+specified by module option.
+<P>All the events from <TT>/dev/sequencer</TT> are parsed at beginning.
+The timing events are also parsed at this moment, so that the events may
+be processed in real-time. Sending an event ABSTIME 0 switches the operation
+mode to real-time mode, and sending an event RELTIME 0 switches it off.
+In the real-time mode, all events are dispatched immediately.
+<P>The queued events are dispatched to the corresponding ALSA sequencer
+ports after scheduled time by ALSA sequencer dispatcher.
+<P>If the write-queue is full, the application sleeps until a certain amount
+(as default one half) becomes empty in blocking mode. The synchronization
+to write timing was implemented, too.
+<P>The input from MIDI devices or echo-back events are stored on read FIFO
+queue. If application reads <TT>/dev/sequencer</TT> in blocking mode, the
+process will be awaked.
+
+<H2>
+7. Interface to Synthesizer Device</H2>
+
+<H3>
+7.1. Registration</H3>
+To register an OSS synthesizer device, use <TT>snd_seq_oss_synth_register</TT>
+function.
+<PRE>int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snd_seq_oss_callback_t *oper, void *private_data)</PRE>
+The arguments <TT>name</TT>, <TT>type</TT>, <TT>subtype</TT> and
+<TT>nvoices</TT>
+are used for making the appropriate synth_info structure for ioctl. The
+return value is an index number of this device. This index must be remembered
+for unregister. If registration is failed, -errno will be returned.
+<P>To release this device, call <TT>snd_seq_oss_synth_unregister function</TT>:
+<PRE>int snd_seq_oss_synth_unregister(int index),</PRE>
+where the <TT>index</TT> is the index number returned by register function.
+<H3>
+7.2. Callbacks</H3>
+OSS synthesizer devices have capability for sample downloading and ioctls
+like sample reset. In OSS emulation, these special features are realized
+by using callbacks. The registration argument oper is used to specify these
+callbacks. The following callback functions must be defined:
+<PRE>snd_seq_oss_callback_t:
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*open)(snd_seq_oss_arg_t *p, void *closure);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*close)(snd_seq_oss_arg_t *p);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*reset)(snd_seq_oss_arg_t *p);
+Except for <TT>open</TT> and <TT>close</TT> callbacks, they are allowed
+to be NULL.
+<P>Each callback function takes the argument type snd_seq_oss_arg_t as the
+first argument.
+<PRE>struct snd_seq_oss_arg_t {
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int app_index;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int file_mode;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int seq_mode;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snd_seq_addr_t addr;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *private_data;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int event_passing;
+};</PRE>
+The first three fields, <TT>app_index</TT>, <TT>file_mode</TT> and
+<TT>seq_mode</TT>
+are initialized by OSS sequencer. The <TT>app_index</TT> is the application
+index which is unique to each application opening OSS sequencer. The
+<TT>file_mode</TT>
+is bit-flags indicating the file operation mode. See
+<TT>seq_oss.h</TT>
+for its meaning. The <TT>seq_mode</TT> is sequencer operation mode. In
+the current version, only <TT>SND_OSSSEQ_MODE_SYNTH</TT> is used.
+<P>The next two fields, <TT>addr</TT> and <TT>private_data</TT>, must be
+filled by the synth driver at open callback. The <TT>addr</TT> contains
+the address of ALSA sequencer port which is assigned to this device. If
+the driver allocates memory for <TT>private_data</TT>, it must be released
+in close callback by itself.
+<P>The last field, <TT>event_passing</TT>, indicates how to translate note-on
+/ off events. In <TT>PROCESS_EVENTS</TT> mode, the note 255 is regarded
+as velocity change, and key pressure event is passed to the port. In <TT>PASS_EVENTS</TT>
+mode, all note on/off events are passed to the port without modified. <TT>PROCESS_KEYPRESS</TT>
+mode checks the note above 128 and regards it as key pressure event (mainly
+for Emu8000 driver).
+<H4>
+7.2.1. Open Callback</H4>
+The <TT>open</TT> is called at each time this device is opened by an application
+using OSS sequencer. This must not be NULL. Typically, the open callback
+does the following procedure:
+<OL>
+<LI>
+Allocate private data record.</LI>
+
+<LI>
+Create an ALSA sequencer port.</LI>
+
+<LI>
+Set the new port address on arg->addr.</LI>
+
+<LI>
+Set the private data record pointer on arg->private_data.</LI>
+</OL>
+Note that the type bit-flags in port_info of this synth port must NOT contain
+<TT>TYPE_MIDI_GENERIC</TT>
+bit. Instead, <TT>TYPE_SPECIFIC</TT> should be used. Also, <TT>CAP_SUBSCRIPTION</TT>
+bit should NOT be included, too. This is necessary to tell it from other
+normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
+return -errno.
+<H4>
+7.2.2 Ioctl Callback</H4>
+The <TT>ioctl</TT> callback is called when the sequencer receives device-specific
+ioctls. The following two ioctls should be processed by this callback:
+<UL>
+<LI>
+<TT>IOCTL_SEQ_RESET_SAMPLES</TT></LI>
+
+<BR>reset all samples on memory -- return 0
+<LI>
+<TT>IOCTL_SYNTH_MEMAVL</TT></LI>
+
+<BR>return the available memory size
+<LI>
+<TT>FM_4OP_ENABLE</TT></LI>
+
+<BR>can be ignored usually</UL>
+The other ioctls are processed inside the sequencer without passing to
+the lowlevel driver.
+<H4>
+7.2.3 Load_Patch Callback</H4>
+The <TT>load_patch</TT> callback is used for sample-downloading. This callback
+must read the data on user-space and transfer to each device. Return 0
+if succeeded, and -errno if failed. The format argument is the patch key
+in patch_info record. The buf is user-space pointer where patch_info record
+is stored. The offs can be ignored. The count is total data size of this
+sample data.
+<H4>
+7.2.4 Close Callback</H4>
+The <TT>close</TT> callback is called when this device is closed by the
+applicaion. If any private data was allocated in open callback, it must
+be released in the close callback. The deletion of ALSA port should be
+done here, too. This callback must not be NULL.
+<H4>
+7.2.5 Reset Callback</H4>
+The <TT>reset</TT> callback is called when sequencer device is reset or
+closed by applications. The callback should turn off the sounds on the
+relevant port immediately, and initialize the status of the port. If this
+callback is undefined, OSS seq sends a <TT>HEARTBEAT</TT> event to the
+port.
+<H3>
+7.3 Events</H3>
+Most of the events are processed by sequencer and translated to the adequate
+ALSA sequencer events, so that each synth device can receive by input_event
+callback of ALSA sequencer port. The following ALSA events should be implemented
+by the driver:
+<BR>&nbsp;
+<TABLE BORDER WIDTH="75%" NOSAVE >
+<TR NOSAVE>
+<TD NOSAVE><B>ALSA event</B></TD>
+
+<TD><B>Original OSS events</B></TD>
+</TR>
+
+<TR>
+<TD>NOTEON</TD>
+
+<TD>SEQ_NOTEON
+<BR>MIDI_NOTEON</TD>
+</TR>
+
+<TR>
+<TD>NOTE</TD>
+
+<TD>SEQ_NOTEOFF
+<BR>MIDI_NOTEOFF</TD>
+</TR>
+
+<TR NOSAVE>
+<TD NOSAVE>KEYPRESS</TD>
+
+<TD>MIDI_KEY_PRESSURE</TD>
+</TR>
+
+<TR NOSAVE>
+<TD>CHANPRESS</TD>
+
+<TD NOSAVE>SEQ_AFTERTOUCH
+<BR>MIDI_CHN_PRESSURE</TD>
+</TR>
+
+<TR NOSAVE>
+<TD NOSAVE>PGMCHANGE</TD>
+
+<TD NOSAVE>SEQ_PGMCHANGE
+<BR>MIDI_PGM_CHANGE</TD>
+</TR>
+
+<TR>
+<TD>PITCHBEND</TD>
+
+<TD>SEQ_CONTROLLER(CTRL_PITCH_BENDER)
+<BR>MIDI_PITCH_BEND</TD>
+</TR>
+
+<TR>
+<TD>CONTROLLER</TD>
+
+<TD>MIDI_CTL_CHANGE
+<BR>SEQ_BALANCE (with CTL_PAN)</TD>
+</TR>
+
+<TR>
+<TD>CONTROL14</TD>
+
+<TD>SEQ_CONTROLLER</TD>
+</TR>
+
+<TR>
+<TD>REGPARAM</TD>
+
+<TD>SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)</TD>
+</TR>
+
+<TR>
+<TD>SYSEX</TD>
+
+<TD>SEQ_SYSEX</TD>
+</TR>
+</TABLE>
+
+<P>The most of these behavior can be realized by MIDI emulation driver
+included in the Emu8000 lowlevel driver. In the future release, this module
+will be independent.
+<P>Some OSS events (<TT>SEQ_PRIVATE</TT> and <TT>SEQ_VOLUME</TT> events) are passed as event
+type SND_SEQ_OSS_PRIVATE. The OSS sequencer passes these event 8 byte
+packets without any modification. The lowlevel driver should process these
+events appropriately.
+<H2>
+8. Interface to MIDI Device</H2>
+Since the OSS emulation probes the creation and deletion of ALSA MIDI sequencer
+ports automatically by receiving announcement from ALSA sequencer, the
+MIDI devices don't need to be registered explicitly like synth devices.
+However, the MIDI port_info registered to ALSA sequencer must include a group
+name <TT>SND_SEQ_GROUP_DEVICE</TT> and a capability-bit <TT>CAP_READ</TT> or
+<TT>CAP_WRITE</TT>. Also, subscription capabilities, <TT>CAP_SUBS_READ</TT> or <TT>CAP_SUBS_WRITE</TT>,
+must be defined, too. If these conditions are not satisfied, the port is not
+registered as OSS sequencer MIDI device.
+<P>The events via MIDI devices are parsed in OSS sequencer and converted
+to the corresponding ALSA sequencer events. The input from MIDI sequencer
+is also converted to MIDI byte events by OSS sequencer. This works just
+a reverse way of seq_midi module.
+<H2>
+9. Known Problems / TODO's</H2>
+
+<UL>
+<LI>
+Patch loading via ALSA instrument layer is not implemented yet.</LI>
+</UL>
+
+</BODY>
+</HTML>
diff --git a/Documentation/sound/AD1816 b/Documentation/sound/oss/AD1816
index 14bd8f25d523..14bd8f25d523 100644
--- a/Documentation/sound/AD1816
+++ b/Documentation/sound/oss/AD1816
diff --git a/Documentation/sound/ALS b/Documentation/sound/oss/ALS
index d01ffbfd5808..d01ffbfd5808 100644
--- a/Documentation/sound/ALS
+++ b/Documentation/sound/oss/ALS
diff --git a/Documentation/sound/AWE32 b/Documentation/sound/oss/AWE32
index 0f50f5d24c28..0f50f5d24c28 100644
--- a/Documentation/sound/AWE32
+++ b/Documentation/sound/oss/AWE32
diff --git a/Documentation/sound/AudioExcelDSP16 b/Documentation/sound/oss/AudioExcelDSP16
index f4ffd9d0c2e1..f4ffd9d0c2e1 100644
--- a/Documentation/sound/AudioExcelDSP16
+++ b/Documentation/sound/oss/AudioExcelDSP16
diff --git a/Documentation/sound/CMI8330 b/Documentation/sound/oss/CMI8330
index 28779988406a..28779988406a 100644
--- a/Documentation/sound/CMI8330
+++ b/Documentation/sound/oss/CMI8330
diff --git a/Documentation/sound/CMI8338 b/Documentation/sound/oss/CMI8338
index 387d058c3f95..387d058c3f95 100644
--- a/Documentation/sound/CMI8338
+++ b/Documentation/sound/oss/CMI8338
diff --git a/Documentation/sound/CS4232 b/Documentation/sound/oss/CS4232
index 7d6af7a5c1c2..7d6af7a5c1c2 100644
--- a/Documentation/sound/CS4232
+++ b/Documentation/sound/oss/CS4232
diff --git a/Documentation/sound/ChangeLog.awe b/Documentation/sound/oss/ChangeLog.awe
index 330cc0e5f102..330cc0e5f102 100644
--- a/Documentation/sound/ChangeLog.awe
+++ b/Documentation/sound/oss/ChangeLog.awe
diff --git a/Documentation/sound/ChangeLog.multisound b/Documentation/sound/oss/ChangeLog.multisound
index a05a74365dd3..a05a74365dd3 100644
--- a/Documentation/sound/ChangeLog.multisound
+++ b/Documentation/sound/oss/ChangeLog.multisound
diff --git a/Documentation/sound/ESS b/Documentation/sound/oss/ESS
index bba93b4d2def..bba93b4d2def 100644
--- a/Documentation/sound/ESS
+++ b/Documentation/sound/oss/ESS
diff --git a/Documentation/sound/ESS1868 b/Documentation/sound/oss/ESS1868
index 55e922f21bc0..55e922f21bc0 100644
--- a/Documentation/sound/ESS1868
+++ b/Documentation/sound/oss/ESS1868
diff --git a/Documentation/sound/INSTALL.awe b/Documentation/sound/oss/INSTALL.awe
index 72219acb2790..72219acb2790 100644
--- a/Documentation/sound/INSTALL.awe
+++ b/Documentation/sound/oss/INSTALL.awe
diff --git a/Documentation/sound/Introduction b/Documentation/sound/oss/Introduction
index 0b7fdc9593a4..0b7fdc9593a4 100644
--- a/Documentation/sound/Introduction
+++ b/Documentation/sound/oss/Introduction
diff --git a/Documentation/sound/MAD16 b/Documentation/sound/oss/MAD16
index 1f3abf7f0db8..1f3abf7f0db8 100644
--- a/Documentation/sound/MAD16
+++ b/Documentation/sound/oss/MAD16
diff --git a/Documentation/sound/Maestro b/Documentation/sound/oss/Maestro
index 4a80eb3f8e00..4a80eb3f8e00 100644
--- a/Documentation/sound/Maestro
+++ b/Documentation/sound/oss/Maestro
diff --git a/Documentation/sound/Maestro3 b/Documentation/sound/oss/Maestro3
index ce6cf791ce6c..ce6cf791ce6c 100644
--- a/Documentation/sound/Maestro3
+++ b/Documentation/sound/oss/Maestro3
diff --git a/Documentation/sound/MultiSound b/Documentation/sound/oss/MultiSound
index e4a18bb7f73a..e4a18bb7f73a 100644
--- a/Documentation/sound/MultiSound
+++ b/Documentation/sound/oss/MultiSound
diff --git a/Documentation/sound/NEWS b/Documentation/sound/oss/NEWS
index de09b8c0a151..de09b8c0a151 100644
--- a/Documentation/sound/NEWS
+++ b/Documentation/sound/oss/NEWS
diff --git a/Documentation/sound/NM256 b/Documentation/sound/oss/NM256
index b503217488b3..b503217488b3 100644
--- a/Documentation/sound/NM256
+++ b/Documentation/sound/oss/NM256
diff --git a/Documentation/sound/OPL3 b/Documentation/sound/oss/OPL3
index 2468ff827688..2468ff827688 100644
--- a/Documentation/sound/OPL3
+++ b/Documentation/sound/oss/OPL3
diff --git a/Documentation/sound/OPL3-SA b/Documentation/sound/oss/OPL3-SA
index 0d91c8bf3b83..0d91c8bf3b83 100644
--- a/Documentation/sound/OPL3-SA
+++ b/Documentation/sound/oss/OPL3-SA
diff --git a/Documentation/sound/OPL3-SA2 b/Documentation/sound/oss/OPL3-SA2
index 4c6c0c7b4931..5da5199a485b 100644
--- a/Documentation/sound/OPL3-SA2
+++ b/Documentation/sound/oss/OPL3-SA2
@@ -65,7 +65,7 @@ Plug 'n Play
------------
In previous kernels (2.2.x), some configuration was required to
-get the driver to talk to the card. Being the new millenium and
+get the driver to talk to the card. Being the new millennium and
all, the 2.4.x kernels now support auto-configuration if ISA PnP
support is configured in. Theoretically, the driver even supports
having more than one card in this case.
diff --git a/Documentation/sound/Opti b/Documentation/sound/oss/Opti
index 246f0224d789..246f0224d789 100644
--- a/Documentation/sound/Opti
+++ b/Documentation/sound/oss/Opti
diff --git a/Documentation/sound/PAS16 b/Documentation/sound/oss/PAS16
index fc0b6fe0716a..fc0b6fe0716a 100644
--- a/Documentation/sound/PAS16
+++ b/Documentation/sound/oss/PAS16
diff --git a/Documentation/sound/PSS b/Documentation/sound/oss/PSS
index 187b9525e1f6..187b9525e1f6 100644
--- a/Documentation/sound/PSS
+++ b/Documentation/sound/oss/PSS
diff --git a/Documentation/sound/PSS-updates b/Documentation/sound/oss/PSS-updates
index 004e894af5c8..004e894af5c8 100644
--- a/Documentation/sound/PSS-updates
+++ b/Documentation/sound/oss/PSS-updates
diff --git a/Documentation/sound/README.OSS b/Documentation/sound/oss/README.OSS
index 453babb26d30..ac1eaf5e977d 100644
--- a/Documentation/sound/README.OSS
+++ b/Documentation/sound/oss/README.OSS
@@ -542,7 +542,7 @@ Yamaha OPL3-SA1
SoftOSS keeps the samples loaded on the system's RAM so much RAM is
required. SoftOSS should never be used on machines with less than 16 MB
- of RAM since this is potentially dangerous (you may accidently run out
+ of RAM since this is potentially dangerous (you may accidentally run out
of memory which probably crashes the machine).
SoftOSS implements the wave table API originally designed for GUS. For
diff --git a/Documentation/sound/README.awe b/Documentation/sound/oss/README.awe
index 80054cd8fcde..80054cd8fcde 100644
--- a/Documentation/sound/README.awe
+++ b/Documentation/sound/oss/README.awe
diff --git a/Documentation/sound/README.modules b/Documentation/sound/oss/README.modules
index 98f525cab6c4..98f525cab6c4 100644
--- a/Documentation/sound/README.modules
+++ b/Documentation/sound/oss/README.modules
diff --git a/Documentation/sound/README.ymfsb b/Documentation/sound/oss/README.ymfsb
index af8a7d3a4e8e..af8a7d3a4e8e 100644
--- a/Documentation/sound/README.ymfsb
+++ b/Documentation/sound/oss/README.ymfsb
diff --git a/Documentation/sound/SoundPro b/Documentation/sound/oss/SoundPro
index 61b9a91973bf..61b9a91973bf 100644
--- a/Documentation/sound/SoundPro
+++ b/Documentation/sound/oss/SoundPro
diff --git a/Documentation/sound/Soundblaster b/Documentation/sound/oss/Soundblaster
index b288d464ba8b..b288d464ba8b 100644
--- a/Documentation/sound/Soundblaster
+++ b/Documentation/sound/oss/Soundblaster
diff --git a/Documentation/sound/Tropez+ b/Documentation/sound/oss/Tropez+
index b93a6b734fc0..b93a6b734fc0 100644
--- a/Documentation/sound/Tropez+
+++ b/Documentation/sound/oss/Tropez+
diff --git a/Documentation/sound/VIA-chipset b/Documentation/sound/oss/VIA-chipset
index 37865234e54d..37865234e54d 100644
--- a/Documentation/sound/VIA-chipset
+++ b/Documentation/sound/oss/VIA-chipset
diff --git a/Documentation/sound/VIBRA16 b/Documentation/sound/oss/VIBRA16
index 0a0aff9d7531..0a0aff9d7531 100644
--- a/Documentation/sound/VIBRA16
+++ b/Documentation/sound/oss/VIBRA16
diff --git a/Documentation/sound/WaveArtist b/Documentation/sound/oss/WaveArtist
index f4f3407cd818..f4f3407cd818 100644
--- a/Documentation/sound/WaveArtist
+++ b/Documentation/sound/oss/WaveArtist
diff --git a/Documentation/sound/Wavefront b/Documentation/sound/oss/Wavefront
index 5453af77f425..5453af77f425 100644
--- a/Documentation/sound/Wavefront
+++ b/Documentation/sound/oss/Wavefront
diff --git a/Documentation/sound/btaudio b/Documentation/sound/oss/btaudio
index 1a693e69d44b..1a693e69d44b 100644
--- a/Documentation/sound/btaudio
+++ b/Documentation/sound/oss/btaudio
diff --git a/Documentation/sound/cs46xx b/Documentation/sound/oss/cs46xx
index 1f93c03ceaa4..1f93c03ceaa4 100644
--- a/Documentation/sound/cs46xx
+++ b/Documentation/sound/oss/cs46xx
diff --git a/Documentation/sound/es1370 b/Documentation/sound/oss/es1370
index 7b38b1a096a3..7b38b1a096a3 100644
--- a/Documentation/sound/es1370
+++ b/Documentation/sound/oss/es1370
diff --git a/Documentation/sound/es1371 b/Documentation/sound/oss/es1371
index c3151266771c..c3151266771c 100644
--- a/Documentation/sound/es1371
+++ b/Documentation/sound/oss/es1371
diff --git a/Documentation/sound/mwave b/Documentation/sound/oss/mwave
index 858334bb46b0..858334bb46b0 100644
--- a/Documentation/sound/mwave
+++ b/Documentation/sound/oss/mwave
diff --git a/Documentation/sound/solo1 b/Documentation/sound/oss/solo1
index 6f53d407d027..6f53d407d027 100644
--- a/Documentation/sound/solo1
+++ b/Documentation/sound/oss/solo1
diff --git a/Documentation/sound/sonicvibes b/Documentation/sound/oss/sonicvibes
index 84dee2e0b37d..84dee2e0b37d 100644
--- a/Documentation/sound/sonicvibes
+++ b/Documentation/sound/oss/sonicvibes
diff --git a/Documentation/sound/ultrasound b/Documentation/sound/oss/ultrasound
index 32cd50478b36..32cd50478b36 100644
--- a/Documentation/sound/ultrasound
+++ b/Documentation/sound/oss/ultrasound
diff --git a/Documentation/sound/vwsnd b/Documentation/sound/oss/vwsnd
index a6ea0a1df9e4..a6ea0a1df9e4 100644
--- a/Documentation/sound/vwsnd
+++ b/Documentation/sound/oss/vwsnd
diff --git a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt
index 519bcf8bcd9e..2fa12665a2d7 100644
--- a/Documentation/usb/ov511.txt
+++ b/Documentation/usb/ov511.txt
@@ -182,9 +182,9 @@ MODULE PARAMETERS:
DEFAULT: 1 (Always on)
DESC: Controls whether the LED (the little light) on the front of the camera
is always off (0), always on (1), or only on when driver is open (2).
- This is only supported with the OV511+ chipset, and even then only on
- some cameras (ones that actually have the LED wired to the control pin,
- and not just hardwired to be on all the time).
+ This is not supported with the OV511, and might only work with certain
+ cameras (ones that actually have the LED wired to the control pin, and
+ not just hard-wired to be on all the time).
NAME: dump_bridge
TYPE: integer (Boolean)
diff --git a/MAINTAINERS b/MAINTAINERS
index 9c92cf3da7d2..2a366462e718 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1606,6 +1606,12 @@ L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
+USB EHCI DRIVER
+P: David Brownell
+M: dbrownell@users.sourceforge.net
+L: linux-usb-devel@lists.sourceforge.net
+S: Maintained
+
USB HID/HIDBP/INPUT DRIVERS
P: Vojtech Pavlik
M: vojtech@suse.cz
@@ -1739,6 +1745,12 @@ L: linux-usb-devel@lists.sourceforge.net
W: http://usb.in.tum.de
S: Maintained
+USB "USBNET" DRIVER
+P: David Brownell
+M: dbrownell@users.sourceforge.net
+L: linux-usb-devel@lists.sourceforge.net
+S: Maintained
+
VFAT FILESYSTEM:
P: Gordon Chaffee
M: chaffee@cs.berkeley.edu
diff --git a/Makefile b/Makefile
index 6069410cd6fd..763dab7b3bc4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 6
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
@@ -162,6 +162,7 @@ DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o
DRIVERS-$(CONFIG_NET_PCMCIA) += drivers/net/pcmcia/pcmcia_net.o
DRIVERS-$(CONFIG_NET_WIRELESS) += drivers/net/wireless/wireless_net.o
+DRIVERS-$(CONFIG_NET_TULIP) += drivers/net/tulip/tulip_net.o
DRIVERS-$(CONFIG_PCMCIA_CHRDEV) += drivers/char/pcmcia/pcmcia_char.o
DRIVERS-$(CONFIG_DIO) += drivers/dio/dio.a
DRIVERS-$(CONFIG_SBUS) += drivers/sbus/sbus_all.o
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index b1c6709aad87..8309ed9cc89d 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -237,7 +237,6 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
#
# IDE chipset support/bugfixes
@@ -250,7 +249,6 @@ CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_IDEDMA=y
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index 58e4aa037076..7fdc699f4dd3 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -495,7 +495,7 @@ alpha_switch_to:
ret $31,($26),1
.end alpha_switch_to
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
.globl ret_from_fork
.align 3
.ent ret_from_fork
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 7fdca800a30f..f69db6f8608e 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -682,7 +682,6 @@ comment 'Kernel hacking'
bool 'Compile kernel without frame pointer' CONFIG_NO_FRAME_POINTER
bool 'Verbose user fault messages' CONFIG_DEBUG_USER
bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
-dep_bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE $CONFIG_CPU_26
bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
dep_bool ' Debug memory allocations' CONFIG_DEBUG_SLAB $CONFIG_DEBUG_KERNEL
diff --git a/arch/arm/def-configs/shannon b/arch/arm/def-configs/shannon
index c59fb0cb67d7..3ff37c2fcf9c 100644
--- a/arch/arm/def-configs/shannon
+++ b/arch/arm/def-configs/shannon
@@ -378,7 +378,6 @@ CONFIG_BLK_DEV_IDE=m
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
#
# IDE chipset support/bugfixes
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 035f0f43699a..a84ba04ad73e 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -169,10 +169,6 @@ EXPORT_SYMBOL(__virt_to_bus);
EXPORT_SYMBOL(__bus_to_virt);
#endif
-#ifndef CONFIG_NO_PGT_CACHE
-EXPORT_SYMBOL(quicklists);
-#endif
-
/* string / mem functions */
EXPORT_SYMBOL_NOVERS(strcpy);
EXPORT_SYMBOL_NOVERS(strncpy);
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index e0b2eac9faa0..c95b4f4b68e3 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -95,9 +95,6 @@ void cpu_idle(void)
idle();
leds_event(led_idle_end);
schedule();
-#ifndef CONFIG_NO_PGT_CACHE
- check_pgt_cache();
-#endif
}
}
diff --git a/arch/arm/mach-adifcc/mm.c b/arch/arm/mach-adifcc/mm.c
index 3d0db7087fdf..a77f235f5c24 100644
--- a/arch/arm/mach-adifcc/mm.c
+++ b/arch/arm/mach-adifcc/mm.c
@@ -14,7 +14,7 @@
static struct map_desc adifcc_io_desc[] __initdata = {
/* on-board devices */
- { 0xff400000, 0x00400000, 0x00300000, DOMAIN_IO, 1, 1, 0, 0},
+ { 0xff400000, 0x00400000, 0x00300000, DOMAIN_IO, 0, 1, 0, 0},
LAST_DESC
};
diff --git a/arch/arm/mach-anakin/mm.c b/arch/arm/mach-anakin/mm.c
index 631e7d7daebe..39bb59668930 100644
--- a/arch/arm/mach-anakin/mm.c
+++ b/arch/arm/mach-anakin/mm.c
@@ -20,7 +20,7 @@
static struct map_desc anakin_io_desc[] __initdata = {
{ IO_BASE, IO_START, IO_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
- { FLASH_BASE, FLASH_START, FLASH_SIZE, DOMAIN_IO, 1, 1, 0, 0 },
+ { FLASH_BASE, FLASH_START, FLASH_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
{ VGA_BASE, VGA_START, VGA_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
LAST_DESC
};
diff --git a/arch/arm/mach-arc/mm.c b/arch/arm/mach-arc/mm.c
index aec1dad545c8..6a96065fbab2 100644
--- a/arch/arm/mach-arc/mm.c
+++ b/arch/arm/mach-arc/mm.c
@@ -78,15 +78,16 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
if (!new_pmd)
goto no_pmd;
- new_pte = pte_alloc(mm, new_pmd, 0);
+ new_pte = pte_alloc_map(mm, new_pmd, 0);
if (!new_pte)
goto no_pte;
init_pgd = pgd_offset_k(0);
init_pmd = pmd_offset(init_pgd, 0);
- init_pte = pte_offset(init_pmd, 0);
-
+ init_pte = pte_offset_map_nested(init_pmd, 0);
set_pte(new_pte, *init_pte);
+ pte_unmap_nested(init_pte);
+ pte_unmap(new_pte);
/*
* most of the page table entries are zeroed
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index dff16c19364d..82b2839ed899 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -51,7 +51,7 @@ static struct map_desc autcpu12_io_desc[] __initdata = {
/* virtual, physical, length, domain, r, w, c, b */
/* memory-mapped extra io and CS8900A Ethernet chip */
/* ethernet chip */
- { AUTCPU12_VIRT_CS8900A, AUTCPU12_PHYS_CS8900A, SZ_1M, DOMAIN_IO, 1, 1, 0, 0 },
+ { AUTCPU12_VIRT_CS8900A, AUTCPU12_PHYS_CS8900A, SZ_1M, DOMAIN_IO, 0, 1, 0, 0 },
LAST_DESC
};
diff --git a/arch/arm/mach-clps711x/edb7211-mm.c b/arch/arm/mach-clps711x/edb7211-mm.c
index e4e970451f18..47e999599226 100644
--- a/arch/arm/mach-clps711x/edb7211-mm.c
+++ b/arch/arm/mach-clps711x/edb7211-mm.c
@@ -56,12 +56,12 @@ static struct map_desc edb7211_io_desc[] __initdata = {
/* virtual, physical, length, domain, r, w, c, b */
/* memory-mapped extra keyboard row and CS8900A Ethernet chip */
- { EP7211_VIRT_EXTKBD, EP7211_PHYS_EXTKBD, MB1, DOMAIN_IO, 1, 1, 0, 0 },
- { EP7211_VIRT_CS8900A, EP7211_PHYS_CS8900A, MB1, DOMAIN_IO, 1, 1, 0, 0 },
+ { EP7211_VIRT_EXTKBD, EP7211_PHYS_EXTKBD, MB1, DOMAIN_IO, 0, 1, 0, 0 },
+ { EP7211_VIRT_CS8900A, EP7211_PHYS_CS8900A, MB1, DOMAIN_IO, 0, 1, 0, 0 },
/* flash banks */
- { EP7211_VIRT_FLASH1, EP7211_PHYS_FLASH1, MB1 * 8, DOMAIN_KERNEL, 1, 1, 0, 0 },
- { EP7211_VIRT_FLASH2, EP7211_PHYS_FLASH2, MB1 * 8, DOMAIN_KERNEL, 1, 1, 0, 0 },
+ { EP7211_VIRT_FLASH1, EP7211_PHYS_FLASH1, MB1 * 8, DOMAIN_KERNEL, 0, 1, 0, 0 },
+ { EP7211_VIRT_FLASH2, EP7211_PHYS_FLASH2, MB1 * 8, DOMAIN_KERNEL, 0, 1, 0, 0 },
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c
index eedeabb18634..72e7c953061c 100644
--- a/arch/arm/mach-sa1100/adsbitsy.c
+++ b/arch/arm/mach-sa1100/adsbitsy.c
@@ -125,7 +125,7 @@ fixup_adsbitsy(struct machine_desc *desc, struct param_struct *params,
static struct map_desc adsbitsy_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1111 */
+ { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 35d05f80e31b..5f8ed1c0d556 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -230,8 +230,8 @@ fixup_assabet(struct machine_desc *desc, struct param_struct *params,
static struct map_desc assabet_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf1000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
+ { 0xf1000000, 0x12000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */
+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
/* f3000000 - neponset system registers */
/* f4000000 - neponset SA1111 registers */
LAST_DESC
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index bf2385ab4cd4..8ebd37634fc5 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -64,11 +64,11 @@ fixup_cerf(struct machine_desc *desc, struct param_struct *params,
static struct map_desc cerf_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Crystal Ethernet Chip */
+ { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Crystal Ethernet Chip */
#ifdef CONFIG_SA1100_CERF_CPLD
- { 0xf1000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* CPLD Chip */
- { 0xf2000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* CerfPDA Bluetooth */
- { 0xf3000000, 0x18000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* CerfPDA Serial */
+ { 0xf1000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD Chip */
+ { 0xf2000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CerfPDA Bluetooth */
+ { 0xf3000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CerfPDA Serial */
#endif
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/empeg.c b/arch/arm/mach-sa1100/empeg.c
index 682e99d522d2..d35f3c71534a 100644
--- a/arch/arm/mach-sa1100/empeg.c
+++ b/arch/arm/mach-sa1100/empeg.c
@@ -31,7 +31,7 @@ fixup_empeg(struct machine_desc *desc, struct param_struct *params,
static struct map_desc empeg_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
+ { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c
index 8ce7cea310c8..a470b49e3815 100644
--- a/arch/arm/mach-sa1100/flexanet.c
+++ b/arch/arm/mach-sa1100/flexanet.c
@@ -172,10 +172,10 @@ fixup_flexanet(struct machine_desc *desc, struct param_struct *params,
static struct map_desc flexanet_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
- { 0xf1000000, 0x18000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Ethernet controller */
- { 0xD0000000, 0x40000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Instrument boards */
- { 0xD8000000, 0x48000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* External peripherals */
+ { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */
+ { 0xf1000000, 0x18000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Ethernet controller */
+ { 0xD0000000, 0x40000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Instrument boards */
+ { 0xD8000000, 0x48000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* External peripherals */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c
index 3a28685b6a21..c0b6e5f7b9d1 100644
--- a/arch/arm/mach-sa1100/freebird.c
+++ b/arch/arm/mach-sa1100/freebird.c
@@ -66,8 +66,8 @@ fixup_freebird(struct machine_desc *desc, struct param_struct *params,
static struct map_desc freebird_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
- { 0xf2000000, 0x19000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0},
+ { 0xf0000000, 0x12000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */
+ { 0xf2000000, 0x19000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0},
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c
index 9178fed76dec..9997cdc11686 100644
--- a/arch/arm/mach-sa1100/graphicsclient.c
+++ b/arch/arm/mach-sa1100/graphicsclient.c
@@ -32,67 +32,62 @@
* Handlers for GraphicsClient's external IRQ logic
*/
-static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+static void
+gc_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
- int i;
+ unsigned int mask;
+
+ while ((mask = ADS_INT_ST1 | (ADS_INT_ST2 << 8))) {
+ /* clear the parent IRQ */
+ GEDR = GPIO_GPIO0;
- while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){
- for( i = 0; i < 16; i++ )
- if( irq & (1<<i) )
- do_IRQ( ADS_EXT_IRQ(i), regs );
+ irq = ADS_EXT_IRQ(0);
+ desc = irq_desc + irq;
+
+ do {
+ if (mask & 1)
+ desc->handle(irq, desc, regs);
+ mask >>= 1;
+ irq++;
+ desc++;
+ } while (mask);
}
}
-static struct irqaction ADS_ext_irq = {
- name: "ADS_ext_IRQ",
- handler: ADS_IRQ_demux,
- flags: SA_INTERRUPT
-};
-
-static void ADS_mask_and_ack_irq0(unsigned int irq)
+static void gc_mask_irq1(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(0)));
ADS_INT_EN1 &= ~mask;
ADS_INT_ST1 = mask;
}
-static void ADS_mask_irq0(unsigned int irq)
-{
- ADS_INT_ST1 = (1 << (irq - ADS_EXT_IRQ(0)));
-}
-
-static void ADS_unmask_irq0(unsigned int irq)
+static void gc_unmask_irq1(unsigned int irq)
{
ADS_INT_EN1 |= (1 << (irq - ADS_EXT_IRQ(0)));
}
-static struct irqchip ADS0_chip = {
- ack: ADS_mask_and_ack_irq0,
- mask: ADS_mask_irq0,
- unmask: ADS_unmask_irq0,
+static struct irqchip gc_irq1_chip = {
+ ack: gc_mask_irq1,
+ mask: gc_mask_irq1,
+ unmask: gc_unmask_irq1,
};
-static void ADS_mask_and_ack_irq1(unsigned int irq)
+static void gc_mask_irq2(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(8)));
ADS_INT_EN2 &= ~mask;
ADS_INT_ST2 = mask;
}
-static void ADS_mask_irq1(unsigned int irq)
-{
- ADS_INT_ST2 = (1 << (irq - ADS_EXT_IRQ(8)));
-}
-
-static void ADS_unmask_irq1(unsigned int irq)
+static void gc_unmask_irq2(unsigned int irq)
{
ADS_INT_EN2 |= (1 << (irq - ADS_EXT_IRQ(8)));
}
-static struct irqchip ADS1_chip = {
- ack: ADS_mask_and_ack_irq1,
- mask: ADS_mask_irq1,
- unmask: ADS_unmask_irq1,
+static struct irqchip gc_irq2_chip = {
+ ack: gc_mask_irq2,
+ mask: gc_mask_irq2,
+ unmask: gc_unmask_irq2,
};
static void __init graphicsclient_init_irq(void)
@@ -105,22 +100,23 @@ static void __init graphicsclient_init_irq(void)
/* disable all IRQs */
ADS_INT_EN1 = 0;
ADS_INT_EN2 = 0;
+
/* clear all IRQs */
ADS_INT_ST1 = 0xff;
ADS_INT_ST2 = 0xff;
for (irq = ADS_EXT_IRQ(0); irq <= ADS_EXT_IRQ(7); irq++) {
- set_irq_chip(irq, &ADS0_chip);
+ set_irq_chip(irq, &gc_irq1_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
for (irq = ADS_EXT_IRQ(8); irq <= ADS_EXT_IRQ(15); irq++) {
- set_irq_chip(irq, &ADS1_chip);
+ set_irq_chip(irq, &gc_irq2_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
- set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
- setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
+ set_irq_type(IRQ_GPIO0, IRQT_FALLING);
+ set_irq_chained_handler(IRQ_GPIO0, gc_irq_handler);
}
@@ -148,111 +144,6 @@ static struct map_desc graphicsclient_io_desc[] __initdata = {
LAST_DESC
};
-static struct gc_uart_ctrl_data_t gc_uart_ctrl_data[] = {
- { GPIO_GC_UART0_CTS, 0, NULL,NULL },
- { GPIO_GC_UART1_CTS, 0, NULL,NULL },
- { GPIO_GC_UART2_CTS, 0, NULL,NULL }
-};
-
-#error Old code. Someone needs to decide what to do with this
-#if 0
-static void
-graphicsclient_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct gc_uart_ctrl_data_t * uart_data = (struct gc_uart_ctrl_data_t *)dev_id;
- int cts = !(GPLR & uart_data->cts_gpio);
-
- /* NOTE: I supose that we will no get any interrupt
- if the GPIO is not changed, so maybe
- the cts_prev_state can be removed ... */
- if (cts != uart_data->cts_prev_state) {
- uart_data->cts_prev_state = cts;
-
- uart_handle_cts_change(uart_data->info, cts);
- }
-}
-
-static int
-graphicsclient_register_cts_intr(int gpio, int irq,
- struct gc_uart_ctrl_data_t *uart_data)
-{
- int ret = 0;
-
- set_GPIO_IRQ_edge(gpio, GPIO_BOTH_EDGES);
-
- ret = request_irq(irq, graphicsclient_cts_intr,
- 0, "GC RS232 CTS", uart_data);
- if (ret) {
- printk(KERN_ERR "uart_open: failed to register CTS irq (%d)\n",
- ret);
- free_irq(irq, uart_data);
- }
-
- return ret;
-}
-
-static int
-graphicsclient_uart_open(struct uart_port *port, struct uart_info *info)
-{
- int ret = 0;
-
- if (port->mapbase == _Ser1UTCR0) {
- Ser1SDCR0 |= SDCR0_UART;
- /* Set RTS Output */
- GPSR = GPIO_GC_UART0_RTS;
-
- gc_uart_ctrl_data[0].cts_prev_state = 0;
- gc_uart_ctrl_data[0].info = info;
- gc_uart_ctrl_data[0].port = port;
-
- /* register uart0 CTS irq */
- ret = graphicsclient_register_cts_intr(GPIO_GC_UART0_CTS,
- IRQ_GC_UART0_CTS,
- &gc_uart_ctrl_data[0]);
- } else if (port->mapbase == _Ser2UTCR0) {
- Ser2UTCR4 = Ser2HSCR0 = 0;
- /* Set RTS Output */
- GPSR = GPIO_GC_UART1_RTS;
-
- gc_uart_ctrl_data[1].cts_prev_state = 0;
- gc_uart_ctrl_data[1].info = info;
- gc_uart_ctrl_data[1].port = port;
-
- /* register uart1 CTS irq */
- ret = graphicsclient_register_cts_intr(GPIO_GC_UART1_CTS,
- IRQ_GC_UART1_CTS,
- &gc_uart_ctrl_data[1]);
- } else if (port->mapbase == _Ser3UTCR0) {
- /* Set RTS Output */
- GPSR = GPIO_GC_UART2_RTS;
-
- gc_uart_ctrl_data[2].cts_prev_state = 0;
- gc_uart_ctrl_data[2].info = info;
- gc_uart_ctrl_data[2].port = port;
-
- /* register uart2 CTS irq */
- ret = graphicsclient_register_cts_intr(GPIO_GC_UART2_CTS,
- IRQ_GC_UART2_CTS,
- &gc_uart_ctrl_data[2]);
- }
- return ret;
-}
-
-static int
-graphicsclient_uart_close(struct uart_port *port, struct uart_info *info)
-{
- if (port->mapbase == _Ser1UTCR0) {
- free_irq(IRQ_GC_UART0_CTS, &gc_uart_ctrl_data[0]);
- } else if (port->mapbase == _Ser2UTCR0) {
- free_irq(IRQ_GC_UART1_CTS, &gc_uart_ctrl_data[1]);
- } else if (port->mapbase == _Ser3UTCR0) {
- free_irq(IRQ_GC_UART2_CTS, &gc_uart_ctrl_data[2]);
- }
-
- return 0;
-}
-#endif
-
static u_int graphicsclient_get_mctrl(struct uart_port *port)
{
u_int result = TIOCM_CD | TIOCM_DSR;
diff --git a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c
index c4e52db5e428..b2eaecb33257 100644
--- a/arch/arm/mach-sa1100/graphicsmaster.c
+++ b/arch/arm/mach-sa1100/graphicsmaster.c
@@ -93,68 +93,62 @@ __initcall(graphicsmaster_init);
* Handlers for GraphicsMaster's external IRQ logic
*/
-static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+static void
+gm_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
- int i;
-
- while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){
- for( i = 0; i < 16; i++ )
- if( irq & (1<<i) ) {
- do_IRQ( ADS_EXT_IRQ(i), regs );
- }
+ unsigned int mask;
+
+ while ((mask = ADS_INT_ST1 | (ADS_INT_ST2 << 8))) {
+ /* clear the parent IRQ */
+ GEDR = GPIO_GPIO0;
+
+ irq = ADS_EXT_IRQ(0);
+ desc = irq_desc + irq;
+
+ do {
+ if (mask & 1)
+ desc->handle(irq, desc, regs);
+ mask >>= 1;
+ irq++;
+ desc++;
+ } while (mask);
}
}
-static struct irqaction ADS_ext_irq = {
- name: "ADS_ext_IRQ",
- handler: ADS_IRQ_demux,
- flags: SA_INTERRUPT
-};
-
-static void ADS_mask_and_ack_irq0(unsigned int irq)
+static void gm_mask_irq1(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(0)));
ADS_INT_EN1 &= ~mask;
ADS_INT_ST1 = mask;
}
-static void ADS_mask_irq0(unsigned int irq)
-{
- ADS_INT_ST1 = (1 << (irq - ADS_EXT_IRQ(0)));
-}
-
-static void ADS_unmask_irq0(unsigned int irq)
+static void gm_unmask_irq1(unsigned int irq)
{
ADS_INT_EN1 |= (1 << (irq - ADS_EXT_IRQ(0)));
}
-static struct irqchip ADS0_chip = {
- ack: ADS_mask_and_ack_irq0,
- mask: ADS_mask_irq0,
- unmask: ADS_unmask_irq0,
+static struct irqchip gm_irq1_chip = {
+ ack: gm_mask_irq1,
+ mask: gm_mask_irq1,
+ unmask: gm_unmask_irq1,
};
-static void ADS_mask_and_ack_irq1(unsigned int irq)
+static void gm_mask_irq2(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(8)));
ADS_INT_EN2 &= ~mask;
ADS_INT_ST2 = mask;
}
-static void ADS_mask_irq1(unsigned int irq)
-{
- ADS_INT_ST2 = (1 << (irq - ADS_EXT_IRQ(8)));
-}
-
-static void ADS_unmask_irq1(unsigned int irq)
+static void gm_unmask_irq2(unsigned int irq)
{
ADS_INT_EN2 |= (1 << (irq - ADS_EXT_IRQ(8)));
}
-static struct irqchip ADS1_chip = {
- ack: ADS_mask_irq1,
- mask: ADS_mask_irq1,
- unmask: ADS_mask_irq1,
+static struct irqchip gm_irq2_chip = {
+ ack: gm_mask_irq2,
+ mask: gm_mask_irq2,
+ unmask: gm_unmask_irq2,
};
static void __init graphicsmaster_init_irq(void)
@@ -167,22 +161,23 @@ static void __init graphicsmaster_init_irq(void)
/* disable all IRQs */
ADS_INT_EN1 = 0;
ADS_INT_EN2 = 0;
+
/* clear all IRQs */
ADS_INT_ST1 = 0xff;
ADS_INT_ST2 = 0xff;
for (irq = ADS_EXT_IRQ(0); irq <= ADS_EXT_IRQ(7); irq++) {
- set_irq_chip(irq, &ADS0_chip);
+ set_irq_chip(irq, &gm_irq1_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_PROBE | IRQF_VALID);
}
for (irq = ADS_EXT_IRQ(8); irq <= ADS_EXT_IRQ(15); irq++) {
- set_irq_chip(irq, &ADS1_chip);
+ set_irq_chip(irq, &gm_irq2_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_PROBE | IRQF_VALID);
}
- set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
- setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
+ set_irq_type(IRQ_GPIO0, IRQT_FALLING);
+ set_irq_chained_handler(IRQ_GPIO0, gm_irq_handler);
}
@@ -206,9 +201,9 @@ fixup_graphicsmaster(struct machine_desc *desc, struct param_struct *params,
static struct map_desc graphicsmaster_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* CPLD */
- { 0xf1000000, 0x40000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* CAN */
- { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+ { 0xf1000000, 0x40000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CAN */
+ { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index 633166a0ae05..6ce68739ce4a 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -489,9 +489,9 @@ static struct sa1100_port_fns h3600_port_fns __initdata = {
static struct map_desc h3600_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { H3600_EGPIO_VIRT, 0x49000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 CS#5 */
- { H3600_BANK_2_VIRT, 0x10000000, 0x02800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 CS#2 */
- { H3600_BANK_4_VIRT, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 CS#4 */
+ { H3600_EGPIO_VIRT, 0x49000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 CS#5 */
+ { H3600_BANK_2_VIRT, 0x10000000, 0x02800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 2 CS#2 */
+ { H3600_BANK_4_VIRT, 0x40000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 4 CS#4 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c
index 41a8ec5eedbf..98aba2ee8e8b 100644
--- a/arch/arm/mach-sa1100/huw_webpanel.c
+++ b/arch/arm/mach-sa1100/huw_webpanel.c
@@ -77,7 +77,7 @@ fixup_huw_webpanel(struct machine_desc *desc, struct param_struct *params,
**/
static struct map_desc huw_webpanel_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0xc1fb8000, 0x00048000, DOMAIN_IO, 1, 1, 0, 0 }, /* Parameter */
+ { 0xf0000000, 0xc1fb8000, 0x00048000, DOMAIN_IO, 0, 1, 0, 0 }, /* Parameter */
{ 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Paules CS3, write only */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/itsy.c b/arch/arm/mach-sa1100/itsy.c
index b715af6c3b9b..4594855326b1 100644
--- a/arch/arm/mach-sa1100/itsy.c
+++ b/arch/arm/mach-sa1100/itsy.c
@@ -31,8 +31,8 @@ fixup_itsy(struct machine_desc *desc, struct param_struct *params,
likely wrong. */
static struct map_desc itsy_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf0000000, 0x49000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf0000000, 0x49000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index c9dd8efc1379..98e94f85a9c1 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -66,9 +66,9 @@ fixup_jornada720(struct machine_desc *desc, struct param_struct *params,
static struct map_desc jornada720_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x48000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Epson registers */
- { 0xf1000000, 0x48200000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Epson frame buffer */
- { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xf0000000, 0x48000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Epson registers */
+ { 0xf1000000, 0x48200000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Epson frame buffer */
+ { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index fd1895dd4e32..4141747fcc80 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -18,8 +18,8 @@
static struct map_desc lart_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash memory */
- { 0xec000000, 0x08000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash, alternative location */
+ { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash memory */
+ { 0xec000000, 0x08000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash, alternative location */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
index 8aad8bd919b3..bf12430352cd 100644
--- a/arch/arm/mach-sa1100/nanoengine.c
+++ b/arch/arm/mach-sa1100/nanoengine.c
@@ -34,9 +34,9 @@ fixup_nanoengine(struct machine_desc *desc, struct param_struct *params,
static struct map_desc nanoengine_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
- { 0xf1000000, 0x18A00000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Internal PCI Config Space */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
+ { 0xf1000000, 0x18A00000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Internal PCI Config Space */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index e9ecf3498a6d..34158578a552 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -184,8 +184,8 @@ __initcall(neponset_init);
static struct map_desc neponset_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
- { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
+ { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c
index 76eaa1fb724d..604d9265a46f 100644
--- a/arch/arm/mach-sa1100/omnimeter.c
+++ b/arch/arm/mach-sa1100/omnimeter.c
@@ -54,7 +54,7 @@ fixup_omnimeter(struct machine_desc *desc, struct param_struct *params,
static struct map_desc omnimeter_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xd2000000, 0x10000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* TS */
+ { 0xd2000000, 0x10000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* TS */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/pangolin.c b/arch/arm/mach-sa1100/pangolin.c
index f27c7f4aa836..37c4f6cbdf6a 100644
--- a/arch/arm/mach-sa1100/pangolin.c
+++ b/arch/arm/mach-sa1100/pangolin.c
@@ -30,7 +30,7 @@ fixup_pangolin(struct machine_desc *desc, struct param_struct *params,
static struct map_desc pangolin_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c
index 8820c4a97b3f..18a1396deccf 100644
--- a/arch/arm/mach-sa1100/pfs168.c
+++ b/arch/arm/mach-sa1100/pfs168.c
@@ -103,20 +103,20 @@ fixup_pfs168(struct machine_desc *desc, struct param_struct *params,
static struct map_desc pfs168_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* 16C752 DUART port A (COM5) */
- { 0xf0001000, 0x10800000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* 16C752 DUART port B (COM6) */
- { 0xf0002000, 0x11000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* COM1 RTS control (SYSC1RTS) */
- { 0xf0003000, 0x11400000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Status LED control (SYSLED) */
- { 0xf0004000, 0x11800000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* DTMF code read (SYSDTMF) */
- { 0xf0005000, 0x11c00000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* LCD configure, enable (SYSLCDDE) */
- { 0xf0006000, 0x12000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* COM1 DSR and motion sense (SYSC1DSR) */
- { 0xf0007000, 0x12800000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* COM3 xmit enable (SYSC3TEN) */
- { 0xf0008000, 0x13000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Control register A (SYSCTLA) */
- { 0xf0009000, 0x13800000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Control register B (SYSCTLB) */
- { 0xf000a000, 0x18000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* SMC91C96 */
- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
- { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* 16C752 DUART port A (COM5) */
+ { 0xf0001000, 0x10800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* 16C752 DUART port B (COM6) */
+ { 0xf0002000, 0x11000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* COM1 RTS control (SYSC1RTS) */
+ { 0xf0003000, 0x11400000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Status LED control (SYSLED) */
+ { 0xf0004000, 0x11800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* DTMF code read (SYSDTMF) */
+ { 0xf0005000, 0x11c00000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD configure, enable (SYSLCDDE) */
+ { 0xf0006000, 0x12000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* COM1 DSR and motion sense (SYSC1DSR) */
+ { 0xf0007000, 0x12800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* COM3 xmit enable (SYSC3TEN) */
+ { 0xf0008000, 0x13000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Control register A (SYSCTLA) */
+ { 0xf0009000, 0x13800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Control register B (SYSCTLB) */
+ { 0xf000a000, 0x18000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* SMC91C96 */
+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
+ { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 49c608198034..d6fb7a186491 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -35,8 +35,8 @@ fixup_pleb(struct machine_desc *desc, struct param_struct *params,
static struct map_desc pleb_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash memory */
- { 0xe8400000, 0x08000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash, alternative location */
+ { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash memory */
+ { 0xe8400000, 0x08000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash, alternative location */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 3f897f5c98ce..ec23699c6b38 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -58,7 +58,7 @@ fixup_simpad(struct machine_desc *desc, struct param_struct *params,
static struct map_desc simpad_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
{ 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Paules CS3, write only */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c
index eacf6f8d786f..b57d653571c9 100644
--- a/arch/arm/mach-sa1100/stork.c
+++ b/arch/arm/mach-sa1100/stork.c
@@ -305,10 +305,10 @@ stork_kbd_unexpected_up(unsigned char code)
struct map_desc stork_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { STORK_VM_BASE_CS1, STORK_VM_OFF_CS1, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 */
- { 0xf1000000, 0x10000000, 0x02800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 */
- { 0xf3800000, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { STORK_VM_BASE_CS1, STORK_VM_OFF_CS1, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 */
+ { 0xf1000000, 0x10000000, 0x02800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 2 */
+ { 0xf3800000, 0x40000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 4 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
index 9745fea25720..34d08d17dc75 100644
--- a/arch/arm/mach-sa1100/system3.c
+++ b/arch/arm/mach-sa1100/system3.c
@@ -58,6 +58,7 @@
#include "generic.h"
#include "sa1111.h"
+#include <asm/hardware/sa1111.h>
#define DEBUG 1
@@ -74,19 +75,17 @@
/* init funcs */
static void __init fixup_system3(struct machine_desc *desc,
struct param_struct *params, char **cmdline, struct meminfo *mi);
-static void __init get_system3_scr(void);
static int __init system3_init(void);
static void __init system3_init_irq(void);
static void __init system3_map_io(void);
-static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs );
-static int system3_get_mctrl(struct uart_port *port);
+static u_int system3_get_mctrl(struct uart_port *port);
static void system3_set_mctrl(struct uart_port *port, u_int mctrl);
static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
static int sdram_notifier(struct notifier_block *nb, unsigned long event, void *data);
-static int system3_lcd_power(int on);
-static int system3_backlight_power(int on);
+static void system3_lcd_power(int on);
+static void system3_backlight_power(int on);
extern void convert_to_tag_list(struct param_struct *params, int mem_init);
@@ -101,9 +100,9 @@ extern void convert_to_tag_list(struct param_struct *params, int mem_init);
static struct map_desc system3_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
- { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf3000000, PT_CPLD_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
+ { 0xf4000000, PT_SA1111_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
@@ -113,12 +112,6 @@ static struct sa1100_port_fns system3_port_fns __initdata = {
pm: system3_uart_pm,
};
-static struct irqaction system3_irq = {
- name: "PT Digital Board SA1111 IRQ",
- handler: system3_IRQ_demux,
- flags: SA_INTERRUPT
-};
-
static struct notifier_block system3_clkchg_block = {
notifier_call: sdram_notifier,
};
@@ -145,56 +138,82 @@ static void __init system3_map_io(void)
/*********************************************************************
* Install IRQ handler
*/
-static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+static void
+system3_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
u_char irr;
- for(;;){
- //irr = PTCPLD_REG_IRQSR & (PT_IRQ_LAN | PT_IRQ_USAR | PT_IRQ_SA1111);
- irr = PT_IRQSR & (PT_IRQ_LAN | PT_IRQ_SA1111);
+ //DPRINTK( "irq=%d, desc=%p, regs=%p\n", irq, desc, regs );
- irr ^= (PT_IRQ_LAN);
- if (!irr) break;
+ while (1) {
+ struct irqdesc *d;
- if( irr & PT_IRQ_LAN )
- do_IRQ(IRQ_SYSTEM3_SMC9196, regs);
+ /*
+ * Acknowledge the parent IRQ.
+ */
+ desc->chip->ack(irq);
-#if 0
- /* Highspeed Serial Bus not yet used */
- if( irr & PT_IRQ_USAR )
- do_IRQ(PT_USAR_IRQ, regs);
-#endif
+ /*
+ * Read the interrupt reason register. Let's have all
+ * active IRQ bits high. Note: there is a typo in the
+ * Neponset user's guide for the SA1111 IRR level.
+ */
+ //irr = PT_IRQSR & (PT_IRR_LAN | PT_IRR_SA1111);
+ irr = PT_IRQSR & (PT_IRR_SA1111);
- if( irr & PT_IRQ_SA1111 )
- sa1111_IRQ_demux(irq, dev_id, regs);
- }
-}
+ /* SMC IRQ is low-active, so "switch" bit over */
+ //irr ^= (PT_IRR_LAN);
+ //DPRINTK( "irr=0x%02x\n", irr );
-static void __init system3_init_irq(void)
-{
- int irq;
+ if ((irr & (PT_IRR_LAN | PT_IRR_SA1111)) == 0)
+ break;
- DPRINTK( "%s\n", "START" );
+ /*
+ * Since there is no individual mask, we have to
+ * mask the parent IRQ. This is safe, since we'll
+ * recheck the register for any pending IRQs.
+ */
+ if (irr & (PT_IRR_LAN)) {
+ desc->chip->mask(irq);
+
+ if (irr & PT_IRR_LAN) {
+ //DPRINTK( "SMC9196, irq=%d\n", IRQ_SYSTEM3_SMC9196 );
+ d = irq_desc + IRQ_SYSTEM3_SMC9196;
+ d->handle(IRQ_SYSTEM3_SMC9196, d, regs);
+ }
+
+#if 0 /* no SSP yet on system 4 */
+ if (irr & IRR_USAR) {
+ d = irq_desc + IRQ_NEPONSET_USAR;
+ d->handle(IRQ_NEPONSET_USAR, d, regs);
+ }
+#endif
- /* SA1111 IRQ not routed to a GPIO. */
- sa1111_init_irq(-1);
+ desc->chip->unmask(irq);
+ }
- /* setup extra IRQs */
- irq = IRQ_SYSTEM3_SMC9196;
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
+ if (irr & PT_IRR_SA1111) {
+ //DPRINTK( "SA1111, irq=%d\n", IRQ_SYSTEM3_SA1111 );
+ d = irq_desc + IRQ_SYSTEM3_SA1111;
+ d->handle(IRQ_SYSTEM3_SA1111, d, regs);
+ }
+ }
+}
-#if 0
- /* Highspeed Serial Bus not yet used */
- irq = PT_USAR_IRQ;
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
-#endif
+static void __init system3_init_irq(void)
+{
+ /*
+ * Install handler for GPIO25.
+ */
+ set_irq_type(IRQ_GPIO25, IRQT_RISING);
+ set_irq_chained_handler(IRQ_GPIO25, system3_irq_handler);
- /* IRQ by CPLD */
- set_GPIO_IRQ_edge( GPIO_GPIO(25), GPIO_RISING_EDGE );
- setup_arm_irq( IRQ_GPIO25, &system3_irq );
+ /*
+ * install eth irq
+ */
+ set_irq_handler(IRQ_SYSTEM3_SMC9196, do_simple_IRQ);
+ set_irq_flags(IRQ_SYSTEM3_SMC9196, IRQF_VALID | IRQF_PROBE);
}
/**********************************************************************
@@ -270,7 +289,7 @@ static void system3_set_mctrl(struct uart_port *port, u_int mctrl)
}
}
-static int system3_get_mctrl(struct uart_port *port)
+static u_int system3_get_mctrl(struct uart_port *port)
{
u_int ret = 0;
u_int irqsr = PT_IRQSR;
@@ -358,12 +377,8 @@ static void system3_lcd_brightness(unsigned char value)
static void system3_lcd_power(int on)
{
-#error why is backlight stuff here???
if (on) {
system3_lcd_on();
- system3_lcd_backlight_on();
- system3_lcd_contrast(0x95);
- system3_lcd_brightness(240);
} else {
system3_lcd_off();
}
@@ -407,10 +422,12 @@ static int __init system3_init(void)
*/
sa1110_mb_disable();
+ system3_init_irq();
+
/*
* Probe for a SA1111.
*/
- ret = sa1111_probe(0x40000000);
+ ret = sa1111_probe(PT_SA1111_BASE);
if (ret < 0) {
printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" );
goto DONE;
@@ -443,7 +460,11 @@ static int __init system3_init(void)
*/
sa1110_mb_enable();
- system3_init_irq();
+ /*
+ * Initialise SA1111 IRQs
+ */
+ sa1111_init_irq(IRQ_SYSTEM3_SA1111);
+
#if defined( CONFIG_CPU_FREQ )
ret = cpufreq_register_notifier(&system3_clkchg_block);
@@ -453,6 +474,7 @@ static int __init system3_init(void)
}
#endif
+
ret = 0;
DONE:
DPRINTK( "ret=%d\n", ret );
diff --git a/arch/arm/mach-sa1100/victor.c b/arch/arm/mach-sa1100/victor.c
index a4378e32d4a2..27611b41fd7a 100644
--- a/arch/arm/mach-sa1100/victor.c
+++ b/arch/arm/mach-sa1100/victor.c
@@ -60,7 +60,7 @@ fixup_victor(struct machine_desc *desc, struct param_struct *params,
static struct map_desc victor_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
+ { 0xe8000000, 0x00000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/xp860.c b/arch/arm/mach-sa1100/xp860.c
index 4e9f38b56869..c4ad798742ee 100644
--- a/arch/arm/mach-sa1100/xp860.c
+++ b/arch/arm/mach-sa1100/xp860.c
@@ -67,9 +67,9 @@ fixup_xp860(struct machine_desc *desc, struct param_struct *params,
static struct map_desc xp860_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SCSI */
- { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* LAN */
- { 0xf4000000, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCSI */
+ { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN */
+ { 0xf4000000, 0x40000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/yopy.c b/arch/arm/mach-sa1100/yopy.c
index fa8b5c8fc9c6..fc36c00aa49b 100644
--- a/arch/arm/mach-sa1100/yopy.c
+++ b/arch/arm/mach-sa1100/yopy.c
@@ -69,9 +69,9 @@ __initcall(yopy_hw_init);
static struct map_desc yopy_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash 0 */
- { 0xec000000, 0x08000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash 1 */
- { 0xf0000000, 0x48000000, 0x00300000, DOMAIN_IO, 1, 1, 0, 0 }, /* LCD */
+ { 0xe8000000, 0x00000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash 0 */
+ { 0xec000000, 0x08000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash 1 */
+ { 0xf0000000, 0x48000000, 0x00300000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD */
{ 0xf1000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO */
LAST_DESC
};
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 30a10cb07775..22428e7d98b4 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -151,7 +151,7 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
if (pmd_bad(*pmd))
goto bad_pmd;
- pte = pte_offset(pmd, address);
+ pte = pte_offset_map(pmd, address);
entry = *pte;
/*
@@ -164,6 +164,7 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
set_pte(pte, entry);
flush_tlb_page(vma, address);
}
+ pte_unmap(pte);
return;
bad_pgd:
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index 699e5208d1d4..b39fd67963f7 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -83,11 +83,15 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
break;
}
- pte = pte_offset(pmd, addr);
+#ifndef CONFIG_HIGHMEM
+ /* We must not map this if we have highmem enabled */
+ pte = pte_offset_map(pmd, addr);
printk(", *pte = %08lx", pte_val(*pte));
#ifdef CONFIG_CPU_32
printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE]));
#endif
+ pte_unmap(pte);
+#endif
} while(0);
printk("\n");
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index b2fcc416756f..c9b4ba1f39ea 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -64,38 +64,6 @@ static struct meminfo meminfo __initdata = { 0, };
*/
struct page *empty_zero_page;
-#ifndef CONFIG_NO_PGT_CACHE
-struct pgtable_cache_struct quicklists;
-
-int do_check_pgt_cache(int low, int high)
-{
- int freed = 0;
-
- if(pgtable_cache_size > high) {
- do {
- if(pgd_quicklist) {
- free_pgd_slow(get_pgd_fast());
- freed++;
- }
- if(pmd_quicklist) {
- pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
- freed++;
- }
- if(pte_quicklist) {
- pte_free_slow(pte_alloc_one_fast(NULL, 0));
- freed++;
- }
- } while(pgtable_cache_size > low);
- }
- return freed;
-}
-#else
-int do_check_pgt_cache(int low, int high)
-{
- return 0;
-}
-#endif
-
/* This is currently broken
* PG_skip is used on sparc/sparc64 architectures to "skip" certain
* parts of the address space.
@@ -145,9 +113,6 @@ void show_mem(void)
printk("%d slab pages\n", slab);
printk("%d pages shared\n", shared);
printk("%d pages swap cached\n", cached);
-#ifndef CONFIG_NO_PGT_CACHE
- printk("%ld page tables cached\n", pgtable_cache_size);
-#endif
show_buffers();
}
diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c
index 8aa87e9b2487..7f20b9d0ea85 100644
--- a/arch/arm/mm/minicache.c
+++ b/arch/arm/mm/minicache.c
@@ -58,7 +58,7 @@ static int __init minicache_init(void)
pmd = pmd_alloc(&init_mm, pgd, minicache_address);
if (!pmd)
BUG();
- minicache_pte = pte_alloc(&init_mm, pmd, minicache_address);
+ minicache_pte = pte_alloc_kernel(&init_mm, pmd, minicache_address);
if (!minicache_pte)
BUG();
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 10605d6aa11e..d8dfc4e019ac 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -98,11 +98,15 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
if (!new_pmd)
goto no_pmd;
- new_pte = pte_alloc(mm, new_pmd, 0);
+ new_pte = pte_alloc_map(mm, new_pmd, 0);
if (!new_pte)
goto no_pte;
+ init_pmd = pmd_offset(init_pgd, 0);
+ init_pte = pte_offset_map_nested(init_pmd, 0);
set_pte(new_pte, *init_pte);
+ pte_unmap_nested(init_pte);
+ pte_unmap(new_pte);
spin_unlock(&mm->page_table_lock);
}
@@ -138,7 +142,7 @@ no_pgd:
void free_pgd_slow(pgd_t *pgd)
{
pmd_t *pmd;
- pte_t *pte;
+ struct page *pte;
if (!pgd)
return;
@@ -153,7 +157,7 @@ void free_pgd_slow(pgd_t *pgd)
goto free;
}
- pte = pte_offset(pmd, 0);
+ pte = pmd_page(*pmd);
pmd_clear(pmd);
pte_free(pte);
pmd_free(pmd);
@@ -198,7 +202,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, int domain, int prot)
set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain)));
}
- ptep = pte_offset(pmdp, virt);
+ ptep = pte_offset_kernel(pmdp, virt);
set_pte(ptep, mk_pte_phys(phys, __pgprot(prot)));
}
@@ -225,6 +229,20 @@ static void __init create_mapping(struct map_desc *md)
int prot_sect, prot_pte;
long off;
+ if (md->prot_read && md->prot_write &&
+ !md->cacheable && !md->bufferable) {
+ printk(KERN_WARNING "Security risk: creating user "
+ "accessible mapping for 0x%08lx at 0x%08lx\n",
+ md->physical, md->virtual);
+ }
+
+ if (md->virtual != vectors_base() && md->virtual < PAGE_OFFSET) {
+ printk(KERN_WARNING "MM: not creating mapping for "
+ "0x%08lx at 0x%08lx in user region\n",
+ md->physical, md->virtual);
+ return;
+ }
+
prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
(md->prot_read ? L_PTE_USER : 0) |
(md->prot_write ? L_PTE_WRITE : 0) |
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index f4a2ed50ba23..3e67f274c60a 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -663,8 +663,8 @@ cpu_manu_name:
cpu_80200_name:
.asciz "XScale-80200"
-cpu_cotulla_name:
- .asciz "XScale-Cotulla"
+cpu_pxa250_name:
+ .asciz "XScale-PXA250"
.align
@@ -734,11 +734,11 @@ cpu_80200_info:
.long cpu_80200_name
.size cpu_80200_info, . - cpu_80200_info
- .type cpu_cotulla_info, #object
-cpu_cotulla_info:
+ .type cpu_pxa250_info, #object
+cpu_pxa250_info:
.long cpu_manu_name
- .long cpu_cotulla_name
- .size cpu_cotulla_info, . - cpu_cotulla_info
+ .long cpu_pxa250_name
+ .size cpu_pxa250_info, . - cpu_pxa250_info
.type cpu_arch_name, #object
cpu_arch_name:
@@ -767,8 +767,8 @@ __80200_proc_info:
.long v4wbi_tlb_fns
.size __80200_proc_info, . - __80200_proc_info
- .type __cotulla_proc_info,#object
-__cotulla_proc_info:
+ .type __pxa250_proc_info,#object
+__pxa250_proc_info:
.long 0x69052100
.long 0xfffffff0
.long 0x00000c0e
@@ -776,8 +776,9 @@ __cotulla_proc_info:
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_cotulla_info
+ .long cpu_pxa250_info
.long xscale_processor_functions
.long v4wbi_tlb_fns
.size __cotulla_proc_info, . - __cotulla_proc_info
+ .size __pxa250_proc_info, . - __pxa250_proc_info
diff --git a/arch/cris/drivers/ide.c b/arch/cris/drivers/ide.c
index 89f79ceaa9f4..252da5a0eef6 100644
--- a/arch/cris/drivers/ide.c
+++ b/arch/cris/drivers/ide.c
@@ -94,8 +94,6 @@
* device can't do DMA handshaking for some stupid reason. We don't need to do that.
*/
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 4a10517ab77e..6bb2816fb84e 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -98,6 +98,7 @@ CONFIG_CARDBUS=y
# CONFIG_I82092 is not set
# CONFIG_I82365 is not set
# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_SA1100 is not set
#
# PCI Hotplug Support
@@ -239,10 +240,9 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
-CONFIG_IDE_TASK_IOCTL=y
#
-# IDE chipset support/bugfixes
+# IDE chipset support
#
CONFIG_BLK_DEV_CMD640=y
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
@@ -252,7 +252,6 @@ CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_IDEDMA=y
@@ -656,6 +655,9 @@ CONFIG_RAMFS=y
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index d7fd9193ddbc..7f3bf5d80e51 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -14,7 +14,7 @@ all: kernel.o head.o init_task.o
O_TARGET := kernel.o
-export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o
+export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 2e52b14f75d3..3a397576b41a 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -812,7 +812,7 @@ recalc:
t1 = IDLE_LEAKY_MAX;
- while (need_resched()) {
+ while (!need_resched()) {
if (use_apm_idle) {
unsigned int t;
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 813a5e55ddba..cea5ec00e4f4 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -195,7 +195,7 @@ ENTRY(lcall27)
ENTRY(ret_from_fork)
-#if CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
call SYMBOL_NAME(schedule_tail)
#endif
GET_THREAD_INFO(%ebx)
@@ -716,6 +716,7 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_lremovexattr)
.long SYMBOL_NAME(sys_fremovexattr)
.long SYMBOL_NAME(sys_tkill)
+ .long SYMBOL_NAME(sys_sendfile64)
.rept NR_syscalls-(.-sys_call_table)/4
.long SYMBOL_NAME(sys_ni_syscall)
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 1f98f7abbb7a..a4fbd819aa7f 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -67,7 +67,7 @@ static struct irq_pin_list {
* shared ISA-space IRQs, so we have to support them. We are super
* fast in the common case, and fast for shared ISA-space IRQs.
*/
-static void add_pin_to_irq(unsigned int irq, int apic, int pin)
+static void __init add_pin_to_irq(unsigned int irq, int apic, int pin)
{
static int first_free_entry = NR_IRQS;
struct irq_pin_list *entry = irq_2_pin + irq;
@@ -85,6 +85,26 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
entry->pin = pin;
}
+/*
+ * Reroute an IRQ to a different pin.
+ */
+static void __init replace_pin_at_irq(unsigned int irq,
+ int oldapic, int oldpin,
+ int newapic, int newpin)
+{
+ struct irq_pin_list *entry = irq_2_pin + irq;
+
+ while (1) {
+ if (entry->apic == oldapic && entry->pin == oldpin) {
+ entry->apic = newapic;
+ entry->pin = newpin;
+ }
+ if (!entry->next)
+ break;
+ entry = irq_2_pin + entry->next;
+ }
+}
+
#define __DO_ACTION(R, ACTION, FINAL) \
\
{ \
@@ -1533,6 +1553,10 @@ static inline void check_timer(void)
setup_ExtINT_IRQ0_pin(pin2, vector);
if (timer_irq_works()) {
printk("works.\n");
+ if (pin1 != -1)
+ replace_pin_at_irq(0, 0, pin1, 0, pin2);
+ else
+ add_pin_to_irq(0, 0, pin2);
if (nmi_watchdog == NMI_IO_APIC) {
setup_nmi();
check_nmi_watchdog();
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index eb6f71e02b02..862e80c26f3a 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -37,6 +37,8 @@ int smp_found_config;
int apic_version [MAX_APICS];
int mp_bus_id_to_type [MAX_MP_BUSSES];
int mp_bus_id_to_node [MAX_MP_BUSSES];
+int mp_bus_id_to_local [MAX_MP_BUSSES];
+int quad_local_to_mp_bus_id [NR_CPUS/4][4];
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
int mp_current_pci_id;
@@ -241,13 +243,17 @@ void __init MP_processor_info (struct mpc_config_processor *m)
static void __init MP_bus_info (struct mpc_config_bus *m)
{
char str[7];
+ int quad;
memcpy(str, m->mpc_bustype, 6);
str[6] = 0;
if (clustered_apic_mode) {
- mp_bus_id_to_node[m->mpc_busid] = translation_table[mpc_record]->trans_quad;
- printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, mp_bus_id_to_node[m->mpc_busid]);
+ quad = translation_table[mpc_record]->trans_quad;
+ mp_bus_id_to_node[m->mpc_busid] = quad;
+ mp_bus_id_to_local[m->mpc_busid] = translation_table[mpc_record]->trans_local;
+ quad_local_to_mp_bus_id[quad][translation_table[mpc_record]->trans_local] = m->mpc_busid;
+ printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, quad);
} else {
Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
}
@@ -324,13 +330,14 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
static void __init MP_translation_info (struct mpc_config_translation *m)
{
- printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type,
- m->trans_quad, m->trans_global, m->trans_local);
+ printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
if (mpc_record >= MAX_MPC_ENTRY)
printk("MAX_MPC_ENTRY exceeded!\n");
else
translation_table[mpc_record] = m; /* stash this for later */
+ if (m->trans_quad+1 > numnodes)
+ numnodes = m->trans_quad+1;
}
/*
@@ -495,10 +502,6 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
}
++mpc_record;
}
- if (clustered_apic_mode && nr_ioapics > 2) {
- /* don't initialise IO apics on secondary quads */
- nr_ioapics = 2;
- }
if (!num_processors)
printk(KERN_ERR "SMP mptable: no processors registered!\n");
return num_processors;
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index 5abb2259c192..7281c71e0467 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -14,6 +14,7 @@
#include <asm/segment.h>
#include <asm/io.h>
+#include <asm/smp.h>
#include "pci-i386.h"
@@ -26,6 +27,16 @@ struct pci_ops *pci_root_ops = NULL;
int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
+#ifdef CONFIG_MULTIQUAD
+#define BUS2QUAD(global) (mp_bus_id_to_node[global])
+#define BUS2LOCAL(global) (mp_bus_id_to_local[global])
+#define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
+#else
+#define BUS2QUAD(global) (0)
+#define BUS2LOCAL(global) (global)
+#define QUADLOCAL2BUS(quad,local) (local)
+#endif
+
/*
* This interrupt-safe spinlock protects all accesses to PCI
* configuration space.
@@ -39,10 +50,71 @@ static spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
#ifdef CONFIG_PCI_DIRECT
+#ifdef CONFIG_MULTIQUAD
+#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
+ (0x80000000 | (BUS2LOCAL(bus) << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
+
+static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) /* CONFIG_MULTIQUAD */
+{
+ unsigned long flags;
+
+ if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ outl_quad(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8, BUS2QUAD(bus));
+
+ switch (len) {
+ case 1:
+ *value = inb_quad(0xCFC + (reg & 3), BUS2QUAD(bus));
+ break;
+ case 2:
+ *value = inw_quad(0xCFC + (reg & 2), BUS2QUAD(bus));
+ break;
+ case 4:
+ *value = inl_quad(0xCFC, BUS2QUAD(bus));
+ break;
+ }
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return 0;
+}
+
+static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) /* CONFIG_MULTIQUAD */
+{
+ unsigned long flags;
+
+ if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ return -EINVAL;
+
+ spin_lock_irqsave(&pci_config_lock, flags);
+
+ outl_quad(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8, BUS2QUAD(bus));
+
+ switch (len) {
+ case 1:
+ outb_quad((u8)value, 0xCFC + (reg & 3), BUS2QUAD(bus));
+ break;
+ case 2:
+ outw_quad((u16)value, 0xCFC + (reg & 2), BUS2QUAD(bus));
+ break;
+ case 4:
+ outl_quad((u32)value, 0xCFC, BUS2QUAD(bus));
+ break;
+ }
+
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+
+ return 0;
+}
+
+#else /* !CONFIG_MULTIQUAD */
#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
(0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
-static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
+static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) /* !CONFIG_MULTIQUAD */
{
unsigned long flags;
@@ -70,7 +142,7 @@ static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len,
return 0;
}
-static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) /* !CONFIG_MULTIQUAD */
{
unsigned long flags;
@@ -98,6 +170,8 @@ static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len,
return 0;
}
+#endif /* CONFIG_MULTIQUAD */
+
#undef PCI_CONF1_ADDRESS
static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value)
@@ -1017,6 +1091,8 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
*/
int pxb, reg;
u8 busno, suba, subb;
+ int quad = BUS2QUAD(d->bus->number);
+
printk("PCI: Searching for i450NX host bridges on %s\n", d->slot_name);
reg = 0xd0;
for(pxb=0; pxb<2; pxb++) {
@@ -1025,9 +1101,9 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
pci_read_config_byte(d, reg++, &subb);
DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
if (busno)
- pci_scan_bus(busno, pci_root_ops, NULL); /* Bus A */
+ pci_scan_bus(QUADLOCAL2BUS(quad,busno), pci_root_ops, NULL); /* Bus A */
if (suba < subb)
- pci_scan_bus(suba+1, pci_root_ops, NULL); /* Bus B */
+ pci_scan_bus(QUADLOCAL2BUS(quad,suba+1), pci_root_ops, NULL); /* Bus B */
}
pcibios_last_bus = -1;
}
@@ -1199,6 +1275,8 @@ void __devinit pcibios_config_init(void)
void __init pcibios_init(void)
{
+ int quad;
+
if (!pci_root_ops)
pcibios_config_init();
if (!pci_root_ops) {
@@ -1208,6 +1286,14 @@ void __init pcibios_init(void)
printk("PCI: Probing PCI hardware\n");
pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
+ if (clustered_apic_mode && (numnodes > 1)) {
+ for (quad = 1; quad < numnodes; ++quad) {
+ printk("Scanning PCI bus %d for quad %d\n",
+ QUADLOCAL2BUS(quad,0), quad);
+ pci_scan_bus(QUADLOCAL2BUS(quad,0),
+ pci_root_ops, NULL);
+ }
+ }
pcibios_irq_init();
pcibios_fixup_peer_bridges();
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 993c37d47332..34b0d8ac6f9a 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -240,7 +240,7 @@ extern unsigned long fast_gettimeoffset_quotient;
* ^---- (this multiplication can overflow)
*/
-static unsigned long long div64 (unsigned long long a, unsigned long b0)
+static unsigned long long __init div64 (unsigned long long a, unsigned long b0)
{
unsigned int a1, a2;
unsigned long long res;
@@ -1012,11 +1012,14 @@ void __init smp_boot_cpus(void)
{
int apicid, cpu, bit;
- if (clustered_apic_mode) {
- /* remap the 1st quad's 256k range for cross-quad I/O */
- xquad_portio = ioremap (XQUAD_PORTIO_BASE, XQUAD_PORTIO_LEN);
- printk("Cross quad port I/O vaddr 0x%08lx, len %08lx\n",
- (u_long) xquad_portio, (u_long) XQUAD_PORTIO_LEN);
+ if (clustered_apic_mode && (numnodes > 1)) {
+ printk("Remapping cross-quad port I/O for %d quads\n",
+ numnodes);
+ printk("xquad_portio vaddr 0x%08lx, len %08lx\n",
+ (u_long) xquad_portio,
+ (u_long) numnodes * XQUAD_PORTIO_LEN);
+ xquad_portio = ioremap (XQUAD_PORTIO_BASE,
+ numnodes * XQUAD_PORTIO_LEN);
}
#ifdef CONFIG_MTRR
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index c0fe3e74fdc0..df5c150d3945 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -41,6 +41,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/smp.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/smp.h>
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 4a40438bdf2c..0b237ad2895c 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -557,6 +557,8 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
* allowing programs to debug themselves without the ptrace()
* interface.
*/
+ if ((regs->xcs & 3) == 0)
+ goto clear_TF;
if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
goto clear_TF;
}
diff --git a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds
index cd994f0b9b05..dd27a25e0f49 100644
--- a/arch/i386/vmlinux.lds
+++ b/arch/i386/vmlinux.lds
@@ -57,6 +57,10 @@ SECTIONS
*(.initcall7.init)
}
__initcall_end = .;
+ . = ALIGN(32);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/ia64/sn/io/pci_bus_cvlink.c b/arch/ia64/sn/io/pci_bus_cvlink.c
index 52b546cea659..06096e779260 100644
--- a/arch/ia64/sn/io/pci_bus_cvlink.c
+++ b/arch/ia64/sn/io/pci_bus_cvlink.c
@@ -112,9 +112,9 @@ devfn_to_vertex(unsigned char busnum, unsigned int devfn)
pci_bus = pci_bus_to_vertex(busnum);
if (!pci_bus) {
/*
- * During probing, the Linux pci code invents non existant
+ * During probing, the Linux pci code invents non-existent
* bus numbers and pci_dev structures and tries to access
- * them to determine existance. Don't crib during probing.
+ * them to determine existence. Don't crib during probing.
*/
if (done_probing)
printk("devfn_to_vertex: Invalid bus number %d given.\n", busnum);
diff --git a/arch/mips64/sgi-ip27/ip27-rtc.c b/arch/mips64/sgi-ip27/ip27-rtc.c
index c893d10cfe67..a44ad0fccbad 100644
--- a/arch/mips64/sgi-ip27/ip27-rtc.c
+++ b/arch/mips64/sgi-ip27/ip27-rtc.c
@@ -201,7 +201,8 @@ static int __init rtc_init(void)
KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0;
printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION);
- misc_register(&rtc_dev);
+ if (misc_register(&rtc_dev))
+ return -ENODEV;
create_proc_read_entry ("rtc", 0, NULL, rtc_read_proc, NULL);
save_flags(flags);
diff --git a/arch/ppc/boot/ld.script b/arch/ppc/boot/ld.script
index df5df8fcbe43..9d4de80f8ba3 100644
--- a/arch/ppc/boot/ld.script
+++ b/arch/ppc/boot/ld.script
@@ -44,6 +44,7 @@ SECTIONS
{
*(.data)
*(.data1)
+ *(.data.boot)
*(.sdata)
*(.sdata2)
*(.got.plt) *(.got)
diff --git a/arch/ppc/boot/simple/misc-embedded.c b/arch/ppc/boot/simple/misc-embedded.c
index 8f2f9a8e0fd8..ad2f403dccae 100644
--- a/arch/ppc/boot/simple/misc-embedded.c
+++ b/arch/ppc/boot/simple/misc-embedded.c
@@ -59,7 +59,9 @@ char netroot_string[] = "root=/dev/nfs rw ip=auto";
/* Serial port to use. */
unsigned long com_port;
-bd_t hold_resid_buf;
+/* We need to make sure that this is before the images to ensure
+ * that it's in a mapped location. - Tom */
+bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
bd_t *hold_residual = &hold_resid_buf;
extern unsigned long serial_init(int chan, bd_t *bp);
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 02ccbb6bf388..0ce770f31088 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -258,8 +258,9 @@ endmenu
mainmenu_option next_comment
comment 'General setup'
-bool 'Prompt for advanced kernel configuration options' CONFIG_ADVANCED_OPTIONS
bool 'High memory support' CONFIG_HIGHMEM
+dep_bool ' Support for PTEs in high memory' CONFIG_HIGHPTE $CONFIG_HIGHMEM
+bool 'Prompt for advanced kernel configuration options' CONFIG_ADVANCED_OPTIONS
if [ "$CONFIG_ADVANCED_OPTIONS" = "y" ]; then
if [ "$CONFIG_HIGHMEM" = "y" ]; then
bool " Set high memory pool address" CONFIG_HIGHMEM_START_BOOL
diff --git a/arch/ppc/iSeries/rtc.c b/arch/ppc/iSeries/rtc.c
index 55e1861d4158..78461ff14d6f 100644
--- a/arch/ppc/iSeries/rtc.c
+++ b/arch/ppc/iSeries/rtc.c
@@ -192,7 +192,8 @@ static struct miscdevice rtc_dev=
static int __init rtc_init(void)
{
- misc_register(&rtc_dev);
+ if (misc_register(&rtc_dev))
+ return -ENODEV;
create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
printk(KERN_INFO "iSeries Real Time Clock Driver v" RTC_VERSION "\n");
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 2bd06ecca9f6..e610ac65445d 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -288,15 +288,12 @@ ret_from_syscall_2:
*/
_GLOBAL(_switch)
stwu r1,-INT_FRAME_SIZE(r1)
- stw r0,GPR0(r1)
- lwz r0,0(r1)
- stw r0,GPR1(r1)
+ mflr r0
+ stw r0,INT_FRAME_SIZE+4(r1)
/* r3-r13 are caller saved -- Cort */
- SAVE_GPR(2, r1)
SAVE_8GPRS(14, r1)
SAVE_10GPRS(22, r1)
- mflr r20 /* Return to switch caller */
- stw r20,INT_FRAME_SIZE+4(r1)
+ stw r0,_NIP(r1) /* Return to switch caller */
mfmsr r22
li r0,MSR_FP /* Disable floating-point */
#ifdef CONFIG_ALTIVEC
@@ -309,17 +306,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
andc r22,r22,r0
mtmsr r22
isync
-1: stw r20,_NIP(r1)
- stw r22,_MSR(r1)
- stw r20,_LINK(r1)
+1: stw r22,_MSR(r1)
mfcr r20
- mfctr r22
- mfspr r23,XER
stw r20,_CCR(r1)
- stw r22,_CTR(r1)
- stw r23,_XER(r1)
- li r0,0x0ff0
- stw r0,TRAP(r1)
stw r1,KSP(r3) /* Set old stack pointer */
tophys(r0,r4)
@@ -343,7 +332,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
.globl ret_from_fork
ret_from_fork:
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
bl schedule_tail
#endif
rlwinm r3,r1,0,0,18
diff --git a/arch/ppc/kernel/iSeries_head.S b/arch/ppc/kernel/iSeries_head.S
index a191f75ae4ea..21cccb15cb2a 100644
--- a/arch/ppc/kernel/iSeries_head.S
+++ b/arch/ppc/kernel/iSeries_head.S
@@ -839,7 +839,7 @@ hash_page:
/*
* We hard enable here (but first soft disable) so that the hash_page
- * code can spin on the hash_table_lock without problem on a shared
+ * code can spin on the mmu_hash_lock without problem on a shared
* processor
*/
li r0,0
diff --git a/arch/ppc/kernel/iSeries_misc.S b/arch/ppc/kernel/iSeries_misc.S
index 983611b80276..357e75a35f9e 100644
--- a/arch/ppc/kernel/iSeries_misc.S
+++ b/arch/ppc/kernel/iSeries_misc.S
@@ -29,7 +29,7 @@
.align 5
#ifdef CONFIG_SMP
- .comm hash_table_lock,4
+ .comm mmu_hash_lock,4
#endif /* CONFIG_SMP */
_GLOBAL(is_msr_enabled)
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index ed68a0397634..1c302403cc49 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -47,17 +47,10 @@ extern unsigned long yield_count;
#define run_light_on(x) do { } while (0)
#endif /* CONFIG_PPC_ISERIES */
-void zero_paged(void);
void power_save(void);
-unsigned long zero_paged_on = 0;
-unsigned long powersave_nap = 0;
-
-unsigned long *zero_cache; /* head linked list of pre-zero'd pages */
-atomic_t zerototal; /* # pages zero'd over time */
-atomic_t zeropage_hits; /* # zero'd pages request that we've done */
-atomic_t zero_sz; /* # currently pre-zero'd pages */
-atomic_t zeropage_calls; /* # zero'd pages request that've been made */
+unsigned long zero_paged_on;
+unsigned long powersave_nap;
int idled(void)
{
@@ -92,7 +85,6 @@ int idled(void)
if (need_resched()) {
run_light_on(1);
schedule();
- check_pgt_cache();
}
#ifdef CONFIG_PPC_ISERIES
else {
@@ -115,141 +107,6 @@ int cpu_idle(void)
return 0;
}
-#if 0
-/*
- * Returns a pre-zero'd page from the list otherwise returns
- * NULL.
- */
-unsigned long get_zero_page_fast(void)
-{
- unsigned long page = 0;
-
- atomic_inc(&zero_cache_calls);
- if ( zero_quicklist )
- {
- /* atomically remove this page from the list */
- register unsigned long tmp;
- asm ( "101:lwarx %1,0,%3\n" /* reserve zero_cache */
- " lwz %0,0(%1)\n" /* get next -- new zero_cache */
- PPC405_ERR77(0,%3)
- " stwcx. %0,0,%3\n" /* update zero_cache */
- " bne- 101b\n" /* if lost reservation try again */
- : "=&r" (tmp), "=&r" (page), "+m" (zero_cache)
- : "r" (&zero_quicklist)
- : "cc" );
-#ifdef CONFIG_SMP
- /* if another cpu beat us above this can happen -- Cort */
- if ( page == 0 )
- return 0;
-#endif /* CONFIG_SMP */
- /* we can update zerocount after the fact since it is not
- * used for anything but control of a loop which doesn't
- * matter since it won't affect anything if it zeros one
- * less page -- Cort
- */
- atomic_inc((atomic_t *)&zero_cache_hits);
- atomic_dec((atomic_t *)&zero_cache_sz);
-
- /* zero out the pointer to next in the page */
- *(unsigned long *)page = 0;
- return page;
- }
- return 0;
-}
-
-/*
- * Experimental stuff to zero out pages in the idle task
- * to speed up get_free_pages(). Zero's out pages until
- * we've reached the limit of zero'd pages. We handle
- * reschedule()'s in here so when we return we know we've
- * zero'd all we need to for now.
- */
-int zero_cache_water[2] = { 25, 96 }; /* high and low water marks for zero cache */
-void zero_paged(void)
-{
- unsigned long pageptr = 0; /* current page being zero'd */
- unsigned long bytecount = 0;
- register unsigned long tmp;
- pte_t *pte;
-
- if ( atomic_read(&zero_cache_sz) >= zero_cache_water[0] )
- return;
- while ( (atomic_read(&zero_cache_sz) < zero_cache_water[1]) && !need_resched() )
- {
- /*
- * Mark a page as reserved so we can mess with it
- * If we're interrupted we keep this page and our place in it
- * since we validly hold it and it's reserved for us.
- */
- pageptr = __get_free_pages(GFP_ATOMIC, 0);
- if ( !pageptr )
- return;
-
- cond_resched();
-
- /*
- * Make the page no cache so we don't blow our cache with 0's
- */
- pte = find_pte(&init_mm, pageptr);
- if ( !pte )
- {
- printk("pte NULL in zero_paged()\n");
- return;
- }
-
- pte_uncache(*pte);
- flush_tlb_page(find_vma(&init_mm,pageptr),pageptr);
- /*
- * Important here to not take time away from real processes.
- */
- for ( bytecount = 0; bytecount < PAGE_SIZE ; bytecount += 4 )
- {
- cond_resched();
- *(unsigned long *)(bytecount + pageptr) = 0;
- }
-
- /*
- * If we finished zero-ing out a page add this page to
- * the zero_cache atomically -- we can't use
- * down/up since we can't sleep in idle.
- * Disabling interrupts is also a bad idea since we would
- * steal time away from real processes.
- * We can also have several zero_paged's running
- * on different processors so we can't interfere with them.
- * So we update the list atomically without locking it.
- * -- Cort
- */
-
- /* turn cache on for this page */
- pte_cache(*pte);
- flush_tlb_page(find_vma(&init_mm,pageptr),pageptr);
- /* atomically add this page to the list */
- asm ( "101:lwarx %0,0,%2\n" /* reserve zero_cache */
- " stw %0,0(%3)\n" /* update *pageptr */
-#ifdef CONFIG_SMP
- " sync\n" /* let store settle */
-#endif
- PPC405_ERR77(0,%2)
- " stwcx. %3,0,%2\n" /* update zero_cache in mem */
- " bne- 101b\n" /* if lost reservation try again */
- : "=&r" (tmp), "+m" (zero_quicklist)
- : "r" (&zero_quicklist), "r" (pageptr)
- : "cc" );
- /*
- * This variable is used in the above loop and nowhere
- * else so the worst that could happen is we would
- * zero out one more or one less page than we want
- * per processor on the machine. This is because
- * we could add our page to the list but not have
- * zerocount updated yet when another processor
- * reads it. -- Cort
- */
- atomic_inc((atomic_t *)&zero_cache_sz);
- atomic_inc((atomic_t *)&zero_cache_total);
- }
-}
-#endif /* 0 */
-
void power_save(void)
{
unsigned long hid0;
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index c3f1a448616d..0b6e58a1b645 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -369,34 +369,39 @@ _GLOBAL(_tlbia)
isync
#else
#if defined(CONFIG_SMP)
+ rlwinm r8,r1,0,0,18
+ lwz r8,TI_CPU(r8)
+ oris r8,r8,10
mfmsr r10
SYNC
rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
+ rlwinm r0,r0,0,28,26 /* clear DR */
mtmsr r0
- SYNC
- lis r9,hash_table_lock@h
- ori r9,r9,hash_table_lock@l
- rlwinm r8,r1,0,0,18
- lwz r8,TI_CPU(r8)
- oris r8,r8,10
+ SYNC_601
+ isync
+ lis r9,mmu_hash_lock@h
+ ori r9,r9,mmu_hash_lock@l
+ tophys(r9,r9)
10: lwarx r7,0,r9
cmpi 0,r7,0
bne- 10b
- /* No 405 Erratum 77 fix needed here, because 4xx can't do SMP */
stwcx. r8,0,r9
bne- 10b
-#endif /* CONFIG_SMP */
sync
tlbia
sync
-#ifdef CONFIG_SMP
TLBSYNC
li r0,0
- stw r0,0(r9) /* clear hash_table_lock */
+ stw r0,0(r9) /* clear mmu_hash_lock */
mtmsr r10
- SYNC
-#endif
-#endif
+ SYNC_601
+ isync
+#else /* CONFIG_SMP */
+ sync
+ tlbia
+ sync
+#endif /* CONFIG_SMP */
+#endif /* CONFIG_4xx */
blr
/*
@@ -415,33 +420,37 @@ _GLOBAL(_tlbie)
10:
#else
#if defined(CONFIG_SMP)
+ rlwinm r8,r1,0,0,18
+ lwz r8,TI_CPU(r8)
+ oris r8,r8,11
mfmsr r10
SYNC
rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
+ rlwinm r0,r0,0,28,26 /* clear DR */
mtmsr r0
- SYNC
- lis r9,hash_table_lock@h
- ori r9,r9,hash_table_lock@l
- rlwinm r8,r1,0,0,18
- lwz r8,TI_CPU(r8)
- oris r8,r8,11
+ SYNC_601
+ isync
+ lis r9,mmu_hash_lock@h
+ ori r9,r9,mmu_hash_lock@l
+ tophys(r9,r9)
10: lwarx r7,0,r9
cmpi 0,r7,0
bne- 10b
- PPC405_ERR77(0,r9)
stwcx. r8,0,r9
bne- 10b
eieio
-#endif /* CONFIG_SMP */
tlbie r3
sync
-#ifdef CONFIG_SMP
TLBSYNC
li r0,0
- stw r0,0(r9) /* clear hash_table_lock */
+ stw r0,0(r9) /* clear mmu_hash_lock */
mtmsr r10
- SYNC
-#endif
+ SYNC_601
+ isync
+#else /* CONFIG_SMP */
+ tlbie r3
+ sync
+#endif /* CONFIG_SMP */
#endif /* CONFIG_4xx */
blr
@@ -629,6 +638,40 @@ _GLOBAL(__flush_dcache_icache)
sync
isync
blr
+
+/*
+ * Flush a particular page from the data cache to RAM, identified
+ * by its physical address. We turn off the MMU so we can just use
+ * the physical address (this may be a highmem page without a kernel
+ * mapping).
+ *
+ * void __flush_dcache_icache_phys(unsigned long physaddr)
+ */
+_GLOBAL(__flush_dcache_icache_phys)
+ mfspr r5,PVR
+ rlwinm r5,r5,16,16,31
+ cmpi 0,r5,1
+ beqlr /* for 601, do nothing */
+ mfmsr r10
+ rlwinm r0,r10,0,28,26 /* clear DR */
+ mtmsr r0
+ isync
+ rlwinm r3,r3,0,0,19 /* Get page base address */
+ li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
+ mtctr r4
+ mr r6,r3
+0: dcbst 0,r3 /* Write line to ram */
+ addi r3,r3,L1_CACHE_LINE_SIZE
+ bdnz 0b
+ sync
+ mtctr r4
+1: icbi 0,r6
+ addi r6,r6,L1_CACHE_LINE_SIZE
+ bdnz 1b
+ sync
+ mtmsr r10 /* restore DR */
+ isync
+ blr
/*
* Clear a page using the dcbz instruction, which doesn't cause any
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 2649b327c7f2..1f45d577df52 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -218,13 +218,13 @@ EXPORT_SYMBOL(__global_sti);
EXPORT_SYMBOL(__global_save_flags);
EXPORT_SYMBOL(__global_restore_flags);
#ifdef SPINLOCK_DEBUG
-EXPORT_SYMBOL(_spin_lock);
-EXPORT_SYMBOL(_spin_unlock);
-EXPORT_SYMBOL(spin_trylock);
-EXPORT_SYMBOL(_read_lock);
-EXPORT_SYMBOL(_read_unlock);
-EXPORT_SYMBOL(_write_lock);
-EXPORT_SYMBOL(_write_unlock);
+EXPORT_SYMBOL(_raw_spin_lock);
+EXPORT_SYMBOL(_raw_spin_unlock);
+EXPORT_SYMBOL(_raw_spin_trylock);
+EXPORT_SYMBOL(_raw_read_lock);
+EXPORT_SYMBOL(_raw_read_unlock);
+EXPORT_SYMBOL(_raw_write_lock);
+EXPORT_SYMBOL(_raw_write_unlock);
#endif
EXPORT_SYMBOL(smp_call_function);
EXPORT_SYMBOL(smp_hw_index);
@@ -361,7 +361,7 @@ EXPORT_SYMBOL(set_context);
EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
EXPORT_SYMBOL_NOVERS(disarm_decr);
#ifdef CONFIG_PPC_STD_MMU
-EXPORT_SYMBOL(flush_hash_page); /* For MOL */
+EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
extern long *intercept_table;
EXPORT_SYMBOL(intercept_table);
#endif
diff --git a/arch/ppc/kernel/qspan_pci.c b/arch/ppc/kernel/qspan_pci.c
index 49dc9c04586b..dfad3692815c 100644
--- a/arch/ppc/kernel/qspan_pci.c
+++ b/arch/ppc/kernel/qspan_pci.c
@@ -14,7 +14,7 @@
* PCI access and QSpan control register addresses. The selection is
* further selected by a bit setting in a board control register.
* Although it should happen, we disable interrupts during this operation
- * to make sure some driver doesn't accidently access the PCI while
+ * to make sure some driver doesn't accidentally access the PCI while
* we have switched the chip select.
*/
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index fddffbe59d83..78355f6b3df0 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -291,26 +291,6 @@ void smp_call_function_interrupt(void)
atomic_inc(&call_data->finished);
}
-/*
- * Task migration callback.
- */
-void smp_task_migration_interrupt(void *new_task)
-{
- task_t *p;
-
- p = new_task;
- sched_task_migrated(p);
-}
-
-/*
- * This function sends a 'task migration' IPI to another CPU.
- * Must be called from syscall contexts, with interrupts *enabled*.
- */
-void smp_migrate_task(int cpu, task_t *p)
-{
- __smp_call_function(smp_task_migration_interrupt, p, 0, cpu);
-}
-
void __init smp_boot_cpus(void)
{
int i, cpu_nr;
diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c
index ab3a87e3cdfb..579bd69906f6 100644
--- a/arch/ppc/lib/locks.c
+++ b/arch/ppc/lib/locks.c
@@ -28,7 +28,7 @@
* since they may inhibit forward progress by other CPUs in getting
* a lock.
*/
-static unsigned long __spin_trylock(volatile unsigned long *lock)
+unsigned long __spin_trylock(volatile unsigned long *lock)
{
unsigned long ret;
diff --git a/arch/ppc/mm/cachemap.c b/arch/ppc/mm/cachemap.c
index 7399f7e9d4b3..562cd9560de2 100644
--- a/arch/ppc/mm/cachemap.c
+++ b/arch/ppc/mm/cachemap.c
@@ -50,8 +50,6 @@
#include <asm/smp.h>
#include <asm/machdep.h>
-extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
-
/* This function will allocate the requested contiguous pages and
* map them into the kernel's vmalloc() space. This is done so we
* get unique mapping for these pages, outside of the kernel's 1:1
@@ -157,6 +155,6 @@ size_t size, int direction)
{
unsigned long start;
- start = (unsigned long)(page->virtual) + offset;
+ start = page_address(page) + offset;
consistent_sync(start, size, direction);
}
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 8a05e58ba965..6a7923a0cf03 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -154,6 +154,7 @@ good_area:
/* Since 4xx supports per-page execute permission,
* we lazily flush dcache to icache. */
+ ptep = NULL;
if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
struct page *page = pte_page(*ptep);
@@ -164,9 +165,12 @@ good_area:
}
pte_update(ptep, 0, _PAGE_HWEXEC);
_tlbie(address);
+ pte_unmap(ptep);
up_read(&mm->mmap_sem);
return;
}
+ if (ptep != NULL)
+ pte_unmap(ptep);
#endif
/* a read */
} else {
@@ -289,27 +293,18 @@ pte_t *va_to_pte(unsigned long address)
struct mm_struct *mm;
if (address < TASK_SIZE)
- mm = current->mm;
- else
- mm = &init_mm;
+ return NULL;
- dir = pgd_offset(mm, address & PAGE_MASK);
+ dir = pgd_offset(&init_mm, address);
if (dir) {
pmd = pmd_offset(dir, address & PAGE_MASK);
if (pmd && pmd_present(*pmd)) {
- pte = pte_offset(pmd, address & PAGE_MASK);
- if (pte && pte_present(*pte)) {
+ pte = pte_offset_kernel(pmd, address & PAGE_MASK);
+ if (pte && pte_present(*pte))
return(pte);
- }
- }
- else {
- return (0);
}
}
- else {
- return (0);
- }
- return (0);
+ return NULL;
}
unsigned long va_to_phys(unsigned long address)
@@ -334,7 +329,7 @@ print_8xx_pte(struct mm_struct *mm, unsigned long addr)
if (pgd) {
pmd = pmd_offset(pgd, addr & PAGE_MASK);
if (pmd && pmd_present(*pmd)) {
- pte = pte_offset(pmd, addr & PAGE_MASK);
+ pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
if (pte) {
printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
(long)pgd, (long)pte, (long)pte_val(*pte));
@@ -375,9 +370,9 @@ get_8xx_pte(struct mm_struct *mm, unsigned long addr)
if (pgd) {
pmd = pmd_offset(pgd, addr & PAGE_MASK);
if (pmd && pmd_present(*pmd)) {
- pte = pte_offset(pmd, addr & PAGE_MASK);
+ pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
if (pte) {
- retval = (int)pte_val(*pte);
+ retval = (int)pte_val(*pte);
}
}
}
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
index 889588bcf2cc..7ab04dab55a5 100644
--- a/arch/ppc/mm/hashtable.S
+++ b/arch/ppc/mm/hashtable.S
@@ -36,7 +36,7 @@
#include <kernel/ppc_defs.h>
#ifdef CONFIG_SMP
- .comm hash_table_lock,4
+ .comm mmu_hash_lock,4
#endif /* CONFIG_SMP */
/*
@@ -62,8 +62,8 @@ hash_page:
#endif
tophys(r7,0) /* gets -KERNELBASE into r7 */
#ifdef CONFIG_SMP
- addis r2,r7,hash_table_lock@h
- ori r2,r2,hash_table_lock@l
+ addis r2,r7,mmu_hash_lock@h
+ ori r2,r2,mmu_hash_lock@l
lis r0,0x0fff
b 10f
11: lwz r6,0(r2)
@@ -88,8 +88,8 @@ hash_page:
rlwimi r3,r23,32-12,29,29 /* MSR_PR -> _PAGE_USER */
112: add r5,r5,r7 /* convert to phys addr */
rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */
- lwz r5,0(r5) /* get pmd entry */
- rlwinm. r5,r5,0,0,19 /* extract address of pte page */
+ lwz r2,0(r5) /* get pmd entry */
+ rlwinm. r2,r2,0,0,19 /* extract address of pte page */
#ifdef CONFIG_SMP
beq- hash_page_out /* return if no mapping */
#else
@@ -99,7 +99,6 @@ hash_page:
to the address following the rfi. */
beqlr-
#endif
- add r2,r5,r7 /* convert to phys addr */
rlwimi r2,r4,22,20,29 /* insert next 10 bits of address */
rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */
ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
@@ -142,9 +141,9 @@ retry:
#ifdef CONFIG_SMP
eieio
- addis r2,r7,hash_table_lock@ha
+ addis r2,r7,mmu_hash_lock@ha
li r0,0
- stw r0,hash_table_lock@l(r2)
+ stw r0,mmu_hash_lock@l(r2)
#endif
/* Return from the exception */
@@ -174,16 +173,16 @@ retry:
#ifdef CONFIG_SMP
hash_page_out:
eieio
- addis r2,r7,hash_table_lock@ha
+ addis r2,r7,mmu_hash_lock@ha
li r0,0
- stw r0,hash_table_lock@l(r2)
+ stw r0,mmu_hash_lock@l(r2)
blr
#endif /* CONFIG_SMP */
/*
* Add an entry for a particular page to the hash table.
*
- * add_hash_page(unsigned context, unsigned long va, pte_t pte)
+ * add_hash_page(unsigned context, unsigned long va, unsigned long pmdval)
*
* We assume any necessary modifications to the pte (e.g. setting
* the accessed bit) have already been done and that there is actually
@@ -199,31 +198,41 @@ _GLOBAL(add_hash_page)
mulli r0,r0,0x111 /* multiply by ESID skew */
add r3,r3,r0 /* note create_hpte trims to 24 bits */
+#ifdef CONFIG_SMP
+ rlwinm r8,r1,0,0,18 /* use cpu number to make tag */
+ lwz r8,TI_CPU(r8) /* to go in mmu_hash_lock */
+ oris r8,r8,12
+#endif /* CONFIG_SMP */
+
/*
* We disable interrupts here, even on UP, because we don't
* want to race with hash_page, and because we want the
* _PAGE_HASHPTE bit to be a reliable indication of whether
- * the HPTE exists (or at least whether one did once). -- paulus
+ * the HPTE exists (or at least whether one did once).
+ * We also turn off the MMU for data accesses so that we
+ * we can't take a hash table miss (assuming the code is
+ * covered by a BAT). -- paulus
*/
mfmsr r10
SYNC
rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
+ rlwinm r0,r0,0,28,26 /* clear MSR_DR */
mtmsr r0
- SYNC
+ SYNC_601
+ isync
+
+ tophys(r7,0)
#ifdef CONFIG_SMP
- lis r9,hash_table_lock@h
- ori r9,r9,hash_table_lock@l
- rlwinm r8,r1,0,0,18
- lwz r8,TI_CPU(r8)
- oris r8,r8,12
-10: lwarx r7,0,r9
- cmpi 0,r7,0
+ addis r9,r7,mmu_hash_lock@ha
+ addi r9,r9,mmu_hash_lock@l
+10: lwarx r0,0,r9 /* take the mmu_hash_lock */
+ cmpi 0,r0,0
bne- 11f
stwcx. r8,0,r9
beq+ 12f
-11: lwz r7,0(r9)
- cmpi 0,r7,0
+11: lwz r0,0(r9)
+ cmpi 0,r0,0
beq 10b
b 11b
12: isync
@@ -234,18 +243,18 @@ _GLOBAL(add_hash_page)
* If _PAGE_HASHPTE was already set, we don't replace the existing
* HPTE, so we just unlock and return.
*/
- mr r7,r5
-1: lwarx r6,0,r7
+ mr r8,r5
+ rlwimi r8,r4,22,20,29
+1: lwarx r6,0,r8
andi. r0,r6,_PAGE_HASHPTE
bne 9f /* if HASHPTE already set, done */
- ori r5,r6,_PAGE_ACCESSED|_PAGE_HASHPTE
- stwcx. r5,0,r7
+ ori r5,r6,_PAGE_HASHPTE
+ stwcx. r5,0,r8
bne- 1b
- li r7,0 /* no address offset needed */
bl create_hpte
- lis r8,htab_preloads@ha
+ addis r8,r7,htab_preloads@ha
lwz r3,htab_preloads@l(r8)
addi r3,r3,1
stw r3,htab_preloads@l(r8)
@@ -254,15 +263,16 @@ _GLOBAL(add_hash_page)
#ifdef CONFIG_SMP
eieio
li r0,0
- stw r0,0(r9) /* clear hash_table_lock */
+ stw r0,0(r9) /* clear mmu_hash_lock */
#endif
+ /* reenable interrupts and DR */
+ mtmsr r10
+ SYNC_601
+ isync
+
lwz r0,4(r1)
mtlr r0
-
- /* reenable interrupts */
- mtmsr r10
- SYNC
blr
/*
@@ -273,7 +283,7 @@ _GLOBAL(add_hash_page)
* linux PTE (before setting _PAGE_HASHPTE) and r7 contains the
* offset to be added to addresses (0 if the MMU is on,
* -KERNELBASE if it is off).
- * On SMP, the caller should have the hash_table_lock held.
+ * On SMP, the caller should have the mmu_hash_lock held.
* We assume that the caller has (or will) set the _PAGE_HASHPTE
* bit in the linux PTE in memory. The value passed in r6 should
* be the old linux PTE value; if it doesn't have _PAGE_HASHPTE set
@@ -486,41 +496,73 @@ found_slot:
/*
* Flush the entry for a particular page from the hash table.
*
- * flush_hash_page(unsigned context, unsigned long va, pte_t *ptep)
+ * flush_hash_pages(unsigned context, unsigned long va, unsigned long pmdval,
+ * int count)
*
* We assume that there is a hash table in use (Hash != 0).
*/
-_GLOBAL(flush_hash_page)
- /* Convert context and va to VSID */
- mulli r3,r3,897*16 /* multiply context by context skew */
- rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */
- mulli r0,r0,0x111 /* multiply by ESID skew */
- add r3,r3,r0 /* note code below trims to 24 bits */
+_GLOBAL(flush_hash_pages)
+ tophys(r7,0)
/*
* We disable interrupts here, even on UP, because we want
* the _PAGE_HASHPTE bit to be a reliable indication of
- * whether the HPTE exists. -- paulus
+ * whether the HPTE exists (or at least whether one did once).
+ * We also turn off the MMU for data accesses so that we
+ * we can't take a hash table miss (assuming the code is
+ * covered by a BAT). -- paulus
*/
mfmsr r10
- rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
SYNC
+ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
+ rlwinm r0,r0,0,28,26 /* clear MSR_DR */
mtmsr r0
- SYNC
+ SYNC_601
+ isync
+
+ /* First find a PTE in the range that has _PAGE_HASHPTE set */
+ rlwimi r5,r4,22,20,29
+1: lwz r0,0(r5)
+ cmpwi cr1,r6,1
+ andi. r0,r0,_PAGE_HASHPTE
+ bne 2f
+ ble cr1,19f
+ addi r4,r4,0x1000
+ addi r5,r5,4
+ addi r6,r6,-1
+ b 1b
+
+ /* Convert context and va to VSID */
+2: mulli r3,r3,897*16 /* multiply context by context skew */
+ rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */
+ mulli r0,r0,0x111 /* multiply by ESID skew */
+ add r3,r3,r0 /* note code below trims to 24 bits */
+
+ /* Construct the high word of the PPC-style PTE (r11) */
+#ifndef CONFIG_PPC64BRIDGE
+ rlwinm r11,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
+ rlwimi r11,r4,10,26,31 /* put in API (abbrev page index) */
+#else /* CONFIG_PPC64BRIDGE */
+ clrlwi r3,r3,8 /* reduce vsid to 24 bits */
+ sldi r11,r3,12 /* shift vsid into position */
+ rlwimi r11,r4,16,20,24 /* put in API (abbrev page index) */
+#endif /* CONFIG_PPC64BRIDGE */
+ SET_V(r11) /* set V (valid) bit */
#ifdef CONFIG_SMP
- lis r9,hash_table_lock@h
- ori r9,r9,hash_table_lock@l
+ addis r9,r7,mmu_hash_lock@ha
+ addi r9,r9,mmu_hash_lock@l
rlwinm r8,r1,0,0,18
+ add r8,r8,r7
lwz r8,TI_CPU(r8)
oris r8,r8,9
-10: lwarx r7,0,r9
- cmpi 0,r7,0
+10: lwarx r0,0,r9
+ cmpi 0,r0,0
bne- 11f
stwcx. r8,0,r9
beq+ 12f
-11: lwz r7,0(r9)
- cmpi 0,r7,0
+11: lwz r0,0(r9)
+ cmpi 0,r0,0
beq 10b
b 11b
12: isync
@@ -528,69 +570,72 @@ _GLOBAL(flush_hash_page)
/*
* Check the _PAGE_HASHPTE bit in the linux PTE. If it is
- * already clear, we're done. If not, clear it (atomically)
- * and proceed. -- paulus.
+ * already clear, we're done (for this pte). If not,
+ * clear it (atomically) and proceed. -- paulus.
*/
-1: lwarx r6,0,r5 /* fetch the pte */
- andi. r0,r6,_PAGE_HASHPTE
- beq 9f /* done if HASHPTE is already clear */
- rlwinm r6,r6,0,31,29 /* clear HASHPTE bit */
- stwcx. r6,0,r5 /* update the pte */
- bne- 1b
-
- /* Construct the high word of the PPC-style PTE (r5) */
-#ifndef CONFIG_PPC64BRIDGE
- rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
- rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
- clrlwi r3,r3,8 /* reduce vsid to 24 bits */
- sldi r5,r3,12 /* shift vsid into position */
- rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
- SET_V(r5) /* set V (valid) bit */
+33: lwarx r8,0,r5 /* fetch the pte */
+ andi. r0,r8,_PAGE_HASHPTE
+ beq 8f /* done if HASHPTE is already clear */
+ rlwinm r8,r8,0,31,29 /* clear HASHPTE bit */
+ stwcx. r8,0,r5 /* update the pte */
+ bne- 33b
/* Get the address of the primary PTE group in the hash table (r3) */
.globl flush_hash_patch_A
flush_hash_patch_A:
- lis r8,Hash_base@h /* base address of hash table */
+ addis r8,r7,Hash_base@h /* base address of hash table */
rlwimi r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */
- rlwinm r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
- xor r3,r3,r8 /* make primary hash */
- li r8,8 /* PTEs/group */
+ rlwinm r0,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
+ xor r8,r0,r8 /* make primary hash */
/* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
- mtctr r8
- addi r7,r3,-PTE_SIZE
-1: LDPTEu r0,PTE_SIZE(r7) /* get next PTE */
- CMPPTE 0,r0,r5
+ li r0,8 /* PTEs/group */
+ mtctr r0
+ addi r12,r8,-PTE_SIZE
+1: LDPTEu r0,PTE_SIZE(r12) /* get next PTE */
+ CMPPTE 0,r0,r11
bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
beq+ 3f
/* Search the secondary PTEG for a matching PTE */
- ori r5,r5,PTE_H /* set H (secondary hash) bit */
+ ori r11,r11,PTE_H /* set H (secondary hash) bit */
+ li r0,8 /* PTEs/group */
.globl flush_hash_patch_B
flush_hash_patch_B:
- xoris r7,r3,Hash_msk>>16 /* compute secondary hash */
- xori r7,r7,(-PTEG_SIZE & 0xffff)
- addi r7,r7,-PTE_SIZE
- mtctr r8
-2: LDPTEu r0,PTE_SIZE(r7)
- CMPPTE 0,r0,r5
+ xoris r12,r8,Hash_msk>>16 /* compute secondary hash */
+ xori r12,r12,(-PTEG_SIZE & 0xffff)
+ addi r12,r12,-PTE_SIZE
+ mtctr r0
+2: LDPTEu r0,PTE_SIZE(r12)
+ CMPPTE 0,r0,r11
bdnzf 2,2b
- bne- 4f /* should never fail to find it */
+ xori r11,r11,PTE_H /* clear H again */
+ bne- 4f /* should rarely fail to find it */
3: li r0,0
- STPTE r0,0(r7) /* invalidate entry */
+ STPTE r0,0(r12) /* invalidate entry */
4: sync
tlbie r4 /* in hw tlb too */
sync
+8: ble cr1,9f /* if all ptes checked */
+81: addi r6,r6,-1
+ addi r5,r5,4 /* advance to next pte */
+ addi r4,r4,0x1000
+ lwz r0,0(r5) /* check next pte */
+ cmpwi cr1,r6,1
+ andi. r0,r0,_PAGE_HASHPTE
+ bne 33b
+ bgt cr1,81b
+
+9:
#ifdef CONFIG_SMP
TLBSYNC
-9: li r0,0
- stw r0,0(r9) /* clear hash_table_lock */
+ li r0,0
+ stw r0,0(r9) /* clear mmu_hash_lock */
#endif
-9: mtmsr r10
- SYNC
+19: mtmsr r10
+ SYNC_601
+ isync
blr
diff --git a/arch/ppc/mm/iSeries_hashtable.c b/arch/ppc/mm/iSeries_hashtable.c
index 0d4a57cbd0c9..98e15292e026 100644
--- a/arch/ppc/mm/iSeries_hashtable.c
+++ b/arch/ppc/mm/iSeries_hashtable.c
@@ -39,7 +39,7 @@
int iSeries_hpt_loaded;
-static spinlock_t hash_table_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t mmu_hash_lock = SPIN_LOCK_UNLOCKED;
extern unsigned long htab_reloads; // Defined in ppc/kernel/ppc_htab.c
extern unsigned long htab_evicts;
@@ -159,10 +159,10 @@ int iSeries_create_hpte( unsigned long access, unsigned long va )
access |= _PAGE_PRESENT; // _PAGE_PRESENT also needed
- spin_lock( &hash_table_lock );
+ spin_lock( &mmu_hash_lock );
// check if pte is in the required state
if ( ( access & ~(pte_val(*pt)) ) ) {
- spin_unlock( &hash_table_lock );
+ spin_unlock( &mmu_hash_lock );
return 1;
}
@@ -177,18 +177,18 @@ int iSeries_create_hpte( unsigned long access, unsigned long va )
va,
pte_val(*pt));
- spin_unlock( &hash_table_lock );
+ spin_unlock( &mmu_hash_lock );
return 0;
}
void add_hash_page(unsigned context, unsigned long va, pte_t *ptep)
{
- spin_lock( &hash_table_lock );
+ spin_lock( &mmu_hash_lock );
pte_update(ptep,0,_PAGE_HASHPTE);
__create_hpte(CTX_TO_VSID(context, va),
va,
pte_val(*ptep));
- spin_unlock( &hash_table_lock );
+ spin_unlock( &mmu_hash_lock );
}
int flush_hash_page(unsigned context, unsigned long va, pte_t *ptep)
@@ -208,7 +208,7 @@ int flush_hash_page(unsigned context, unsigned long va, pte_t *ptep)
hpte1Ptr = hpte0Ptr + 1;
*hpte0Ptr = *hpte1Ptr = 0;
- spin_lock( &hash_table_lock );
+ spin_lock( &mmu_hash_lock );
rtnIndex = HvCallHpt_findValid( &hpte, vpn );
if ( hpte.v ) {
@@ -217,7 +217,7 @@ int flush_hash_page(unsigned context, unsigned long va, pte_t *ptep)
rc = 0;
} else
rc = 1;
- spin_unlock( &hash_table_lock );
+ spin_unlock( &mmu_hash_lock );
return rc;
}
diff --git a/arch/ppc/mm/iSeries_mmu.c b/arch/ppc/mm/iSeries_mmu.c
index 4d1a4d2f997c..e5c809703f93 100644
--- a/arch/ppc/mm/iSeries_mmu.c
+++ b/arch/ppc/mm/iSeries_mmu.c
@@ -175,12 +175,13 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
pte_t *ptep;
static int nopreload;
- if (nopreload)
+ if (nopreload || address >= TASK_SIZE)
return;
- mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
+ mm = vma->vm_mm;
pmd = pmd_offset(pgd_offset(mm, address), address);
if (!pmd_none(*pmd)) {
- ptep = pte_offset(pmd, address);
+ ptep = pte_offset_map(pmd, address);
add_hash_page(mm->context, address, ptep);
+ pte_unmap(ptep);
}
}
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index e91a9761b745..76410ed65ea5 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -113,24 +113,6 @@ unsigned long __max_memory;
/* max amount of low RAM to map in */
unsigned long __max_low_memory = MAX_LOW_MEM;
-int do_check_pgt_cache(int low, int high)
-{
- int freed = 0;
- if (pgtable_cache_size > high) {
- do {
- if (pgd_quicklist) {
- free_pgd_slow(get_pgd_fast());
- freed++;
- }
- if (pte_quicklist) {
- pte_free_slow(pte_alloc_one_fast(NULL, 0));
- freed++;
- }
- } while (pgtable_cache_size > low);
- }
- return freed;
-}
-
void show_mem(void)
{
int i,free = 0,total = 0,reserved = 0;
@@ -160,7 +142,6 @@ void show_mem(void)
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
- printk("%d pages in page table cache\n",(int)pgtable_cache_size);
show_buffers();
}
@@ -396,9 +377,11 @@ void __init paging_init(void)
#ifdef CONFIG_HIGHMEM
map_page(PKMAP_BASE, 0, 0); /* XXX gross */
- pkmap_page_table = pte_offset(pmd_offset(pgd_offset_k(PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
+ pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
+ (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
- kmap_pte = pte_offset(pmd_offset(pgd_offset_k(KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
+ kmap_pte = pte_offset_kernel(pmd_offset(pgd_offset_k
+ (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
kmap_prot = PAGE_KERNEL;
#endif /* CONFIG_HIGHMEM */
@@ -588,10 +571,12 @@ void flush_dcache_page(struct page *page)
void flush_icache_page(struct vm_area_struct *vma, struct page *page)
{
+ unsigned long phys;
+
if (page->mapping && !PageReserved(page)
&& !test_bit(PG_arch_1, &page->flags)) {
- __flush_dcache_icache(kmap(page));
- kunmap(page);
+ phys = ((page - mem_map) << PAGE_SHIFT) + PPC_MEMSTART;
+ __flush_dcache_icache_phys(phys);
set_bit(PG_arch_1, &page->flags);
}
}
diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
index 20e1a9712e5a..0e6e9121ac52 100644
--- a/arch/ppc/mm/mmu_decl.h
+++ b/arch/ppc/mm/mmu_decl.h
@@ -61,11 +61,12 @@ extern void MMU_init_hw(void);
* which includes all new 82xx processors. We need tlbie/tlbsync here
* in that case (I think). -- Dan.
*/
-static inline void flush_HPTE(unsigned context, unsigned long va, pte_t *pg)
+static inline void flush_HPTE(unsigned context, unsigned long va,
+ unsigned long pdval)
{
if ((Hash != 0) &&
(cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE))
- flush_hash_page(0, va, pg);
+ flush_hash_pages(0, va, pdval, 1);
else
_tlbie(va);
}
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index d0725d847729..14bb83cf09f0 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -39,10 +39,6 @@ unsigned long ioremap_base;
unsigned long ioremap_bot;
int io_bat_index;
-#ifndef CONFIG_SMP
-struct pgtable_cache_struct quicklists;
-#endif
-
#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
#define HAVE_BATS 1
#endif
@@ -173,12 +169,12 @@ map_page(unsigned long va, unsigned long pa, int flags)
/* Use upper 10 bits of VA to index the first level map */
pd = pmd_offset(pgd_offset_k(va), va);
/* Use middle 10 bits of VA to index the second-level map */
- pg = pte_alloc(&init_mm, pd, va);
+ pg = pte_alloc_kernel(&init_mm, pd, va);
if (pg != 0) {
err = 0;
set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
if (mem_init_done)
- flush_HPTE(0, va, pg);
+ flush_HPTE(0, va, pmd_val(*pd));
}
spin_unlock(&init_mm.page_table_lock);
return err;
@@ -272,10 +268,11 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
if (pgd) {
pmd = pmd_offset(pgd, addr & PAGE_MASK);
if (pmd_present(*pmd)) {
- pte = pte_offset(pmd, addr & PAGE_MASK);
+ pte = pte_offset_map(pmd, addr & PAGE_MASK);
if (pte) {
retval = 1;
*ptep = pte;
+ /* XXX caller needs to do pte_unmap, yuck */
}
}
}
@@ -312,8 +309,10 @@ unsigned long iopa(unsigned long addr)
mm = &init_mm;
pa = 0;
- if (get_pteptr(mm, addr, &pte))
+ if (get_pteptr(mm, addr, &pte)) {
pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
+ pte_unmap(pte);
+ }
return(pa);
}
diff --git a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
index ecfefdd78e80..a48229530d80 100644
--- a/arch/ppc/mm/ppc_mmu.c
+++ b/arch/ppc/mm/ppc_mmu.c
@@ -33,6 +33,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/highmem.h>
#include <asm/prom.h>
#include <asm/mmu.h>
@@ -289,7 +290,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
{
struct mm_struct *mm;
pmd_t *pmd;
- pte_t *ptep;
static int nopreload;
if (Hash == 0 || nopreload)
@@ -299,8 +299,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
return;
mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
pmd = pmd_offset(pgd_offset(mm, address), address);
- if (!pmd_none(*pmd)) {
- ptep = pte_offset(pmd, address);
- add_hash_page(mm->context, address, ptep);
- }
+ if (!pmd_none(*pmd))
+ add_hash_page(mm->context, address, pmd_val(*pmd));
}
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
index fed74ef24e2a..0e5a624ebf13 100644
--- a/arch/ppc/mm/tlb.c
+++ b/arch/ppc/mm/tlb.c
@@ -30,6 +30,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/highmem.h>
#include "mmu_decl.h"
@@ -104,7 +105,6 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
{
struct mm_struct *mm;
pmd_t *pmd;
- pte_t *pte;
if (Hash == 0) {
_tlbie(vmaddr);
@@ -112,11 +112,8 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
}
mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
- if (!pmd_none(*pmd)) {
- pte = pte_offset(pmd, vmaddr);
- if (pte_val(*pte) & _PAGE_HASHPTE)
- flush_hash_page(mm->context, vmaddr, pte);
- }
+ if (!pmd_none(*pmd))
+ flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
#ifdef CONFIG_SMP
smp_send_tlb_invalidate(0);
#endif
@@ -133,8 +130,8 @@ local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned
{
struct mm_struct *mm = vma->vm_mm;
pmd_t *pmd;
- pte_t *pte;
unsigned long pmd_end;
+ int count;
unsigned int ctx = mm->context;
if (Hash == 0) {
@@ -144,24 +141,21 @@ local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned
start &= PAGE_MASK;
if (start >= end)
return;
+ end = (end - 1) | ~PAGE_MASK;
pmd = pmd_offset(pgd_offset(mm, start), start);
- do {
- pmd_end = (start + PGDIR_SIZE) & PGDIR_MASK;
+ for (;;) {
+ pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
+ if (pmd_end > end)
+ pmd_end = end;
if (!pmd_none(*pmd)) {
- if (!pmd_end || pmd_end > end)
- pmd_end = end;
- pte = pte_offset(pmd, start);
- do {
- if ((pte_val(*pte) & _PAGE_HASHPTE) != 0)
- flush_hash_page(ctx, start, pte);
- start += PAGE_SIZE;
- ++pte;
- } while (start && start < pmd_end);
- } else {
- start = pmd_end;
+ count = ((pmd_end - start) >> PAGE_SHIFT) + 1;
+ flush_hash_pages(ctx, start, pmd_val(*pmd), count);
}
+ if (pmd_end == end)
+ break;
+ start = pmd_end + 1;
++pmd;
- } while (start && start < end);
+ }
#ifdef CONFIG_SMP
smp_send_tlb_invalidate(0);
diff --git a/arch/ppc/vmlinux.lds b/arch/ppc/vmlinux.lds
index 8a12e1706542..531ba24f1912 100644
--- a/arch/ppc/vmlinux.lds
+++ b/arch/ppc/vmlinux.lds
@@ -111,6 +111,10 @@ SECTIONS
*(.initcall7.init)
}
__initcall_end = .;
+ . = ALIGN(32);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
index 3df2b8b09239..af7f525696b1 100644
--- a/arch/ppc64/kernel/entry.S
+++ b/arch/ppc64/kernel/entry.S
@@ -311,7 +311,7 @@ _GLOBAL(_switch)
blr
_GLOBAL(ret_from_fork)
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
bl .schedule_tail
#endif
clrrdi r4,r1,THREAD_SHIFT
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 8a1ab082620e..064adae3ad11 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -295,7 +295,7 @@ ret_from_fork:
stosm 24(%r15),0x03 # reenable interrupts
sr %r0,%r0 # child returns 0
st %r0,SP_R2(%r15) # store return value (change R2 on stack)
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
l %r1,BASED(.Lschedtail)
la %r14,BASED(sysc_return)
br %r1 # call schedule_tail, return to sysc_return
@@ -896,7 +896,7 @@ restart_go:
#error .Ltrace: .long syscall_trace
.Lvfork: .long sys_vfork
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
.Lschedtail: .long schedule_tail
#endif
diff --git a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S
index c761c92bfdff..ef638bc446f9 100644
--- a/arch/s390x/kernel/entry.S
+++ b/arch/s390x/kernel/entry.S
@@ -280,7 +280,7 @@ ret_from_fork:
GET_CURRENT # load pointer to task_struct to R9
stosm 48(%r15),0x03 # reenable interrupts
xc SP_R2(8,%r15),SP_R2(%r15) # child returns 0
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
larl %r14,sysc_return
jg schedule_tail # return to sysc_return
#else
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 3100e0fcd1d0..6c948f4f3aa3 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -273,7 +273,6 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
#
# IDE chipset support/bugfixes
@@ -286,7 +285,6 @@ CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
CONFIG_IDEDMA_ONLYDISK=y
CONFIG_BLK_DEV_IDEDMA=y
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index b5eb95bd7f5f..37cef2d1a808 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -188,7 +188,6 @@ CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
#
# IDE chipset support/bugfixes
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index e46bd97f9e34..6b98b90891f4 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -102,8 +102,6 @@
* A newly forked process directly context switches into this.
*/
ENTRY(ret_from_fork)
- movq %rbx, %rdi
- call schedule_tail
GET_THREAD_INFO(%rcx)
bt $TIF_SYSCALL_TRACE,threadinfo_flags(%rcx)
jc rff_trace
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 82fb82432ef5..b9dab9831a21 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -1222,7 +1222,7 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
case BLKROSET:
case BLKROGET:
case BLKPG:
- return blk_ioctl(dev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
return -EINVAL;
diff --git a/drivers/acorn/char/mouse_ps2.c b/drivers/acorn/char/mouse_ps2.c
index 544e7cf5e2a5..0b00b556ff1f 100644
--- a/drivers/acorn/char/mouse_ps2.c
+++ b/drivers/acorn/char/mouse_ps2.c
@@ -271,7 +271,8 @@ int __init psaux_init(void)
iomd_writeb(0, IOMD_MSECTL);
iomd_writeb(8, IOMD_MSECTL);
- misc_register(&psaux_mouse);
+ if (misc_register(&psaux_mouse))
+ return -ENODEV;
queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
memset(queue, 0, sizeof(*queue));
queue->head = queue->tail = 0;
diff --git a/drivers/acorn/scsi/ecoscsi.c b/drivers/acorn/scsi/ecoscsi.c
index a605212d2e64..0e283b20d076 100644
--- a/drivers/acorn/scsi/ecoscsi.c
+++ b/drivers/acorn/scsi/ecoscsi.c
@@ -125,7 +125,11 @@ int ecoscsi_detect(Scsi_Host_Template * tpnt)
}
NCR5380_init(instance, 0);
- request_region (instance->io_port, instance->n_io_port, "ecoscsi");
+ if (request_region (instance->io_port, instance->n_io_port, "ecoscsi") == NULL)
+ {
+ scsi_unregister(instance);
+ return 0;
+ }
if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
index 1609599038d6..18cb0838ad8d 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/executer/exresnte.c
@@ -44,7 +44,7 @@
* FUNCTION: Acpi_ex_resolve_node_to_value
*
* PARAMETERS: Object_ptr - Pointer to a location that contains
- * a pointer to a NS node, and will recieve a
+ * a pointer to a NS node, and will receive a
* pointer to the resolved object.
* Walk_state - Current state. Valid only if executing AML
* code. NULL if simply resolving an object
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 433531d63435..d205bf2c4a8d 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -5398,7 +5398,7 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File,
case BLKFLSBUF:
case BLKBSZGET:
case BLKBSZSET:
- return blk_ioctl(Inode->i_rdev, Request, Argument);
+ return blk_ioctl(Inode->i_bdev, Request, Argument);
case BLKRRPART:
/* Re-Read Partition Table. */
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 3721705e70e5..85224abc2bfe 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -1141,7 +1141,7 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
case BLKROGET:
case BLKFLSBUF:
case BLKPG:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
case BLKRRPART: /* Re-read partition tables */
if (!capable(CAP_SYS_ADMIN))
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index bdc585c419ff..7f18fca76d08 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1574,7 +1574,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
case BLKROSET:
case BLKROGET:
case BLKFLSBUF:
- return blk_ioctl(device, cmd, param);
+ return blk_ioctl(inode->i_bdev, cmd, param);
}
drive = minor (device);
type = drive >> 2;
diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c
index a1f9a13a749f..264d9824535c 100644
--- a/drivers/block/blkpg.c
+++ b/drivers/block/blkpg.c
@@ -34,7 +34,6 @@
#include <linux/blk.h> /* for set_device_ro() */
#include <linux/blkpg.h>
#include <linux/genhd.h>
-#include <linux/swap.h> /* for is_swap_partition() */
#include <linux/module.h> /* for EXPORT_SYMBOL */
#include <asm/uaccess.h>
@@ -63,12 +62,13 @@
* or has the same number as an existing one
* 0: all OK.
*/
-int add_partition(kdev_t dev, struct blkpg_partition *p)
+int add_partition(struct block_device *bdev, struct blkpg_partition *p)
{
struct gendisk *g;
long long ppstart, pplength;
long pstart, plength;
int i, drive, first_minor, end_minor, minor;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
/* convert bytes to sectors, check for fit in a hd_struct */
ppstart = (p->start >> 9);
@@ -126,11 +126,14 @@ int add_partition(kdev_t dev, struct blkpg_partition *p)
*
* Note that the dev argument refers to the entire disk, not the partition.
*/
-int del_partition(kdev_t dev, struct blkpg_partition *p)
+int del_partition(struct block_device *bdev, struct blkpg_partition *p)
{
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
struct gendisk *g;
kdev_t devp;
+ struct block_device *bdevp;
int drive, first_minor, minor;
+ int holder;
/* find the drive major */
g = get_gendisk(dev);
@@ -153,22 +156,29 @@ int del_partition(kdev_t dev, struct blkpg_partition *p)
/* partition in use? Incomplete check for now. */
devp = mk_kdev(major(dev), minor);
- if (is_mounted(devp) || is_swap_partition(devp))
+ bdevp = bdget(kdev_t_to_nr(devp));
+ if (!bdevp)
+ return -ENOMEM;
+ if (bd_claim(bdevp, &holder) < 0) {
+ bdput(bdevp);
return -EBUSY;
+ }
/* all seems OK */
- fsync_dev(devp);
- invalidate_buffers(devp);
+ fsync_bdev(bdevp);
+ invalidate_bdev(bdevp, 0);
g->part[minor].start_sect = 0;
g->part[minor].nr_sects = 0;
if (g->sizes)
g->sizes[minor] = 0;
+ bd_release(bdevp);
+ bdput(bdevp);
return 0;
}
-int blkpg_ioctl(kdev_t dev, struct blkpg_ioctl_arg *arg)
+int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg)
{
struct blkpg_ioctl_arg a;
struct blkpg_partition p;
@@ -188,9 +198,9 @@ int blkpg_ioctl(kdev_t dev, struct blkpg_ioctl_arg *arg)
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (a.op == BLKPG_ADD_PARTITION)
- return add_partition(dev, &p);
+ return add_partition(bdev, &p);
else
- return del_partition(dev, &p);
+ return del_partition(bdev, &p);
default:
return -EINVAL;
}
@@ -200,16 +210,15 @@ int blkpg_ioctl(kdev_t dev, struct blkpg_ioctl_arg *arg)
* Common ioctl's for block devices
*/
extern int block_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg);
-int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
+int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
{
request_queue_t *q;
struct gendisk *g;
u64 ullval = 0;
int intval;
unsigned short usval;
-
- if (kdev_none(dev))
- return -EINVAL;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
+ int holder;
intval = block_ioctl(dev, cmd, arg);
if (intval != -ENOTTY)
@@ -265,7 +274,7 @@ int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
#endif
case BLKPG:
- return blkpg_ioctl(dev, (struct blkpg_ioctl_arg *) arg);
+ return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg *) arg);
/*
* deprecated, use the /proc/iosched interface instead
@@ -290,9 +299,10 @@ int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
if (intval > PAGE_SIZE || intval < 512 ||
(intval & (intval - 1)))
return -EINVAL;
- if (is_mounted(dev) || is_swap_partition(dev))
+ if (bd_claim(bdev, &holder) < 0)
return -EBUSY;
set_blocksize(dev, intval);
+ bd_release(bdev);
return 0;
default:
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 47d9b0808280..d87635dd23ea 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -469,7 +469,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
case BLKROSET:
case BLKROGET:
case BLKPG:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
case CCISS_GETPCIINFO:
{
cciss_pci_info_struct pciinfo;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 694a1efd4578..c8cf5871273b 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -1179,7 +1179,7 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
case BLKROSET:
case BLKROGET:
case BLKPG:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
return -EINVAL;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 5359938e99e8..052d2a6b8f60 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3449,7 +3449,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
case BLKROSET:
case BLKROGET:
case BLKFLSBUF:
- return blk_ioctl(device, cmd, param);
+ return blk_ioctl(inode->i_bdev, cmd, param);
}
type = TYPE(device);
drive = DRIVE(device);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index eb1f8813b421..cfce7b234c57 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -852,7 +852,7 @@ static int lo_ioctl(struct inode * inode, struct file * file,
break;
case BLKBSZGET:
case BLKBSZSET:
- err = blk_ioctl(inode->i_rdev, cmd, arg);
+ err = blk_ioctl(inode->i_bdev, cmd, arg);
break;
default:
err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 7d0f6a6a5f7a..91cc8e3eac35 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -481,7 +481,7 @@ static int pd_ioctl(struct inode *inode,struct file *file,
case BLKROGET:
case BLKFLSBUF:
case BLKPG:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
return -EINVAL;
}
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 034705f2f1c1..be857543c111 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -433,7 +433,7 @@ static int pf_ioctl(struct inode *inode,struct file *file,
case BLKROSET:
case BLKROGET:
case BLKFLSBUF:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
return -EINVAL;
}
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 95493ea0f1fe..79370ff00905 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -1111,7 +1111,7 @@ static int ps2esdi_ioctl(struct inode *inode,
case BLKBSZGET:
case BLKBSZSET:
case BLKPG:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
}
return (-EINVAL);
}
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 3edd33c306ce..f9cf01e79412 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -311,7 +311,7 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
case BLKROSET:
case BLKROGET:
case BLKSSZGET:
- error = blk_ioctl(inode->i_rdev, cmd, arg);
+ error = blk_ioctl(inode->i_bdev, cmd, arg);
};
out:
return error;
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 30d2e864add5..76e87ad39cfd 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -355,7 +355,7 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
case BLKROSET:
case BLKROGET:
case BLKPG:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
return -EINVAL;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 229df11fee90..14107f29c363 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -263,6 +263,7 @@
#include <linux/cdrom.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
+#include <linux/blkpg.h>
#include <linux/init.h>
#include <asm/fcntl.h>
@@ -1724,6 +1725,11 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
because they fill up the sys log when CD players poll
the drive. */
switch (cmd) {
+ case BLKROSET:
+ case BLKROGET:
+ case BLKFLSBUF:
+ case BLKSSZGET:
+ return blk_ioctl(ip->i_bdev, cmd, arg);
case CDROMSUBCHNL: {
struct cdrom_subchnl q;
u_char requested, back;
diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c
index df2938ade0da..37a3420c9285 100644
--- a/drivers/char/acquirewdt.c
+++ b/drivers/char/acquirewdt.c
@@ -207,7 +207,8 @@ static int __init acq_init(void)
printk("WDT driver for Acquire single board computer initialising.\n");
spin_lock_init(&acq_lock);
- misc_register(&acq_miscdev);
+ if (misc_register(&acq_miscdev))
+ return -ENODEV;
request_region(WDT_STOP, 1, "Acquire WDT");
request_region(WDT_START, 1, "Acquire WDT");
register_reboot_notifier(&acq_notifier);
diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c
index 3335b538deaf..fdd404f50e0f 100644
--- a/drivers/char/agp/agpgart_be.c
+++ b/drivers/char/agp/agpgart_be.c
@@ -622,7 +622,7 @@ static int agp_generic_create_gatt_table(void)
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
- set_bit(PG_reserved, &page->flags);
+ SetPageReserved(page);
agp_bridge.gatt_table_real = (unsigned long *) table;
CACHE_FLUSH();
@@ -632,7 +632,7 @@ static int agp_generic_create_gatt_table(void)
if (agp_bridge.gatt_table == NULL) {
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
- clear_bit(PG_reserved, &page->flags);
+ ClearPageReserved(page);
free_pages((unsigned long) table, page_order);
@@ -699,7 +699,7 @@ static int agp_generic_free_gatt_table(void)
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
- clear_bit(PG_reserved, &page->flags);
+ ClearPageReserved(page);
free_pages((unsigned long) agp_bridge.gatt_table_real, page_order);
return 0;
@@ -812,8 +812,8 @@ static unsigned long agp_generic_alloc_page(void)
if (page == NULL) {
return 0;
}
- atomic_inc(&page->count);
- set_bit(PG_locked, &page->flags);
+ get_page(page);
+ LockPage(page);
atomic_inc(&agp_bridge.current_memory_agp);
return (unsigned long)page_address(page);
}
@@ -828,9 +828,8 @@ static void agp_generic_destroy_page(unsigned long addr)
}
page = virt_to_page(pt);
- atomic_dec(&page->count);
- clear_bit(PG_locked, &page->flags);
- wake_up_page(page);
+ put_page(page);
+ UnlockPage(page);
free_page((unsigned long) pt);
atomic_dec(&agp_bridge.current_memory_agp);
}
@@ -2278,13 +2277,12 @@ static int amd_create_page_map(amd_page_map *page_map)
if (page_map->real == NULL) {
return -ENOMEM;
}
- set_bit(PG_reserved, &virt_to_page(page_map->real)->flags);
+ SetPageReserved(virt_to_page(page_map->real));
CACHE_FLUSH();
page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
- clear_bit(PG_reserved,
- &virt_to_page(page_map->real)->flags);
+ ClearPageReserved(virt_to_page(page_map->real));
free_page((unsigned long) page_map->real);
page_map->real = NULL;
return -ENOMEM;
@@ -2301,8 +2299,7 @@ static int amd_create_page_map(amd_page_map *page_map)
static void amd_free_page_map(amd_page_map *page_map)
{
iounmap(page_map->remapped);
- clear_bit(PG_reserved,
- &virt_to_page(page_map->real)->flags);
+ ClearPageReserved(virt_to_page(page_map->real));
free_page((unsigned long) page_map->real);
}
@@ -2790,8 +2787,8 @@ static unsigned long ali_alloc_page(void)
if (page == NULL)
return 0;
- atomic_inc(&page->count);
- set_bit(PG_locked, &page->flags);
+ get_page(page);
+ LockPage(page);
atomic_inc(&agp_bridge.current_memory_agp);
global_cache_flush();
@@ -2826,9 +2823,8 @@ static void ali_destroy_page(unsigned long addr)
}
page = virt_to_page(pt);
- atomic_dec(&page->count);
- clear_bit(PG_locked, &page->flags);
- wake_up_page(page);
+ put_page(page);
+ UnlockPage(page);
free_page((unsigned long) pt);
atomic_dec(&agp_bridge.current_memory_agp);
}
@@ -2910,13 +2906,12 @@ static int serverworks_create_page_map(serverworks_page_map *page_map)
if (page_map->real == NULL) {
return -ENOMEM;
}
- set_bit(PG_reserved, &virt_to_page(page_map->real)->flags);
+ SetPageReserved(virt_to_page(page_map->real));
CACHE_FLUSH();
page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
- clear_bit(PG_reserved,
- &virt_to_page(page_map->real)->flags);
+ ClearPageReserved(virt_to_page(page_map->real));
free_page((unsigned long) page_map->real);
page_map->real = NULL;
return -ENOMEM;
@@ -2933,8 +2928,7 @@ static int serverworks_create_page_map(serverworks_page_map *page_map)
static void serverworks_free_page_map(serverworks_page_map *page_map)
{
iounmap(page_map->remapped);
- clear_bit(PG_reserved,
- &virt_to_page(page_map->real)->flags);
+ ClearPageReserved(virt_to_page(page_map->real));
free_page((unsigned long) page_map->real);
}
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 2f40db80106e..8629e0e5fa09 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -286,8 +286,8 @@ static unsigned long i810_alloc_page(drm_device_t *dev)
if(address == 0UL)
return 0;
- atomic_inc(&virt_to_page(address)->count);
- set_bit(PG_locked, &virt_to_page(address)->flags);
+ get_page(virt_to_page(address));
+ LockPage(virt_to_page(address));
return address;
}
@@ -296,9 +296,8 @@ static void i810_free_page(drm_device_t *dev, unsigned long page)
{
if (page) {
struct page *p = virt_to_page(page);
- atomic_dec(p);
- clear_bit(PG_locked, &p->flags);
- wake_up_page(p);
+ put_page(p);
+ UnlockPage(p);
free_page(page);
}
}
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 80a894193622..de1c67b8e9db 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1812,7 +1812,7 @@ static int startup(struct mgsl_struct * info)
/* Allocate and claim adapter resources */
retval = mgsl_claim_resources(info);
- /* perform existance check and diagnostics */
+ /* perform existence check and diagnostics */
if ( !retval )
retval = mgsl_adapter_test(info);
diff --git a/drivers/ide/Config.help b/drivers/ide/Config.help
index 7cf29240fcc7..90eff264afc4 100644
--- a/drivers/ide/Config.help
+++ b/drivers/ide/Config.help
@@ -581,13 +581,6 @@ CONFIG_IDE_CHIPSETS
People with SCSI-only systems can say N here.
-CONFIG_BLK_DEV_4DRIVES
- Certain older chipsets, including the Tekram 690CD, use a single set
- of I/O ports at 0x1f0 to control up to four drives, instead of the
- customary two drives per port. Support for this can be enabled at
- runtime using the "ide0=four" kernel boot parameter if you say Y
- here.
-
CONFIG_BLK_DEV_ALI14XX
This driver is enabled at runtime using the "ide0=ali14xx" kernel
boot parameter. It enables support for the secondary IDE interface
@@ -807,19 +800,6 @@ CONFIG_IDEDISK_STROKE
If you are unsure, say N here.
-CONFIG_IDE_TASK_IOCTL
- This is a direct raw access to the media. It is a complex but
- elegant solution to test and validate the domain of the hardware and
- perform below the driver data recovery if needed. This is the most
- basic form of media-forensics.
-
- If you are unsure, say N here.
-
-CONFIG_BLK_DEV_IDEDMA_FORCED
- This is an old piece of lost code from Linux 2.0 Kernels.
-
- Generally say N here.
-
CONFIG_IDEDMA_ONLYDISK
This is used if you know your ATAPI Devices are going to fail DMA
Transfers.
diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in
index ac177c4cdad4..1f09fc2dc76f 100644
--- a/drivers/ide/Config.in
+++ b/drivers/ide/Config.in
@@ -33,9 +33,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI
- bool ' IDE Taskfile Access' CONFIG_IDE_TASK_IOCTL
-
- comment 'IDE chipset support/bugfixes'
+ comment 'IDE chipset support'
if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86
dep_bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED $CONFIG_BLK_DEV_CMD640
@@ -47,7 +45,6 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
bool ' Sharing PCI IDE interrupts support' CONFIG_IDEPCI_SHARE_IRQ
bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI
bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
- dep_bool ' Force enable legacy 2.0.X HOSTS to use DMA' CONFIG_BLK_DEV_IDEDMA_FORCED $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO
define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI
@@ -143,7 +140,6 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS
if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
comment 'Note: most of these also require special kernel boot parameters'
- bool ' Generic 4 drives/port support' CONFIG_BLK_DEV_4DRIVES
bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX
bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278
bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
index 43c01a4e25b1..658a15b008d9 100644
--- a/drivers/ide/ali14xx.c
+++ b/drivers/ide/ali14xx.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/ali14xx.c Version 0.03 Feb 09, 1996
- *
* Copyright (C) 1996 Linus Torvalds & author (see below)
*/
@@ -37,8 +35,6 @@
* mode 4 for a while now with no trouble.) -Derek
*/
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
index a59c21146723..2e8d0cf3480d 100644
--- a/drivers/ide/cmd640.c
+++ b/drivers/ide/cmd640.c
@@ -1,12 +1,10 @@
/*
- * linux/drivers/ide/cmd640.c Version 1.02 Sep 01, 1996
- *
* Copyright (C) 1995-1996 Linus Torvalds & authors (see below)
*/
/*
* Original authors: abramov@cecmow.enet.dec.com (Igor Abramov)
- * mlord@pobox.com (Mark Lord)
+ * mlord@pobox.com (Mark Lord)
*
* See linux/MAINTAINERS for address of current maintainer.
*
@@ -98,7 +96,6 @@
* (patch courtesy of Zoltan Hidvegi)
*/
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
#define CMD640_PREFETCH_MASKS 1
#include <linux/config.h>
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index e81a9d194745..ad584e89c578 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -238,7 +238,7 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ
*/
if (channel) {
drive->drive_data = setup_count;
- setup_count = IDE_MAX(drives[0].drive_data, drives[1].drive_data);
+ setup_count = max(drives[0].drive_data, drives[1].drive_data);
cmdprintk("Secondary interface, setup_count = %d\n", setup_count);
}
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
index 16fbceac264f..4aebe99a7c3c 100644
--- a/drivers/ide/dtc2278.c
+++ b/drivers/ide/dtc2278.c
@@ -1,11 +1,7 @@
/*
- * linux/drivers/ide/dtc2278.c Version 0.02 Feb 10, 1996
- *
* Copyright (C) 1996 Linus Torvalds & author (see below)
*/
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
diff --git a/drivers/ide/hd.c b/drivers/ide/hd.c
index 71e1ffefd0c2..6c708f38ba20 100644
--- a/drivers/ide/hd.c
+++ b/drivers/ide/hd.c
@@ -654,7 +654,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
case BLKROGET:
case BLKFLSBUF:
case BLKPG:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
return -EINVAL;
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index b2374dd4b76a..53b79071db50 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -374,7 +374,8 @@ static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
class_rev &= 0xff;
p += sprintf(p, "\nController: %d\n", i);
- p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]);
+ p += sprintf(p, "Chipset: HPT%s\n",
+ class_rev < sizeof(chipset_nums) / sizeof(char *) ? chipset_nums[class_rev] : "???");
p += sprintf(p, "--------------- Primary Channel "
"--------------- Secondary Channel "
"--------------\n");
@@ -1119,12 +1120,11 @@ unsigned int __init pci_init_hpt366(struct pci_dev *dev)
if (test != 0x08)
pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
- if (pci_rev_check_hpt3xx(dev)) {
+ if (pci_rev_check_hpt3xx(dev))
init_hpt370(dev);
+
+ if (n_hpt_devs < HPT366_MAX_DEVS)
hpt_devs[n_hpt_devs++] = dev;
- } else {
- hpt_devs[n_hpt_devs++] = dev;
- }
#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
if (!hpt366_proc) {
diff --git a/drivers/ide/hptraid.c b/drivers/ide/hptraid.c
index 9a61e5112846..88f8858143fc 100644
--- a/drivers/ide/hptraid.c
+++ b/drivers/ide/hptraid.c
@@ -126,7 +126,7 @@ static int hptraid_ioctl(struct inode *inode, struct file *file, unsigned int cm
case BLKROSET:
case BLKROGET:
case BLKSSZGET:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
return -EINVAL;
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
index 59dacf6266ed..faa5a13b43a2 100644
--- a/drivers/ide/ht6560b.c
+++ b/drivers/ide/ht6560b.c
@@ -1,10 +1,5 @@
/*
- * linux/drivers/ide/ht6560b.c Version 0.07 Feb 1, 2000
- *
* Copyright (C) 1995-2000 Linus Torvalds & author (see below)
- */
-
-/*
*
* Version 0.01 Initial version hacked out of ide.c
*
@@ -36,8 +31,6 @@
#define HT6560B_VERSION "v0.07"
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 3266e7ef0721..714b0d8b2361 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1633,6 +1633,7 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
return startstop;
}
+#define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
/****************************************************************************
* cdrom driver request routine.
@@ -2906,69 +2907,29 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
return 0;
}
-static int ide_cdrom_reinit (ide_drive_t *drive);
-
static struct ata_operations ide_cdrom_driver = {
owner: THIS_MODULE,
cleanup: ide_cdrom_cleanup,
standby: NULL,
- flushcache: NULL,
do_request: ide_do_rw_cdrom,
end_request: NULL,
ioctl: ide_cdrom_ioctl,
open: ide_cdrom_open,
release: ide_cdrom_release,
- media_change: ide_cdrom_check_media_change,
+ check_media_change: ide_cdrom_check_media_change,
revalidate: ide_cdrom_revalidate,
pre_reset: NULL,
capacity: ide_cdrom_capacity,
special: NULL,
- proc: NULL,
- driver_reinit: ide_cdrom_reinit,
+ proc: NULL
};
/* options */
-char *ignore = NULL;
+static char *ignore = NULL;
MODULE_PARM(ignore, "s");
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
-static int ide_cdrom_reinit (ide_drive_t *drive)
-{
- struct cdrom_info *info;
- int failed = 0;
-
- MOD_INC_USE_COUNT;
- info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
- if (info == NULL) {
- printk ("%s: Can't allocate a cdrom structure\n", drive->name);
- return 1;
- }
- if (ide_register_subdriver (drive, &ide_cdrom_driver)) {
- printk ("%s: Failed to register the driver with ide.c\n", drive->name);
- kfree (info);
- return 1;
- }
- memset (info, 0, sizeof (struct cdrom_info));
- drive->driver_data = info;
-
- /* ATA-PATTERN */
- ata_ops(drive)->busy++;
- if (ide_cdrom_setup (drive)) {
- ata_ops(drive)->busy--;
- if (ide_cdrom_cleanup (drive))
- printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name);
- return 1;
- }
- ata_ops(drive)->busy--;
-
- failed--;
-
- revalidate_drives();
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
static void __exit ide_cdrom_exit(void)
{
ide_drive_t *drive;
@@ -2980,7 +2941,7 @@ static void __exit ide_cdrom_exit(void)
failed++;
}
}
-
+
int ide_cdrom_init(void)
{
ide_drive_t *drive;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index fb4350c2e7e4..ef806c5d4ffc 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1,10 +1,6 @@
/*
- * linux/drivers/ide/ide-disk.c Version 1.13 Nov 28, 2001
- *
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- */
-
-/*
+ *
* Mostly written by Mark Lord <mlord@pobox.com>
* and Gadi Oxman <gadio@netvision.net.il>
* and Andre Hedrick <andre@linux-ide.org>
@@ -34,8 +30,6 @@
#define IDEDISK_VERSION "1.13"
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -351,7 +345,19 @@ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *dr
return 0;
}
-static int do_idedisk_flushcache(ide_drive_t *drive);
+static int idedisk_flushcache(ide_drive_t *drive)
+{
+ struct hd_drive_task_hdr taskfile;
+ struct hd_drive_hob_hdr hobfile;
+ memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
+ memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+ if (drive->id->cfs_enable_2 & 0x2400) {
+ taskfile.command = WIN_FLUSH_CACHE_EXT;
+ } else {
+ taskfile.command = WIN_FLUSH_CACHE;
+ }
+ return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
+}
static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
{
@@ -367,15 +373,16 @@ static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t
drive->doorlocking = 0;
}
if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
- if (do_idedisk_flushcache(drive))
+ if (idedisk_flushcache(drive))
printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
drive->name);
MOD_DEC_USE_COUNT;
}
-static int idedisk_media_change (ide_drive_t *drive)
+static int idedisk_check_media_change (ide_drive_t *drive)
{
- return drive->removable; /* if removable, always assume it was changed */
+ /* if removable, always assume it was changed */
+ return drive->removable;
}
/*
@@ -707,7 +714,7 @@ static int get_smart_values(ide_drive_t *drive, byte *buf)
taskfile.low_cylinder = SMART_LCYL_PASS;
taskfile.high_cylinder = SMART_HCYL_PASS;
taskfile.command = WIN_SMART;
- (void) smart_enable(drive);
+ smart_enable(drive);
return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
}
@@ -722,7 +729,7 @@ static int get_smart_thresholds(ide_drive_t *drive, byte *buf)
taskfile.low_cylinder = SMART_LCYL_PASS;
taskfile.high_cylinder = SMART_HCYL_PASS;
taskfile.command = WIN_SMART;
- (void) smart_enable(drive);
+ smart_enable(drive);
return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
}
@@ -831,12 +838,12 @@ static int write_cache (ide_drive_t *drive, int arg)
if (!(drive->id->cfs_enable_2 & 0x3000))
return 1;
- (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
+ ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
drive->wcache = arg;
return 0;
}
-static int do_idedisk_standby (ide_drive_t *drive)
+static int idedisk_standby (ide_drive_t *drive)
{
struct hd_drive_task_hdr taskfile;
struct hd_drive_hob_hdr hobfile;
@@ -846,20 +853,6 @@ static int do_idedisk_standby (ide_drive_t *drive)
return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
}
-static int do_idedisk_flushcache (ide_drive_t *drive)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- if (drive->id->cfs_enable_2 & 0x2400) {
- taskfile.command = WIN_FLUSH_CACHE_EXT;
- } else {
- taskfile.command = WIN_FLUSH_CACHE;
- }
- return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
-}
-
static int set_acoustic (ide_drive_t *drive, int arg)
{
struct hd_drive_task_hdr taskfile;
@@ -871,7 +864,7 @@ static int set_acoustic (ide_drive_t *drive, int arg)
taskfile.sector_count = arg;
taskfile.command = WIN_SETFEATURES;
- (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
+ ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
drive->acoustic = arg;
return 0;
}
@@ -1040,72 +1033,36 @@ static void idedisk_setup(ide_drive_t *drive)
static int idedisk_cleanup (ide_drive_t *drive)
{
-
- /* FIXME: we will have to think twice whatever this is the proper place
- * to do it.
- */
-
put_device(&drive->device);
if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
- if (do_idedisk_flushcache(drive))
+ if (idedisk_flushcache(drive))
printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
drive->name);
return ide_unregister_subdriver(drive);
}
-static int idedisk_reinit(ide_drive_t *drive);
-
/*
* IDE subdriver functions, registered with ide.c
*/
static struct ata_operations idedisk_driver = {
owner: THIS_MODULE,
cleanup: idedisk_cleanup,
- standby: do_idedisk_standby,
- flushcache: do_idedisk_flushcache,
+ standby: idedisk_standby,
do_request: do_rw_disk,
end_request: NULL,
ioctl: NULL,
open: idedisk_open,
release: idedisk_release,
- media_change: idedisk_media_change,
- revalidate: ide_revalidate_drive,
+ check_media_change: idedisk_check_media_change,
+ revalidate: NULL, /* use default method */
pre_reset: idedisk_pre_reset,
capacity: idedisk_capacity,
special: idedisk_special,
- proc: idedisk_proc,
- driver_reinit: idedisk_reinit,
+ proc: idedisk_proc
};
MODULE_DESCRIPTION("ATA DISK Driver");
-static int idedisk_reinit(ide_drive_t *drive)
-{
- int failed = 0;
-
- MOD_INC_USE_COUNT;
-
- if (ide_register_subdriver (drive, &idedisk_driver)) {
- printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
- return 1;
- }
-
- ata_ops(drive)->busy++;
- idedisk_setup(drive);
- if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
- printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);
- idedisk_cleanup(drive);
- ata_ops(drive)->busy--;
- return 1;
- }
- ata_ops(drive)->busy--;
- failed--;
-
- revalidate_drives();
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
static void __exit idedisk_exit (void)
{
ide_drive_t *drive;
@@ -1136,15 +1093,12 @@ int idedisk_init (void)
printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
continue;
}
- ata_ops(drive)->busy++;
idedisk_setup(drive);
if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);
idedisk_cleanup(drive);
- ata_ops(drive)->busy--;
continue;
}
- ata_ops(drive)->busy--;
failed--;
}
revalidate_drives();
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index c1c61cb8acc6..cd5278d5fd97 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/ide-dma.c Version 4.10 June 9, 2000
- *
* Copyright (c) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* May be copied or modified under the terms of the GNU General Public License
*/
@@ -15,7 +13,7 @@
/*
* This module provides support for the bus-master IDE DMA functions
* of various PCI chipsets, including the Intel PIIX (i82371FB for
- * the 430 FX chipset), the PIIX3 (i82371SB for the 430 HX/VX and
+ * the 430 FX chipset), the PIIX3 (i82371SB for the 430 HX/VX and
* 440 chipsets), and the PIIX4 (i82371AB for the 430 TX chipset)
* ("PIIX" stands for "PCI ISA IDE Xcellerator").
*
@@ -73,8 +71,6 @@
* check_drive_lists(ide_drive_t *drive, int good_bad)
*
* ATA-66/100 and recovery functions, I forgot the rest......
- * SELECT_READ_WRITE(hwif,drive,func) for active tuning based on IO direction.
- *
*/
#include <linux/config.h>
@@ -426,7 +422,7 @@ int check_drive_lists (ide_drive_t *drive, int good_bad)
return 0;
}
-int report_drive_dmaing (ide_drive_t *drive)
+static int report_drive_dmaing (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
@@ -606,7 +602,10 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_read:
reading = 1 << 3;
case ide_dma_write:
- SELECT_READ_WRITE(hwif,drive,func);
+ /* active tuning based on IO direction */
+ if (hwif->rwproc)
+ hwif->rwproc(drive, func);
+
if (!(count = ide_build_dmatable(drive, func)))
return 1; /* try PIO instead of DMA */
outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */
@@ -617,9 +616,9 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
return 0;
#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); /* issue cmd to drive */
-#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
+#else
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */
-#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
+#endif
if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) &&
(drive->addressing == 1)) {
ide_task_t *args = HWGROUP(drive)->rq->special;
@@ -728,9 +727,8 @@ int ide_release_dma (ide_hwif_t *hwif)
}
/*
- * This can be called for a dynamically installed interface. Don't __init it
+ * This can be called for a dynamically installed interface. Don't __init it
*/
-
void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
{
printk(" %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, dma_base, dma_base + num_ports - 1);
@@ -768,81 +766,3 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
dma_alloc_failure:
printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n");
}
-
-/*
- * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
- */
-unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name)
-{
- unsigned long dma_base = 0;
- struct pci_dev *dev = hwif->pci_dev;
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
- int second_chance = 0;
-
-second_chance_to_dma:
-#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
-
- if (hwif->mate && hwif->mate->dma_base) {
- dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
- } else {
- dma_base = pci_resource_start(dev, 4);
- if (!dma_base) {
- printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base);
- dma_base = 0;
- }
- }
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
- if ((!dma_base) && (!second_chance)) {
- unsigned long set_bmiba = 0;
- second_chance++;
- switch(dev->vendor) {
- case PCI_VENDOR_ID_AL:
- set_bmiba = DEFAULT_BMALIBA; break;
- case PCI_VENDOR_ID_VIA:
- set_bmiba = DEFAULT_BMCRBA; break;
- case PCI_VENDOR_ID_INTEL:
- set_bmiba = DEFAULT_BMIBA; break;
- default:
- return dma_base;
- }
- pci_write_config_dword(dev, 0x20, set_bmiba|1);
- goto second_chance_to_dma;
- }
-#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
-
- if (dma_base) {
- if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
- request_region(dma_base+16, extra, name);
- dma_base += hwif->channel ? 8 : 0;
- hwif->dma_extra = extra;
-
- switch(dev->device) {
- case PCI_DEVICE_ID_AL_M5219:
- case PCI_DEVICE_ID_AMD_VIPER_7409:
- case PCI_DEVICE_ID_CMD_643:
- outb(inb(dma_base+2) & 0x60, dma_base+2);
- if (inb(dma_base+2) & 0x80) {
- printk("%s: simplex device: DMA forced\n", name);
- }
- break;
- default:
- /*
- * If the device claims "simplex" DMA,
- * this means only one of the two interfaces
- * can be trusted with DMA at any point in time.
- * So we should enable DMA only on one of the
- * two interfaces.
- */
- if ((inb(dma_base+2) & 0x80)) { /* simplex device? */
- if ((!hwif->drives[0].present && !hwif->drives[1].present) ||
- (hwif->mate && hwif->mate->dma_base)) {
- printk("%s: simplex device: DMA disabled\n", name);
- dma_base = 0;
- }
- }
- }
- }
- return dma_base;
-}
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 24de2a826a96..a10c9d99aea9 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1113,7 +1113,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
pc->retries++;
pc->actually_transferred=0; /* We haven't transferred any data yet */
pc->current_position=pc->buffer;
- bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024);
+ bcount.all = min(pc->request_transfer, 63 * 1024);
#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
@@ -1819,10 +1819,10 @@ static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive
/*
* Check media change. Use a simple algorithm for now.
*/
-static int idefloppy_media_change (ide_drive_t *drive)
+static int idefloppy_check_media_change (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
-
+
return test_and_clear_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
}
@@ -2038,8 +2038,6 @@ static ide_proc_entry_t idefloppy_proc[] = {
#endif /* CONFIG_PROC_FS */
-static int idefloppy_reinit(ide_drive_t *drive);
-
/*
* IDE subdriver functions, registered with ide.c
*/
@@ -2047,58 +2045,19 @@ static struct ata_operations idefloppy_driver = {
owner: THIS_MODULE,
cleanup: idefloppy_cleanup,
standby: NULL,
- flushcache: NULL,
do_request: idefloppy_do_request,
end_request: idefloppy_end_request,
ioctl: idefloppy_ioctl,
open: idefloppy_open,
release: idefloppy_release,
- media_change: idefloppy_media_change,
- revalidate: ide_revalidate_drive,
+ check_media_change: idefloppy_check_media_change,
+ revalidate: NULL, /* use default method */
pre_reset: NULL,
capacity: idefloppy_capacity,
special: NULL,
- proc: idefloppy_proc,
- driver_reinit: idefloppy_reinit,
+ proc: idefloppy_proc
};
-static int idefloppy_reinit (ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy;
- int failed = 0;
-
- MOD_INC_USE_COUNT;
- while ((drive = ide_scan_devices(ATA_FLOPPY, "ide-floppy", NULL, failed++)) != NULL) {
- if (!idefloppy_identify_device (drive, drive->id)) {
- printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name);
- continue;
- }
- if (drive->scsi) {
- printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
- continue;
- }
- if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
- printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
- continue;
- }
- if (ide_register_subdriver (drive, &idefloppy_driver)) {
- printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
- kfree (floppy);
- continue;
- }
-
- /* ATA-PATTERN */
- ata_ops(drive)->busy++;
- idefloppy_setup (drive, floppy);
- ata_ops(drive)->busy--;
-
- failed--;
- }
- revalidate_drives();
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
static void __exit idefloppy_exit (void)
diff --git a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c
index fc38389c53a6..7a203365420a 100644
--- a/drivers/ide/ide-geometry.c
+++ b/drivers/ide/ide-geometry.c
@@ -14,14 +14,14 @@
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
extern ide_drive_t * get_info_ptr(kdev_t);
-extern unsigned long current_capacity (ide_drive_t *);
/*
* If heads is nonzero: find a translation with this many heads and S=63.
* Otherwise: find out how OnTrack Disk Manager would translate the disk.
*/
static void
-ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) {
+ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s)
+{
static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
const byte *headp = dm_head_vals;
unsigned long total;
@@ -34,7 +34,7 @@ ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) {
* computes a geometry different from what OnTrack uses.]
*/
- total = ata_ops(drive)->capacity(drive);
+ total = ata_capacity(drive);
*s = 63;
@@ -136,7 +136,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg)
ret = 1;
}
- drive->part[0].nr_sects = current_capacity(drive);
+ drive->part[0].nr_sects = ata_capacity(drive);
if (ret)
printk("%s%s [%d/%d/%d]", msg, msg1,
diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
index f93985160bff..27c2050ff878 100644
--- a/drivers/ide/ide-pci.c
+++ b/drivers/ide/ide-pci.c
@@ -1,9 +1,7 @@
/*
- * linux/drivers/ide/ide-pci.c Version 1.05 June 9, 2000
- *
* Copyright (c) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *
* Copyright (c) 1995-1998 Mark Lord
+ *
* May be copied or modified under the terms of the GNU General Public License
*/
@@ -168,9 +166,9 @@ extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long);
#endif
typedef struct ide_pci_enablebit_s {
- byte reg; /* byte pci reg holding the enable-bit */
- byte mask; /* mask to isolate the enable-bit */
- byte val; /* value of masked reg when "enabled" */
+ u8 reg; /* pci configuration register holding the enable-bit */
+ u8 mask; /* mask used to isolate the enable-bit */
+ u8 val; /* expected value of masked register when "enabled" */
} ide_pci_enablebit_t;
/* Flags used to untangle quirk handling.
@@ -230,9 +228,10 @@ static ide_pci_device_t pci_chipsets[] __initdata = {
{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48, ATA_F_IRQ | ATA_F_DMA },
# endif
{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
- /* Promise used a different PCI ident for the raid card apparently to try and
- prevent Linux detecting it and using our own raid code. We want to detect
- it for the ataraid drivers, so we have to list both here.. */
+ /* Promise used a different PCI identification for the raid card
+ * apparently to try and prevent Linux detecting it and using our own
+ * raid code. We want to detect it for the ataraid drivers, so we have
+ * to list both here.. */
{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
@@ -303,7 +302,9 @@ static ide_pci_device_t pci_chipsets[] __initdata = {
#ifdef CONFIG_BLK_DEV_IT8172
{PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G, pci_init_it8172, NULL, ide_init_it8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0, 0 },
#endif
- /* Those are id's of chips we don't deal currently with. */
+ /* Those are id's of chips we don't deal currently with,
+ * but which still need some generic quirk handling.
+ */
{PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
{PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
{PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0, 0 },
@@ -313,10 +314,11 @@ static ide_pci_device_t pci_chipsets[] __initdata = {
{PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_FIXIRQ },
{PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_FIXIRQ },
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, ATA_F_NOADMA },
+ {PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, NULL, NULL, IDE_NO_DRIVER, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240, ATA_F_IRQ | ATA_F_HPTHACK },
{0, 0, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }};
/*
- * This allows offboard ide-pci cards the enable a BIOS, verify interrupt
+ * This allows off board ide-pci cards the enable a BIOS, verify interrupt
* settings of split-mirror pci-config space, place chipset into init-mode,
* and/or preserve an interrupt if the card is not native ide support.
*/
@@ -332,7 +334,7 @@ static unsigned int __init trust_pci_irq(ide_pci_device_t *d, struct pci_dev *de
* Match a PCI IDE port against an entry in ide_hwifs[],
* based on io_base port if possible.
*/
-static ide_hwif_t __init *lookup_hwif (unsigned long io_base, byte bootable, const char *name)
+static ide_hwif_t __init *lookup_hwif (unsigned long io_base, int bootable, const char *name)
{
int h;
ide_hwif_t *hwif;
@@ -396,7 +398,8 @@ static ide_hwif_t __init *lookup_hwif (unsigned long io_base, byte bootable, con
static int __init setup_pci_baseregs (struct pci_dev *dev, const char *name)
{
- byte reg, progif = 0;
+ u8 reg;
+ u8 progif = 0;
/*
* Place both IDE interfaces into PCI "native" mode:
@@ -428,10 +431,111 @@ static int __init setup_pci_baseregs (struct pci_dev *dev, const char *name)
return 0;
}
+#ifdef CONFIG_BLK_DEV_IDEDMA
+
+/*
+ * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
+ */
+static unsigned long __init get_dma_base(ide_hwif_t *hwif, int extra, const char *name)
+{
+ unsigned long dma_base = 0;
+ struct pci_dev *dev = hwif->pci_dev;
+
+ /*
+ * If we are on the second channel, the dma base address will be one
+ * entry away from the primary interface.
+ */
+
+ if (hwif->mate && hwif->mate->dma_base)
+ dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
+ else
+ dma_base = pci_resource_start(dev, 4);
+
+ if (!dma_base)
+ return 0;
+
+ if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
+ request_region(dma_base + 16, extra, name);
+
+ dma_base += hwif->channel ? 8 : 0;
+ hwif->dma_extra = extra;
+
+ if ((dev->vendor == PCI_VENDOR_ID_AL && dev->device == PCI_DEVICE_ID_AL_M5219) ||
+ (dev->vendor == PCI_VENDOR_ID_AMD && dev->device == PCI_DEVICE_ID_AMD_VIPER_7409) ||
+ (dev->vendor == PCI_VENDOR_ID_CMD && dev->device == PCI_DEVICE_ID_CMD_643)) {
+ outb(inb(dma_base + 2) & 0x60, dma_base+2);
+ if (inb(dma_base + 2) & 0x80)
+ printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
+ } else {
+
+ /*
+ * If the device claims "simplex" DMA, this means only one of
+ * the two interfaces can be trusted with DMA at any point in
+ * time. So we should enable DMA only on one of the two
+ * interfaces.
+ */
+
+ if ((inb(dma_base + 2) & 0x80)) {
+ if ((!hwif->drives[0].present && !hwif->drives[1].present) ||
+ (hwif->mate && hwif->mate->dma_base)) {
+ printk("%s: simplex device: DMA disabled\n", name);
+ dma_base = 0;
+ }
+ }
+ }
+
+ return dma_base;
+}
+
+/*
+ * Setup DMA transfers on a channel.
+ */
+static void __init setup_channel_dma(ide_hwif_t *hwif, struct pci_dev *dev,
+ ide_pci_device_t *d,
+ int port,
+ u8 class_rev,
+ int pciirq, ide_hwif_t **mate,
+ int autodma, unsigned short *pcicmd)
+{
+ unsigned long dma_base;
+
+ if (d->flags & ATA_F_NOADMA)
+ autodma = 0;
+
+ if (autodma)
+ hwif->autodma = 1;
+
+ if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
+ return;
+
+ dma_base = get_dma_base(hwif, (!*mate && d->extra) ? d->extra : 0, dev->name);
+ if (dma_base && !(*pcicmd & PCI_COMMAND_MASTER)) {
+
+ /*
+ * Set up BM-DMA capability (PnP BIOS should have done this already)
+ */
+ if (!(d->vendor == PCI_VENDOR_ID_CYRIX && d->device == PCI_DEVICE_ID_CYRIX_5530_IDE))
+ hwif->autodma = 0; /* default DMA off if we had to configure it here */
+ pci_write_config_word(dev, PCI_COMMAND, *pcicmd | PCI_COMMAND_MASTER);
+ if (pci_read_config_word(dev, PCI_COMMAND, pcicmd) || !(*pcicmd & PCI_COMMAND_MASTER)) {
+ printk("%s: %s error updating PCICMD\n", hwif->name, dev->name);
+ dma_base = 0;
+ }
+ }
+ if (dma_base) {
+ if (d->dma_init)
+ d->dma_init(hwif, dma_base);
+ else
+ ide_setup_dma(hwif, dma_base, 8);
+ } else
+ printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
+}
+#endif
+
/*
* Setup a particular port on an ATA host controller.
*
- * This get's called once for the master and for the slave interface.
+ * This gets called once for the master and for the slave interface.
*/
static int __init setup_host_channel(struct pci_dev *dev,
ide_pci_device_t *d,
@@ -525,9 +629,9 @@ controller_ok:
}
}
- /* Hard wired IRQ lines on UMC chips and no DMA transfers.*/
+ /* Cross wired IRQ lines on UMC chips and no DMA transfers.*/
if (d->flags & ATA_F_FIXIRQ) {
- hwif->irq = hwif->channel ? 15 : 14;
+ hwif->irq = port ? 15 : 14;
goto no_dma;
}
if (d->flags & ATA_F_NODMA)
@@ -540,53 +644,22 @@ controller_ok:
if (d->ata66_check)
hwif->udma_four = d->ata66_check(hwif);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (d->flags & ATA_F_NOADMA)
- autodma = 0;
-
- if (autodma)
- hwif->autodma = 1;
-
- if ((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
- unsigned long dma_base;
-
- dma_base = ide_get_or_set_dma_base(hwif, (!*mate && d->extra) ? d->extra : 0, dev->name);
- if (dma_base && !(*pcicmd & PCI_COMMAND_MASTER)) {
- /*
- * Set up BM-DMA capability (PnP BIOS should have done this already)
- */
- if (!(d->vendor == PCI_VENDOR_ID_CYRIX && d->device == PCI_DEVICE_ID_CYRIX_5530_IDE))
- hwif->autodma = 0; /* default DMA off if we had to configure it here */
- pci_write_config_word(dev, PCI_COMMAND, *pcicmd | PCI_COMMAND_MASTER);
- if (pci_read_config_word(dev, PCI_COMMAND, pcicmd) || !(*pcicmd & PCI_COMMAND_MASTER)) {
- printk("%s: %s error updating PCICMD\n", hwif->name, dev->name);
- dma_base = 0;
- }
- }
- if (dma_base) {
- if (d->dma_init)
- d->dma_init(hwif, dma_base);
- else /* FIXME: use a generic device descriptor instead */
- ide_setup_dma(hwif, dma_base, 8);
- } else {
- printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
- }
- }
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ setup_channel_dma(hwif, dev, d, port, class_rev, pciirq, mate, autodma, pcicmd);
#endif
+
no_dma:
if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */
d->init_hwif(hwif);
*mate = hwif;
- /* we are done */
-
return 0;
}
/*
- * Looks at the primary/secondary chanells on a PCI IDE device and, if they
+ * Looks at the primary/secondary channels on a PCI IDE device and, if they
* are enabled, prepares the IDE driver for use with them. This generic code
* works for most PCI chipsets.
*
@@ -628,10 +701,11 @@ check_if_enabled:
if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */
/*
* PnP BIOS was *supposed* to have set this device up for us,
- * but we can do it ourselves, so long as the BIOS has assigned an IRQ
- * (or possibly the device is using a "legacy header" for IRQs).
- * Maybe the user deliberately *disabled* the device,
- * but we'll eventually ignore it again if no drives respond.
+ * but we can do it ourselves, so long as the BIOS has assigned
+ * an IRQ (or possibly the device is using a "legacy header"
+ * for IRQs). Maybe the user deliberately *disabled* the
+ * device, but we'll eventually ignore it again if no drives
+ * respond.
*/
if (tried_config++
|| setup_pci_baseregs(dev, dev->name)
@@ -663,7 +737,7 @@ check_if_enabled:
if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) {
/* By rights we want to ignore these, but the Promise Fastrak
people have some strange ideas about proprietary so we have
- to act otherwise on those. The supertrak however we need
+ to act otherwise on those. The Supertrak however we need
to skip */
if (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) {
printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n");
@@ -680,7 +754,7 @@ check_if_enabled:
if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
printk("%s: not 100%% native mode: will probe irqs later\n", dev->name);
/*
- * This allows offboard ide-pci cards the enable a BIOS,
+ * This allows off board ide-pci cards the enable a BIOS,
* verify interrupt settings of split-mirror pci-config
* space, place chipset into init-mode, and/or preserve
* an interrupt if the card is not native ide support.
@@ -690,10 +764,10 @@ check_if_enabled:
else
pciirq = trust_pci_irq(d, dev);
} else if (tried_config) {
- printk("%s: will probe irqs later\n", dev->name);
+ printk("%s: will probe IRQs later\n", dev->name);
pciirq = 0;
} else if (!pciirq) {
- printk("%s: bad irq (%d): will probe later\n", dev->name, pciirq);
+ printk("%s: bad IRQ (%d): will probe later\n", dev->name, pciirq);
pciirq = 0;
} else {
if (d->init_chipset)
@@ -729,7 +803,8 @@ static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_dev
if ((findev->vendor == dev->vendor) &&
(findev->device == dev->device) &&
(PCI_SLOT(findev->devfn) & 2)) {
- byte irq = 0, irq2 = 0;
+ u8 irq = 0;
+ u8 irq2 = 0;
dev2 = findev;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2);
@@ -805,7 +880,7 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
}
/*
- * This finds all PCI IDE controllers and calls appriopriate initialization
+ * This finds all PCI IDE controllers and calls appropriate initialization
* functions for them.
*/
static void __init ide_scan_pcidev(struct pci_dev *dev)
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 37fbf82d2dc2..a4616ae26bca 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1,10 +1,6 @@
/*
- * linux/drivers/ide/ide-probe.c Version 1.07 March 18, 2001
- *
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- */
-
-/*
+ *
* Mostly written by Mark Lord <mlord@pobox.com>
* and Gadi Oxman <gadio@netvision.net.il>
* and Andre Hedrick <andre@linux-ide.org>
@@ -26,11 +22,9 @@
* with new flag : drive->ata_flash : 1;
* Version 1.06 stream line request queue and prep for cascade project.
* Version 1.07 max_sect <= 255; slower disks would get behind and
- * then fall over when they get to 256. Paul G.
+ * then fall over when they get to 256. Paul G.
*/
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -94,7 +88,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
goto err_misc;
}
-#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */
+#endif
/*
* WIN_IDENTIFY returns little-endian info,
@@ -128,7 +122,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
printk(" -- not supported on 2nd Promise port\n");
goto err_misc;
}
-#endif /* CONFIG_BLK_DEV_PDC4030 */
+#endif
switch (type) {
case ATA_FLOPPY:
if (!strstr(id->model, "CD-ROM")) {
@@ -186,7 +180,11 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
}
drive->type = ATA_DISK;
printk("ATA DISK drive\n");
- QUIRK_LIST(HWIF(drive),drive);
+
+ /* Initialize our quirk list. */
+ if (HWIF(drive)->quirkproc)
+ drive->quirk_list = HWIF(drive)->quirkproc(drive);
+
return;
err_misc:
@@ -282,24 +280,15 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
if (autoprobe) {
int irq;
- OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
- (void) GET_STAT(); /* clear drive IRQ */
+ OUT_BYTE(drive->ctl | 0x02, IDE_CONTROL_REG); /* mask device irq */
+ GET_STAT(); /* clear drive IRQ */
udelay(5);
irq = probe_irq_off(cookie);
if (!HWIF(drive)->irq) {
- if (irq > 0) {
+ if (irq > 0)
HWIF(drive)->irq = irq;
- } else { /* Mmmm.. multiple IRQs.. don't know which was ours */
+ else /* Mmmm.. multiple IRQs.. don't know which was ours */
printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie);
-#ifdef CONFIG_BLK_DEV_CMD640
-#ifdef CMD640_DUMP_REGS
- if (HWIF(drive)->chipset == ide_cmd640) {
- printk("%s: Hmmm.. probably a driver problem.\n", drive->name);
- CMD640_DUMP_REGS;
- }
-#endif /* CMD640_DUMP_REGS */
-#endif /* CONFIG_BLK_DEV_CMD640 */
- }
}
}
return retval;
@@ -471,9 +460,11 @@ static void hwif_register (ide_hwif_t *hwif)
sprintf(hwif->device.bus_id, "%04x", hwif->io_ports[IDE_DATA_OFFSET]);
sprintf(hwif->device.name, "ide");
hwif->device.driver_data = hwif;
+#ifdef CONFIG_BLK_DEV_IDEPCI
if (hwif->pci_dev)
hwif->device.parent = &hwif->pci_dev->dev;
else
+#endif
hwif->device.parent = NULL; /* Would like to do = &device_legacy */
device_register(&hwif->device);
@@ -520,11 +511,11 @@ static void probe_hwif (ide_hwif_t *hwif)
if (hwif->noprobe)
return;
- if ((hwif->chipset != ide_4drives || !hwif->mate->present) &&
+ if (
#if CONFIG_BLK_DEV_PDC4030
(hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- (hwif_check_regions(hwif))) {
+#endif
+ hwif_check_regions(hwif)) {
int msgout = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
@@ -550,9 +541,7 @@ static void probe_hwif (ide_hwif_t *hwif)
probe_for_drive (drive);
if (drive->present && !hwif->present) {
hwif->present = 1;
- if (hwif->chipset != ide_4drives || !hwif->mate->present) {
- hwif_register(hwif);
- }
+ hwif_register(hwif);
}
}
if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
@@ -580,32 +569,6 @@ static void probe_hwif (ide_hwif_t *hwif)
}
}
-#if MAX_HWIFS > 1
-/*
- * save_match() is used to simplify logic in init_irq() below.
- *
- * A loophole here is that we may not know about a particular
- * hwif's irq until after that hwif is actually probed/initialized..
- * This could be a problem for the case where an hwif is on a
- * dual interface that requires serialization (eg. cmd640) and another
- * hwif using one of the same irqs is initialized beforehand.
- *
- * This routine detects and reports such situations, but does not fix them.
- */
-static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
-{
- ide_hwif_t *m = *match;
-
- if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
- if (!new->hwgroup)
- return;
- printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name);
- }
- if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
- *match = new;
-}
-#endif /* MAX_HWIFS > 1 */
-
/*
* init request queue
*/
@@ -634,6 +597,33 @@ static void ide_init_queue(ide_drive_t *drive)
blk_queue_max_phys_segments(q, PRD_ENTRIES);
}
+#if MAX_HWIFS > 1
+
+/*
+ * This is used to simplify logic in init_irq() below.
+ *
+ * A loophole here is that we may not know about a particular hwif's irq until
+ * after that hwif is actually probed/initialized.. This could be a problem
+ * for the case where an hwif is on a dual interface that requires
+ * serialization (eg. cmd640) and another hwif using one of the same irqs is
+ * initialized beforehand.
+ *
+ * This routine detects and reports such situations, but does not fix them.
+ */
+static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
+{
+ ide_hwif_t *m = *match;
+
+ if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
+ if (!new->hwgroup)
+ return;
+ printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name);
+ }
+ if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
+ *match = new;
+}
+#endif
+
/*
* This routine sets up the irq for an ide interface, and creates a new
* hwgroup for the irq/hwif if none was previously assigned.
@@ -654,15 +644,14 @@ static int init_irq (ide_hwif_t *hwif)
ide_hwgroup_t *hwgroup, *new_hwgroup;
ide_hwif_t *match = NULL;
-
+
/* Allocate the buffer and potentially sleep first */
-
+
new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
-
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
+ spin_lock_irqsave(&ide_lock, flags);
hwif->hwgroup = NULL;
+
#if MAX_HWIFS > 1
/*
* Group up with any other hwifs that share our irq(s).
@@ -672,9 +661,8 @@ static int init_irq (ide_hwif_t *hwif)
if (h->hwgroup) { /* scan only initialized hwif's */
if (hwif->irq == h->irq) {
hwif->sharing_irq = h->sharing_irq = 1;
- if (hwif->chipset != ide_pci || h->chipset != ide_pci) {
+ if (hwif->chipset != ide_pci || h->chipset != ide_pci)
save_match(hwif, h, &match);
- }
}
if (hwif->serialized) {
if (hwif->mate && hwif->mate->irq == h->irq)
@@ -686,7 +674,7 @@ static int init_irq (ide_hwif_t *hwif)
}
}
}
-#endif /* MAX_HWIFS > 1 */
+#endif
/*
* If we are still without a hwgroup, then form a new one
*/
@@ -697,7 +685,7 @@ static int init_irq (ide_hwif_t *hwif)
} else {
hwgroup = new_hwgroup;
if (!hwgroup) {
- restore_flags(flags); /* all CPUs */
+ spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
memset(hwgroup, 0, sizeof(ide_hwgroup_t));
@@ -717,9 +705,9 @@ static int init_irq (ide_hwif_t *hwif)
if (!match || match->irq != hwif->irq) {
#ifdef CONFIG_IDEPCI_SHARE_IRQ
int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_SHIRQ : SA_INTERRUPT;
-#else /* !CONFIG_IDEPCI_SHARE_IRQ */
+#else
int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
+#endif
if (hwif->io_ports[IDE_CONTROL_OFFSET])
OUT_BYTE(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); /* clear nIEN */
@@ -727,13 +715,13 @@ static int init_irq (ide_hwif_t *hwif)
if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) {
if (!match)
kfree(hwgroup);
- restore_flags(flags); /* all CPUs */
+ spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
}
/*
- * Everything is okay, so link us into the hwgroup
+ * Everything is okay, so link us into the hwgroup.
*/
hwif->hwgroup = hwgroup;
hwif->next = hwgroup->hwif->next;
@@ -755,7 +743,7 @@ static int init_irq (ide_hwif_t *hwif)
printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
#endif
}
- restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */
+ spin_unlock_irqrestore(&ide_lock, flags);
#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 468d91c2ac1c..0891bcc1e2c4 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -161,7 +161,6 @@ static int proc_ide_read_imodel
case ide_trm290: name = "trm290"; break;
case ide_cmd646: name = "cmd646"; break;
case ide_cy82c693: name = "cy82c693"; break;
- case ide_4drives: name = "4drives"; break;
case ide_pmac: name = "mac-io"; break;
default: name = "(unknown)"; break;
}
@@ -298,8 +297,8 @@ static int proc_ide_write_settings
}
if (*p != ':')
goto parse_error;
- len = IDE_MIN(p - start, MAX_LEN);
- strncpy(name, start, IDE_MIN(len, MAX_LEN));
+ len = min(p - start, MAX_LEN);
+ strncpy(name, start, min(len, MAX_LEN));
name[len] = 0;
if (n > 0) {
@@ -307,7 +306,7 @@ static int proc_ide_write_settings
p++;
} else
goto parse_error;
-
+
digits = 0;
while (n > 0 && (d = ide_getdigit(*p)) >= 0) {
val = (val * 10) + d;
@@ -353,7 +352,7 @@ int proc_ide_read_capacity
if (!driver)
len = sprintf(page, "(none)\n");
else
- len = sprintf(page,"%llu\n", (unsigned long long) drive->driver->capacity(drive));
+ len = sprintf(page,"%llu\n", (unsigned long long) ata_capacity(drive));
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index e5d85ae7d381..1a35a4f69663 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1504,7 +1504,7 @@ static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigne
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDE_MIN (bio->bi_size - pc->b_count, bcount);
+ count = min(bio->bi_size - pc->b_count, bcount);
atapi_input_bytes (drive, bio_data(bio) + pc->b_count, count);
bcount -= count;
pc->b_count += bio->bi_size;
@@ -1529,7 +1529,7 @@ static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsign
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDE_MIN (pc->b_count, bcount);
+ count = min(pc->b_count, bcount);
atapi_output_bytes (drive, bio_data(bio), count);
bcount -= count;
pc->b_data += count;
@@ -1559,7 +1559,7 @@ static void idetape_update_buffers (idetape_pc_t *pc)
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDE_MIN (bio->bi_size, bcount);
+ count = min(bio->bi_size, bcount);
pc->b_count = count;
if (pc->b_count == bio->bi_size)
bio = bio->bi_next;
@@ -1759,8 +1759,8 @@ static void idetape_increase_max_pipeline_stages (ide_drive_t *drive)
#endif /* IDETAPE_DEBUG_LOG */
tape->max_stages += increase;
- tape->max_stages = IDE_MAX(tape->max_stages, tape->min_pipeline);
- tape->max_stages = IDE_MIN(tape->max_stages, tape->max_pipeline);
+ tape->max_stages = max(tape->max_stages, tape->min_pipeline);
+ tape->max_stages = min(tape->max_stages, tape->max_pipeline);
}
/*
@@ -2084,7 +2084,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
if (!status.b.drq) { /* No more interrupts */
cmd_time = (jiffies - tape->cmd_start_time) * 1000 / HZ;
- tape->max_cmd_time = IDE_MAX(cmd_time, tape->max_cmd_time);
+ tape->max_cmd_time = max(cmd_time, tape->max_cmd_time);
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 2)
printk (KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
@@ -2442,7 +2442,7 @@ static void calculate_speeds(ide_drive_t *drive)
tape->uncontrolled_pipeline_head_time = jiffies;
}
}
- tape->pipeline_head_speed = IDE_MAX(tape->uncontrolled_pipeline_head_speed, tape->controlled_pipeline_head_speed);
+ tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed, tape->controlled_pipeline_head_speed);
if (tape->speed_control == 0) {
tape->max_insert_speed = 5000;
} else if (tape->speed_control == 1) {
@@ -2459,7 +2459,7 @@ static void calculate_speeds(ide_drive_t *drive)
(tape->pipeline_head_speed * full / 100 - tape->pipeline_head_speed * empty / 100) * tape->nr_pending_stages / tape->max_stages;
} else
tape->max_insert_speed = tape->speed_control;
- tape->max_insert_speed = IDE_MAX(tape->max_insert_speed, 500);
+ tape->max_insert_speed = max(tape->max_insert_speed, 500);
}
static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
@@ -2920,7 +2920,7 @@ static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDE_MIN (bio->bi_size - tape->b_count, n);
+ count = min(bio->bi_size - tape->b_count, n);
copy_from_user (bio_data(bio) + tape->b_count, buf, count);
n -= count;
bio->bi_size += count;
@@ -2946,7 +2946,7 @@ static void idetape_copy_stage_to_user (idetape_tape_t *tape, char *buf, idetape
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDE_MIN (tape->b_count, n);
+ count = min(tape->b_count, n);
copy_to_user (buf, tape->b_data, count);
n -= count;
tape->b_data += count;
@@ -3878,7 +3878,7 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
printk(KERN_INFO "ide-tape: bug, bio NULL\n");
break;
}
- min = IDE_MIN(i, bio->bi_size - atomic_read(&bio->bi_cnt));
+ min = min(i, bio->bi_size - atomic_read(&bio->bi_cnt));
memset(bio_data(bio) + bio->bi_size, 0, min);
atomic_add(min, &bio->bi_cnt);
i -= min;
@@ -4149,11 +4149,11 @@ static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
while (bcount) {
bio = tape->merge_stage->bio;
- count = IDE_MIN (tape->stage_size, bcount);
+ count = min(tape->stage_size, bcount);
bcount -= count;
blocks = count / tape->tape_block_size;
while (count) {
- atomic_set(&bio->bi_cnt, IDE_MIN (count, bio->bi_size));
+ atomic_set(&bio->bi_cnt, min(count, bio->bi_size));
memset (bio_data(bio), 0, bio->bi_size);
count -= atomic_read(&bio->bi_cnt);
bio = bio->bi_next;
@@ -4596,7 +4596,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char *buf,
if (count == 0)
return (0);
if (tape->merge_stage_size) {
- actually_read = IDE_MIN (tape->merge_stage_size, count);
+ actually_read = min(tape->merge_stage_size, count);
idetape_copy_stage_to_user (tape, buf, tape->merge_stage, actually_read);
buf += actually_read;
tape->merge_stage_size -= actually_read;
@@ -4615,7 +4615,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char *buf,
bytes_read=idetape_add_chrdev_read_request (drive, tape->capabilities.ctl);
if (bytes_read <= 0)
goto finish;
- temp = IDE_MIN (count, bytes_read);
+ temp = min(count, bytes_read);
idetape_copy_stage_to_user (tape, buf, tape->merge_stage, temp);
actually_read += temp;
tape->merge_stage_size = bytes_read-temp;
@@ -4890,7 +4890,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char *buf,
tape->merge_stage_size = 0;
}
#endif /* IDETAPE_DEBUG_BUGS */
- actually_written = IDE_MIN (tape->stage_size - tape->merge_stage_size, count);
+ actually_written = min(tape->stage_size - tape->merge_stage_size, count);
idetape_copy_stage_from_user (tape, tape->merge_stage, buf, actually_written);
buf += actually_written;
tape->merge_stage_size += actually_written;
@@ -6049,7 +6049,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
* Select the "best" DSC read/write polling frequency
* and pipeline size.
*/
- speed = IDE_MAX (tape->capabilities.speed, tape->capabilities.max_speed);
+ speed = max(tape->capabilities.speed, tape->capabilities.max_speed);
tape->max_stages = speed * 1000 * 10 / tape->stage_size;
@@ -6075,7 +6075,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
* Ensure that the number we got makes sense; limit
* it within IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
*/
- tape->best_dsc_rw_frequency = IDE_MAX (IDE_MIN (t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
+ tape->best_dsc_rw_frequency = max(min(t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
printk (KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, %dkB pipeline, %lums tDSC%s\n",
drive->name, tape->name, tape->capabilities.speed, (tape->capabilities.buffer_size * 512) / tape->stage_size,
tape->stage_size / 1024, tape->max_stages * tape->stage_size / 1024,
@@ -6140,7 +6140,12 @@ static ide_proc_entry_t idetape_proc[] = {
#endif
-static int idetape_reinit(ide_drive_t *drive);
+static void idetape_revalidate(ide_drive_t *_dummy)
+{
+ /* We don't have to handle any partition information here, which is the
+ * default behaviour of this method.
+ */
+}
/*
* IDE subdriver functions, registered with ide.c
@@ -6149,18 +6154,16 @@ static struct ata_operations idetape_driver = {
owner: THIS_MODULE,
cleanup: idetape_cleanup,
standby: NULL,
- flushcache: NULL,
do_request: idetape_do_request,
end_request: idetape_end_request,
ioctl: idetape_blkdev_ioctl,
open: idetape_blkdev_open,
release: idetape_blkdev_release,
- media_change: NULL,
- revalidate: NULL,
+ check_media_change: NULL,
+ revalidate: idetape_revalidate,
pre_reset: idetape_pre_reset,
capacity: NULL,
- proc: idetape_proc,
- driver_reinit: idetape_reinit,
+ proc: idetape_proc
};
/*
@@ -6175,12 +6178,6 @@ static struct file_operations idetape_fops = {
release: idetape_chrdev_release,
};
-/* This will propably just go entierly away... */
-static int idetape_reinit (ide_drive_t *drive)
-{
- return 1;
-}
-
MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 75fa398fc363..138d5e7fdae7 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -1,12 +1,8 @@
/*
- * linux/drivers/ide/ide-taskfile.c Version 0.20 Oct 11, 2000
- *
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
*
* May be copied or modified under the terms of the GNU General Public License
- *
- * IDE_DEBUG(__LINE__);
*/
#include <linux/config.h>
@@ -48,7 +44,7 @@
static inline char *ide_map_rq(struct request *rq, unsigned long *flags)
{
if (rq->bio)
- return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq);
+ return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq);
else
return rq->buffer + task_rq_offset(rq);
}
@@ -60,13 +56,6 @@ static inline void ide_unmap_rq(struct request *rq, char *to,
bio_kunmap_irq(to, flags);
}
-inline u32 task_read_24 (ide_drive_t *drive)
-{
- return (IN_BYTE(IDE_HCYL_REG)<<16) |
- (IN_BYTE(IDE_LCYL_REG)<<8) |
- IN_BYTE(IDE_SECTOR_REG);
-}
-
static void ata_bswap_data (void *buffer, int wcount)
{
u16 *p = buffer;
@@ -85,12 +74,13 @@ static void ata_bswap_data (void *buffer, int wcount)
* of the sector count register location, with interrupts disabled
* to ensure that the reads all happen together.
*/
-static inline void task_vlb_sync (ide_ioreg_t port) {
- (void) IN_BYTE (port);
- (void) IN_BYTE (port);
- (void) IN_BYTE (port);
+static inline void task_vlb_sync(ide_ioreg_t port)
+{
+ IN_BYTE (port);
+ IN_BYTE (port);
+ IN_BYTE (port);
}
-#endif /* SUPPORT_VLB_SYNC */
+#endif
/*
* This is used for most PIO data transfers *from* the IDE interface
@@ -121,7 +111,7 @@ void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
insl(IDE_DATA_REG, buffer, wcount);
__restore_flags(flags); /* local CPU only */
} else
-#endif /* SUPPORT_VLB_SYNC */
+#endif
insl(IDE_DATA_REG, buffer, wcount);
} else {
#if SUPPORT_SLOW_DATA_PORTS
@@ -132,7 +122,7 @@ void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
*ptr++ = inw_p(IDE_DATA_REG);
}
} else
-#endif /* SUPPORT_SLOW_DATA_PORTS */
+#endif
insw(IDE_DATA_REG, buffer, wcount<<1);
}
}
@@ -161,7 +151,7 @@ void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
outsl(IDE_DATA_REG, buffer, wcount);
__restore_flags(flags); /* local CPU only */
} else
-#endif /* SUPPORT_VLB_SYNC */
+#endif
outsl(IDE_DATA_REG, buffer, wcount);
} else {
#if SUPPORT_SLOW_DATA_PORTS
@@ -172,7 +162,7 @@ void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
outw_p(*ptr++, IDE_DATA_REG);
}
} else
-#endif /* SUPPORT_SLOW_DATA_PORTS */
+#endif
outsw(IDE_DATA_REG, buffer, wcount<<1);
}
}
@@ -273,7 +263,90 @@ int drive_is_ready (ide_drive_t *drive)
return 1; /* drive ready: *might* be interrupting */
}
-ide_startstop_t bio_mulout_intr (ide_drive_t *drive);
+/*
+ * Polling wait until the drive is ready.
+ *
+ * Stuff the first sector(s) by implicitly calling the handler driectly
+ * therafter.
+ */
+void ata_poll_drive_ready(ide_drive_t *drive)
+{
+ int i;
+
+
+ if (drive_is_ready(drive))
+ return;
+
+ /* FIXME: Replace hard-coded 100, what about error handling?
+ */
+ for (i = 0; i < 100; ++i) {
+ if (drive_is_ready(drive))
+ break;
+ }
+}
+static ide_startstop_t bio_mulout_intr(ide_drive_t *drive);
+
+/*
+ * Handler for command write multiple
+ * Called directly from execute_drive_cmd for the first bunch of sectors,
+ * afterwards only by the ISR
+ */
+static ide_startstop_t task_mulout_intr (ide_drive_t *drive)
+{
+ unsigned int msect, nsect;
+ byte stat = GET_STAT();
+ byte io_32bit = drive->io_32bit;
+ struct request *rq = HWGROUP(drive)->rq;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ char *pBuf = NULL;
+ unsigned long flags;
+
+ /*
+ * (ks/hs): Handle last IRQ on multi-sector transfer,
+ * occurs after all data was sent in this chunk
+ */
+ if (rq->current_nr_sectors == 0) {
+ if (stat & (ERR_STAT|DRQ_STAT))
+ return ide_error(drive, "task_mulout_intr", stat);
+
+ /*
+ * there may be more, ide_do_request will restart it if
+ * necessary
+ */
+ ide_end_request(drive, 1);
+ return ide_stopped;
+ }
+
+ if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
+ if (stat & (ERR_STAT|DRQ_STAT)) {
+ return ide_error(drive, "task_mulout_intr", stat);
+ }
+ /* no data yet, so wait for another interrupt */
+ if (hwgroup->handler == NULL)
+ ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
+ return ide_started;
+ }
+
+ /* (ks/hs): See task_mulin_intr */
+ msect = drive->mult_count;
+ nsect = rq->current_nr_sectors;
+ if (nsect > msect)
+ nsect = msect;
+
+ pBuf = ide_map_rq(rq, &flags);
+ DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
+ pBuf, nsect, rq->current_nr_sectors);
+ drive->io_32bit = 0;
+ taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
+ ide_unmap_rq(rq, pBuf, &flags);
+ drive->io_32bit = io_32bit;
+ rq->errors = 0;
+ rq->current_nr_sectors -= nsect;
+ if (hwgroup->handler == NULL)
+ ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
+ return ide_started;
+}
+
ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
{
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
@@ -311,7 +384,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
ide_set_handler (drive, task->handler, WAIT_CMD, NULL);
OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
/*
- * warning check for race between handler and prehandler for
+ * Warning check for race between handler and prehandler for
* writing first block of data. however since we are well
* inside the boundaries of the seek, we should be okay.
*/
@@ -366,310 +439,12 @@ void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct
}
}
-#if 0
-ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
-{
- task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
- hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
- struct hd_driveid *id = drive->id;
-
- /*
- * (KS) Check taskfile in/out flags.
- * If set, then execute as it is defined.
- * If not set, then define default settings.
- * The default values are:
- * write and read all taskfile registers (except data)
- * write and read the hob registers (sector,nsector,lcyl,hcyl)
- */
- if (task->tf_out_flags.all == 0) {
- task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS;
- if ((id->command_set_2 & 0x0400) &&
- (id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- task->tf_out_flags.all != (IDE_HOB_STD_OUT_FLAGS << 8);
- }
- }
-
- if (task->tf_in_flags.all == 0) {
- task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
- if ((id->command_set_2 & 0x0400) &&
- (id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- task->tf_in_flags.all != (IDE_HOB_STD_IN_FLAGS << 8);
- }
- }
-
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
- SELECT_MASK(HWIF(drive), drive, 0);
-
- if (task->tf_out_flags.b.data) {
- unsigned short data = taskfile->data + (hobfile->data << 8);
- OUT_WORD (data, IDE_DATA_REG);
- }
-
- /* (KS) send hob registers first */
- if (task->tf_out_flags.b.nsector_hob)
- OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG);
- if (task->tf_out_flags.b.sector_hob)
- OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl_hob)
- OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl_hob)
- OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG);
-
-
- /* (KS) Send now the standard registers */
- if (task->tf_out_flags.b.error_feature)
- OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
- /* refers to number of sectors to transfer */
- if (task->tf_out_flags.b.nsector)
- OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
- /* refers to sector offset or start sector */
- if (task->tf_out_flags.b.sector)
- OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl)
- OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl)
- OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG);
-
- /*
- * (KS) Do not modify the specified taskfile. We want to have a
- * universal pass through, so we must execute ALL specified values.
- *
- * (KS) The drive head register is mandatory.
- * Don't care about the out flags !
- */
- OUT_BYTE(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
- if (task->handler != NULL) {
- ide_set_handler (drive, task->handler, WAIT_CMD, NULL);
- OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
- /*
- * warning check for race between handler and prehandler for
- * writing first block of data. however since we are well
- * inside the boundaries of the seek, we should be okay.
- */
- if (task->prehandler != NULL) {
- return task->prehandler(drive, task->rq);
- }
- } else {
- /* for dma commands we down set the handler */
- if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
- }
-
- return ide_started;
-}
-#endif
-
-#if 0
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- */
-byte taskfile_dump_status (ide_drive_t *drive, const char *msg, byte stat)
-{
- unsigned long flags;
- byte err = 0;
-
- __save_flags (flags); /* local CPU only */
- ide__sti(); /* local CPU only */
- printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
- printk(" { ");
- if (stat & BUSY_STAT)
- printk("Busy ");
- else {
- if (stat & READY_STAT) printk("DriveReady ");
- if (stat & WRERR_STAT) printk("DeviceFault ");
- if (stat & SEEK_STAT) printk("SeekComplete ");
- if (stat & DRQ_STAT) printk("DataRequest ");
- if (stat & ECC_STAT) printk("CorrectedError ");
- if (stat & INDEX_STAT) printk("Index ");
- if (stat & ERR_STAT) printk("Error ");
- }
- printk("}");
-#endif /* FANCY_STATUS_DUMPS */
- printk("\n");
- if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
- err = GET_ERR();
- printk("%s: %s: error=0x%02x", drive->name, msg, err);
-#if FANCY_STATUS_DUMPS
- if (drive->media == ide_disk) {
- printk(" { ");
- if (err & ABRT_ERR) printk("DriveStatusError ");
- if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector ");
- if (err & ECC_ERR) printk("UncorrectableError ");
- if (err & ID_ERR) printk("SectorIdNotFound ");
- if (err & TRK0_ERR) printk("TrackZeroNotFound ");
- if (err & MARK_ERR) printk("AddrMarkNotFound ");
- printk("}");
- if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
- if ((drive->id->command_set_2 & 0x0400) &&
- (drive->id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- __u64 sectors = 0;
- u32 low = 0, high = 0;
- low = task_read_24(drive);
- OUT_BYTE(0x80, IDE_CONTROL_REG);
- high = task_read_24(drive);
- sectors = ((__u64)high << 24) | low;
- printk(", LBAsect=%lld", sectors);
- } else {
- byte cur = IN_BYTE(IDE_SELECT_REG);
- if (cur & 0x40) { /* using LBA? */
- printk(", LBAsect=%ld", (unsigned long)
- ((cur&0xf)<<24)
- |(IN_BYTE(IDE_HCYL_REG)<<16)
- |(IN_BYTE(IDE_LCYL_REG)<<8)
- | IN_BYTE(IDE_SECTOR_REG));
- } else {
- printk(", CHS=%d/%d/%d",
- (IN_BYTE(IDE_HCYL_REG)<<8) +
- IN_BYTE(IDE_LCYL_REG),
- cur & 0xf,
- IN_BYTE(IDE_SECTOR_REG));
- }
- }
- if (HWGROUP(drive)->rq)
- printk(", sector=%llu", (__u64) HWGROUP(drive)->rq->sector);
- }
- }
-#endif /* FANCY_STATUS_DUMPS */
- printk("\n");
- }
- __restore_flags (flags); /* local CPU only */
- return err;
-}
-
-/*
- * Clean up after success/failure of an explicit taskfile operation.
- */
-void ide_end_taskfile (ide_drive_t *drive, byte stat, byte err)
-{
- unsigned long flags;
- struct request *rq;
- ide_task_t *args;
- task_ioreg_t command;
-
- spin_lock_irqsave(&ide_lock, flags);
- rq = HWGROUP(drive)->rq;
- spin_unlock_irqrestore(&ide_lock, flags);
- args = (ide_task_t *) rq->special;
-
- command = args->tfRegister[IDE_COMMAND_OFFSET];
-
- rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-
- args->tfRegister[IDE_ERROR_OFFSET] = err;
- args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG);
- args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG);
- args->tfRegister[IDE_LCYL_OFFSET] = IN_BYTE(IDE_LCYL_REG);
- args->tfRegister[IDE_HCYL_OFFSET] = IN_BYTE(IDE_HCYL_REG);
- args->tfRegister[IDE_SELECT_OFFSET] = IN_BYTE(IDE_SELECT_REG);
- args->tfRegister[IDE_STATUS_OFFSET] = stat;
- if ((drive->id->command_set_2 & 0x0400) &&
- (drive->id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
- args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG);
- args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG);
- args->hobRegister[IDE_SECTOR_OFFSET_HOB] = IN_BYTE(IDE_SECTOR_REG);
- args->hobRegister[IDE_LCYL_OFFSET_HOB] = IN_BYTE(IDE_LCYL_REG);
- args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG);
- }
-
-/* taskfile_settings_update(drive, args, command); */
-
- spin_lock_irqsave(&ide_lock, flags);
- blkdev_dequeue_request(rq);
- HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq);
- spin_unlock_irqrestore(&ide_lock, flags);
-}
-
-/*
- * try_to_flush_leftover_data() is invoked in response to a drive
- * unexpectedly having its DRQ_STAT bit set. As an alternative to
- * resetting the drive, this routine tries to clear the condition
- * by read a sector's worth of data from the drive. Of course,
- * this may not help if the drive is *waiting* for data from *us*.
- */
-void task_try_to_flush_leftover_data (ide_drive_t *drive)
-{
- int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS;
-
- if (drive->media != ide_disk)
- return;
- while (i > 0) {
- u32 buffer[16];
- unsigned int wcount = (i > 16) ? 16 : i;
- i -= wcount;
- taskfile_input_data (drive, buffer, wcount);
- }
-}
-
-/*
- * taskfile_error() takes action based on the error returned by the drive.
- */
-ide_startstop_t taskfile_error (ide_drive_t *drive, const char *msg, byte stat)
-{
- struct request *rq;
- byte err;
-
- err = taskfile_dump_status(drive, msg, stat);
- if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
- return ide_stopped;
- /* retry only "normal" I/O: */
- if (rq->flags & REQ_DRIVE_TASKFILE) {
- rq->errors = 1;
- ide_end_taskfile(drive, stat, err);
- return ide_stopped;
- }
- if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */
- rq->errors |= ERROR_RESET;
- } else {
- if (drive->media == ide_disk && (stat & ERR_STAT)) {
- /* err has different meaning on cdrom and tape */
- if (err == ABRT_ERR) {
- if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
- return ide_stopped; /* some newer drives don't support WIN_SPECIFY */
- } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) {
- drive->crc_count++; /* UDMA crc error -- just retry the operation */
- } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
- rq->errors = ERROR_MAX;
- else if (err & TRK0_ERR) /* help it find track zero */
- rq->errors |= ERROR_RECAL;
- }
- /* pre bio (rq->cmd != WRITE) */
- if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
- task_try_to_flush_leftover_data(drive);
- }
- if (GET_STAT() & (BUSY_STAT|DRQ_STAT))
- OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */
-
- if (rq->errors >= ERROR_MAX) {
- if (drive->driver != NULL)
- ata_ops(drive)->end_request(0, HWGROUP(drive));
- else
- ide_end_request(drive, 0);
- } else {
- if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
- ++rq->errors;
- return ide_do_reset(drive);
- }
- if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
- drive->special.b.recalibrate = 1;
- ++rq->errors;
- }
- return ide_stopped;
-}
-#endif
-
/*
* Handler for special commands without a data phase from ide-disk
*/
/*
- * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
+ * This is invoked on completion of a WIN_SETMULT cmd.
*/
ide_startstop_t set_multmode_intr (ide_drive_t *drive)
{
@@ -680,15 +455,15 @@ ide_startstop_t set_multmode_intr (ide_drive_t *drive)
} else {
drive->mult_req = drive->mult_count = 0;
drive->special.b.recalibrate = 1;
- (void) ide_dump_status(drive, "set_multmode", stat);
+ ide_dump_status(drive, "set_multmode", stat);
}
return ide_stopped;
}
/*
- * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
+ * This is invoked on completion of a WIN_SPECIFY cmd.
*/
-ide_startstop_t set_geometry_intr (ide_drive_t *drive)
+static ide_startstop_t set_geometry_intr (ide_drive_t *drive)
{
byte stat;
@@ -703,9 +478,9 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive)
}
/*
- * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
+ * This is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
*/
-ide_startstop_t recal_intr (ide_drive_t *drive)
+static ide_startstop_t recal_intr (ide_drive_t *drive)
{
byte stat = GET_STAT();
@@ -736,7 +511,7 @@ ide_startstop_t task_no_data_intr (ide_drive_t *drive)
/*
* Handler for command with PIO data-in phase
*/
-ide_startstop_t task_in_intr (ide_drive_t *drive)
+static ide_startstop_t task_in_intr (ide_drive_t *drive)
{
byte stat = GET_STAT();
byte io_32bit = drive->io_32bit;
@@ -751,7 +526,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
if (!(stat & BUSY_STAT)) {
DTF("task_in_intr to Soon wait for next interrupt\n");
ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL);
- return ide_started;
+ return ide_started;
}
}
DTF("stat: %02x\n", stat);
@@ -777,134 +552,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
return ide_stopped;
}
-#undef ALTSTAT_SCREW_UP
-
-#ifdef ALTSTAT_SCREW_UP
-/*
- * (ks/hs): Poll Alternate Status Register to ensure
- * that drive is not busy.
- */
-byte altstat_multi_busy (ide_drive_t *drive, byte stat, const char *msg)
-{
- int i;
-
- DTF("multi%s: ASR = %x\n", msg, stat);
- if (stat & BUSY_STAT) {
- /* (ks/hs): FIXME: Replace hard-coded 100, error handling? */
- for (i=0; i<100; i++) {
- stat = GET_ALTSTAT();
- if ((stat & BUSY_STAT) == 0)
- break;
- }
- }
- /*
- * (ks/hs): Read Status AFTER Alternate Status Register
- */
- return(GET_STAT());
-}
-
-/*
- * (ks/hs): Poll Alternate status register to wait for drive
- * to become ready for next transfer
- */
-byte altstat_multi_poll (ide_drive_t *drive, byte stat, const char *msg)
-{
- /* (ks/hs): FIXME: Error handling, time-out? */
- while (stat & BUSY_STAT)
- stat = GET_ALTSTAT();
- DTF("multi%s: nsect=1, ASR = %x\n", msg, stat);
- return(GET_STAT()); /* (ks/hs): Clear pending IRQ */
-}
-#endif /* ALTSTAT_SCREW_UP */
-
-/*
- * Handler for command with Read Multiple
- */
-ide_startstop_t task_mulin_intr (ide_drive_t *drive)
-{
- unsigned int msect, nsect;
-
-#ifdef ALTSTAT_SCREW_UP
- byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "read");
-#else
- byte stat = GET_STAT();
-#endif /* ALTSTAT_SCREW_UP */
-
- byte io_32bit = drive->io_32bit;
- struct request *rq = HWGROUP(drive)->rq;
- char *pBuf = NULL;
- unsigned long flags;
-
- if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
- if (stat & (ERR_STAT|DRQ_STAT)) {
- return ide_error(drive, "task_mulin_intr", stat);
- }
- /* no data yet, so wait for another interrupt */
- ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
- return ide_started;
- }
-
- /* (ks/hs): Fixed Multi-Sector transfer */
- msect = drive->mult_count;
-
-#ifdef ALTSTAT_SCREW_UP
- /*
- * Screw the request we do not support bad data-phase setups!
- * Either read and learn the ATA standard or crash yourself!
- */
- if (!msect) {
- /*
- * (ks/hs): Drive supports multi-sector transfer,
- * drive->mult_count was not set
- */
- nsect = 1;
- while (rq->current_nr_sectors) {
- pBuf = ide_map_rq(rq, &flags);
- DTF("Multiread: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
- ide_unmap_rq(rq, pBuf, &flags);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- stat = altstat_multi_poll(drive, GET_ALTSTAT(), "read");
- }
- ide_end_request(drive, 1);
- return ide_stopped;
- }
-#endif /* ALTSTAT_SCREW_UP */
-
- do {
- nsect = rq->current_nr_sectors;
- if (nsect > msect)
- nsect = msect;
-
- pBuf = ide_map_rq(rq, &flags);
-
- DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
- pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
- ide_unmap_rq(rq, pBuf, &flags);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- msect -= nsect;
- if (!rq->current_nr_sectors) {
- if (!ide_end_request(drive, 1))
- return ide_stopped;
- }
- } while (msect);
-
-
- /*
- * more data left
- */
- ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
- return ide_started;
-}
-
-ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
{
ide_task_t *args = rq->special;
ide_startstop_t startstop;
@@ -924,21 +572,7 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
rq->current_nr_sectors--;
ide_unmap_rq(rq, buf, &flags);
} else {
- /*
- * (ks/hs): Stuff the first sector(s)
- * by implicitly calling the handler
- */
- if (!(drive_is_ready(drive))) {
- int i;
- /*
- * (ks/hs): FIXME: Replace hard-coded
- * 100, error handling?
- */
- for (i=0; i<100; i++) {
- if (drive_is_ready(drive))
- break;
- }
- }
+ ata_poll_drive_ready(drive);
return args->handler(drive);
}
return ide_started;
@@ -947,7 +581,7 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
/*
* Handler for command with PIO data-out phase
*/
-ide_startstop_t task_out_intr (ide_drive_t *drive)
+static ide_startstop_t task_out_intr(ide_drive_t *drive)
{
byte stat = GET_STAT();
byte io_32bit = drive->io_32bit;
@@ -978,98 +612,7 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
return ide_started;
}
-/*
- * Handler for command write multiple
- * Called directly from execute_drive_cmd for the first bunch of sectors,
- * afterwards only by the ISR
- */
-ide_startstop_t task_mulout_intr (ide_drive_t *drive)
-{
- unsigned int msect, nsect;
-
-#ifdef ALTSTAT_SCREW_UP
- byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write");
-#else
- byte stat = GET_STAT();
-#endif /* ALTSTAT_SCREW_UP */
-
- byte io_32bit = drive->io_32bit;
- struct request *rq = HWGROUP(drive)->rq;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- char *pBuf = NULL;
- unsigned long flags;
-
- /*
- * (ks/hs): Handle last IRQ on multi-sector transfer,
- * occurs after all data was sent in this chunk
- */
- if (rq->current_nr_sectors == 0) {
- if (stat & (ERR_STAT|DRQ_STAT))
- return ide_error(drive, "task_mulout_intr", stat);
-
- /*
- * there may be more, ide_do_request will restart it if
- * necessary
- */
- ide_end_request(drive, 1);
- return ide_stopped;
- }
-
- if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
- if (stat & (ERR_STAT|DRQ_STAT)) {
- return ide_error(drive, "task_mulout_intr", stat);
- }
- /* no data yet, so wait for another interrupt */
- if (hwgroup->handler == NULL)
- ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
- return ide_started;
- }
-
- /* (ks/hs): See task_mulin_intr */
- msect = drive->mult_count;
-
-#ifdef ALTSTAT_SCREW_UP
- /*
- * Screw the request we do not support bad data-phase setups!
- * Either read and learn the ATA standard or crash yourself!
- */
- if (!msect) {
- nsect = 1;
- while (rq->current_nr_sectors) {
- pBuf = ide_map_rq(rq, &flags);
- DTF("Multiwrite: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
- ide_unmap_rq(pBuf, &flags);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- stat = altstat_multi_poll(drive, GET_ALTSTAT(), "write");
- }
- ide_end_request(drive, 1);
- return ide_stopped;
- }
-#endif /* ALTSTAT_SCREW_UP */
-
- nsect = rq->current_nr_sectors;
- if (nsect > msect)
- nsect = msect;
-
- pBuf = ide_map_rq(rq, &flags);
- DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
- pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
- ide_unmap_rq(rq, pBuf, &flags);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- if (hwgroup->handler == NULL)
- ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
- return ide_started;
-}
-
-ide_startstop_t pre_bio_out_intr (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t pre_bio_out_intr(ide_drive_t *drive, struct request *rq)
{
ide_task_t *args = rq->special;
ide_startstop_t startstop;
@@ -1082,34 +625,14 @@ ide_startstop_t pre_bio_out_intr (ide_drive_t *drive, struct request *rq)
if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
return startstop;
- /*
- * (ks/hs): Stuff the first sector(s)
- * by implicitly calling the handler
- */
- if (!(drive_is_ready(drive))) {
- int i;
- /*
- * (ks/hs): FIXME: Replace hard-coded
- * 100, error handling?
- */
- for (i=0; i<100; i++) {
- if (drive_is_ready(drive))
- break;
- }
- }
-
+ ata_poll_drive_ready(drive);
return args->handler(drive);
}
-ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
+static ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
{
-#ifdef ALTSTAT_SCREW_UP
- byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write");
-#else
byte stat = GET_STAT();
-#endif /* ALTSTAT_SCREW_UP */
-
byte io_32bit = drive->io_32bit;
struct request *rq = &HWGROUP(drive)->wrq;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
@@ -1147,8 +670,8 @@ ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
}
do {
- char *buffer;
- int nsect = rq->current_nr_sectors;
+ char *buffer;
+ int nsect = rq->current_nr_sectors;
unsigned long flags;
if (nsect > mcount)
@@ -1221,6 +744,60 @@ ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile,
return(NULL);
}
+/*
+ * Handler for command with Read Multiple
+ */
+static ide_startstop_t task_mulin_intr(ide_drive_t *drive)
+{
+ unsigned int msect, nsect;
+ byte stat = GET_STAT();
+ byte io_32bit = drive->io_32bit;
+ struct request *rq = HWGROUP(drive)->rq;
+ char *pBuf = NULL;
+ unsigned long flags;
+
+ if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
+ if (stat & (ERR_STAT|DRQ_STAT)) {
+ return ide_error(drive, "task_mulin_intr", stat);
+ }
+ /* no data yet, so wait for another interrupt */
+ ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
+ return ide_started;
+ }
+
+ /* (ks/hs): Fixed Multi-Sector transfer */
+ msect = drive->mult_count;
+
+ do {
+ nsect = rq->current_nr_sectors;
+ if (nsect > msect)
+ nsect = msect;
+
+ pBuf = ide_map_rq(rq, &flags);
+
+ DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
+ pBuf, nsect, rq->current_nr_sectors);
+ drive->io_32bit = 0;
+ taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
+ ide_unmap_rq(rq, pBuf, &flags);
+ drive->io_32bit = io_32bit;
+ rq->errors = 0;
+ rq->current_nr_sectors -= nsect;
+ msect -= nsect;
+ if (!rq->current_nr_sectors) {
+ if (!ide_end_request(drive, 1))
+ return ide_stopped;
+ }
+ } while (msect);
+
+
+ /*
+ * more data left
+ */
+ ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
+ return ide_started;
+}
+
/* Called by internal to feature out type of command being called */
ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
{
@@ -1316,8 +893,8 @@ ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct h
case WIN_QUEUED_SERVICE:
case WIN_PACKETCMD:
default:
- return(NULL);
- }
+ return NULL;
+ }
}
/* Called by ioctl to feature out type of command being called */
@@ -1450,7 +1027,7 @@ int ide_cmd_type_parser (ide_task_t *args)
/*
* This function is intended to be used prior to invoking ide_do_drive_cmd().
*/
-void ide_init_drive_taskfile (struct request *rq)
+static void ide_init_drive_taskfile (struct request *rq)
{
memset(rq, 0, sizeof(*rq));
rq->flags = REQ_DRIVE_TASKFILE;
@@ -1463,7 +1040,7 @@ void ide_init_drive_taskfile (struct request *rq)
*
* ide_raw_taskfile is the one that user-space executes.
*/
-int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf)
+int ide_wait_taskfile(ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf)
{
struct request rq;
ide_task_t args;
@@ -1499,7 +1076,7 @@ int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, s
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
-int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf)
+int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *args, byte *buf)
{
struct request rq;
ide_init_drive_taskfile(&rq);
@@ -1512,24 +1089,11 @@ int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf)
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
-
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
-char * ide_ioctl_verbose (unsigned int cmd)
-{
- return("unknown");
-}
-
-char * ide_task_cmd_verbose (byte task)
-{
- return("unknown");
-}
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
/*
* The taskfile glue table
*
* reqtask.data_phase reqtask.req_cmd
- * args.command_type args.handler
+ * args.command_type args.handler
*
* TASKFILE_P_OUT_DMAQ ?? ??
* TASKFILE_P_IN_DMAQ ?? ??
@@ -1555,202 +1119,35 @@ char * ide_task_cmd_verbose (byte task)
* TASKFILE_IN IDE_DRIVE_TASK_IN task_in_intr
* TASKFILE_NO_DATA IDE_DRIVE_TASK_NO_DATA task_no_data_intr
*
- * IDE_DRIVE_TASK_SET_XFER task_no_data_intr
- * IDE_DRIVE_TASK_INVALID
+ * IDE_DRIVE_TASK_SET_XFER task_no_data_intr
+ * IDE_DRIVE_TASK_INVALID
*
*/
-#define MAX_DMA (256*SECTOR_WORDS)
-
-int ide_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+/*
+ * Issue ATA command and wait for completion. use for implementing commands in
+ * kernel.
+ *
+ * The caller has to make sure buf is never NULL!
+ */
+static int ide_wait_cmd(ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *argbuf)
{
- ide_task_request_t *req_task;
- ide_task_t args;
-
- byte *outbuf = NULL;
- byte *inbuf = NULL;
- task_ioreg_t *argsptr = args.tfRegister;
- task_ioreg_t *hobsptr = args.hobRegister;
- int err = 0;
- int tasksize = sizeof(struct ide_task_request_s);
- int taskin = 0;
- int taskout = 0;
-
- req_task = kmalloc(tasksize, GFP_KERNEL);
- if (req_task == NULL) return -ENOMEM;
- memset(req_task, 0, tasksize);
- if (copy_from_user(req_task, (void *) arg, tasksize)) {
- kfree(req_task);
- return -EFAULT;
- }
-
- taskout = (int) req_task->out_size;
- taskin = (int) req_task->in_size;
-
- if (taskout) {
- int outtotal = tasksize;
- outbuf = kmalloc(taskout, GFP_KERNEL);
- if (outbuf == NULL) {
- err = -ENOMEM;
- goto abort;
- }
- memset(outbuf, 0, taskout);
- if (copy_from_user(outbuf, (void *)arg + outtotal, taskout)) {
- err = -EFAULT;
- goto abort;
- }
- }
-
- if (taskin) {
- int intotal = tasksize + taskout;
- inbuf = kmalloc(taskin, GFP_KERNEL);
- if (inbuf == NULL) {
- err = -ENOMEM;
- goto abort;
- }
- memset(inbuf, 0, taskin);
- if (copy_from_user(inbuf, (void *)arg + intotal , taskin)) {
- err = -EFAULT;
- goto abort;
- }
- }
-
- memset(argsptr, 0, HDIO_DRIVE_TASK_HDR_SIZE);
- memset(hobsptr, 0, HDIO_DRIVE_HOB_HDR_SIZE);
- memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
- memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
-
- args.tf_in_flags = req_task->in_flags;
- args.tf_out_flags = req_task->out_flags;
- args.data_phase = req_task->data_phase;
- args.command_type = req_task->req_cmd;
-
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
- DTF("%s: ide_ioctl_cmd %s: ide_task_cmd %s\n",
- drive->name,
- ide_ioctl_verbose(cmd),
- ide_task_cmd_verbose(args.tfRegister[IDE_COMMAND_OFFSET]));
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
- switch(req_task->data_phase) {
- case TASKFILE_OUT_DMAQ:
- case TASKFILE_OUT_DMA:
- args.prehandler = NULL;
- args.handler = NULL;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, outbuf);
- break;
- case TASKFILE_IN_DMAQ:
- case TASKFILE_IN_DMA:
- args.prehandler = NULL;
- args.handler = NULL;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, inbuf);
- break;
- case TASKFILE_IN_OUT:
-#if 0
- args.prehandler = &pre_task_out_intr;
- args.handler = &task_out_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, outbuf);
- args.prehandler = NULL;
- args.handler = &task_in_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, inbuf);
- break;
-#else
- err = -EFAULT;
- goto abort;
-#endif
- case TASKFILE_MULTI_OUT:
- if (drive->mult_count) {
- args.prehandler = &pre_task_out_intr;
- args.handler = &task_mulout_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, outbuf);
- } else {
- /* (hs): give up if multcount is not set */
- printk("%s: %s Multimode Write " \
- "multcount is not set\n",
- drive->name, __FUNCTION__);
- err = -EPERM;
- goto abort;
- }
- break;
- case TASKFILE_OUT:
- args.prehandler = &pre_task_out_intr;
- args.handler = &task_out_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, outbuf);
- break;
- case TASKFILE_MULTI_IN:
- if (drive->mult_count) {
- args.prehandler = NULL;
- args.handler = &task_mulin_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, inbuf);
- } else {
- /* (hs): give up if multcount is not set */
- printk("%s: %s Multimode Read failure " \
- "multcount is not set\n",
- drive->name, __FUNCTION__);
- err = -EPERM;
- goto abort;
- }
- break;
- case TASKFILE_IN:
- args.prehandler = NULL;
- args.handler = &task_in_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, inbuf);
- break;
- case TASKFILE_NO_DATA:
- args.prehandler = NULL;
- args.handler = &task_no_data_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, NULL);
- break;
- default:
- args.prehandler = NULL;
- args.handler = NULL;
- args.posthandler = NULL;
- err = -EFAULT;
- goto abort;
- }
+ struct request rq;
- memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
- memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
- req_task->in_flags = args.tf_in_flags;
- req_task->out_flags = args.tf_out_flags;
+ /* FIXME: Do we really have to zero out the buffer?
+ */
+ memset(argbuf, 0, 4 + SECTOR_WORDS * 4 * sectors);
+ ide_init_drive_cmd(&rq);
+ rq.buffer = argbuf;
+ *argbuf++ = cmd;
+ *argbuf++ = nsect;
+ *argbuf++ = feature;
+ *argbuf++ = sectors;
- if (copy_to_user((void *)arg, req_task, tasksize)) {
- err = -EFAULT;
- goto abort;
- }
- if (taskout) {
- int outtotal = tasksize;
- if (copy_to_user((void *)arg+outtotal, outbuf, taskout)) {
- err = -EFAULT;
- goto abort;
- }
- }
- if (taskin) {
- int intotal = tasksize + taskout;
- if (copy_to_user((void *)arg+intotal, inbuf, taskin)) {
- err = -EFAULT;
- goto abort;
- }
- }
-abort:
- kfree(req_task);
- if (outbuf != NULL)
- kfree(outbuf);
- if (inbuf != NULL)
- kfree(inbuf);
- return err;
+ return ide_do_drive_cmd(drive, &rq, ide_wait);
}
-int ide_cmd_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+int ide_cmd_ioctl(ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int err = 0;
byte args[4], *argbuf = args;
@@ -1806,19 +1203,26 @@ abort:
int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int err = 0;
- byte args[7], *argbuf = args;
+ u8 args[7];
+ u8 *argbuf;
int argsize = 7;
+ struct request rq;
+
+ argbuf = args;
if (copy_from_user(args, (void *)arg, 7))
return -EFAULT;
- err = ide_wait_cmd_task(drive, argbuf);
+
+ ide_init_drive_cmd(&rq);
+ rq.flags = REQ_DRIVE_TASK;
+ rq.buffer = argbuf;
+ err = ide_do_drive_cmd(drive, &rq, ide_wait);
if (copy_to_user((void *)arg, argbuf, argsize))
err = -EFAULT;
return err;
}
EXPORT_SYMBOL(drive_is_ready);
-EXPORT_SYMBOL(task_read_24);
EXPORT_SYMBOL(ata_input_data);
EXPORT_SYMBOL(ata_output_data);
EXPORT_SYMBOL(atapi_input_bytes);
@@ -1827,166 +1231,15 @@ EXPORT_SYMBOL(taskfile_input_data);
EXPORT_SYMBOL(taskfile_output_data);
EXPORT_SYMBOL(do_rw_taskfile);
EXPORT_SYMBOL(do_taskfile);
-// EXPORT_SYMBOL(flagged_taskfile);
-
-//EXPORT_SYMBOL(ide_end_taskfile);
EXPORT_SYMBOL(set_multmode_intr);
-EXPORT_SYMBOL(set_geometry_intr);
-EXPORT_SYMBOL(recal_intr);
EXPORT_SYMBOL(task_no_data_intr);
-EXPORT_SYMBOL(task_in_intr);
-EXPORT_SYMBOL(task_mulin_intr);
-EXPORT_SYMBOL(pre_task_out_intr);
-EXPORT_SYMBOL(task_out_intr);
-EXPORT_SYMBOL(task_mulout_intr);
-EXPORT_SYMBOL(ide_init_drive_taskfile);
EXPORT_SYMBOL(ide_wait_taskfile);
EXPORT_SYMBOL(ide_raw_taskfile);
EXPORT_SYMBOL(ide_pre_handler_parser);
EXPORT_SYMBOL(ide_handler_parser);
EXPORT_SYMBOL(ide_cmd_type_parser);
-EXPORT_SYMBOL(ide_taskfile_ioctl);
EXPORT_SYMBOL(ide_cmd_ioctl);
EXPORT_SYMBOL(ide_task_ioctl);
-
-
-#ifdef CONFIG_PKT_TASK_IOCTL
-
-#if 0
-{
-
-{ /* start cdrom */
-
- struct cdrom_info *info = drive->driver_data;
-
- if (info->dma) {
- if (info->cmd == READ) {
- info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive);
- } else if (info->cmd == WRITE) {
- info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive);
- } else {
- printk("ide-cd: DMA set, but not allowed\n");
- }
- }
-
- /* Set up the controller registers. */
- OUT_BYTE (info->dma, IDE_FEATURE_REG);
- OUT_BYTE (0, IDE_NSECTOR_REG);
- OUT_BYTE (0, IDE_SECTOR_REG);
-
- OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
- OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG);
- if (IDE_CONTROL_REG)
- OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
-
- if (info->dma)
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
-
- if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
- ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- return ide_started;
- } else {
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- return (*handler) (drive);
- }
-
-} /* end cdrom */
-
-{ /* start floppy */
-
- idefloppy_floppy_t *floppy = drive->driver_data;
- idefloppy_bcount_reg_t bcount;
- int dma_ok = 0;
-
- floppy->pc=pc; /* Set the current packet command */
-
- pc->retries++;
- pc->actually_transferred=0; /* We haven't transferred any data yet */
- pc->current_position=pc->buffer;
- bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024);
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
- (void) HWIF(drive)->dmaproc(ide_dma_off, drive);
- }
- if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
- dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
- if (IDE_CONTROL_REG)
- OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */
- OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
- OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
- OUT_BYTE (drive->select.all,IDE_SELECT_REG);
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (dma_ok) { /* Begin DMA, if necessary */
- set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
- }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-} /* end floppy */
-
-{ /* start tape */
-
- idetape_tape_t *tape = drive->driver_data;
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
- printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n");
- (void) HWIF(drive)->dmaproc(ide_dma_off, drive);
- }
- if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
- dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
- if (IDE_CONTROL_REG)
- OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */
- OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
- OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
- OUT_BYTE (drive->select.all,IDE_SELECT_REG);
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (dma_ok) { /* Begin DMA, if necessary */
- set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
- }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
- if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
- ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
- OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
- return ide_started;
- } else {
- OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
- return idetape_transfer_pc(drive);
- }
-
-} /* end tape */
-
-}
-#endif
-
-int pkt_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-#if 0
- switch(req_task->data_phase) {
- case TASKFILE_P_OUT_DMAQ:
- case TASKFILE_P_IN_DMAQ:
- case TASKFILE_P_OUT_DMA:
- case TASKFILE_P_IN_DMA:
- case TASKFILE_P_OUT:
- case TASKFILE_P_IN:
- }
-#endif
- return -ENOMSG;
-}
-
-EXPORT_SYMBOL(pkt_taskfile_ioctl);
-
-#endif /* CONFIG_PKT_TASK_IOCTL */
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 944f69636012..116e51e5ce5f 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1,8 +1,6 @@
/*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- */
-
-/*
+ *
* Mostly written by Mark Lord <mlord@pobox.com>
* and Gadi Oxman <gadio@netvision.net.il>
* and Andre Hedrick <andre@linux-ide.org>
@@ -119,8 +117,6 @@
#define VERSION "7.0.0"
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -135,8 +131,8 @@
#include <linux/blkpg.h>
#include <linux/slab.h>
#ifndef MODULE
-#include <linux/init.h>
-#endif /* MODULE */
+# include <linux/init.h>
+#endif
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
@@ -155,9 +151,52 @@
#include "ide_modes.h"
-/* Constant tables for PIO mode programming:
+/*
+ * Those will be moved into separate header files eventually.
*/
+#ifdef CONFIG_BLK_DEV_RZ1000
+extern void ide_probe_for_rz100x(void);
+#endif
+#ifdef CONFIG_ETRAX_IDE
+extern void init_e100_ide(void);
+#endif
+#ifdef CONFIG_BLK_DEV_CMD640
+extern void ide_probe_for_cmd640x(void);
+#endif
+#ifdef CONFIG_BLK_DEV_PDC4030
+extern int ide_probe_for_pdc4030(void);
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+extern void pmac_ide_probe(void);
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
+extern void icside_init(void);
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
+extern void rapide_init(void);
+#endif
+#ifdef CONFIG_BLK_DEV_GAYLE
+extern void gayle_init(void);
+#endif
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
+extern void falconide_init(void);
+#endif
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+extern void macide_init(void);
+#endif
+#ifdef CONFIG_BLK_DEV_Q40IDE
+extern void q40ide_init(void);
+#endif
+#ifdef CONFIG_BLK_DEV_BUDDHA
+extern void buddha_init(void);
+#endif
+#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
+extern void pnpide_init(int);
+#endif
+/*
+ * Constant tables for PIO mode programming:
+ */
const ide_pio_timings_t ide_pio_timings[6] = {
{ 70, 165, 600 }, /* PIO Mode 0 */
{ 50, 125, 383 }, /* PIO Mode 1 */
@@ -174,7 +213,7 @@ const ide_pio_timings_t ide_pio_timings[6] = {
static struct ide_pio_info {
const char *name;
int pio;
-} ide_pio_blacklist [] = {
+} ide_pio_blacklist[] = {
/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */
{ "Conner Peripherals 540MB - CFS540A", 3 },
@@ -224,8 +263,8 @@ static struct ide_pio_info {
{ "ST3600A", 1 },
{ "ST3290A", 0 },
{ "ST3144A", 0 },
- { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */
- /* drive) according to Seagates FIND-ATA program */
+ { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on
+ * drive) according to Seagates FIND-ATA program */
{ "QUANTUM ELS127A", 0 },
{ "QUANTUM ELS170A", 0 },
@@ -238,7 +277,7 @@ static struct ide_pio_info {
{ "QUANTUM LIGHTNING 730A", 3 },
{ "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */
- { "QUANTUM FIREBALL_640", 3 },
+ { "QUANTUM FIREBALL_640", 3 },
{ "QUANTUM FIREBALL_1080", 3 },
{ "QUANTUM FIREBALL_1280", 3 },
{ NULL, 0 }
@@ -247,34 +286,33 @@ static struct ide_pio_info {
/* default maximum number of failures */
#define IDE_DEFAULT_MAX_FAILURES 1
-static int idebus_parameter; /* holds the "idebus=" parameter */
-int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
-static int initializing; /* set while initializing built-in drivers */
+static int idebus_parameter; /* holds the "idebus=" parameter */
+int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
+static int initializing; /* set while initializing built-in drivers */
/*
- * protects global structures etc, we want to split this into per-hwgroup
- * instead.
+ * Protects access to global structures etc.
*/
spinlock_t ide_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
#ifdef CONFIG_BLK_DEV_IDEPCI
-static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
-#endif /* CONFIG_BLK_DEV_IDEPCI */
+static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
+#endif
#if defined(__mc68000__) || defined(CONFIG_APUS)
/*
- * ide_lock is used by the Atari code to obtain access to the IDE interrupt,
+ * This is used by the Atari code to obtain access to the IDE interrupt,
* which is shared between several drivers.
*/
static int ide_intr_lock;
-#endif /* __mc68000__ || CONFIG_APUS */
+#endif
int noautodma = 0;
/*
* This is declared extern in ide.h, for access by other IDE modules:
*/
-ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
+ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
/*
@@ -378,7 +416,7 @@ byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode,
#if (DISK_RECOVERY_TIME > 0)
/*
- * For really screwy hardware (hey, at least it *can* be used with Linux)
+ * For really screwed hardware (hey, at least it *can* be used with Linux)
* we can enforce a minimum delay time between successive operations.
*/
static unsigned long read_timer (void)
@@ -389,7 +427,7 @@ static unsigned long read_timer (void)
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
t = jiffies * 11932;
- outb_p(0, 0x43);
+ outb_p(0, 0x43);
i = inb_p(0x40);
i |= inb(0x40) << 8;
__restore_flags(flags); /* local CPU only */
@@ -476,7 +514,7 @@ static void __init init_ide_data (void)
return; /* already initialized */
magic_cookie = 0;
- /* Initialise all interface structures */
+ /* Initialize all interface structures */
for (index = 0; index < MAX_HWIFS; ++index)
init_hwif_data(index);
@@ -487,11 +525,13 @@ static void __init init_ide_data (void)
}
/*
- * CompactFlash cards and their brethern pretend to be removable hard disks, except:
+ * CompactFlash cards and their relatives pretend to be removable hard disks, except:
* (1) they never have a slave unit, and
- * (2) they don't have doorlock mechanisms.
+ * (2) they don't have a door lock mechanisms.
* This test catches them, and is invoked elsewhere when setting appropriate config bits.
*
+ * FIXME FIXME: Yes this is for certain applicable for all of them as time has shown.
+ *
* FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) devices,
* so in linux 2.3.x we should change this to just treat all PCMCIA drives this way,
* and get rid of the model-name tests below (too big of an interface change for 2.2.x).
@@ -503,7 +543,8 @@ int drive_is_flashcard (ide_drive_t *drive)
struct hd_driveid *id = drive->id;
if (drive->removable && id != NULL) {
- if (id->config == 0x848a) return 1; /* CompactFlash */
+ if (id->config == 0x848a)
+ return 1; /* CompactFlash */
if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
|| !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
|| !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */
@@ -581,15 +622,76 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
spin_unlock_irqrestore(&ide_lock, flags);
}
+static void ata_pre_reset (ide_drive_t *drive)
+{
+ if (ata_ops(drive) && ata_ops(drive)->pre_reset)
+ ata_ops(drive)->pre_reset(drive);
+
+ if (!drive->keep_settings && !drive->using_dma) {
+ drive->unmask = 0;
+ drive->io_32bit = 0;
+ }
+
+ if (drive->using_dma) {
+ /* check the DMA crc count */
+ if (drive->crc_count) {
+ HWIF(drive)->dmaproc(ide_dma_off_quietly, drive);
+ if ((HWIF(drive)->speedproc) != NULL)
+ HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive));
+ if (drive->current_speed >= XFER_SW_DMA_0)
+ HWIF(drive)->dmaproc(ide_dma_on, drive);
+ } else
+ HWIF(drive)->dmaproc(ide_dma_off, drive);
+ }
+}
+
/*
* The capacity of a drive according to its current geometry/LBA settings in
* sectors.
*/
-unsigned long current_capacity (ide_drive_t *drive)
+unsigned long ata_capacity(ide_drive_t *drive)
{
if (!drive->present || !drive->driver)
return 0;
- return ata_ops(drive)->capacity(drive);
+
+ if (ata_ops(drive) && ata_ops(drive)->capacity)
+ return ata_ops(drive)->capacity(drive);
+
+ /* FIXME: This magic number seems to be bogous. */
+ return 0x7fffffff;
+}
+
+/*
+ * This is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT commands to
+ * a drive. It used to do much more, but has been scaled back.
+ */
+static ide_startstop_t ata_special (ide_drive_t *drive)
+{
+ special_t *s = &drive->special;
+
+#ifdef DEBUG
+ printk("%s: ata_special: 0x%02x\n", drive->name, s->all);
+#endif
+ if (s->b.set_tune) {
+ ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
+ s->b.set_tune = 0;
+ if (tuneproc != NULL)
+ tuneproc(drive, drive->tune_req);
+ } else if (drive->driver != NULL) {
+ if (ata_ops(drive)->special)
+ return ata_ops(drive)->special(drive);
+ else {
+ drive->special.all = 0;
+ drive->mult_req = 0;
+
+ return ide_stopped;
+ }
+ } else if (s->all) {
+ printk("%s: bad special flag: 0x%02x\n", drive->name, s->all);
+ s->all = 0;
+ }
+
+ return ide_stopped;
}
extern struct block_device_operations ide_fops[];
@@ -612,17 +714,16 @@ void ide_geninit (ide_hwif_t *hwif)
register_disk(gd,mk_kdev(hwif->major,unit<<PARTN_BITS),
#ifdef CONFIG_BLK_DEV_ISAPNP
(drive->forced_geom && drive->noprobe) ? 1 :
-#endif /* CONFIG_BLK_DEV_ISAPNP */
- 1<<PARTN_BITS, ide_fops,
- current_capacity(drive));
+#endif
+ 1 << PARTN_BITS, ide_fops, ata_capacity(drive));
}
}
static ide_startstop_t do_reset1 (ide_drive_t *, int); /* needed below */
/*
- * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an atapi drive reset operation. If the drive has not yet responded,
+ * ATAPI_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
+ * during an ATAPI drive reset operation. If the drive has not yet responded,
* and we have not yet hit our maximum waiting time, then the timer is restarted
* for another 50ms.
*/
@@ -695,44 +796,13 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
printk("\n");
#else
printk("failed\n");
-#endif /* FANCY_STATUS_DUMPS */
+#endif
}
}
hwgroup->poll_timeout = 0; /* done polling */
return ide_stopped;
}
-static void check_dma_crc (ide_drive_t *drive)
-{
- if (drive->crc_count) {
- (void) HWIF(drive)->dmaproc(ide_dma_off_quietly, drive);
- if ((HWIF(drive)->speedproc) != NULL)
- HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive));
- if (drive->current_speed >= XFER_SW_DMA_0)
- (void) HWIF(drive)->dmaproc(ide_dma_on, drive);
- } else {
- (void) HWIF(drive)->dmaproc(ide_dma_off, drive);
- }
-}
-
-static void pre_reset (ide_drive_t *drive)
-{
- if (drive->driver != NULL)
- ata_ops(drive)->pre_reset(drive);
-
- if (!drive->keep_settings) {
- if (drive->using_dma) {
- check_dma_crc(drive);
- } else {
- drive->unmask = 0;
- drive->io_32bit = 0;
- }
- return;
- }
- if (drive->using_dma)
- check_dma_crc(drive);
-}
-
/*
* do_reset1() attempts to recover a confused drive by resetting it.
* Unfortunately, resetting a disk drive actually resets all devices on
@@ -745,7 +815,7 @@ static void pre_reset (ide_drive_t *drive)
* Unfortunately, the IDE interface does not generate an interrupt to let
* us know when the reset operation has finished, so we must poll for this.
* Equally poor, though, is the fact that this may a very long time to complete,
- * (up to 30 seconds worstcase). So, instead of busy-waiting here for it,
+ * (up to 30 seconds worst case). So, instead of busy-waiting here for it,
* we set a timer to poll at 50ms intervals.
*/
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
@@ -760,7 +830,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
/* For an ATAPI device, first try an ATAPI SRST. */
if (drive->type != ATA_DISK && !do_not_try_atapi) {
- pre_reset(drive);
+ ata_pre_reset(drive);
SELECT_DRIVE(hwif,drive);
udelay (20);
OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
@@ -775,7 +845,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
* for any of the drives on this interface.
*/
for (unit = 0; unit < MAX_DRIVES; ++unit)
- pre_reset(&hwif->drives[unit]);
+ ata_pre_reset(&hwif->drives[unit]);
#if OK_TO_RESET_CONTROLLER
if (!IDE_CONTROL_REG) {
@@ -809,7 +879,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
if (hwif->resetproc != NULL)
hwif->resetproc(drive);
-#endif /* OK_TO_RESET_CONTROLLER */
+#endif
__restore_flags (flags); /* local CPU only */
return ide_started;
@@ -1011,11 +1081,6 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat)
/* retry only "normal" I/O: */
if (!(rq->flags & REQ_CMD)) {
rq->errors = 1;
-#if 0
- if (rq->flags & REQ_DRIVE_TASKFILE)
- ide_end_taskfile(drive, stat, err);
- else
-#endif
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
@@ -1044,7 +1109,7 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat)
if (rq->errors >= ERROR_MAX) {
/* ATA-PATTERN */
- if (drive->driver != NULL)
+ if (ata_ops(drive) && ata_ops(drive)->end_request)
ata_ops(drive)->end_request(drive, 0);
else
ide_end_request(drive, 0);
@@ -1101,31 +1166,6 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
}
/*
- * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
- * commands to a drive. It used to do much more, but has been scaled back.
- */
-static ide_startstop_t do_special (ide_drive_t *drive)
-{
- special_t *s = &drive->special;
-
-#ifdef DEBUG
- printk("%s: do_special: 0x%02x\n", drive->name, s->all);
-#endif
- if (s->b.set_tune) {
- ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
- s->b.set_tune = 0;
- if (tuneproc != NULL)
- tuneproc(drive, drive->tune_req);
- } else if (drive->driver != NULL) {
- return ata_ops(drive)->special(drive);
- } else if (s->all) {
- printk("%s: bad special flag: 0x%02x\n", drive->name, s->all);
- s->all = 0;
- }
- return ide_stopped;
-}
-
-/*
* This routine busy-waits for the drive status to be not "busy".
* It then checks the status for all of the "good" bits and none
* of the "bad" bits, and if all is okay it returns 0. All other
@@ -1140,7 +1180,7 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, by
byte stat;
int i;
unsigned long flags;
-
+
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
*startstop = ide_stopped;
@@ -1186,39 +1226,13 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq
if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special;
- if (!(args)) goto args_error;
+ if (!(args))
+ goto args_error;
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
- {
- printk(KERN_INFO "%s: ", drive->name);
-// printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]);
- printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]);
- printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]);
- printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]);
- printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]);
- printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]);
- printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]);
- printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]);
- printk(KERN_INFO "%s: ", drive->name);
-// printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET_HOB]);
- printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET_HOB]);
- printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET_HOB]);
- printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET_HOB]);
- printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET_HOB]);
- printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]);
- printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]);
- printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]);
- }
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
-// if (args->tf_out_flags.all == 0) {
- do_taskfile(drive,
+ do_taskfile(drive,
(struct hd_drive_task_hdr *)&args->tfRegister,
(struct hd_drive_hob_hdr *)&args->hobRegister,
args->handler);
-// } else {
-// return flagged_taskfile(drive, args);
-// }
if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) ||
(args->command_type == IDE_DRIVE_TASK_OUT)) &&
@@ -1338,16 +1352,21 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE))
return execute_drive_cmd(drive, rq);
- if (drive->driver != NULL) {
- return ata_ops(drive)->do_request(drive, rq, block);
+ if (ata_ops(drive)) {
+ if (ata_ops(drive)->do_request)
+ return ata_ops(drive)->do_request(drive, rq, block);
+ else {
+ ide_end_request(drive, 0);
+ return ide_stopped;
+ }
}
printk(KERN_WARNING "%s: device type %d not supported\n",
drive->name, drive->type);
goto kill_rq;
}
- return do_special(drive);
+ return ata_special(drive);
kill_rq:
- if (drive->driver != NULL)
+ if (ata_ops(drive) && ata_ops(drive)->end_request)
ata_ops(drive)->end_request(drive, 0);
else
ide_end_request(drive, 0);
@@ -1389,7 +1408,7 @@ static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
{
ide_drive_t *drive, *best;
-repeat:
+repeat:
best = NULL;
drive = hwgroup->drive;
do {
@@ -1416,7 +1435,7 @@ repeat:
&& 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
&& 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
{
- ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP));
+ ide_stall_queue(best, min(t, 10L * WAIT_MIN_SLEEP));
goto repeat;
}
} while ((drive = drive->next) != best);
@@ -1455,7 +1474,7 @@ repeat:
* will start the next request from the queue. If no more work remains,
* the driver will clear the hwgroup->flags IDE_BUSY flag and exit.
*/
-static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
+static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
{
ide_drive_t *drive;
ide_hwif_t *hwif;
@@ -1502,7 +1521,11 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
hwif = HWIF(drive);
if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) {
/* set nIEN for previous hwif */
- SELECT_INTERRUPT(hwif, drive);
+
+ if (hwif->intrproc)
+ hwif->intrproc(drive);
+ else
+ OUT_BYTE((drive)->ctl|2, hwif->io_ports[IDE_CONTROL_OFFSET]);
}
hwgroup->hwif = hwif;
hwgroup->drive = drive;
@@ -1539,7 +1562,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
}
/*
- * ide_get_queue() returns the queue which corresponds to a given device.
+ * Returns the queue which corresponds to a given device.
*/
request_queue_t *ide_get_queue (kdev_t dev)
{
@@ -1558,7 +1581,7 @@ void do_ide_request(request_queue_t *q)
/*
* un-busy the hwgroup etc, and clear any pending DMA status. we want to
- * retry the current request in pio mode instead of risking tossing it
+ * retry the current request in PIO mode instead of risking tossing it
* all away
*/
void ide_dma_timeout_retry(ide_drive_t *drive)
@@ -1569,13 +1592,13 @@ void ide_dma_timeout_retry(ide_drive_t *drive)
/*
* end current dma transaction
*/
- (void) hwif->dmaproc(ide_dma_end, drive);
+ hwif->dmaproc(ide_dma_end, drive);
/*
* complain a little, later we might remove some of this verbosity
*/
printk("%s: timeout waiting for DMA\n", drive->name);
- (void) hwif->dmaproc(ide_dma_timeout, drive);
+ hwif->dmaproc(ide_dma_timeout, drive);
/*
* disable dma for now, but remember that we did so because of
@@ -1584,7 +1607,7 @@ void ide_dma_timeout_retry(ide_drive_t *drive)
*/
drive->retry_pio++;
drive->state = DMA_PIO_RETRY;
- (void) hwif->dmaproc(ide_dma_off_quietly, drive);
+ hwif->dmaproc(ide_dma_off_quietly, drive);
/*
* un-busy drive etc (hwgroup->busy is cleared on return) and
@@ -1611,7 +1634,7 @@ void ide_timer_expiry (unsigned long data)
ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
ide_handler_t *handler;
ide_expiry_t *expiry;
- unsigned long flags;
+ unsigned long flags;
unsigned long wait;
/*
@@ -1712,7 +1735,7 @@ void ide_timer_expiry (unsigned long data)
* drive is ready to accept one, in which case we know the drive is not
* trying to interrupt us. And ide_set_handler() is always invoked before
* completing the issuance of any new drive command, so we will not be
- * accidently invoked as a result of any valid command completion interrupt.
+ * accidentally invoked as a result of any valid command completion interrupt.
*
*/
static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
@@ -1937,16 +1960,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
}
-/* Common for ide-floppy.c and ide-disk.c */
-void ide_revalidate_drive (ide_drive_t *drive)
-{
- struct gendisk *g = HWIF(drive)->gd;
- int minor = (drive->select.b.unit << g->minor_shift);
- kdev_t dev = mk_kdev(g->major, minor);
-
- grok_partitions(dev, current_capacity(drive));
-}
-
/*
* This routine is called to flush all partitions and partition tables
* for a changed disk, and then re-read the new partition table.
@@ -1975,13 +1988,16 @@ int ide_revalidate_disk (kdev_t i_rdev)
spin_unlock_irqrestore(&ide_lock, flags);
res = wipe_partitions(i_rdev);
- if (res)
- goto leave;
-
- if (ata_ops(drive)->revalidate)
- ata_ops(drive)->revalidate(drive);
+ if (!res) {
+ if (ata_ops(drive) && ata_ops(drive)->revalidate) {
+ ata_get(ata_ops(drive));
+ /* this is a no-op for tapes and SCSI based access */
+ ata_ops(drive)->revalidate(drive);
+ ata_put(ata_ops(drive));
+ } else
+ grok_partitions(i_rdev, ata_capacity(drive));
+ }
- leave:
drive->busy = 0;
wake_up(&drive->wqueue);
MOD_DEC_USE_COUNT;
@@ -1990,13 +2006,14 @@ int ide_revalidate_disk (kdev_t i_rdev)
/*
* Look again for all drives in the system on all interfaces. This is used
- * after a new driver cathegory has been loaded as module.
+ * after a new driver category has been loaded as module.
*/
-void revalidate_drives (void)
+void revalidate_drives(void)
{
ide_hwif_t *hwif;
ide_drive_t *drive;
- int index, unit;
+ int index;
+ int unit;
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
@@ -2011,7 +2028,7 @@ void revalidate_drives (void)
}
}
-static void ide_probe_module (void)
+static void ide_probe_module(void)
{
ideprobe_init();
revalidate_drives();
@@ -2030,7 +2047,7 @@ search:
revalidate_drives();
}
-static int ide_open (struct inode * inode, struct file * filp)
+static int ide_open(struct inode * inode, struct file * filp)
{
ide_drive_t *drive;
@@ -2048,35 +2065,42 @@ static int ide_open (struct inode * inode, struct file * filp)
#ifdef CONFIG_KMOD
if (drive->driver == NULL) {
+ char *module = NULL;
+
switch (drive->type) {
case ATA_DISK:
- request_module("ide-disk");
+ module = "ide-disk";
break;
case ATA_ROM:
- request_module("ide-cd");
+ module = "ide-cd";
break;
case ATA_TAPE:
- request_module("ide-tape");
+ module = "ide-tape";
break;
case ATA_FLOPPY:
- request_module("ide-floppy");
+ module = "ide-floppy";
break;
-#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI)
case ATA_SCSI:
- request_module("ide-scsi");
+ module = "ide-scsi";
break;
-#endif
default:
- /* nothing to be done about it */ ;
+ /* nothing we can do about it */ ;
}
+ if (module)
+ request_module(module);
}
-#endif /* CONFIG_KMOD */
+#endif
while (drive->busy)
sleep_on(&drive->wqueue);
- drive->usage++;
- if (drive->driver != NULL)
+ ++drive->usage;
+ if (ata_ops(drive) && ata_ops(drive)->open)
return ata_ops(drive)->open(inode, filp, drive);
- printk ("%s: driver not present\n", drive->name);
+ else {
+ --drive->usage;
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "%s: driver not present\n", drive->name);
drive->usage--;
return -ENXIO;
}
@@ -2085,15 +2109,16 @@ static int ide_open (struct inode * inode, struct file * filp)
* Releasing a block device means we sync() it, so that it can safely
* be forgotten about...
*/
-static int ide_release (struct inode * inode, struct file * file)
+static int ide_release(struct inode * inode, struct file * file)
{
ide_drive_t *drive;
- if ((drive = get_info_ptr(inode->i_rdev)) != NULL) {
- drive->usage--;
- if (drive->driver != NULL)
- ata_ops(drive)->release(inode, file, drive);
- }
+ if (!(drive = get_info_ptr(inode->i_rdev)))
+ return 0;
+
+ drive->usage--;
+ if (ata_ops(drive) && ata_ops(drive)->release)
+ ata_ops(drive)->release(inode, file, drive);
return 0;
}
@@ -2136,7 +2161,7 @@ jump_eight:
#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
if (hwif->io_ports[IDE_IRQ_OFFSET])
ide_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
+#endif
}
void ide_unregister (unsigned int index)
@@ -2164,11 +2189,16 @@ void ide_unregister (unsigned int index)
continue;
if (drive->busy || drive->usage)
goto abort;
- if (drive->driver != NULL && ata_ops(drive)->cleanup(drive))
- goto abort;
+ if (ata_ops(drive)) {
+ if (ata_ops(drive)->cleanup) {
+ if (ata_ops(drive)->cleanup(drive))
+ goto abort;
+ } else
+ ide_unregister_subdriver(drive);
+ }
}
hwif->present = 0;
-
+
/*
* All clear? Then blow away the buffer cache
*/
@@ -2268,7 +2298,7 @@ void ide_unregister (unsigned int index)
hwif->gd = NULL;
}
old_hwif = *hwif;
- init_hwif_data (index); /* restore hwif data to pristine status */
+ init_hwif_data(index); /* restore hwif data to pristine status */
hwif->hwgroup = old_hwif.hwgroup;
hwif->tuneproc = old_hwif.tuneproc;
hwif->speedproc = old_hwif.speedproc;
@@ -2289,14 +2319,14 @@ void ide_unregister (unsigned int index)
hwif->proc = old_hwif.proc;
#ifndef CONFIG_BLK_DEV_IDECS
hwif->irq = old_hwif.irq;
-#endif /* CONFIG_BLK_DEV_IDECS */
+#endif
hwif->major = old_hwif.major;
hwif->chipset = old_hwif.chipset;
hwif->autodma = old_hwif.autodma;
hwif->udma_four = old_hwif.udma_four;
#ifdef CONFIG_BLK_DEV_IDEPCI
hwif->pci_dev = old_hwif.pci_dev;
-#endif /* CONFIG_BLK_DEV_IDEPCI */
+#endif
hwif->straight8 = old_hwif.straight8;
abort:
restore_flags(flags); /* all CPUs */
@@ -2342,7 +2372,7 @@ void ide_setup_ports ( hw_regs_t *hw,
* Register an IDE interface, specifing exactly the registers etc
* Set init=1 iff calling before probes have taken place.
*/
-int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
+int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp)
{
int index, retry = 1;
ide_hwif_t *hwif;
@@ -2392,7 +2422,7 @@ found:
* Compatability function with existing drivers. If you want
* something different, use the function above.
*/
-int ide_register (int arg1, int arg2, int irq)
+int ide_register(int arg1, int arg2, int irq)
{
hw_regs_t hw;
ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL);
@@ -2503,7 +2533,7 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive)
/*
* FIXME: This should be changed to enqueue a special request
- * to the driver to change settings, and then wait on a sema for completion.
+ * to the driver to change settings, and then wait on a semaphore for completion.
* The current scheme of polling is kludgey, though safe enough.
*/
int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
@@ -2595,33 +2625,6 @@ void ide_add_generic_settings (ide_drive_t *drive)
ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL);
}
-int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf)
-{
- struct request rq;
- byte buffer[4];
-
- if (!buf)
- buf = buffer;
- memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
- ide_init_drive_cmd(&rq);
- rq.buffer = buf;
- *buf++ = cmd;
- *buf++ = nsect;
- *buf++ = feature;
- *buf++ = sectors;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
-int ide_wait_cmd_task (ide_drive_t *drive, byte *buf)
-{
- struct request rq;
-
- ide_init_drive_cmd(&rq);
- rq.flags = REQ_DRIVE_TASK;
- rq.buffer = buf;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
/*
* Delay for *at least* 50ms. As we don't know how much time is left
* until the next tick occurs, we wait an extra tick to be safe.
@@ -2721,7 +2724,8 @@ static int ide_ioctl (struct inode *inode, struct file *file,
}
case BLKRRPART: /* Re-read partition tables */
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return ide_revalidate_disk(inode->i_rdev);
case HDIO_OBSOLETE_IDENTITY:
@@ -2742,24 +2746,6 @@ static int ide_ioctl (struct inode *inode, struct file *file,
drive->nice2 << IDE_NICE_2,
(long *) arg);
-#ifdef CONFIG_IDE_TASK_IOCTL
- case HDIO_DRIVE_TASKFILE:
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- return -EACCES;
- switch(drive->type) {
- case ATA_DISK:
- return ide_taskfile_ioctl(drive, inode, file, cmd, arg);
-#ifdef CONFIG_PKT_TASK_IOCTL
- case ATA_CDROM:
- case ATA_TAPE:
- case ATA_FLOPPY:
- return pkt_taskfile_ioctl(drive, inode, file, cmd, arg);
-#endif
- default:
- return -ENOMSG;
- }
-#endif /* CONFIG_IDE_TASK_IOCTL */
-
case HDIO_DRIVE_CMD:
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
@@ -2807,28 +2793,15 @@ static int ide_ioctl (struct inode *inode, struct file *file,
spin_lock_irqsave(&ide_lock, flags);
if (hwgroup->handler != NULL) {
printk("%s: ide_set_handler: handler not null; %p\n", drive->name, hwgroup->handler);
- (void) hwgroup->handler(drive);
-// hwgroup->handler = NULL;
-// hwgroup->expiry = NULL;
+ hwgroup->handler(drive);
hwgroup->timer.expires = jiffies + 0;;
del_timer(&hwgroup->timer);
}
spin_unlock_irqrestore(&ide_lock, flags);
-
#endif
- (void) ide_do_reset(drive);
- if (drive->suspend_reset) {
-/*
- * APM WAKE UP todo !!
- * int nogoodpower = 1;
- * while(nogoodpower) {
- * check_power1() or check_power2()
- * nogoodpower = 0;
- * }
- * HWIF(drive)->multiproc(drive);
- */
+ ide_do_reset(drive);
+ if (drive->suspend_reset)
return ide_revalidate_disk(inode->i_rdev);
- }
return 0;
}
case BLKGETSIZE:
@@ -2842,7 +2815,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case BLKELVSET:
case BLKBSZGET:
case BLKBSZSET:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
/*
* uniform packet command handling
@@ -2866,9 +2839,9 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return 0;
default:
- if (drive->driver != NULL)
+ if (ata_ops(drive) && ata_ops(drive)->ioctl)
return ata_ops(drive)->ioctl(drive, inode, file, cmd, arg);
- return -EPERM;
+ return -EINVAL;
}
}
@@ -2878,8 +2851,14 @@ static int ide_check_media_change (kdev_t i_rdev)
if ((drive = get_info_ptr(i_rdev)) == NULL)
return -ENODEV;
- if (drive->driver != NULL)
- return ata_ops(drive)->media_change(drive);
+ if (ata_ops(drive)) {
+ ata_get(ata_ops(drive));
+ if (ata_ops(drive)->check_media_change)
+ return ata_ops(drive)->check_media_change(drive);
+ else
+ return 1; /* assume it was changed */
+ ata_put(ata_ops(drive));
+ }
return 0;
}
@@ -2975,9 +2954,11 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
}
/*
- * ide_setup() gets called VERY EARLY during initialization,
- * to handle kernel "command line" strings beginning with "hdx="
- * or "ide". Here is the complete set currently supported:
+ * This gets called VERY EARLY during initialization, to handle kernel "command
+ * line" strings beginning with "hdx=" or "ide".It gets called even before the
+ * actual module gets initialized.
+ *
+ * Here is the complete set currently supported comand line options:
*
* "hdx=" is recognized for all "x" from "a" to "h", such as "hdc".
* "idex=" is recognized for all "x" from "0" to "3", such as "ide1".
@@ -3017,7 +2998,7 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
* As for VLB, it is safest to not specify it.
*
* "idex=noprobe" : do not attempt to access/use this interface
- * "idex=base" : probe for an interface at the addr specified,
+ * "idex=base" : probe for an interface at the address specified,
* where "base" is usually 0x1f0 or 0x170
* and "ctl" is assumed to be "base"+0x206
* "idex=base,ctl" : specify both base and ctl
@@ -3063,8 +3044,8 @@ int __init ide_setup (char *s)
const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
const char max_hwif = '0' + (MAX_HWIFS - 1);
- if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */
- return 0; /* driver and not us */
+ if (!strncmp(s, "hd=", 3)) /* hd= is for hd.c driver and not us */
+ return 0;
if (strncmp(s,"ide",3) &&
strncmp(s,"idebus",6) &&
@@ -3082,7 +3063,7 @@ int __init ide_setup (char *s)
ide_doubler = 1;
return 1;
}
-#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+#endif
if (!strcmp(s, "ide=nodma")) {
printk("IDE: Prevented DMA\n");
@@ -3214,8 +3195,8 @@ int __init ide_setup (char *s)
*/
const char *ide_words[] = {
"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
- "minus8", "minus9", "minus10",
- "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
+ "minus8", "minus9", "minus10", "minus11",
+ "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
hw = s[3] - '0';
hwif = &ide_hwifs[hw];
i = match_parm(&s[4], ide_words, vals, 3);
@@ -3290,18 +3271,7 @@ int __init ide_setup (char *s)
goto done;
}
#endif /* CONFIG_BLK_DEV_QD65XX */
-#ifdef CONFIG_BLK_DEV_4DRIVES
- case -11: /* "four" drives on one set of ports */
- {
- ide_hwif_t *mate = &ide_hwifs[hw^1];
- mate->drives[0].select.all ^= 0x20;
- mate->drives[1].select.all ^= 0x20;
- hwif->chipset = mate->chipset = ide_4drives;
- mate->irq = hwif->irq;
- memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports));
- goto do_serialize;
- }
-#endif /* CONFIG_BLK_DEV_4DRIVES */
+ case -11: /* minus11 */
case -10: /* minus10 */
case -9: /* minus9 */
case -8: /* minus8 */
@@ -3368,230 +3338,14 @@ done:
return 1;
}
-/*
- * probe_for_hwifs() finds/initializes "known" IDE interfaces
- */
-static void __init probe_for_hwifs (void)
-{
-#ifdef CONFIG_PCI
- if (pci_present())
- {
-#ifdef CONFIG_BLK_DEV_IDEPCI
- ide_scan_pcibus(ide_scan_direction);
-#else
-#ifdef CONFIG_BLK_DEV_RZ1000
- {
- extern void ide_probe_for_rz100x(void);
- ide_probe_for_rz100x();
- }
-#endif /* CONFIG_BLK_DEV_RZ1000 */
-#endif /* CONFIG_BLK_DEV_IDEPCI */
- }
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_ETRAX_IDE
- {
- extern void init_e100_ide(void);
- init_e100_ide();
- }
-#endif /* CONFIG_ETRAX_IDE */
-#ifdef CONFIG_BLK_DEV_CMD640
- {
- extern void ide_probe_for_cmd640x(void);
- ide_probe_for_cmd640x();
- }
-#endif /* CONFIG_BLK_DEV_CMD640 */
-#ifdef CONFIG_BLK_DEV_PDC4030
- {
- extern int ide_probe_for_pdc4030(void);
- (void) ide_probe_for_pdc4030();
- }
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
- {
- extern void pmac_ide_probe(void);
- pmac_ide_probe();
- }
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
- {
- extern void icside_init(void);
- icside_init();
- }
-#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */
-#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
- {
- extern void rapide_init(void);
- rapide_init();
- }
-#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
-#ifdef CONFIG_BLK_DEV_GAYLE
- {
- extern void gayle_init(void);
- gayle_init();
- }
-#endif /* CONFIG_BLK_DEV_GAYLE */
-#ifdef CONFIG_BLK_DEV_FALCON_IDE
- {
- extern void falconide_init(void);
- falconide_init();
- }
-#endif /* CONFIG_BLK_DEV_FALCON_IDE */
-#ifdef CONFIG_BLK_DEV_MAC_IDE
- {
- extern void macide_init(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);
- buddha_init();
- }
-#endif /* CONFIG_BLK_DEV_BUDDHA */
-#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
- {
- extern void pnpide_init(int enable);
- pnpide_init(1);
- }
-#endif /* CONFIG_BLK_DEV_ISAPNP */
-}
-
-void __init ide_init_builtin_drivers (void)
-{
- /*
- * Probe for special PCI and other "known" interface chipsets
- */
- probe_for_hwifs ();
-
-#ifdef CONFIG_BLK_DEV_IDE
-#if defined(__mc68000__) || defined(CONFIG_APUS)
- if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
- ide_get_lock(&ide_intr_lock, NULL, NULL);/* for atari only */
- disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */
-// disable_irq_nosync(ide_hwifs[0].irq);
- }
-#endif /* __mc68000__ || CONFIG_APUS */
-
- ideprobe_init();
-
-#if defined(__mc68000__) || defined(CONFIG_APUS)
- if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
- enable_irq(ide_hwifs[0].irq);
- ide_release_lock(&ide_intr_lock);/* for atari only */
- }
-#endif /* __mc68000__ || CONFIG_APUS */
-#endif /* CONFIG_BLK_DEV_IDE */
-
-#ifdef CONFIG_PROC_FS
- proc_ide_create();
-#endif
-
- /*
- * Initialize all device type driver modules.
- */
-#ifdef CONFIG_BLK_DEV_IDEDISK
- idedisk_init();
-#endif
-#ifdef CONFIG_BLK_DEV_IDECD
- ide_cdrom_init();
-#endif
-#ifdef CONFIG_BLK_DEV_IDETAPE
- idetape_init();
-#endif
-#ifdef CONFIG_BLK_DEV_IDEFLOPPY
- idefloppy_init();
-#endif
-#ifdef CONFIG_BLK_DEV_IDESCSI
- #ifdef CONFIG_SCSI
- idescsi_init();
- #else
- #warning ide scsi-emulation selected but no SCSI-subsystem in kernel
- #endif
-#endif
-}
-
-static int default_cleanup (ide_drive_t *drive)
-{
- return ide_unregister_subdriver(drive);
-}
-
-static int default_standby (ide_drive_t *drive)
-{
- return 0;
-}
-
-static int default_flushcache (ide_drive_t *drive)
-{
- return 0;
-}
-
-static ide_startstop_t default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
-{
- ide_end_request(drive, 0);
- return ide_stopped;
-}
-
/* This is the default end request function as well */
int ide_end_request(ide_drive_t *drive, int uptodate)
{
return __ide_end_request(drive, uptodate, 0);
}
-static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -EIO;
-}
-
-static int default_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- drive->usage--;
- return -EIO;
-}
-
-static void default_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
-}
-
-static int default_check_media_change (ide_drive_t *drive)
-{
- return 1;
-}
-
-static void default_pre_reset (ide_drive_t *drive)
-{
-}
-
-static unsigned long default_capacity (ide_drive_t *drive)
-{
- return 0x7fffffff;
-}
-
-static ide_startstop_t default_special (ide_drive_t *drive)
-{
- special_t *s = &drive->special;
-
- s->all = 0;
- drive->mult_req = 0;
- return ide_stopped;
-}
-
-static int default_driver_reinit (ide_drive_t *drive)
-{
- printk(KERN_ERR "%s: does not support hotswap of device class !\n", drive->name);
-
- return 0;
-}
-
/*
- * Lookup IDE devices, which requested a particular deriver
+ * Lookup IDE devices, which requested a particular driver
*/
ide_drive_t *ide_scan_devices(byte type, const char *name, struct ata_operations *driver, int n)
{
@@ -3627,37 +3381,11 @@ int ide_register_subdriver(ide_drive_t *drive, struct ata_operations *driver)
return 1;
}
- drive->driver = driver;
-
- /* Fill in the default handlers
+ /* FIXME: This will be pushed to the drivers! Thus allowing us to
+ * save one parameter here eparate this out.
*/
- if (driver->cleanup == NULL)
- driver->cleanup = default_cleanup;
- if (driver->standby == NULL)
- driver->standby = default_standby;
- if (driver->flushcache == NULL)
- driver->flushcache = default_flushcache;
- if (driver->do_request == NULL)
- driver->do_request = default_do_request;
- if (driver->end_request == NULL)
- driver->end_request = ide_end_request;
- if (driver->ioctl == NULL)
- driver->ioctl = default_ioctl;
- if (driver->open == NULL)
- driver->open = default_open;
- if (driver->release == NULL)
- driver->release = default_release;
- if (driver->media_change == NULL)
- driver->media_change = default_check_media_change;
- if (driver->pre_reset == NULL)
- driver->pre_reset = default_pre_reset;
- if (driver->capacity == NULL)
- driver->capacity = default_capacity;
- if (driver->special == NULL)
- driver->special = default_special;
- if (driver->driver_reinit == NULL)
- driver->driver_reinit = default_driver_reinit;
+ drive->driver = driver;
restore_flags(flags); /* all CPUs */
/* FIXME: Check what this magic number is supposed to be about? */
@@ -3684,26 +3412,33 @@ int ide_register_subdriver(ide_drive_t *drive, struct ata_operations *driver)
drive->suspend_reset = 0;
#ifdef CONFIG_PROC_FS
ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive);
- ide_add_proc_entries(drive->proc, driver->proc, drive);
+ if (ata_ops(drive))
+ ide_add_proc_entries(drive->proc, ata_ops(drive)->proc, drive);
#endif
return 0;
}
+/*
+ * This is in fact the default cleanup routine.
+ *
+ * FIXME: Check whatever we maybe don't call it twice!.
+ */
int ide_unregister_subdriver(ide_drive_t *drive)
{
unsigned long flags;
save_flags(flags); /* all CPUs */
cli(); /* all CPUs */
- if (drive->usage || drive->busy || drive->driver == NULL || ata_ops(drive)->busy) {
+ if (drive->usage || drive->busy || !ata_ops(drive) || ata_ops(drive)->busy) {
restore_flags(flags); /* all CPUs */
return 1;
}
#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
pnpide_init(0);
-#endif /* CONFIG_BLK_DEV_ISAPNP */
+#endif
#ifdef CONFIG_PROC_FS
- ide_remove_proc_entries(drive->proc, ata_ops(drive)->proc);
+ if (ata_ops(drive))
+ ide_remove_proc_entries(drive->proc, ata_ops(drive)->proc);
ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
#endif
auto_remove_settings(drive);
@@ -3778,11 +3513,8 @@ EXPORT_SYMBOL(ide_do_drive_cmd);
EXPORT_SYMBOL(ide_end_drive_cmd);
EXPORT_SYMBOL(__ide_end_request);
EXPORT_SYMBOL(ide_end_request);
-EXPORT_SYMBOL(ide_revalidate_drive);
EXPORT_SYMBOL(ide_revalidate_disk);
EXPORT_SYMBOL(ide_cmd);
-EXPORT_SYMBOL(ide_wait_cmd);
-EXPORT_SYMBOL(ide_wait_cmd_task);
EXPORT_SYMBOL(ide_delay_50ms);
EXPORT_SYMBOL(ide_stall_queue);
#ifdef CONFIG_PROC_FS
@@ -3798,7 +3530,6 @@ EXPORT_SYMBOL(ide_register);
EXPORT_SYMBOL(ide_unregister);
EXPORT_SYMBOL(ide_setup_ports);
EXPORT_SYMBOL(get_info_ptr);
-EXPORT_SYMBOL(current_capacity);
static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x)
{
@@ -3828,12 +3559,14 @@ static int ide_notify_reboot (struct notifier_block *this, unsigned long event,
/* set the drive to standby */
printk("%s ", drive->name);
- if (event != SYS_RESTART)
- if (drive->driver != NULL && ata_ops(drive)->standby(drive))
- continue;
+ if (ata_ops(drive)) {
+ if (event != SYS_RESTART)
+ if (ata_ops(drive)->standby && ata_ops(drive)->standby(drive))
+ continue;
- if (drive->driver != NULL && ata_ops(drive)->cleanup(drive))
- continue;
+ if (ata_ops(drive)->cleanup)
+ ata_ops(drive)->cleanup(drive);
+ }
}
}
printk("\n");
@@ -3881,7 +3614,103 @@ static int __init ata_module_init(void)
initializing = 1;
- ide_init_builtin_drivers();
+ /*
+ * Detect and initialize "known" IDE host chip types.
+ */
+#ifdef CONFIG_PCI
+ if (pci_present()) {
+# ifdef CONFIG_BLK_DEV_IDEPCI
+ ide_scan_pcibus(ide_scan_direction);
+# else
+# ifdef CONFIG_BLK_DEV_RZ1000
+ ide_probe_for_rz100x();
+# endif
+# endif
+ }
+#endif
+
+#ifdef CONFIG_ETRAX_IDE
+ init_e100_ide();
+#endif
+#ifdef CONFIG_BLK_DEV_CMD640
+ ide_probe_for_cmd640x();
+#endif
+#ifdef CONFIG_BLK_DEV_PDC4030
+ ide_probe_for_pdc4030();
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ pmac_ide_probe();
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
+ icside_init();
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
+ rapide_init();
+#endif
+#ifdef CONFIG_BLK_DEV_GAYLE
+ gayle_init();
+#endif
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
+ falconide_init();
+#endif
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+ macide_init();
+#endif
+#ifdef CONFIG_BLK_DEV_Q40IDE
+ q40ide_init();
+#endif
+#ifdef CONFIG_BLK_DEV_BUDDHA
+ buddha_init();
+#endif
+#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
+ pnpide_init(1);
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULES)
+# if defined(__mc68000__) || defined(CONFIG_APUS)
+ if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
+ ide_get_lock(&ide_intr_lock, NULL, NULL);/* for atari only */
+ disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */
+// disable_irq_nosync(ide_hwifs[0].irq);
+ }
+# endif
+
+ ideprobe_init();
+
+# if defined(__mc68000__) || defined(CONFIG_APUS)
+ if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
+ enable_irq(ide_hwifs[0].irq);
+ ide_release_lock(&ide_intr_lock);/* for atari only */
+ }
+# endif
+#endif
+
+#ifdef CONFIG_PROC_FS
+ proc_ide_create();
+#endif
+
+ /*
+ * Initialize all device type driver modules.
+ */
+#ifdef CONFIG_BLK_DEV_IDEDISK
+ idedisk_init();
+#endif
+#ifdef CONFIG_BLK_DEV_IDECD
+ ide_cdrom_init();
+#endif
+#ifdef CONFIG_BLK_DEV_IDETAPE
+ idetape_init();
+#endif
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+ idefloppy_init();
+#endif
+#ifdef CONFIG_BLK_DEV_IDESCSI
+# ifdef CONFIG_SCSI
+ idescsi_init();
+# else
+ #warning ATA SCSI emulation selected but no SCSI-subsystem in kernel
+# endif
+#endif
initializing = 0;
@@ -3928,7 +3757,7 @@ static void __exit cleanup_ata (void)
ide_unregister(index);
# if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
if (ide_hwifs[index].dma_base)
- (void) ide_release_dma(&ide_hwifs[index]);
+ ide_release_dma(&ide_hwifs[index]);
# endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
}
diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c
index 4de087b3675d..0101c3399249 100644
--- a/drivers/ide/opti621.c
+++ b/drivers/ide/opti621.c
@@ -1,10 +1,6 @@
/*
- * linux/drivers/ide/opti621.c Version 0.6 Jan 02, 1999
- *
* Copyright (C) 1996-1998 Linus Torvalds & authors (see below)
- */
-
-/*
+ *
* Authors:
* Jaromir Koutek <miri@punknet.cz>,
* Jan Harkes <jaharkes@cwi.nl>,
@@ -62,9 +58,9 @@
* by hdparm.
*
* Version 0.1, Nov 8, 1996
- * by Jaromir Koutek, for 2.1.8.
+ * by Jaromir Koutek, for 2.1.8.
* Initial version of driver.
- *
+ *
* Version 0.2
* Number 0.2 skipped.
*
@@ -80,14 +76,13 @@
* by Jaromir Koutek
* Updates for use with (again) new IDE block driver.
* Update of documentation.
- *
+ *
* Version 0.6, Jan 2, 1999
* by Jaromir Koutek
* Reversed to version 0.3 of the driver, because
* 0.5 doesn't work.
*/
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
#define OPTI621_DEBUG /* define for debug messages */
#include <linux/types.h>
diff --git a/drivers/ide/pdcraid.c b/drivers/ide/pdcraid.c
index 93e65583cac3..cdb18724f39d 100644
--- a/drivers/ide/pdcraid.c
+++ b/drivers/ide/pdcraid.c
@@ -148,7 +148,7 @@ static int pdcraid_ioctl(struct inode *inode, struct file *file, unsigned int cm
case BLKROSET:
case BLKROGET:
case BLKSSZGET:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
printk("Invalid ioctl \n");
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index c517f2d947c3..8e72e450e6a5 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -214,7 +214,7 @@ static void piix_tune_drive (ide_drive_t *drive, byte pio)
{
unsigned long flags;
u16 master_data;
- byte slave_data;
+ u8 slave_data;
int is_slave = (&HWIF(drive)->drives[1] == drive);
int master_port = HWIF(drive)->index ? 0x42 : 0x40;
int slave_port = 0x44;
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
index b22afe68b319..334343b1ee44 100644
--- a/drivers/ide/qd65xx.c
+++ b/drivers/ide/qd65xx.c
@@ -1,6 +1,4 @@
/*
- * linux/drivers/ide/qd65xx.c Version 0.07 Sep 30, 2001
- *
* Copyright (C) 1996-2001 Linus Torvalds & author (see below)
*/
@@ -9,24 +7,20 @@
* Version 0.04 Added second channel tuning
* Version 0.05 Enhanced tuning ; added qd6500 support
* Version 0.06 Added dos driver's list
- * Version 0.07 Second channel bug fix
+ * Version 0.07 Second channel bug fix
*
* QDI QD6500/QD6580 EIDE controller fast support
*
* Please set local bus speed using kernel parameter idebus
- * for example, "idebus=33" stands for 33Mhz VLbus
+ * for example, "idebus=33" stands for 33Mhz VLbus
* To activate controller support, use "ide0=qd65xx"
* To enable tuning, use "ide0=autotune"
* To enable second channel tuning (qd6580 only), use "ide1=autotune"
- */
-
-/*
+ *
* Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
* Samuel Thibault <samuel.thibault@fnac.net>
*/
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
@@ -262,7 +256,7 @@ static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time)) {
pio = ide_get_best_pio_mode(drive, pio, 255, &d);
- pio = IDE_MIN(pio,4);
+ pio = min(pio,4);
switch (pio) {
case 0: break;
diff --git a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c
index 43c88bfda697..644ed6038a44 100644
--- a/drivers/ide/rz1000.c
+++ b/drivers/ide/rz1000.c
@@ -1,10 +1,6 @@
/*
- * linux/drivers/ide/rz1000.c Version 0.05 December 8, 1997
- *
* Copyright (C) 1995-1998 Linus Torvalds & author (see below)
- */
-
-/*
+ *
* Principal Author: mlord@pobox.com (Mark Lord)
*
* See linux/MAINTAINERS for address of current maintainer.
@@ -15,8 +11,6 @@
* Dunno if this fixes both ports, or only the primary port (?).
*/
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
#include <linux/config.h> /* for CONFIG_BLK_DEV_IDEPCI */
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
index a87861ac0b22..c687fade4b1d 100644
--- a/drivers/ide/serverworks.c
+++ b/drivers/ide/serverworks.c
@@ -660,8 +660,10 @@ void __init ide_init_svwks (ide_hwif_t *hwif)
hwif->autodma = 0;
#else /* CONFIG_BLK_DEV_IDEDMA */
if (hwif->dma_base) {
+#ifdef CONFIG_IDEDMA_AUTO
if (!noautodma)
hwif->autodma = 1;
+#endif
hwif->dmaproc = &svwks_dmaproc;
hwif->highmem = 1;
} else {
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index 5bde8e15689c..136d3a346204 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -178,7 +178,8 @@ act2000_isa_config_port(act2000_card * card, unsigned short portbase)
card->flags &= ~ACT2000_FLAGS_PVALID;
}
if (!check_region(portbase, ISA_REGION)) {
- request_region(portbase, ACT2000_PORTLEN, card->regname);
+ if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
+ return -EIO;
card->port = portbase;
card->flags |= ACT2000_FLAGS_PVALID;
return 0;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3bbbc201f4ee..5e542a243ea4 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -645,8 +645,14 @@ static int lock_rdev(mdk_rdev_t *rdev)
if (!bdev)
return -ENOMEM;
err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW);
- if (!err)
- rdev->bdev = bdev;
+ if (err)
+ return err;
+ err = bd_claim(bdev, lock_rdev);
+ if (err) {
+ blkdev_put(bdev, BDEV_RAW);
+ return err;
+ }
+ rdev->bdev = bdev;
return err;
}
@@ -656,6 +662,7 @@ static void unlock_rdev(mdk_rdev_t *rdev)
rdev->bdev = NULL;
if (!bdev)
MD_BUG();
+ bd_release(bdev);
blkdev_put(bdev, BDEV_RAW);
}
@@ -1086,13 +1093,6 @@ static int md_import_device(kdev_t newdev, int on_disk)
}
memset(rdev, 0, sizeof(*rdev));
- if (is_mounted(newdev)) {
- printk(KERN_WARNING "md: can not import %s, has active inodes!\n",
- partition_name(newdev));
- err = -EBUSY;
- goto abort_free;
- }
-
if ((err = alloc_disk_sb(rdev)))
goto abort_free;
@@ -2625,7 +2625,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
case BLKFLSBUF:
case BLKBSZGET:
case BLKBSZSET:
- err = blk_ioctl(dev, cmd, arg);
+ err = blk_ioctl(inode->i_bdev, cmd, arg);
goto abort;
default:;
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 243b962d66ab..c229b896d48a 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -1105,7 +1105,7 @@ static int i2ob_ioctl(struct inode *inode, struct file *file,
case BLKROSET:
case BLKROGET:
case BLKPG:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
default:
return -EINVAL;
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index cc647503bccb..cbe5996c9ef7 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -715,7 +715,7 @@ int __init init_pmc551(void)
}
/*
- * This is needed untill the driver is capable of reading the
+ * This is needed until the driver is capable of reading the
* onboard I2C SROM to discover the "real" memory size.
*/
if(msize) {
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 8e6ce8dab20e..1fc63d360def 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1144,7 +1144,7 @@ static int ftl_ioctl(struct inode *inode, struct file *file,
case BLKROSET:
case BLKROGET:
case BLKFLSBUF:
- ret = blk_ioctl(inode->i_rdev, cmd, arg);
+ ret = blk_ioctl(inode->i_bdev, cmd, arg);
break;
default:
ret = -EINVAL;
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
index 4c7c9a57056f..df2f7bc6c560 100644
--- a/drivers/mtd/nand/spia.c
+++ b/drivers/mtd/nand/spia.c
@@ -113,7 +113,7 @@ int __init spia_init (void)
this->ALE = 0x02;
this->NCE = 0x04;
- /* Scan to find existance of the device */
+ /* Scan to find existence of the device */
if (nand_scan (spia_mtd)) {
kfree (spia_mtd);
return -ENXIO;
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index 7b41b62ad37c..2b60ed1319e4 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -823,7 +823,7 @@ static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd
case BLKROSET:
case BLKROGET:
case BLKSSZGET:
- return blk_ioctl(inode->i_rdev, cmd, arg);
+ return blk_ioctl(inode->i_bdev, cmd, arg);
#endif
default:
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index b0967446175d..945476049d31 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -692,9 +692,11 @@ static int xcvr[MAX_EL2_CARDS]; /* choose int. or ext. xcvr */
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i");
MODULE_PARM(xcvr, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i");
-MODULE_PARM_DESC(io, "EtherLink II I/O base address(es)");
-MODULE_PARM_DESC(irq, "EtherLink II IRQ number(s) (assigned)");
-MODULE_PARM_DESC(xcvr, "EtherLink II tranceiver(s) (0=internal, 1=external)");
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_PARM_DESC(xcvr, "tranceiver(s) (0=internal, 1=external)");
+MODULE_DESCRIPTION("3Com ISA EtherLink II, II/16 (3c503, 3c503/16) driver");
+MODULE_LICENSE("GPL");
/* This is set up so that only a single autoprobe takes place per call.
ISA device autoprobes on a running machine are not recommended. */
@@ -742,7 +744,6 @@ cleanup_module(void)
}
}
#endif /* MODULE */
-MODULE_LICENSE("GPL");
/*
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index c3d130078869..c49bf4769745 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -1350,87 +1350,6 @@ static void elp_set_mc_list(struct net_device *dev)
}
}
-/**
- * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
- * @dev: network interface on which out-of-band action is to be performed
- * @useraddr: userspace address to which data is to be read and returned
- *
- * Process the various commands of the SIOCETHTOOL interface.
- */
-
-static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
-{
- u32 ethcmd;
-
- /* dev_ioctl() in ../../net/core/dev.c has already checked
- capable(CAP_NET_ADMIN), so don't bother with that here. */
-
- if (get_user(ethcmd, (u32 *)useraddr))
- return -EFAULT;
-
- switch (ethcmd) {
-
- case ETHTOOL_GDRVINFO: {
- struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
- strcpy (info.driver, DRV_NAME);
- strcpy (info.version, DRV_VERSION);
- sprintf(info.bus_info, "ISA 0x%lx", dev->base_addr);
- if (copy_to_user (useraddr, &info, sizeof (info)))
- return -EFAULT;
- return 0;
- }
-
- /* get message-level */
- case ETHTOOL_GMSGLVL: {
- struct ethtool_value edata = {ETHTOOL_GMSGLVL};
- edata.data = debug;
- if (copy_to_user(useraddr, &edata, sizeof(edata)))
- return -EFAULT;
- return 0;
- }
- /* set message-level */
- case ETHTOOL_SMSGLVL: {
- struct ethtool_value edata;
- if (copy_from_user(&edata, useraddr, sizeof(edata)))
- return -EFAULT;
- debug = edata.data;
- return 0;
- }
-
- default:
- break;
- }
-
- return -EOPNOTSUPP;
-}
-
-/**
- * netdev_ioctl: Handle network interface ioctls
- * @dev: network interface on which out-of-band action is to be performed
- * @rq: user request data
- * @cmd: command issued by user
- *
- * Process the various out-of-band ioctls passed to this driver.
- */
-
-static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
-{
- int rc = 0;
-
- switch (cmd) {
- case SIOCETHTOOL:
- rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
- break;
-
- default:
- rc = -EOPNOTSUPP;
- break;
- }
-
- return rc;
-}
-
-
/******************************************************
*
* initialise Etherlink Plus board
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index f61650db748f..6415a1d880ac 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -1103,14 +1103,15 @@ MODULE_PARM(debug,"i");
MODULE_PARM(irq,"1-8i");
MODULE_PARM(xcvr,"1-8i");
MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM_DESC(debug, "EtherLink III debug level (0-6)");
-MODULE_PARM_DESC(irq, "EtherLink III IRQ number(s) (assigned)");
-MODULE_PARM_DESC(xcvr,"EtherLink III tranceiver(s) (0=internal, 1=external)");
-MODULE_PARM_DESC(max_interrupt_work, "EtherLink III maximum events handled per interrupt");
+MODULE_PARM_DESC(debug, "debug level (0-6)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_PARM_DESC(xcvr,"tranceiver(s) (0=internal, 1=external)");
+MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
#ifdef __ISAPNP__
MODULE_PARM(nopnp, "i");
-MODULE_PARM_DESC(nopnp, "EtherLink III disable ISA PnP support (0-1)");
+MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
#endif /* __ISAPNP__ */
+MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B) ISA/PnP ethernet driver");
int
init_module(void)
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 2c7f24b59aa1..7620cdd6cfec 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -2,6 +2,7 @@
/*
Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com>
+ Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) [tg3.c]
Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) [sungem.c]
Copyright 2001 Manfred Spraul [natsemi.c]
Copyright 1999-2001 by Donald Becker. [natsemi.c]
@@ -29,8 +30,8 @@
* Consider Rx interrupt mitigation using TimerIntr
* Implement 8139C+ statistics dump; maybe not...
h/w stats can be reset only by software reset
- * Rx checksumming
* Tx checksumming
+ * Handle netif_rx return value
* ETHTOOL_GREGS, ETHTOOL_[GS]WOL,
* Investigate using skb->priority with h/w VLAN priority
* Investigate using High Priority Tx Queue with skb->priority
@@ -38,8 +39,8 @@
* Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error
* Implement Tx software interrupt mitigation via
Tx descriptor bit
- * Determine correct value for CP_{MIN,MAX}_MTU, instead of
- using conservative guesses.
+ * The real minimum of CP_MIN_MTU is 4 bytes. However,
+ for this to be supported, one must(?) turn on packet padding.
*/
@@ -48,8 +49,10 @@
#define DRV_RELDATE "Feb 27, 2002"
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/compiler.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
@@ -57,9 +60,15 @@
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
+#include <linux/if_vlan.h>
+#include <linux/crc32.h>
#include <asm/io.h>
#include <asm/uaccess.h>
+#define CP_VLAN_TAG_USED 0
+#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
+ do { (tx_desc)->opts2 = 0; } while (0)
+
/* These identify the driver base version and may not be removed. */
static char version[] __devinitdata =
KERN_INFO DRV_NAME " 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -110,8 +119,8 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered mul
#define TX_TIMEOUT (6*HZ)
/* hardware minimum and maximum for a single frame's data payload */
-#define CP_MIN_MTU 60 /* FIXME: this is a guess */
-#define CP_MAX_MTU 1500 /* FIXME: this is a guess */
+#define CP_MIN_MTU 60 /* TODO: allow lower, but pad */
+#define CP_MAX_MTU 4096
enum {
/* NIC register offsets */
@@ -153,12 +162,17 @@ enum {
IPCS = (1 << 18), /* Calculate IP checksum */
UDPCS = (1 << 17), /* Calculate UDP/IP checksum */
TCPCS = (1 << 16), /* Calculate TCP/IP checksum */
+ TxVlanTag = (1 << 17), /* Add VLAN tag */
+ RxVlanTagged = (1 << 16), /* Rx VLAN tag available */
IPFail = (1 << 15), /* IP checksum failed */
UDPFail = (1 << 14), /* UDP/IP checksum failed */
TCPFail = (1 << 13), /* TCP/IP checksum failed */
NormalTxPoll = (1 << 6), /* One or more normal Tx packets to send */
PID1 = (1 << 17), /* 2 protocol id bits: 0==non-IP, */
PID0 = (1 << 16), /* 1==UDP/IP, 2==TCP/IP, 3==IP */
+ RxProtoTCP = 2,
+ RxProtoUDP = 1,
+ RxProtoIP = 3,
TxFIFOUnder = (1 << 25), /* Tx FIFO underrun */
TxOWC = (1 << 22), /* Tx Out-of-window collision */
TxLinkFail = (1 << 21), /* Link failed during Tx of packet */
@@ -208,6 +222,7 @@ enum {
TxOn = (1 << 2), /* Tx mode enable */
/* C+ mode command register */
+ RxVlanOn = (1 << 6), /* Rx VLAN de-tagging enable */
RxChkSum = (1 << 5), /* Rx checksum offload enable */
PCIMulRW = (1 << 3), /* Enable PCI read/write multiple */
CpRxOn = (1 << 1), /* Rx mode enable */
@@ -278,6 +293,10 @@ struct cp_private {
unsigned rx_buf_sz;
dma_addr_t ring_dma;
+#if CP_VLAN_TAG_USED
+ struct vlan_group *vlgrp;
+#endif
+
u32 msg_enable;
struct net_device_stats net_stats;
@@ -335,14 +354,21 @@ static inline void cp_set_rxbufsize (struct cp_private *cp)
cp->rx_buf_sz = PKT_BUF_SZ;
}
-static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb)
+static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb,
+ struct cp_desc *desc)
{
skb->protocol = eth_type_trans (skb, cp->dev);
cp->net_stats.rx_packets++;
cp->net_stats.rx_bytes += skb->len;
cp->dev->last_rx = jiffies;
- netif_rx (skb);
+
+#if CP_VLAN_TAG_USED
+ if (cp->vlgrp && (desc->opts2 & RxVlanTagged)) {
+ vlan_hwaccel_rx(skb, cp->vlgrp, desc->opts2 & 0xffff);
+ } else
+#endif
+ netif_rx(skb);
}
static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
@@ -425,13 +451,26 @@ drop_frag:
cp_rx_err_acct(cp, rx_tail, status, len);
dev_kfree_skb_irq(copy_skb);
} else
- cp_rx_skb(cp, copy_skb);
+ cp_rx_skb(cp, copy_skb, &cp->rx_ring[rx_tail]);
cp->frag_skb = NULL;
} else {
cp->frag_skb = copy_skb;
}
}
+static inline unsigned int cp_rx_csum_ok (u32 status)
+{
+ unsigned int protocol = (status >> 16) & 0x3;
+
+ if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
+ return 1;
+ else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
+ return 1;
+ else if ((protocol == RxProtoIP) && (!(status & IPFail)))
+ return 1;
+ return 0;
+}
+
static void cp_rx (struct cp_private *cp)
{
unsigned rx_tail = cp->rx_tail;
@@ -441,13 +480,15 @@ static void cp_rx (struct cp_private *cp)
u32 status, len;
dma_addr_t mapping;
struct sk_buff *skb, *new_skb;
+ struct cp_desc *desc;
unsigned buflen;
skb = cp->rx_skb[rx_tail].skb;
if (!skb)
BUG();
- rmb();
- status = le32_to_cpu(cp->rx_ring[rx_tail].opts1);
+
+ desc = &cp->rx_ring[rx_tail];
+ status = le32_to_cpu(desc->opts1);
if (status & DescOwn)
break;
@@ -480,7 +521,13 @@ static void cp_rx (struct cp_private *cp)
pci_unmap_single(cp->pdev, mapping,
buflen, PCI_DMA_FROMDEVICE);
- skb->ip_summed = CHECKSUM_NONE;
+
+ /* Handle checksum offloading for incoming packets. */
+ if (cp_rx_csum_ok(status))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+
skb_put(skb, len);
mapping =
@@ -489,15 +536,14 @@ static void cp_rx (struct cp_private *cp)
buflen, PCI_DMA_FROMDEVICE);
cp->rx_skb[rx_tail].skb = new_skb;
- cp_rx_skb(cp, skb);
+ cp_rx_skb(cp, skb, desc);
rx_next:
if (rx_tail == (CP_RX_RING_SIZE - 1))
- cp->rx_ring[rx_tail].opts1 =
- cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz);
+ desc->opts1 = cpu_to_le32(DescOwn | RingEnd |
+ cp->rx_buf_sz);
else
- cp->rx_ring[rx_tail].opts1 =
- cpu_to_le32(DescOwn | cp->rx_buf_sz);
+ desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
cp->rx_ring[rx_tail].opts2 = 0;
cp->rx_ring[rx_tail].addr_lo = cpu_to_le32(mapping);
rx_tail = NEXT_RX(rx_tail);
@@ -606,6 +652,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
struct cp_private *cp = dev->priv;
unsigned entry;
u32 eor;
+#if CP_VLAN_TAG_USED
+ u32 vlan_tag = 0;
+#endif
spin_lock_irq(&cp->lock);
@@ -615,6 +664,11 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
return 1;
}
+#if CP_VLAN_TAG_USED
+ if (cp->vlgrp && vlan_tx_tag_present(skb))
+ vlan_tag = TxVlanTag | vlan_tx_tag_get(skb);
+#endif
+
entry = cp->tx_head;
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
if (skb_shinfo(skb)->nr_frags == 0) {
@@ -624,7 +678,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
len = skb->len;
mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
- txd->opts2 = 0;
+ CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(mapping);
wmb();
@@ -677,7 +731,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
ctrl |= LastFrag;
txd = &cp->tx_ring[entry];
- txd->opts2 = 0;
+ CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(mapping);
wmb();
@@ -691,7 +745,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
}
txd = &cp->tx_ring[first_entry];
- txd->opts2 = 0;
+ CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(first_mapping);
wmb();
@@ -826,7 +880,7 @@ static void cp_reset_hw (struct cp_private *cp)
static inline void cp_start_hw (struct cp_private *cp)
{
cpw8(Cmd, RxOn | TxOn);
- cpw16(CpCmd, PCIMulRW | CpRxOn | CpTxOn);
+ cpw16(CpCmd, PCIMulRW | RxChkSum | CpRxOn | CpTxOn);
}
static void cp_init_hw (struct cp_private *cp)
@@ -1171,7 +1225,30 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
return rc;
}
+#if CP_VLAN_TAG_USED
+static int cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+{
+ struct cp_private *cp = dev->priv;
+
+ spin_lock_irq(&cp->lock);
+ cp->vlgrp = grp;
+ cpw16(CpCmd, cpr16(CpCmd) | RxVlanOn);
+ spin_unlock_irq(&cp->lock);
+ return 0;
+}
+
+static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+ struct cp_private *cp = dev->priv;
+
+ spin_lock_irq(&cp->lock);
+ cpw16(CpCmd, cpr16(CpCmd) & ~RxVlanOn);
+ if (cp->vlgrp)
+ cp->vlgrp->vlan_devices[vid] = NULL;
+ spin_unlock_irq(&cp->lock);
+}
+#endif
/* Serial EEPROM section. */
@@ -1337,6 +1414,11 @@ static int __devinit cp_init_one (struct pci_dev *pdev,
#ifdef CP_TX_CHECKSUM
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
#endif
+#if CP_VLAN_TAG_USED
+ dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->vlan_rx_register = cp_vlan_rx_register;
+ dev->vlan_rx_kill_vid = cp_vlan_rx_kill_vid;
+#endif
dev->irq = pdev->irq;
diff --git a/drivers/net/Config.help b/drivers/net/Config.help
index 009107037d07..2a1c47dfa8f9 100644
--- a/drivers/net/Config.help
+++ b/drivers/net/Config.help
@@ -797,6 +797,14 @@ CONFIG_SUNGEM
Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
<http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
+CONFIG_TIGON3
+ This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. This is
+ recommended. The module will be called tg3.o.
+
CONFIG_MYRI_SBUS
This driver supports MyriCOM Sbus gigabit Ethernet cards.
@@ -1325,71 +1333,6 @@ CONFIG_APRICOT
<file:Documentation/networking/net-modules.txt>. The module will be
called apricot.o.
-CONFIG_DE4X5
- This is support for the DIGITAL series of PCI/EISA Ethernet cards.
- These include the DE425, DE434, DE435, DE450 and DE500 models. If
- you have a network card of this type, say Y and read the
- Ethernet-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>. More specific
- information is contained in
- <file:Documentation/networking/de4x5.txt>.
-
- 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 de4x5.o. If you want to compile it as a
- module, say M here and read <file:Documentation/modules.txt> as well
- as <file:Documentation/networking/net-modules.txt>.
-
-CONFIG_DE2104X
- This driver is developed for the SMC EtherPower series Ethernet
- cards and also works with cards based on the DECchip
- 21040 (Tulip series) chips. Some LinkSys PCI cards are
- of this type. (If your card is NOT SMC EtherPower 10/100 PCI
- (smc9332dst), you can also try the driver for "Generic DECchip"
- cards, above. However, most people with a network card of this type
- will say Y here.) Do read the Ethernet-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>. More specific
- information is contained in
- <file:Documentation/DocBook/tulip-user.tmpl>.
-
- 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 tulip.o. If you want to compile it as a
- module, say M here and read <file:Documentation/modules.txt> as well
- as <file:Documentation/networking/net-modules.txt>.
-
-CONFIG_TULIP
- This driver is developed for the SMC EtherPower series Ethernet
- cards and also works with cards based on the DECchip
- 21040/21041/21140 (Tulip series) chips. Some LinkSys PCI cards are
- of this type. (If your card is NOT SMC EtherPower 10/100 PCI
- (smc9332dst), you can also try the driver for "Generic DECchip"
- cards, above. However, most people with a network card of this type
- will say Y here.) Do read the Ethernet-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>. More specific
- information is contained in
- <file:Documentation/networking/tulip.txt>.
-
- 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 tulip.o. If you want to compile it as a
- module, say M here and read <file:Documentation/modules.txt> as well
- as <file:Documentation/networking/net-modules.txt>.
-
-CONFIG_TULIP_MWI
- This configures your Tulip card specifically for the card and
- system cache line size type you are using.
-
- This is experimental code, not yet tested on many boards.
-
- If unsure, say N.
-
-CONFIG_TULIP_MMIO
- Use PCI shared memory for the NIC registers, rather than going through
- the Tulip's PIO (programmed I/O ports). Faster, but could produce
- obscure bugs if your mainboard has memory controller timing issues.
- If in doubt, say N.
-
CONFIG_DGRS
This is support for the Digi International RightSwitch series of
PCI/EISA Ethernet switch cards. These include the SE-4 and the SE-6
@@ -1474,18 +1417,6 @@ CONFIG_VIA_RHINE_MMIO
If unsure, say N.
-CONFIG_DM9102
- This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
- Davicom (<http://www.davicom.com.tw/>). If you have such a network
- (Ethernet) card, say Y. Some information is contained in the file
- <file:Documentation/networking/dmfe.txt>.
-
- 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 dmfe.o. If you want to compile it as a
- module, say M here and read <file:Documentation/modules.txt> as well
- as <file:Documentation/networking/net-modules.txt>.
-
CONFIG_ES3210
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@@ -1517,12 +1448,6 @@ CONFIG_SUNDANCE
More specific information and updates are available from
<http://www.scyld.com/network/sundance.html>.
-CONFIG_WINBOND_840
- This driver is for the Winbond W89c840 chip. It also works with
- the TX9882 chip on the Compex RL100-ATX board.
- More specific information and updates are available from
- <http://www.scyld.com/network/drivers.html>.
-
CONFIG_ZNET
The Zenith Z-Note notebook computer has a built-in network
(Ethernet) card, and this is the Linux driver for it. Note that the
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index a752f38279b1..c715ce2ec6a8 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -148,25 +148,18 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
if [ "$CONFIG_NET_PCI" = "y" ]; then
dep_tristate ' AMD PCnet32 PCI support' CONFIG_PCNET32 $CONFIG_PCI
- dep_tristate ' Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI $CONFIG_EXPERIMENTAL
+ dep_tristate ' Adaptec Starfire/DuraLAN support' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI
if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" ]; then
dep_tristate ' Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 $CONFIG_EXPERIMENTAL
fi
dep_tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT $CONFIG_ISA
dep_tristate ' CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA
- dep_tristate ' Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)' CONFIG_DE2104X $CONFIG_PCI $CONFIG_EXPERIMENTAL
- dep_tristate ' DECchip Tulip (dc2114x) PCI support' CONFIG_TULIP $CONFIG_PCI
- if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then
- dep_bool ' New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL
- bool ' Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO
- fi
if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then
- tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
fi
- dep_tristate ' Davicom DM910x/DM980x support' CONFIG_DM9102 $CONFIG_PCI
- dep_tristate ' EtherExpressPro/100 support' CONFIG_EEPRO100 $CONFIG_PCI
+ dep_tristate ' EtherExpressPro/100 support (eepro100, original Becker driver)' CONFIG_EEPRO100 $CONFIG_PCI
+ dep_tristate ' EtherExpressPro/100 support (e100, Alternate Intel driver)' CONFIG_E100 $CONFIG_PCI
dep_tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL
dep_tristate ' Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI
dep_tristate ' National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI
@@ -190,7 +183,6 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
dep_tristate ' VIA Rhine support' CONFIG_VIA_RHINE $CONFIG_PCI
dep_mbool ' Use MMIO instead of PIO (EXPERIMENTAL)' CONFIG_VIA_RHINE_MMIO $CONFIG_VIA_RHINE $CONFIG_EXPERIMENTAL
- dep_tristate ' Winbond W89c840 Ethernet support' CONFIG_WINBOND_840 $CONFIG_PCI
if [ "$CONFIG_OBSOLETE" = "y" ]; then
dep_bool ' Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET $CONFIG_ISA
fi
@@ -237,6 +229,7 @@ dep_tristate 'National Semiconduct DP83820 support' CONFIG_NS83820 $CONFIG_PCI
dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI
dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI
+dep_tristate 'Broadcom Tigon3 support' CONFIG_TIGON3 $CONFIG_PCI
endmenu
@@ -326,6 +319,9 @@ fi
source drivers/net/wan/Config.in
+if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" -o "$CONFIG_CARDBUS" != "n" ]; then
+ source drivers/net/tulip/Config.in
+fi
if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
source drivers/net/pcmcia/Config.in
fi
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index cda7f30811cf..f423ce03e25a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -8,7 +8,7 @@ obj-m :=
obj-n :=
obj- :=
-mod-subdirs := appletalk arcnet fc irda tokenring pcmcia wireless wan
+mod-subdirs := appletalk arcnet fc irda tokenring tulip pcmcia wireless wan
O_TARGET := net.o
@@ -21,10 +21,9 @@ export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.o \
list-multi := rcpci.o
rcpci-objs := rcpci45.o rclanmtl.o
-ifeq ($(CONFIG_TULIP),y)
- obj-y += tulip/tulip.o
+ifeq ($(CONFIG_E100),y)
+ obj-y += e100/e100.o
endif
-
ifeq ($(CONFIG_E1000),y)
obj-y += e1000/e1000.o
endif
@@ -35,7 +34,8 @@ endif
subdir-$(CONFIG_NET_PCMCIA) += pcmcia
subdir-$(CONFIG_NET_WIRELESS) += wireless
-subdir-$(CONFIG_TULIP) += tulip
+subdir-$(CONFIG_NET_TULIP) += tulip
+subdir-$(CONFIG_E100) += e100
subdir-$(CONFIG_E1000) += e1000
subdir-$(CONFIG_IRDA) += irda
subdir-$(CONFIG_TR) += tokenring
@@ -74,7 +74,6 @@ obj-$(CONFIG_EEPRO100) += eepro100.o
obj-$(CONFIG_TLAN) += tlan.o
obj-$(CONFIG_EPIC100) += epic100.o mii.o
obj-$(CONFIG_SIS900) += sis900.o
-obj-$(CONFIG_DM9102) += dmfe.o
obj-$(CONFIG_YELLOWFIN) += yellowfin.o
obj-$(CONFIG_ACENIC) += acenic.o
obj-$(CONFIG_VETH) += veth.o
@@ -82,6 +81,7 @@ obj-$(CONFIG_NATSEMI) += natsemi.o
obj-$(CONFIG_NS83820) += ns83820.o
obj-$(CONFIG_STNIC) += stnic.o 8390.o
obj-$(CONFIG_FEALNX) += fealnx.o mii.o
+obj-$(CONFIG_TIGON3) += tg3.o
ifeq ($(CONFIG_SK98LIN),y)
obj-y += sk98lin/sk98lin.o
@@ -104,7 +104,7 @@ obj-$(CONFIG_AIRONET4500_NONCS) += aironet4500_card.o
obj-$(CONFIG_AIRONET4500_PROC) += aironet4500_proc.o
obj-$(CONFIG_AIRONET4500_CS) += aironet4500_proc.o
-obj-$(CONFIG_WINBOND_840) += winbond-840.o mii.o
+obj-$(CONFIG_WINBOND_840) += mii.o
obj-$(CONFIG_SUNDANCE) += sundance.o
obj-$(CONFIG_HAMACHI) += hamachi.o
obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
@@ -176,8 +176,6 @@ obj-$(CONFIG_LAN_SAA9730) += saa9730.o
obj-$(CONFIG_DEPCA) += depca.o
obj-$(CONFIG_EWRK3) += ewrk3.o
obj-$(CONFIG_ATP) += atp.o
-obj-$(CONFIG_DE4X5) += de4x5.o
-obj-$(CONFIG_DE2104X) += de2104x.o
obj-$(CONFIG_NI5010) += ni5010.o
obj-$(CONFIG_NI52) += ni52.o
obj-$(CONFIG_NI65) += ni65.o
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 7cac667930e3..ced6b5033411 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -346,9 +346,11 @@ static int mem[MAX_AC32_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i");
MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i");
-MODULE_PARM_DESC(io, "ac3200 I/O base adress(es)");
-MODULE_PARM_DESC(irq, "ac3200 IRQ number(s)");
-MODULE_PARM_DESC(mem, "ac3200 Memory base address(es)");
+MODULE_PARM_DESC(io, "I/O base adress(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, "Memory base address(es)");
+MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
+MODULE_LICENSE("GPL");
int
init_module(void)
@@ -395,7 +397,6 @@ cleanup_module(void)
}
}
#endif /* MODULE */
-MODULE_LICENSE("GPL");
/*
diff --git a/drivers/net/e100/Makefile b/drivers/net/e100/Makefile
new file mode 100644
index 000000000000..587a0f1ff5ed
--- /dev/null
+++ b/drivers/net/e100/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the Intel's E100 ethernet driver
+#
+# 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...
+
+O_TARGET := e100.o
+
+obj-y := e100_main.o e100_config.o e100_proc.o e100_phy.o \
+ e100_eeprom.o
+obj-m := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff --git a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h
new file mode 100644
index 000000000000..77e1fb553c65
--- /dev/null
+++ b/drivers/net/e100/e100.h
@@ -0,0 +1,1033 @@
+/*******************************************************************************
+
+This software program is available to you under a choice of one of two
+licenses. You may choose to be licensed under either the GNU General Public
+License (GPL) Version 2, June 1991, available at
+http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+text of which follows:
+
+Recipient has requested a license and Intel Corporation ("Intel") is willing
+to grant a license for the software entitled Linux Base Driver for the
+Intel(R) PRO/100 Family of Adapters (e100) (the "Software") being provided
+by Intel Corporation. The following definitions apply to this license:
+
+"Licensed Patents" means patent claims licensable by Intel Corporation which
+are necessarily infringed by the use of sale of the Software alone or when
+combined with the operating system referred to below.
+
+"Recipient" means the party to whom Intel delivers this Software.
+
+"Licensee" means Recipient and those third parties that receive a license to
+any operating system available under the GNU Public License version 2.0 or
+later.
+
+Copyright (c) 1999 - 2002 Intel Corporation.
+All rights reserved.
+
+The license is provided to Recipient and Recipient's Licensees under the
+following terms.
+
+Redistribution and use in source and binary forms of the Software, with or
+without modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code of the Software may retain the above
+copyright notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form of the Software may reproduce the above
+copyright notice, this list of conditions and the following disclaimer in
+the documentation and/or materials provided with the distribution.
+
+Neither the name of Intel Corporation nor the names of its contributors
+shall be used to endorse or promote products derived from this Software
+without specific prior written permission.
+
+Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell, offer
+to sell, import and otherwise transfer the Software, if any, in source code
+and object code form. This license shall include changes to the Software
+that are error corrections or other minor changes to the Software that do
+not add functionality or features when the Software is incorporated in any
+version of an operating system that has been distributed under the GNU
+General Public License 2.0 or later. This patent license shall apply to the
+combination of the Software and any operating system licensed under the GNU
+Public License version 2.0 or later if, at the time Intel provides the
+Software to Recipient, such addition of the Software to the then publicly
+available versions of such operating systems available under the GNU Public
+License version 2.0 or later (whether in gold, beta or alpha form) causes
+such combination to be covered by the Licensed Patents. The patent license
+shall not apply to any other combinations which include the Software. NO
+hardware per se is licensed hereunder.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) 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.
+*******************************************************************************/
+
+#ifndef _E100_INC_
+#define _E100_INC_
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <asm/processor.h>
+#ifdef SIOCETHTOOL
+#include <linux/ethtool.h>
+#include <linux/inetdevice.h>
+#endif
+
+#include <linux/if.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/ip.h>
+
+/*
+ * Configure parameters for buffers per controller.
+ * If the machine this is being used on is a faster machine (i.e. > 150MHz)
+ * and running on a 10MBS network then more queueing of data occurs. This
+ * may indicate the some of the numbers below should be adjusted. Here are
+ * some typical numbers:
+ * MAX_TCB 64
+ * MAX_RFD 64
+ * The default numbers give work well on most systems tests so no real
+ * adjustments really need to take place. Also, if the machine is connected
+ * to a 100MBS network the numbers described above can be lowered from the
+ * defaults as considerably less data will be queued.
+ */
+
+#define MAX_TCB 64 /* number of transmit control blocks */
+#define MAX_TBD MAX_TCB
+#define TX_FRAME_CNT 8 /* consecutive transmit frames per interrupt */
+/* TX_FRAME_CNT must be less than MAX_TCB */
+#define MAX_RFD 64
+
+#define E100_DEFAULT_TCB MAX_TCB
+#define E100_MIN_TCB 2*TX_FRAME_CNT + 3 /* make room for at least 2 interrupts */
+
+#ifdef __ia64__
+ /* We can't use too many DMAble buffers on IA64 machines with >4 GB mem */
+#define E100_MAX_TCB 64
+#else
+#define E100_MAX_TCB 1024
+#endif /* __ia64__ */
+
+#define E100_DEFAULT_RFD MAX_RFD
+#define E100_MIN_RFD 8
+
+#ifdef __ia64__
+ /* We can't use too many DMAble buffers on IA64 machines with >4 GB mem */
+#define E100_MAX_RFD 64
+#else
+#define E100_MAX_RFD 1024
+#endif /* __ia64__ */
+
+#define E100_DEFAULT_XSUM true
+#define E100_DEFAULT_BER ZLOCK_MAX_ERRORS
+#define E100_DEFAULT_SPEED_DUPLEX 0
+#define E100_DEFAULT_FC 0
+#define E100_DEFAULT_IFS true
+#define E100_DEFAULT_UCODE true
+
+#define TX_THRSHLD 8
+
+/* sleep time is at least 50 ms, in jiffies */
+#define SLEEP_TIME ((HZ / 20) + 1)
+#define CUS_TIMEOUT 1000
+
+/* IFS parameters */
+#define MIN_NUMBER_OF_TRANSMITS_100 1000
+#define MIN_NUMBER_OF_TRANSMITS_10 100
+
+#define E100_MAX_NIC 16
+
+#define E100_MAX_BUSY_WAIT 50 /*Max udelays in wait_scb and wait_cus_idle */
+
+/* CPUSAVER_BUNDLE_MAX: Sets the maximum number of frames that will be bundled.
+ * In some situations, such as the TCP windowing algorithm, it may be
+ * better to limit the growth of the bundle size than let it go as
+ * high as it can, because that could cause too much added latency.
+ * The default is six, because this is the number of packets in the
+ * default TCP window size. A value of 1 would make CPUSaver indicate
+ * an interrupt for every frame received. If you do not want to put
+ * a limit on the bundle size, set this value to xFFFF.
+ */
+#define E100_DEFAULT_CPUSAVER_BUNDLE_MAX 6
+#define E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY 0x600
+#define E100_DEFAULT_BUNDLE_SMALL_FR false
+#define E100_DEFAULT_RX_CONGESTION_CONTROL true
+
+/* end of configurables */
+
+/* ====================================================================== */
+/* hw */
+/* ====================================================================== */
+
+/* timeout for command completion */
+#define E100_CMD_WAIT 100 /* iterations */
+
+struct driver_stats {
+ struct net_device_stats net_stats;
+
+ unsigned long tx_late_col;
+ unsigned long tx_ok_defrd;
+ unsigned long tx_one_retry;
+ unsigned long tx_mt_one_retry;
+ unsigned long rcv_cdt_frames;
+ unsigned long xmt_fc_pkts;
+ unsigned long rcv_fc_pkts;
+ unsigned long rcv_fc_unsupported;
+ unsigned long xmt_tco_pkts;
+ unsigned long rcv_tco_pkts;
+ unsigned long rx_intr_pkts;
+ unsigned long rx_tasklet_pkts;
+ unsigned long poll_intr_switch;
+};
+
+/* TODO: kill me when we can do C99 */
+#define false (0)
+#define true (1)
+
+/* Changed for 82558 and 82559 enhancements */
+/* defines for 82558/9 flow control CSR values */
+#define DFLT_FC_THLD 0x00 /* Rx FIFO threshold of 0.5KB free */
+#define DFLT_FC_CMD 0x00 /* FC Command in CSR */
+
+/* ====================================================================== */
+/* equates */
+/* ====================================================================== */
+
+/*
+ * These are general purpose defines
+ */
+
+/* Bit Mask definitions */
+#define BIT_0 0x0001
+#define BIT_1 0x0002
+#define BIT_2 0x0004
+#define BIT_3 0x0008
+#define BIT_4 0x0010
+#define BIT_5 0x0020
+#define BIT_6 0x0040
+#define BIT_7 0x0080
+#define BIT_8 0x0100
+#define BIT_9 0x0200
+#define BIT_10 0x0400
+#define BIT_11 0x0800
+#define BIT_12 0x1000
+#define BIT_13 0x2000
+#define BIT_14 0x4000
+#define BIT_15 0x8000
+#define BIT_28 0x10000000
+
+#define BIT_0_2 0x0007
+#define BIT_0_3 0x000F
+#define BIT_0_4 0x001F
+#define BIT_0_5 0x003F
+#define BIT_0_6 0x007F
+#define BIT_0_7 0x00FF
+#define BIT_0_8 0x01FF
+#define BIT_0_13 0x3FFF
+#define BIT_0_15 0xFFFF
+#define BIT_1_2 0x0006
+#define BIT_1_3 0x000E
+#define BIT_2_5 0x003C
+#define BIT_3_4 0x0018
+#define BIT_4_5 0x0030
+#define BIT_4_6 0x0070
+#define BIT_4_7 0x00F0
+#define BIT_5_7 0x00E0
+#define BIT_5_12 0x1FE0
+#define BIT_5_15 0xFFE0
+#define BIT_6_7 0x00c0
+#define BIT_7_11 0x0F80
+#define BIT_8_10 0x0700
+#define BIT_9_13 0x3E00
+#define BIT_12_15 0xF000
+#define BIT_8_15 0xFF00
+
+#define BIT_16_20 0x001F0000
+#define BIT_21_25 0x03E00000
+#define BIT_26_27 0x0C000000
+
+/* Transmit Threshold related constants */
+#define DEFAULT_TX_PER_UNDERRUN 20000
+
+#define MAX_MULTICAST_ADDRS 64
+#define MAX_FILTER 16
+
+#define FULL_DUPLEX 2
+#define HALF_DUPLEX 1
+
+/*
+ * These defines are specific to the 82557
+ */
+
+/* E100 PORT functions -- lower 4 bits */
+#define PORT_SOFTWARE_RESET 0
+#define PORT_SELFTEST 1
+#define PORT_SELECTIVE_RESET 2
+#define PORT_DUMP 3
+
+/* SCB Status Word bit definitions */
+/* Interrupt status/ack fields */
+/* ER and FCP interrupts for 82558 masks */
+#define SCB_STATUS_ACK_MASK BIT_8_15 /* Status Mask */
+#define SCB_STATUS_ACK_CX BIT_15 /* CU Completed Action Cmd */
+#define SCB_STATUS_ACK_FR BIT_14 /* RU Received A Frame */
+#define SCB_STATUS_ACK_CNA BIT_13 /* CU Became Inactive (IDLE) */
+#define SCB_STATUS_ACK_RNR BIT_12 /* RU Became Not Ready */
+#define SCB_STATUS_ACK_MDI BIT_11 /* MDI read or write done */
+#define SCB_STATUS_ACK_SWI BIT_10 /* S/W generated interrupt */
+#define SCB_STATUS_ACK_ER BIT_9 /* Early Receive */
+#define SCB_STATUS_ACK_FCP BIT_8 /* Flow Control Pause */
+
+/*- CUS Fields */
+#define SCB_CUS_MASK (BIT_6 | BIT_7) /* CUS 2-bit Mask */
+#define SCB_CUS_IDLE 0 /* CU Idle */
+#define SCB_CUS_SUSPEND BIT_6 /* CU Suspended */
+#define SCB_CUS_ACTIVE BIT_7 /* CU Active */
+
+/*- RUS Fields */
+#define SCB_RUS_IDLE 0 /* RU Idle */
+#define SCB_RUS_MASK BIT_2_5 /* RUS 3-bit Mask */
+#define SCB_RUS_SUSPEND BIT_2 /* RU Suspended */
+#define SCB_RUS_NO_RESOURCES BIT_3 /* RU Out Of Resources */
+#define SCB_RUS_READY BIT_4 /* RU Ready */
+#define SCB_RUS_SUSP_NO_RBDS (BIT_2 | BIT_5) /* RU No More RBDs */
+#define SCB_RUS_NO_RBDS (BIT_3 | BIT_5) /* RU No More RBDs */
+#define SCB_RUS_READY_NO_RBDS (BIT_4 | BIT_5) /* RU Ready, No RBDs */
+
+/* SCB Command Word bit definitions */
+/*- CUC fields */
+/* Changing mask to 4 bits */
+#define SCB_CUC_MASK BIT_4_7 /* CUC 4-bit Mask */
+#define SCB_CUC_NOOP 0
+#define SCB_CUC_START BIT_4 /* CU Start */
+#define SCB_CUC_RESUME BIT_5 /* CU Resume */
+/* Changed for 82558 enhancements */
+#define SCB_CUC_STATIC_RESUME (BIT_5 | BIT_7) /* 82558/9 Static Resume */
+#define SCB_CUC_DUMP_ADDR BIT_6 /* CU Dump Counters Address */
+#define SCB_CUC_DUMP_STAT (BIT_4 | BIT_6) /* CU Dump stat. counters */
+#define SCB_CUC_LOAD_BASE (BIT_5 | BIT_6) /* Load the CU base */
+/* Below was defined as BIT_4_7 */
+#define SCB_CUC_DUMP_RST_STAT BIT_4_6 /* CU Dump & reset statistics cntrs */
+
+/*- RUC fields */
+#define SCB_RUC_MASK BIT_0_2 /* RUC 3-bit Mask */
+#define SCB_RUC_START BIT_0 /* RU Start */
+#define SCB_RUC_RESUME BIT_1 /* RU Resume */
+#define SCB_RUC_ABORT BIT_2 /* RU Abort */
+#define SCB_RUC_LOAD_HDS (BIT_0 | BIT_2) /* Load RFD Header Data Size */
+#define SCB_RUC_LOAD_BASE (BIT_1 | BIT_2) /* Load the RU base */
+#define SCB_RUC_RBD_RESUME BIT_0_2 /* RBD resume */
+
+/* Interrupt fields (assuming byte addressing) */
+#define SCB_INT_MASK BIT_0 /* Mask interrupts */
+#define SCB_SOFT_INT BIT_1 /* Generate a S/W interrupt */
+/* Specific Interrupt Mask Bits (upper byte of SCB Command word) */
+#define SCB_FCP_INT_MASK BIT_2 /* Flow Control Pause */
+#define SCB_ER_INT_MASK BIT_3 /* Early Receive */
+#define SCB_RNR_INT_MASK BIT_4 /* RU Not Ready */
+#define SCB_CNA_INT_MASK BIT_5 /* CU Not Active */
+#define SCB_FR_INT_MASK BIT_6 /* Frame Received */
+#define SCB_CX_INT_MASK BIT_7 /* CU eXecution w/ I-bit done */
+#define SCB_BACHELOR_INT_MASK BIT_2_7 /* 82558 interrupt mask bits */
+
+#define SCB_GCR2_EEPROM_ACCESS_SEMAPHORE BIT_7
+
+/* EEPROM bit definitions */
+/*- EEPROM control register bits */
+#define EN_TRNF 0x10 /* Enable turnoff */
+#define EEDO 0x08 /* EEPROM data out */
+#define EEDI 0x04 /* EEPROM data in (set for writing data) */
+#define EECS 0x02 /* EEPROM chip select (1=hi, 0=lo) */
+#define EESK 0x01 /* EEPROM shift clock (1=hi, 0=lo) */
+
+/*- EEPROM opcodes */
+#define EEPROM_READ_OPCODE 06
+#define EEPROM_WRITE_OPCODE 05
+#define EEPROM_ERASE_OPCODE 07
+#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable */
+#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable */
+
+/*- EEPROM data locations */
+#define EEPROM_NODE_ADDRESS_BYTE_0 0
+#define EEPROM_COMPATIBILITY_WORD 3
+#define EEPROM_PWA_NO 8
+#define EEPROM_ID_WORD 0x0A
+
+#define EEPROM_SUM 0xbaba
+
+// Zero Locking Algorithm definitions:
+#define ZLOCK_ZERO_MASK 0x00F0
+#define ZLOCK_MAX_READS 50
+#define ZLOCK_SET_ZERO 0x2010
+#define ZLOCK_MAX_SLEEP 300 * HZ
+#define ZLOCK_MAX_ERRORS 300
+
+/* E100 Action Commands */
+#define CB_IA_ADDRESS 1
+#define CB_CONFIGURE 2
+#define CB_MULTICAST 3
+#define CB_TRANSMIT 4
+#define CB_LOAD_MICROCODE 5
+#define CB_LOAD_FILTER 8
+#define CB_MAX_NONTX_CMD 9
+#define CB_IPCB_TRANSMIT 9
+
+/* Pre-defined Filter Bits */
+#define CB_FILTER_EL 0x80000000
+#define CB_FILTER_FIX 0x40000000
+#define CB_FILTER_ARP 0x08000000
+#define CB_FILTER_IA_MATCH 0x02000000
+
+/* Command Block (CB) Field Definitions */
+/*- CB Command Word */
+#define CB_EL_BIT BIT_15 /* CB EL Bit */
+#define CB_S_BIT BIT_14 /* CB Suspend Bit */
+#define CB_I_BIT BIT_13 /* CB Interrupt Bit */
+#define CB_TX_SF_BIT BIT_3 /* TX CB Flexible Mode */
+#define CB_CMD_MASK BIT_0_3 /* CB 4-bit CMD Mask */
+#define CB_CID_DEFAULT (0x1f << 8) /* CB 5-bit CID (max value) */
+
+/*- CB Status Word */
+#define CB_STATUS_MASK BIT_12_15 /* CB Status Mask (4-bits) */
+#define CB_STATUS_COMPLETE BIT_15 /* CB Complete Bit */
+#define CB_STATUS_OK BIT_13 /* CB OK Bit */
+#define CB_STATUS_UNDERRUN BIT_12 /* CB A Bit */
+#define CB_STATUS_FAIL BIT_11 /* CB Fail (F) Bit */
+
+/*misc command bits */
+#define CB_TX_EOF_BIT BIT_15 /* TX CB/TBD EOF Bit */
+
+/* Config params */
+#define CB_CFIG_BYTE_COUNT 22 /* 22 config bytes */
+#define CB_CFIG_D102_BYTE_COUNT 10
+
+/* Receive Frame Descriptor Fields */
+
+/*- RFD Status Bits */
+#define RFD_RECEIVE_COLLISION BIT_0 /* Collision detected on Receive */
+#define RFD_IA_MATCH BIT_1 /* Indv Address Match Bit */
+#define RFD_RX_ERR BIT_4 /* RX_ERR pin on Phy was set */
+#define RFD_FRAME_TOO_SHORT BIT_7 /* Receive Frame Short */
+#define RFD_DMA_OVERRUN BIT_8 /* Receive DMA Overrun */
+#define RFD_NO_RESOURCES BIT_9 /* No Buffer Space */
+#define RFD_ALIGNMENT_ERROR BIT_10 /* Alignment Error */
+#define RFD_CRC_ERROR BIT_11 /* CRC Error */
+#define RFD_STATUS_OK BIT_13 /* RFD OK Bit */
+#define RFD_STATUS_COMPLETE BIT_15 /* RFD Complete Bit */
+
+/*- RFD Command Bits*/
+#define RFD_EL_BIT BIT_15 /* RFD EL Bit */
+#define RFD_S_BIT BIT_14 /* RFD Suspend Bit */
+#define RFD_H_BIT BIT_4 /* Header RFD Bit */
+#define RFD_SF_BIT BIT_3 /* RFD Flexible Mode */
+
+/*- RFD misc bits*/
+#define RFD_EOF_BIT BIT_15 /* RFD End-Of-Frame Bit */
+#define RFD_F_BIT BIT_14 /* RFD Buffer Fetch Bit */
+#define RFD_ACT_COUNT_MASK BIT_0_13 /* RFD Actual Count Mask */
+
+/* Receive Buffer Descriptor Fields*/
+#define RBD_EOF_BIT BIT_15 /* RBD End-Of-Frame Bit */
+#define RBD_F_BIT BIT_14 /* RBD Buffer Fetch Bit */
+#define RBD_ACT_COUNT_MASK BIT_0_13 /* RBD Actual Count Mask */
+
+#define SIZE_FIELD_MASK BIT_0_13 /* Size of the associated buffer */
+#define RBD_EL_BIT BIT_15 /* RBD EL Bit */
+
+/* Self Test Results*/
+#define CB_SELFTEST_FAIL_BIT BIT_12
+#define CB_SELFTEST_DIAG_BIT BIT_5
+#define CB_SELFTEST_REGISTER_BIT BIT_3
+#define CB_SELFTEST_ROM_BIT BIT_2
+
+#define CB_SELFTEST_ERROR_MASK ( \
+ CB_SELFTEST_FAIL_BIT | CB_SELFTEST_DIAG_BIT | \
+ CB_SELFTEST_REGISTER_BIT | CB_SELFTEST_ROM_BIT)
+
+/* adapter vendor & device ids */
+#define PCI_OHIO_BOARD 0x10f0 /* subdevice ID, Ohio dual port nic */
+
+/* Values for PCI_REV_ID_REGISTER values */
+#define D101A4_REV_ID 4 /* 82558 A4 stepping */
+#define D101B0_REV_ID 5 /* 82558 B0 stepping */
+#define D101MA_REV_ID 8 /* 82559 A0 stepping */
+#define D101S_REV_ID 9 /* 82559S A-step */
+#define D102_REV_ID 12
+#define D102C_REV_ID 13 /* 82550 step C */
+#define D102E_REV_ID 15
+
+/* ############Start of 82555 specific defines################## */
+
+#define PHY_82555_LED_SWITCH_CONTROL 0x1b /* 82555 led switch control register */
+
+/* 82555 led switch control reg. opcodes */
+#define PHY_82555_LED_NORMAL_CONTROL 0 // control back to the 8255X
+#define PHY_82555_LED_DRIVER_CONTROL BIT_2 // the driver is in control
+#define PHY_82555_LED_OFF BIT_2 // activity LED is off
+#define PHY_82555_LED_ON_559 (BIT_0 | BIT_2) // activity LED is on for 559 and later
+#define PHY_82555_LED_ON_PRE_559 (BIT_0 | BIT_1 | BIT_2) // activity LED is on for 558 and before
+
+// Describe the state of the phy led.
+// needed for the function : 'e100_blink_timer'
+enum led_state_e {
+ LED_OFF = 0,
+ LED_ON,
+};
+
+/* ############End of 82555 specific defines##################### */
+
+#define RFD_PARSE_BIT BIT_3
+#define RFD_TCP_PACKET 0x00
+#define RFD_UDP_PACKET 0x01
+#define TCPUDP_CHECKSUM_BIT_VALID BIT_4
+#define TCPUDP_CHECKSUM_VALID BIT_5
+#define CHECKSUM_PROTOCOL_MASK 0x03
+
+#define VLAN_SIZE 4
+#define CHKSUM_SIZE 2
+#define RFD_DATA_SIZE (ETH_FRAME_LEN + CHKSUM_SIZE + VLAN_SIZE)
+
+/* Bits for bdp->flags */
+#define DF_LINK_FC_CAP 0x00000001 /* Link is flow control capable */
+#define DF_CSUM_OFFLOAD 0x00000002
+#define DF_UCODE_LOADED 0x00000004
+#define USE_IPCB 0x00000008 /* set if using ipcb for transmits */
+#define IS_BACHELOR 0x00000010 /* set if 82558 or newer board */
+#define IS_ICH 0x00000020
+#define DF_SPEED_FORCED 0x00000040 /* set if speed is forced */
+
+typedef struct net_device_stats net_dev_stats_t;
+
+/* needed macros */
+/* These macros use the bdp pointer. If you use them it better be defined */
+#define PREV_TCB_USED(X) ((X).tail ? (X).tail - 1 : bdp->params.TxDescriptors - 1)
+#define NEXT_TCB_TOUSE(X) ((((X) + 1) >= bdp->params.TxDescriptors) ? 0 : (X) + 1)
+#define TCB_TO_USE(X) ((X).tail)
+#define TCBS_AVAIL(X) (NEXT_TCB_TOUSE( NEXT_TCB_TOUSE((X).tail)) != (X).head)
+
+#define RFD_POINTER(skb,bdp) ((rfd_t *) (((unsigned char *)((skb)->data))-((bdp)->rfd_size)))
+#define SKB_RFD_STATUS(skb,bdp) ((RFD_POINTER((skb),(bdp)))->rfd_header.cb_status)
+#define GET_SKB_DMA_ADDR(skb) ( *(dma_addr_t *)( (skb)->cb) )
+#define SET_SKB_DMA_ADDR(skb,dma_addr) ( *(dma_addr_t *)( (skb)->cb) = (dma_addr) )
+
+/* ====================================================================== */
+/* 82557 */
+/* ====================================================================== */
+
+/* Changed for 82558 enhancement */
+typedef struct _d101_scb_ext_t {
+ u32 scb_rx_dma_cnt; /* Rx DMA byte count */
+ u8 scb_early_rx_int; /* Early Rx DMA byte count */
+ u8 scb_fc_thld; /* Flow Control threshold */
+ u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */
+ u8 scb_pmdr; /* Power Mgmt. Driver Reg */
+} d101_scb_ext __attribute__ ((__packed__));
+
+/* Changed for 82559 enhancement */
+typedef struct _d101m_scb_ext_t {
+ u32 scb_rx_dma_cnt; /* Rx DMA byte count */
+ u8 scb_early_rx_int; /* Early Rx DMA byte count */
+ u8 scb_fc_thld; /* Flow Control threshold */
+ u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */
+ u8 scb_pmdr; /* Power Mgmt. Driver Reg */
+ u8 scb_gen_ctrl; /* General Control */
+ u8 scb_gen_stat; /* General Status */
+ u16 scb_reserved; /* Reserved */
+ u32 scb_function_event; /* Cardbus Function Event */
+ u32 scb_function_event_mask; /* Cardbus Function Mask */
+ u32 scb_function_present_state; /* Cardbus Function state */
+ u32 scb_force_event; /* Cardbus Force Event */
+} d101m_scb_ext __attribute__ ((__packed__));
+
+/* Changed for 82550 enhancement */
+typedef struct _d102_scb_ext_t {
+ u32 scb_rx_dma_cnt; /* Rx DMA byte count */
+ u8 scb_early_rx_int; /* Early Rx DMA byte count */
+ u8 scb_fc_thld; /* Flow Control threshold */
+ u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */
+ u8 scb_pmdr; /* Power Mgmt. Driver Reg */
+ u8 scb_gen_ctrl; /* General Control */
+ u8 scb_gen_stat; /* General Status */
+ u8 scb_gen_ctrl2;
+ u8 scb_reserved; /* Reserved */
+ u32 scb_scheduling_reg;
+ u32 scb_reserved2;
+ u32 scb_function_event; /* Cardbus Function Event */
+ u32 scb_function_event_mask; /* Cardbus Function Mask */
+ u32 scb_function_present_state; /* Cardbus Function state */
+ u32 scb_force_event; /* Cardbus Force Event */
+} d102_scb_ext __attribute__ ((__packed__));
+
+/*
+ * 82557 status control block. this will be memory mapped & will hang of the
+ * the bdp, which hangs of the bdp. This is the brain of it.
+ */
+typedef struct _scb_t {
+ u16 scb_status; /* SCB Status register */
+ u8 scb_cmd_low; /* SCB Command register (low byte) */
+ u8 scb_cmd_hi; /* SCB Command register (high byte) */
+ u32 scb_gen_ptr; /* SCB General pointer */
+ u32 scb_port; /* PORT register */
+ u16 scb_flsh_cntrl; /* Flash Control register */
+ u16 scb_eprm_cntrl; /* EEPROM control register */
+ u32 scb_mdi_cntrl; /* MDI Control Register */
+ /* Changed for 82558 enhancement */
+ union {
+ u32 scb_rx_dma_cnt; /* Rx DMA byte count */
+ d101_scb_ext d101_scb; /* 82558/9 specific fields */
+ d101m_scb_ext d101m_scb; /* 82559 specific fields */
+ d102_scb_ext d102_scb;
+ } scb_ext;
+} scb_t __attribute__ ((__packed__));
+
+/* Self test
+ * This is used to dump results of the self test
+ */
+typedef struct _self_test_t {
+ u32 st_sign; /* Self Test Signature */
+ u32 st_result; /* Self Test Results */
+} self_test_t __attribute__ ((__packed__));
+
+/*
+ * Statistical Counters
+ */
+/* 82557 counters */
+typedef struct _basic_cntr_t {
+ u32 xmt_gd_frames; /* Good frames transmitted */
+ u32 xmt_max_coll; /* Fatal frames -- had max collisions */
+ u32 xmt_late_coll; /* Fatal frames -- had a late coll. */
+ u32 xmt_uruns; /* Xmit underruns (fatal or re-transmit) */
+ u32 xmt_lost_crs; /* Frames transmitted without CRS */
+ u32 xmt_deferred; /* Deferred transmits */
+ u32 xmt_sngl_coll; /* Transmits that had 1 and only 1 coll. */
+ u32 xmt_mlt_coll; /* Transmits that had multiple coll. */
+ u32 xmt_ttl_coll; /* Transmits that had 1+ collisions. */
+ u32 rcv_gd_frames; /* Good frames received */
+ u32 rcv_crc_errs; /* Aligned frames that had a CRC error */
+ u32 rcv_algn_errs; /* Receives that had alignment errors */
+ u32 rcv_rsrc_err; /* Good frame dropped cuz no resources */
+ u32 rcv_oruns; /* Overrun errors - bus was busy */
+ u32 rcv_err_coll; /* Received frms. that encountered coll. */
+ u32 rcv_shrt_frames; /* Received frames that were to short */
+} basic_cntr_t;
+
+/* 82558 extended statistic counters */
+typedef struct _ext_cntr_t {
+ u32 xmt_fc_frames;
+ u32 rcv_fc_frames;
+ u32 rcv_fc_unsupported;
+} ext_cntr_t;
+
+/* 82559 TCO statistic counters */
+typedef struct _tco_cntr_t {
+ u16 xmt_tco_frames;
+ u16 rcv_tco_frames;
+} tco_cntr_t;
+
+/* Structures to access thet physical dump area */
+/* Use one of these types, according to the statisitcal counters mode,
+ to cast the pointer to the physical dump area and access the cmd_complete
+ DWORD. */
+
+/* 557-mode : only basic counters + cmd_complete */
+typedef struct _err_cntr_557_t {
+ basic_cntr_t basic_stats;
+ u32 cmd_complete;
+} err_cntr_557_t;
+
+/* 558-mode : basic + extended counters + cmd_complete */
+typedef struct _err_cntr_558_t {
+ basic_cntr_t basic_stats;
+ ext_cntr_t extended_stats;
+ u32 cmd_complete;
+} err_cntr_558_t;
+
+/* 559-mode : basic + extended + TCO counters + cmd_complete */
+typedef struct _err_cntr_559_t {
+ basic_cntr_t basic_stats;
+ ext_cntr_t extended_stats;
+ tco_cntr_t tco_stats;
+ u32 cmd_complete;
+} err_cntr_559_t;
+
+/* This typedef defines the struct needed to hold the largest number of counters */
+typedef err_cntr_559_t max_counters_t;
+
+/* Different statistical-counters mode the controller may be in */
+typedef enum _stat_mode_t {
+ E100_BASIC_STATS = 0, /* 82557 stats : 16 counters / 16 dw */
+ E100_EXTENDED_STATS, /* 82558 stats : 19 counters / 19 dw */
+ E100_TCO_STATS /* 82559 stats : 21 counters / 20 dw */
+} stat_mode_t;
+
+/* dump statistical counters complete codes */
+#define DUMP_STAT_COMPLETED 0xA005
+#define DUMP_RST_STAT_COMPLETED 0xA007
+
+/* Command Block (CB) Generic Header Structure*/
+typedef struct _cb_header_t {
+ u16 cb_status; /* Command Block Status */
+ u16 cb_cmd; /* Command Block Command */
+ u32 cb_lnk_ptr; /* Link To Next CB */
+} cb_header_t __attribute__ ((__packed__));
+
+//* Individual Address Command Block (IA_CB)*/
+typedef struct _ia_cb_t {
+ cb_header_t ia_cb_hdr;
+ u8 ia_addr[ETH_ALEN];
+} ia_cb_t __attribute__ ((__packed__));
+
+/* Configure Command Block (CONFIG_CB)*/
+typedef struct _config_cb_t {
+ cb_header_t cfg_cbhdr;
+ u8 cfg_byte[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT];
+} config_cb_t __attribute__ ((__packed__));
+
+/* MultiCast Command Block (MULTICAST_CB)*/
+typedef struct _multicast_cb_t {
+ cb_header_t mc_cbhdr;
+ u16 mc_count; /* Number of multicast addresses */
+ u8 mc_addr[(ETH_ALEN * MAX_MULTICAST_ADDRS)];
+} mltcst_cb_t __attribute__ ((__packed__));
+
+#define UCODE_MAX_DWORDS 134
+/* Load Microcode Command Block (LOAD_UCODE_CB)*/
+typedef struct _load_ucode_cb_t {
+ cb_header_t load_ucode_cbhdr;
+ u32 ucode_dword[UCODE_MAX_DWORDS];
+} load_ucode_cb_t __attribute__ ((__packed__));
+
+/* Load Programmable Filter Data*/
+typedef struct _filter_cb_t {
+ cb_header_t filter_cb_hdr;
+ u32 filter_data[MAX_FILTER];
+} filter_cb_t __attribute__ ((__packed__));
+
+/* NON_TRANSMIT_CB -- Generic Non-Transmit Command Block
+ */
+typedef struct _nxmit_cb_t {
+ union {
+ config_cb_t config;
+ ia_cb_t setup;
+ load_ucode_cb_t load_ucode;
+ mltcst_cb_t multicast;
+ filter_cb_t filter;
+ } ntcb;
+} nxmit_cb_t __attribute__ ((__packed__));
+
+/*Block for queuing for postponed execution of the non-transmit commands*/
+typedef struct _nxmit_cb_entry_t {
+ struct list_head list_elem;
+ nxmit_cb_t *non_tx_cmd;
+ dma_addr_t dma_addr;
+ unsigned long expiration_time;
+} nxmit_cb_entry_t;
+
+/* States for postponed non tx commands execution */
+typedef enum _non_tx_cmd_state_t {
+ E100_NON_TX_IDLE = 0, /* No queued NON-TX commands */
+ E100_WAIT_TX_FINISH, /* Wait for completion of the TX activities */
+ E100_WAIT_NON_TX_FINISH /* Wait for completion of the non TX command */
+} non_tx_cmd_state_t;
+
+/* some defines for the ipcb */
+#define IPCB_IP_CHECKSUM_ENABLE BIT_4
+#define IPCB_TCPUDP_CHECKSUM_ENABLE BIT_5
+#define IPCB_TCP_PACKET BIT_6
+#define IPCB_LARGESEND_ENABLE BIT_7
+#define IPCB_HARDWAREPARSING_ENABLE BIT_0
+#define IPCB_INSERTVLAN_ENABLE BIT_1
+#define IPCB_IP_ACTIVATION_DEFAULT IPCB_HARDWAREPARSING_ENABLE
+
+/* Transmit Buffer Descriptor (TBD)*/
+typedef struct _tbd_t {
+ u32 tbd_buf_addr; /* Physical Transmit Buffer Address */
+ u16 tbd_buf_cnt; /* Actual Count Of Bytes */
+ u16 padd;
+} tbd_t __attribute__ ((__packed__));
+
+/* d102 specific fields */
+typedef struct _tcb_ipcb_t {
+ u16 schedule_low;
+ u8 ip_schedule;
+ u8 ip_activation_high;
+ u16 vlan;
+ u8 ip_header_offset;
+ u8 tcp_header_offset;
+ union {
+ u32 sec_rec_phys_addr;
+ u32 tbd_zero_address;
+ } tbd_sec_addr;
+ union {
+ u16 sec_rec_size;
+ u16 tbd_zero_size;
+ } tbd_sec_size;
+ u16 total_tcp_payload;
+} tcb_ipcb_t __attribute__ ((__packed__));
+
+#ifdef MAX_SKB_FRAGS
+#define E100_ZEROCOPY
+#endif
+
+#ifdef E100_ZEROCOPY
+#define E100_TBD_ARRAY_SIZE (2+MAX_SKB_FRAGS)
+#else
+#define E100_TBD_ARRAY_SIZE 2
+#endif /*E100_ZEROCOPY */
+
+/* Transmit Command Block (TCB)*/
+struct _tcb_t {
+ cb_header_t tcb_hdr;
+ u32 tcb_tbd_ptr; /* TBD address */
+ u16 tcb_cnt; /* Data Bytes In TCB past header */
+ u8 tcb_thrshld; /* TX Threshold for FIFO Extender */
+ u8 tcb_tbd_num;
+
+ union {
+ tcb_ipcb_t ipcb; /* d102 ipcb fields */
+ tbd_t tbd_array[E100_TBD_ARRAY_SIZE];
+ } tcbu;
+
+ /* From here onward we can dump anything we want as long as the
+ * size of the total structure is a multiple of a paragraph
+ * boundary ( i.e. -16 bit aligned ).
+ */
+ tbd_t *tbd_ptr;
+
+#ifdef E100_ZEROCOPY
+ u32 tcb_tbd_dflt_ptr; /* TBD address for non-segmented packet */
+ u32 tcb_tbd_expand_ptr; /* TBD address for segmented packet */
+#endif /*E100_ZEROCOPY */
+
+ struct sk_buff *tcb_skb; /* the associated socket buffer */
+ dma_addr_t tcb_phys; /* phys addr of the TCB */
+} __attribute__ ((__packed__));
+
+#ifndef _TCB_T_
+#define _TCB_T_
+typedef struct _tcb_t tcb_t;
+#endif
+
+/* Receive Frame Descriptor (RFD) - will be using the simple model*/
+struct _rfd_t {
+ /* 8255x */
+ cb_header_t rfd_header;
+ u32 rfd_rbd_ptr; /* Receive Buffer Descriptor Addr */
+ u16 rfd_act_cnt; /* Number Of Bytes Received */
+ u16 rfd_sz; /* Number Of Bytes In RFD */
+ /* D102 aka Gamla */
+ u16 vlanid;
+ u8 rcvparserstatus;
+ u8 reserved;
+ u16 securitystatus;
+ u8 checksumstatus;
+ u8 zerocopystatus;
+ u8 pad[8]; /* data should be 16 byte aligned */
+ u8 data[RFD_DATA_SIZE];
+
+} __attribute__ ((__packed__));
+
+#ifndef _RFD_T_
+#define _RFD_T_
+typedef struct _rfd_t rfd_t;
+#endif
+
+/* Receive Buffer Descriptor (RBD)*/
+typedef struct _rbd_t {
+ u16 rbd_act_cnt; /* Number Of Bytes Received */
+ u16 rbd_filler;
+ u32 rbd_lnk_addr; /* Link To Next RBD */
+ u32 rbd_rcb_addr; /* Receive Buffer Address */
+ u16 rbd_sz; /* Receive Buffer Size */
+ u16 rbd_filler1;
+} rbd_t __attribute__ ((__packed__));
+
+/*
+ * This structure is used to maintain a FIFO access to a resource that is
+ * maintained as a circular queue. The resource to be maintained is pointed
+ * to by the "data" field in the structure below. In this driver the TCBs',
+ * TBDs' & RFDs' are maintained as a circular queue & are managed thru this
+ * structure.
+ */
+typedef struct _buf_pool_t {
+ unsigned int head; /* index to first used resource */
+ unsigned int tail; /* index to last used resource */
+ void *data; /* points to resource pool */
+} buf_pool_t;
+
+/*Rx skb holding structure*/
+struct rx_list_elem {
+ struct list_head list_elem;
+ dma_addr_t dma_addr;
+ struct sk_buff *skb;
+};
+
+enum next_cu_cmd_e { RESUME_NO_WAIT = 0, RESUME_WAIT, START_WAIT };
+enum zlock_state_e { ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING };
+enum tx_queue_stop_type { LONG_STOP = 0, SHORT_STOP };
+
+/* 64 bit aligned size */
+#define E100_SIZE_64A(X) ((sizeof(X) + 7) & ~0x7)
+
+typedef struct _bd_dma_able_t {
+ char selftest[E100_SIZE_64A(self_test_t)];
+ char stats_counters[E100_SIZE_64A(max_counters_t)];
+} bd_dma_able_t;
+
+/* bit masks for bool parameters */
+#define PRM_XSUMRX 0x00000001
+#define PRM_UCODE 0x00000002
+#define PRM_FC 0x00000004
+#define PRM_IFS 0x00000008
+#define PRM_BUNDLE_SMALL 0x00000010
+#define PRM_RX_CONG 0x00000020
+
+struct cfg_params {
+ int e100_speed_duplex;
+ int RxDescriptors;
+ int TxDescriptors;
+ int IntDelay;
+ int BundleMax;
+ int ber;
+ int PollingMaxWork;
+ u32 b_params;
+};
+
+struct e100_private {
+ u32 flags; /* board management flags */
+ u32 tx_per_underrun; /* number of good tx frames per underrun */
+ unsigned int tx_count; /* count of tx frames, so we can request an interrupt */
+ u8 tx_thld; /* stores transmit threshold */
+ u16 eeprom_size;
+ u32 pwa_no; /* PWA: xxxxxx-0xx */
+ u8 perm_node_address[ETH_ALEN];
+ struct list_head active_rx_list; /* list of rx buffers */
+ struct list_head rx_struct_pool; /* pool of rx buffer struct headers */
+ u16 rfd_size; /* size of the adapter's RFD struct */
+ int skb_req; /* number of skbs neede by the adapter */
+ u8 intr_mask; /* mask for interrupt status */
+
+ void *dma_able; /* dma allocated structs */
+ dma_addr_t dma_able_phys;
+ self_test_t *selftest; /* pointer to self test area */
+ dma_addr_t selftest_phys; /* phys addr of selftest */
+ max_counters_t *stats_counters; /* pointer to stats table */
+ dma_addr_t stat_cnt_phys; /* phys addr of stat counter area */
+
+ stat_mode_t stat_mode; /* statistics mode: extended, TCO, basic */
+ scb_t *scb; /* memory mapped ptr to 82557 scb */
+
+ tcb_t *last_tcb; /* pointer to last tcb sent */
+ buf_pool_t tcb_pool; /* adapter's TCB array */
+ dma_addr_t tcb_phys; /* phys addr of start of TCBs */
+
+ u16 cur_line_speed;
+ u16 cur_dplx_mode;
+
+ struct net_device *device;
+ struct pci_dev *pdev;
+ struct driver_stats drv_stats;
+
+ u8 rev_id; /* adapter PCI revision ID */
+ unsigned long device_type; /* device type from e100_vendor.h */
+
+ unsigned int phy_addr; /* address of PHY component */
+ unsigned int PhyId; /* ID of PHY component */
+ unsigned int PhyState; /* state for the fix squelch algorithm */
+ unsigned int PhyDelay; /* delay for the fix squelch algorithm */
+
+ /* Lock defintions for the driver */
+ spinlock_t bd_lock; /* board lock */
+ spinlock_t bd_non_tx_lock; /* Non transmit command lock */
+ spinlock_t config_lock; /* config block lock */
+ spinlock_t mdi_access_lock; /* mdi lock */
+
+ struct timer_list watchdog_timer; /* watchdog timer id */
+
+ /* non-tx commands parameters */
+ struct timer_list nontx_timer_id; /* non-tx timer id */
+ struct list_head non_tx_cmd_list;
+ non_tx_cmd_state_t non_tx_command_state;
+ nxmit_cb_entry_t *same_cmd_entry[CB_MAX_NONTX_CMD];
+
+ enum next_cu_cmd_e next_cu_cmd;
+
+ /* Zero Locking Algorithm data members */
+ enum zlock_state_e zlock_state;
+ u8 zlock_read_data[16]; /* number of times each value 0-15 was read */
+ u16 zlock_read_cnt; /* counts number of reads */
+ ulong zlock_sleep_cnt; /* keeps track of "sleep" time */
+
+ u8 config[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT];
+
+ /* IFS params */
+ u8 ifs_state;
+ u8 ifs_value;
+
+ struct cfg_params params; /* adapter's command line parameters */
+
+ struct proc_dir_entry *proc_parent;
+
+ rwlock_t isolate_lock;
+ int driver_isolated;
+
+ u32 speed_duplex_caps; /* adapter's speed/duplex capabilities */
+
+ struct tasklet_struct polling_tasklet;
+
+#ifdef ETHTOOL_GWOL
+ /* WOL params for ethtool */
+ u32 wolsupported;
+ u32 wolopts;
+ u16 ip_lbytes;
+#endif
+};
+
+#define E100_AUTONEG 0
+#define E100_SPEED_10_HALF 1
+#define E100_SPEED_10_FULL 2
+#define E100_SPEED_100_HALF 3
+#define E100_SPEED_100_FULL 4
+
+/********* function prototypes *************/
+extern void e100_isolate_driver(struct e100_private *bdp);
+extern void e100_sw_reset(struct e100_private *bdp, u32 reset_cmd);
+extern void e100_start_cu(struct e100_private *bdp, tcb_t *tcb);
+extern void e100_free_non_tx_cmd(struct e100_private *bdp,
+ nxmit_cb_entry_t *non_tx_cmd);
+extern nxmit_cb_entry_t *e100_alloc_non_tx_cmd(struct e100_private *bdp);
+extern unsigned char e100_exec_non_cu_cmd(struct e100_private *bdp,
+ nxmit_cb_entry_t *cmd);
+extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout,
+ u32 *st_result);
+extern unsigned char e100_get_link_state(struct e100_private *bdp);
+extern unsigned char e100_wait_scb(struct e100_private *bdp);
+
+#endif
diff --git a/drivers/net/e100/e100_config.c b/drivers/net/e100/e100_config.c
new file mode 100644
index 000000000000..fe8f3a95f399
--- /dev/null
+++ b/drivers/net/e100/e100_config.c
@@ -0,0 +1,596 @@
+/*******************************************************************************
+
+This software program is available to you under a choice of one of two
+licenses. You may choose to be licensed under either the GNU General Public
+License (GPL) Version 2, June 1991, available at
+http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+text of which follows:
+
+Recipient has requested a license and Intel Corporation ("Intel") is willing
+to grant a license for the software entitled Linux Base Driver for the
+Intel(R) PRO/100 Family of Adapters (e100) (the "Software") being provided
+by Intel Corporation. The following definitions apply to this license:
+
+"Licensed Patents" means patent claims licensable by Intel Corporation which
+are necessarily infringed by the use of sale of the Software alone or when
+combined with the operating system referred to below.
+
+"Recipient" means the party to whom Intel delivers this Software.
+
+"Licensee" means Recipient and those third parties that receive a license to
+any operating system available under the GNU Public License version 2.0 or
+later.
+
+Copyright (c) 1999 - 2002 Intel Corporation.
+All rights reserved.
+
+The license is provided to Recipient and Recipient's Licensees under the
+following terms.
+
+Redistribution and use in source and binary forms of the Software, with or
+without modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code of the Software may retain the above
+copyright notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form of the Software may reproduce the above
+copyright notice, this list of conditions and the following disclaimer in
+the documentation and/or materials provided with the distribution.
+
+Neither the name of Intel Corporation nor the names of its contributors
+shall be used to endorse or promote products derived from this Software
+without specific prior written permission.
+
+Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell, offer
+to sell, import and otherwise transfer the Software, if any, in source code
+and object code form. This license shall include changes to the Software
+that are error corrections or other minor changes to the Software that do
+not add functionality or features when the Software is incorporated in any
+version of an operating system that has been distributed under the GNU
+General Public License 2.0 or later. This patent license shall apply to the
+combination of the Software and any operating system licensed under the GNU
+Public License version 2.0 or later if, at the time Intel provides the
+Software to Recipient, such addition of the Software to the then publicly
+available versions of such operating systems available under the GNU Public
+License version 2.0 or later (whether in gold, beta or alpha form) causes
+such combination to be covered by the Licensed Patents. The patent license
+shall not apply to any other combinations which include the Software. NO
+hardware per se is licensed hereunder.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) 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.
+*******************************************************************************/
+
+/**********************************************************************
+* *
+* INTEL CORPORATION *
+* *
+* This software is supplied under the terms of the license included *
+* above. All use of this driver must be in accordance with the terms *
+* of that license. *
+* *
+* Module Name: e100_config.c *
+* *
+* Abstract: Functions for configuring the network adapter. *
+* *
+* Environment: This file is intended to be specific to the Linux *
+* operating system. *
+* *
+**********************************************************************/
+#ifdef SIOCETHTOOL
+#include <linux/ethtool.h>
+#endif
+
+#include "e100_config.h"
+
+static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable);
+
+static const u8 def_config[] = {
+ CB_CFIG_BYTE_COUNT,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x07, 0x01,
+ 0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2, 0xc8, 0x00,
+ 0x40, 0xf2, 0x80, 0x3f, 0x05
+};
+
+/**
+ * e100_config_init_82557 - config the 82557 adapter
+ * @bdp: atapter's private data struct
+ *
+ * This routine will initialize the 82557 configure block.
+ * All other init functions will only set values that are
+ * different from the 82557 default.
+ */
+static void __devinit
+e100_config_init_82557(struct e100_private *bdp)
+{
+ /* initialize config block */
+ memcpy(bdp->config, def_config, sizeof (def_config));
+ bdp->config[0] = CB_CFIG_BYTE_COUNT; /* just in case */
+
+ e100_config_ifs(bdp);
+
+ /*
+ * Enable extended statistical counters (82558 and up) and TCO counters
+ * (82559 and up) and set the statistical counters' mode in bdp
+ *
+ * stat. mode | TCO stat. bit (2) | Extended stat. bit (5)
+ * ------------------------------------------------------------------
+ * Basic (557) | 0 | 1
+ * ------------------------------------------------------------------
+ * Extended (558) | 0 | 0
+ * ------------------------------------------------------------------
+ * TCO (559) | 1 | 1
+ * ------------------------------------------------------------------
+ * Reserved | 1 | 0
+ * ------------------------------------------------------------------
+ */
+ bdp->config[6] &= ~CB_CFIG_TCO_STAT;
+ bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
+ bdp->stat_mode = E100_BASIC_STATS;
+
+ /* Setup for MII or 503 operation. The CRS+CDT bit should only be set */
+ /* when operating in 503 mode. */
+ if (bdp->phy_addr == 32) {
+ bdp->config[8] &= ~CB_CFIG_503_MII;
+ bdp->config[15] |= CB_CFIG_CRS_OR_CDT;
+ } else {
+ bdp->config[8] |= CB_CFIG_503_MII;
+ bdp->config[15] &= ~CB_CFIG_CRS_OR_CDT;
+ }
+
+ e100_config_fc(bdp);
+ e100_config_force_dplx(bdp);
+ e100_config_promisc(bdp, false);
+ e100_config_mulcast_enbl(bdp, false);
+}
+
+static void __devinit
+e100_config_init_82558(struct e100_private *bdp)
+{
+ /* MWI enable. This should be turned on only if the adapter is a 82558/9
+ * and if the PCI command reg. has enabled the MWI bit. */
+ bdp->config[3] |= CB_CFIG_MWI_EN;
+
+ bdp->config[6] &= ~CB_CFIG_EXT_TCB_DIS;
+
+ if (bdp->rev_id >= D101MA_REV_ID) {
+ /* this is 82559 and up - enable TCO counters */
+ bdp->config[6] |= CB_CFIG_TCO_STAT;
+ bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
+ bdp->stat_mode = E100_TCO_STATS;
+
+ if ((bdp->rev_id < D102_REV_ID) &&
+ (bdp->params.b_params & PRM_XSUMRX) &&
+ (bdp->pdev->device != 0x1209)) {
+
+ bdp->flags |= DF_CSUM_OFFLOAD;
+ bdp->config[9] |= 1;
+ }
+ } else {
+ /* this is 82558 */
+ bdp->config[6] &= ~CB_CFIG_TCO_STAT;
+ bdp->config[6] &= ~CB_CFIG_EXT_STAT_DIS;
+ bdp->stat_mode = E100_EXTENDED_STATS;
+ }
+
+ e100_config_long_rx(bdp, true);
+}
+
+static void __devinit
+e100_config_init_82550(struct e100_private *bdp)
+{
+ /* The D102 chip allows for 32 config bytes. This value is
+ * supposed to be in Byte 0. Just add the extra bytes to
+ * what was already setup in the block. */
+ bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
+
+ /* now we need to enable the extended RFD. When this is
+ * enabled, the immediated receive data buffer starts at offset
+ * 32 from the RFD base address, instead of at offset 16. */
+ bdp->config[7] |= CB_CFIG_EXTENDED_RFD;
+
+ /* put the chip into D102 receive mode. This is neccessary
+ * for any parsing and offloading features. */
+ bdp->config[22] = CB_CFIG_RECEIVE_GAMLA_MODE;
+
+ /* set the flag if checksum offloading was enabled */
+ if (bdp->params.b_params & PRM_XSUMRX) {
+ bdp->flags |= DF_CSUM_OFFLOAD;
+ }
+}
+
+/* Initialize the adapter's configure block */
+void __devinit
+e100_config_init(struct e100_private *bdp)
+{
+ e100_config_init_82557(bdp);
+
+ if (bdp->flags & IS_BACHELOR)
+ e100_config_init_82558(bdp);
+
+ if (bdp->rev_id >= D102_REV_ID)
+ e100_config_init_82550(bdp);
+}
+
+/**
+ * e100_force_config - force a configure command
+ * @bdp: atapter's private data struct
+ *
+ * This routine will force a configure command to the adapter.
+ * The command will be executed in polled mode as interrupts
+ * are _disabled_ at this time.
+ *
+ * Returns:
+ * true: if the configure command was successfully issued and completed
+ * false: otherwise
+ */
+unsigned char
+e100_force_config(struct e100_private *bdp)
+{
+ spin_lock_bh(&(bdp->config_lock));
+
+ bdp->config[0] = CB_CFIG_BYTE_COUNT;
+ if (bdp->rev_id >= D102_REV_ID) {
+ /* The D102 chip allows for 32 config bytes. This value is
+ supposed to be in Byte 0. Just add the extra bytes to
+ what was already setup in the block. */
+ bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
+ }
+
+ spin_unlock_bh(&(bdp->config_lock));
+
+ // although we call config outside the lock, there is no
+ // race condition because config byte count has maximum value
+ return e100_config(bdp);
+}
+
+/**
+ * e100_config - issue a configure command
+ * @bdp: atapter's private data struct
+ *
+ * This routine will issue a configure command to the 82557.
+ * This command will be executed in polled mode as interrupts
+ * are _disabled_ at this time.
+ *
+ * Returns:
+ * true: if the configure command was successfully issued and completed
+ * false: otherwise
+ */
+unsigned char
+e100_config(struct e100_private *bdp)
+{
+ cb_header_t *pntcb_hdr;
+ unsigned char res = true;
+ nxmit_cb_entry_t *cmd;
+
+ if (bdp->config[0] == 0) {
+ goto exit;
+ }
+
+ if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
+ res = false;
+ goto exit;
+ }
+
+ pntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
+ pntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_CONFIGURE);
+
+ spin_lock_bh(&bdp->config_lock);
+
+ if (bdp->config[0] < CB_CFIG_MIN_PARAMS) {
+ bdp->config[0] = CB_CFIG_MIN_PARAMS;
+ }
+
+ /* Copy the device's config block to the device's memory */
+ memcpy(cmd->non_tx_cmd->ntcb.config.cfg_byte, bdp->config,
+ bdp->config[0]);
+ /* reset number of bytes to config next time */
+ bdp->config[0] = 0;
+
+ spin_unlock_bh(&bdp->config_lock);
+
+ res = e100_exec_non_cu_cmd(bdp, cmd);
+
+exit:
+ if (netif_running(bdp->device))
+ netif_wake_queue(bdp->device);
+ return res;
+}
+
+/**
+ * e100_config_fc - config flow-control state
+ * @bdp: atapter's private data struct
+ *
+ * This routine will enable or disable flow control support in the adapter's
+ * config block. Flow control will be enable only if requested using the command
+ * line option, and if the link is flow-contorl capable (both us and the link
+ * partner).
+ *
+ * Returns:
+ * true: if then option was indeed changed
+ * false: if no change was needed
+ */
+unsigned char
+e100_config_fc(struct e100_private *bdp)
+{
+ unsigned char enable = false;
+ unsigned char changed = false;
+
+ /* 82557 doesn't support fc. Don't touch this option */
+ if (!(bdp->flags & IS_BACHELOR))
+ return false;
+
+ /* Enable fc if requested and if the link supports it */
+ if ((bdp->params.b_params & PRM_FC) && (bdp->flags & DF_LINK_FC_CAP)) {
+ enable = true;
+ }
+
+ spin_lock_bh(&(bdp->config_lock));
+
+ if (enable) {
+
+ if (bdp->config[16] != DFLT_FC_DELAY_LSB) {
+ bdp->config[16] = DFLT_FC_DELAY_LSB;
+ E100_CONFIG(bdp, 16);
+ changed = true;
+ }
+
+ if (bdp->config[17] != DFLT_FC_DELAY_LSB) {
+ bdp->config[17] = DFLT_FC_DELAY_MSB;
+ E100_CONFIG(bdp, 17);
+ changed = true;
+ }
+
+ /* check if *all* fc config options were already set */
+ if (((bdp->config[19] & CB_CFIG_FC_OPTS) != CB_CFIG_FC_OPTS) ||
+ (bdp->config[19] & CB_CFIG_TX_FC_DIS)) {
+
+ bdp->config[19] |= CB_CFIG_FC_OPTS;
+ bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
+ E100_CONFIG(bdp, 19);
+ changed = true;
+ }
+
+ } else {
+ if (bdp->config[16] != DFLT_NO_FC_DELAY_LSB) {
+ bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
+ E100_CONFIG(bdp, 16);
+ changed = true;
+ }
+
+ if (bdp->config[17] != DFLT_NO_FC_DELAY_MSB) {
+ bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
+ E100_CONFIG(bdp, 17);
+ changed = true;
+ }
+
+ /* check if *any* fc config options was already set */
+ if ((bdp->config[19] & CB_CFIG_FC_OPTS) ||
+ !(bdp->config[19] & CB_CFIG_TX_FC_DIS)) {
+
+ bdp->config[19] &= ~CB_CFIG_FC_OPTS;
+ bdp->config[19] |= CB_CFIG_TX_FC_DIS;
+ E100_CONFIG(bdp, 19);
+ changed = true;
+ }
+ }
+
+ spin_unlock_bh(&(bdp->config_lock));
+
+ return changed;
+}
+
+/**
+ * e100_config_promisc - configure promiscuous mode
+ * @bdp: atapter's private data struct
+ * @enable: should we enable this option or not
+ *
+ * This routine will enable or disable promiscuous mode
+ * in the adapter's config block.
+ */
+void
+e100_config_promisc(struct e100_private *bdp, unsigned char enable)
+{
+ spin_lock_bh(&(bdp->config_lock));
+
+ /* if in promiscuous mode, save bad frames */
+ if (enable) {
+
+ if (!(bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES)) {
+ bdp->config[6] |= CB_CFIG_SAVE_BAD_FRAMES;
+ E100_CONFIG(bdp, 6);
+ }
+
+ if (bdp->config[7] & (u8) BIT_0) {
+ bdp->config[7] &= (u8) (~BIT_0);
+ E100_CONFIG(bdp, 7);
+ }
+
+ if (!(bdp->config[15] & CB_CFIG_PROMISCUOUS)) {
+ bdp->config[15] |= CB_CFIG_PROMISCUOUS;
+ E100_CONFIG(bdp, 15);
+ }
+
+ } else { /* not in promiscuous mode */
+
+ if (bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES) {
+ bdp->config[6] &= ~CB_CFIG_SAVE_BAD_FRAMES;
+ E100_CONFIG(bdp, 6);
+ }
+
+ if (!(bdp->config[7] & (u8) BIT_0)) {
+ bdp->config[7] |= (u8) (BIT_0);
+ E100_CONFIG(bdp, 7);
+ }
+
+ if (bdp->config[15] & CB_CFIG_PROMISCUOUS) {
+ bdp->config[15] &= ~CB_CFIG_PROMISCUOUS;
+ E100_CONFIG(bdp, 15);
+ }
+ }
+
+ spin_unlock_bh(&(bdp->config_lock));
+}
+
+/**
+ * e100_config_mulcast_enbl - configure allmulti mode
+ * @bdp: atapter's private data struct
+ * @enable: should we enable this option or not
+ *
+ * This routine will enable or disable reception of all multicast packets
+ * in the adapter's config block.
+ */
+void
+e100_config_mulcast_enbl(struct e100_private *bdp, unsigned char enable)
+{
+ spin_lock_bh(&(bdp->config_lock));
+
+ /* this flag is used to enable receiving all multicast packet */
+ if (enable) {
+ if (!(bdp->config[21] & CB_CFIG_MULTICAST_ALL)) {
+ bdp->config[21] |= CB_CFIG_MULTICAST_ALL;
+ E100_CONFIG(bdp, 21);
+ }
+
+ } else {
+ if (bdp->config[21] & CB_CFIG_MULTICAST_ALL) {
+ bdp->config[21] &= ~CB_CFIG_MULTICAST_ALL;
+ E100_CONFIG(bdp, 21);
+ }
+ }
+
+ spin_unlock_bh(&(bdp->config_lock));
+}
+
+/**
+ * e100_config_ifs - configure the IFS parameter
+ * @bdp: atapter's private data struct
+ *
+ * This routine will configure the adaptive IFS value
+ * in the adapter's config block. IFS values are only
+ * relevant in half duplex, so set to 0 in full duplex.
+ */
+void
+e100_config_ifs(struct e100_private *bdp)
+{
+ u8 value = 0;
+
+ spin_lock_bh(&(bdp->config_lock));
+
+ /* IFS value is only needed to be specified at half-duplex mode */
+ if (bdp->cur_dplx_mode == HALF_DUPLEX) {
+ value = (u8) bdp->ifs_value;
+ }
+
+ if (bdp->config[2] != value) {
+ bdp->config[2] = value;
+ E100_CONFIG(bdp, 2);
+ }
+
+ spin_unlock_bh(&(bdp->config_lock));
+}
+
+/**
+ * e100_config_force_dplx - configure the forced full duplex mode
+ * @bdp: atapter's private data struct
+ *
+ * This routine will enable or disable force full duplex
+ * in the adapter's config block. If the PHY is 503, and
+ * the duplex is full, consider the adapter forced.
+ */
+void
+e100_config_force_dplx(struct e100_private *bdp)
+{
+ spin_lock_bh(&(bdp->config_lock));
+
+ /* We must force full duplex on if we are using PHY 0, and we are */
+ /* supposed to run in FDX mode. We do this because the e100 has only */
+ /* one FDX# input pin, and that pin will be connected to PHY 1. */
+ /* Changed the 'if' condition below to fix performance problem * at 10
+ * full. The Phy was getting forced to full duplex while the MAC * was
+ * not, because the cur_dplx_mode was not being set to 2 by SetupPhy. *
+ * This is how the condition was, initially. * This has been changed so
+ * that the MAC gets forced to full duplex * simply if the user has
+ * forced full duplex. * * if (( bdp->phy_addr == 0 ) && (
+ * bdp->cur_dplx_mode == 2 )) */
+ /* The rest of the fix is in the PhyDetect code. */
+ if ((bdp->params.e100_speed_duplex == E100_SPEED_10_FULL) ||
+ (bdp->params.e100_speed_duplex == E100_SPEED_100_FULL) ||
+ ((bdp->phy_addr == 32) && (bdp->cur_dplx_mode == FULL_DUPLEX))) {
+ if (!(bdp->config[19] & (u8) CB_CFIG_FORCE_FDX)) {
+ bdp->config[19] |= (u8) CB_CFIG_FORCE_FDX;
+ E100_CONFIG(bdp, 19);
+ }
+
+ } else {
+ if (bdp->config[19] & (u8) CB_CFIG_FORCE_FDX) {
+ bdp->config[19] &= (u8) (~CB_CFIG_FORCE_FDX);
+ E100_CONFIG(bdp, 19);
+ }
+ }
+
+ spin_unlock_bh(&(bdp->config_lock));
+}
+
+/**
+ * e100_config_long_rx
+ * @bdp: atapter's private data struct
+ * @enable: should we enable this option or not
+ *
+ * This routine will enable or disable reception of larger packets.
+ * This is needed by VLAN implementations.
+ */
+static void
+e100_config_long_rx(struct e100_private *bdp, unsigned char enable)
+{
+ if (enable) {
+ if (!(bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
+ bdp->config[18] |= CB_CFIG_LONG_RX_OK;
+ E100_CONFIG(bdp, 18);
+ }
+
+ } else {
+ if ((bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
+ bdp->config[18] &= ~CB_CFIG_LONG_RX_OK;
+ E100_CONFIG(bdp, 18);
+ }
+ }
+}
+
+#ifdef ETHTOOL_GWOL
+/**
+ * e100_config_wol
+ * @bdp: atapter's private data struct
+ *
+ * This sets configuration options for Wake On LAN functionality (WOL) in the
+ * config record. WOL options are retrieved from wolinfo_wolopts in @bdp
+ */
+void
+e100_config_wol(struct e100_private *bdp)
+{
+ spin_lock_bh(&(bdp->config_lock));
+
+ if (bdp->wolopts & WAKE_PHY) {
+ bdp->config[9] |= CB_LINK_STATUS_WOL;
+ E100_CONFIG(bdp, 9);
+ }
+
+ if (!(bdp->wolopts & WAKE_MAGIC)) {
+ bdp->config[19] |= CB_DISABLE_MAGPAK_WAKE;
+ E100_CONFIG(bdp, 19);
+ }
+
+ spin_unlock_bh(&(bdp->config_lock));
+}
+#endif
+
diff --git a/drivers/net/e100/e100_config.h b/drivers/net/e100/e100_config.h
new file mode 100644
index 000000000000..71618e3f2e65
--- /dev/null
+++ b/drivers/net/e100/e100_config.h
@@ -0,0 +1,206 @@
+/*******************************************************************************
+
+This software program is available to you under a choice of one of two
+licenses. You may choose to be licensed under either the GNU General Public
+License (GPL) Version 2, June 1991, available at
+http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+text of which follows:
+
+Recipient has requested a license and Intel Corporation ("Intel") is willing
+to grant a license for the software entitled Linux Base Driver for the
+Intel(R) PRO/100 Family of Adapters (e100) (the "Software") being provided
+by Intel Corporation. The following definitions apply to this license:
+
+"Licensed Patents" means patent claims licensable by Intel Corporation which
+are necessarily infringed by the use of sale of the Software alone or when
+combined with the operating system referred to below.
+
+"Recipient" means the party to whom Intel delivers this Software.
+
+"Licensee" means Recipient and those third parties that receive a license to
+any operating system available under the GNU Public License version 2.0 or
+later.
+
+Copyright (c) 1999 - 2002 Intel Corporation.
+All rights reserved.
+
+The license is provided to Recipient and Recipient's Licensees under the
+following terms.
+
+Redistribution and use in source and binary forms of the Software, with or
+without modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code of the Software may retain the above
+copyright notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form of the Software may reproduce the above
+copyright notice, this list of conditions and the following disclaimer in
+the documentation and/or materials provided with the distribution.
+
+Neither the name of Intel Corporation nor the names of its contributors
+shall be used to endorse or promote products derived from this Software
+without specific prior written permission.
+
+Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell, offer
+to sell, import and otherwise transfer the Software, if any, in source code
+and object code form. This license shall include changes to the Software
+that are error corrections or other minor changes to the Software that do
+not add functionality or features when the Software is incorporated in any
+version of an operating system that has been distributed under the GNU
+General Public License 2.0 or later. This patent license shall apply to the
+combination of the Software and any operating system licensed under the GNU
+Public License version 2.0 or later if, at the time Intel provides the
+Software to Recipient, such addition of the Software to the then publicly
+available versions of such operating systems available under the GNU Public
+License version 2.0 or later (whether in gold, beta or alpha form) causes
+such combination to be covered by the Licensed Patents. The patent license
+shall not apply to any other combinations which include the Software. NO
+hardware per se is licensed hereunder.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) 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.
+*******************************************************************************/
+
+#ifndef _E100_CONFIG_INC_
+#define _E100_CONFIG_INC_
+
+#include "e100.h"
+
+#define E100_CONFIG(bdp, X) ((bdp)->config[0] = max_t(u8, (bdp)->config[0], (X)+1))
+
+#define CB_CFIG_MIN_PARAMS 8
+
+/* byte 0 bit definitions*/
+#define CB_CFIG_BYTE_COUNT_MASK BIT_0_5 /* Byte count occupies bit 5-0 */
+
+/* byte 1 bit definitions*/
+#define CB_CFIG_RXFIFO_LIMIT_MASK BIT_0_4 /* RxFifo limit mask */
+#define CB_CFIG_TXFIFO_LIMIT_MASK BIT_4_7 /* TxFifo limit mask */
+
+/* byte 2 bit definitions -- ADAPTIVE_IFS*/
+
+/* word 3 bit definitions -- RESERVED*/
+/* Changed for 82558 enhancements */
+/* byte 3 bit definitions */
+#define CB_CFIG_MWI_EN BIT_0 /* Enable MWI on PCI bus */
+#define CB_CFIG_TYPE_EN BIT_1 /* Type Enable */
+#define CB_CFIG_READAL_EN BIT_2 /* Enable Read Align */
+#define CB_CFIG_TERMCL_EN BIT_3 /* Cache line write */
+
+/* byte 4 bit definitions*/
+#define CB_CFIG_RX_MIN_DMA_MASK BIT_0_6 /* Rx minimum DMA count mask */
+
+/* byte 5 bit definitions*/
+#define CB_CFIG_TX_MIN_DMA_MASK BIT_0_6 /* Tx minimum DMA count mask */
+#define CB_CFIG_DMBC_EN BIT_7 /* Enable Tx/Rx min. DMA counts */
+
+/* Changed for 82558 enhancements */
+/* byte 6 bit definitions*/
+#define CB_CFIG_LATE_SCB BIT_0 /* Update SCB After New Tx Start */
+#define CB_CFIG_DIRECT_DMA_DIS BIT_1 /* Direct DMA mode */
+#define CB_CFIG_TNO_INT BIT_2 /* Tx Not OK Interrupt */
+#define CB_CFIG_TCO_STAT BIT_2 /* TCO statistics in 559 and above */
+#define CB_CFIG_CI_INT BIT_3 /* Command Complete Interrupt */
+#define CB_CFIG_EXT_TCB_DIS BIT_4 /* Extended TCB */
+#define CB_CFIG_EXT_STAT_DIS BIT_5 /* Extended Stats */
+#define CB_CFIG_SAVE_BAD_FRAMES BIT_7 /* Save Bad Frames Enabled */
+
+/* byte 7 bit definitions*/
+#define CB_CFIG_DISC_SHORT_FRAMES BIT_0 /* Discard Short Frames */
+#define CB_CFIG_DYNTBD_EN BIT_7 /* Enable dynamic TBD */
+/* Enable extended RFD's on D102 */
+#define CB_CFIG_EXTENDED_RFD BIT_5
+
+/* byte 8 bit definitions*/
+#define CB_CFIG_503_MII BIT_0 /* 503 vs. MII mode */
+
+/* byte 9 bit definitions -- pre-defined all zeros*/
+#define CB_LINK_STATUS_WOL BIT_5
+
+/* byte 10 bit definitions*/
+#define CB_CFIG_NO_SRCADR BIT_3 /* No Source Address Insertion */
+#define CB_CFIG_PREAMBLE_LEN BIT_4_5 /* Preamble Length */
+#define CB_CFIG_LOOPBACK_MODE BIT_6_7 /* Loopback Mode */
+#define CB_CFIG_LOOPBACK_NORMAL 0
+#define CB_CFIG_LOOPBACK_INTERNAL BIT_6
+#define CB_CFIG_LOOPBACK_EXTERNAL BIT_6_7
+
+/* byte 11 bit definitions*/
+#define CB_CFIG_LINEAR_PRIORITY BIT_0_2 /* Linear Priority */
+
+/* byte 12 bit definitions*/
+#define CB_CFIG_LINEAR_PRI_MODE BIT_0 /* Linear Priority mode */
+#define CB_CFIG_IFS_MASK BIT_4_7 /* Interframe Spacing mask */
+
+/* byte 13 bit definitions -- pre-defined all zeros*/
+
+/* byte 14 bit definitions -- pre-defined 0xf2*/
+
+/* byte 15 bit definitions*/
+#define CB_CFIG_PROMISCUOUS BIT_0 /* Promiscuous Mode Enable */
+#define CB_CFIG_BROADCAST_DIS BIT_1 /* Broadcast Mode Disable */
+#define CB_CFIG_CRS_OR_CDT BIT_7 /* CRS Or CDT */
+
+/* byte 16 bit definitions -- pre-defined all zeros*/
+#define DFLT_FC_DELAY_LSB 0x1f /* Delay for outgoing Pause frames */
+#define DFLT_NO_FC_DELAY_LSB 0x00 /* no flow control default value */
+
+/* byte 17 bit definitions -- pre-defined 0x40*/
+#define DFLT_FC_DELAY_MSB 0x01 /* Delay for outgoing Pause frames */
+#define DFLT_NO_FC_DELAY_MSB 0x40 /* no flow control default value */
+
+/* byte 18 bit definitions*/
+#define CB_CFIG_STRIPPING BIT_0 /* Padding Disabled */
+#define CB_CFIG_PADDING BIT_1 /* Padding Disabled */
+#define CB_CFIG_CRC_IN_MEM BIT_2 /* Transfer CRC To Memory */
+
+/* byte 19 bit definitions*/
+#define CB_CFIG_TX_ADDR_WAKE BIT_0 /* Address Wakeup */
+#define CB_DISABLE_MAGPAK_WAKE BIT_1 /* Magic Packet Wakeup disable */
+/* Changed TX_FC_EN to TX_FC_DIS because 0 enables, 1 disables. Jul 8, 1999 */
+#define CB_CFIG_TX_FC_DIS BIT_2 /* Tx Flow Control Disable */
+#define CB_CFIG_FC_RESTOP BIT_3 /* Rx Flow Control Restop */
+#define CB_CFIG_FC_RESTART BIT_4 /* Rx Flow Control Restart */
+#define CB_CFIG_FC_REJECT BIT_5 /* Rx Flow Control Restart */
+#define CB_CFIG_FC_OPTS (CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART | CB_CFIG_FC_REJECT)
+
+/* end 82558/9 specifics */
+
+#define CB_CFIG_FORCE_FDX BIT_6 /* Force Full Duplex */
+#define CB_CFIG_FDX_ENABLE BIT_7 /* Full Duplex Enabled */
+
+/* byte 20 bit definitions*/
+#define CB_CFIG_MULTI_IA BIT_6 /* Multiple IA Addr */
+
+/* byte 21 bit definitions*/
+#define CB_CFIG_MULTICAST_ALL BIT_3 /* Multicast All */
+
+/* byte 22 bit defines */
+#define CB_CFIG_RECEIVE_GAMLA_MODE BIT_0 /* D102 receive mode */
+#define CB_CFIG_VLAN_DROP_ENABLE BIT_1 /* vlan stripping */
+
+#define CB_CFIG_LONG_RX_OK BIT_3
+
+/* function prototypes */
+extern void e100_config_init(struct e100_private *bdp);
+extern unsigned char e100_force_config(struct e100_private *bdp);
+extern unsigned char e100_config(struct e100_private *bdp);
+extern unsigned char e100_config_fc(struct e100_private *bdp);
+extern void e100_config_promisc(struct e100_private *bdp, unsigned char enable);
+extern void e100_config_brdcast_dsbl(struct e100_private *bdp);
+extern void e100_config_mulcast_enbl(struct e100_private *bdp,
+ unsigned char enable);
+extern void e100_config_ifs(struct e100_private *bdp);
+extern void e100_config_force_dplx(struct e100_private *bdp);
+
+#endif /* _E100_CONFIG_INC_ */
diff --git a/drivers/net/e100/e100_eeprom.c b/drivers/net/e100/e100_eeprom.c
new file mode 100644
index 000000000000..df9daebf634c
--- /dev/null
+++ b/drivers/net/e100/e100_eeprom.c
@@ -0,0 +1,614 @@
+/*******************************************************************************
+
+This software program is available to you under a choice of one of two
+licenses. You may choose to be licensed under either the GNU General Public
+License (GPL) Version 2, June 1991, available at
+http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+text of which follows:
+
+Recipient has requested a license and Intel Corporation ("Intel") is willing
+to grant a license for the software entitled Linux Base Driver for the
+Intel(R) PRO/100 Family of Adapters (e100) (the "Software") being provided
+by Intel Corporation. The following definitions apply to this license:
+
+"Licensed Patents" means patent claims licensable by Intel Corporation which
+are necessarily infringed by the use of sale of the Software alone or when
+combined with the operating system referred to below.
+
+"Recipient" means the party to whom Intel delivers this Software.
+
+"Licensee" means Recipient and those third parties that receive a license to
+any operating system available under the GNU Public License version 2.0 or
+later.
+
+Copyright (c) 1999 - 2002 Intel Corporation.
+All rights reserved.
+
+The license is provided to Recipient and Recipient's Licensees under the
+following terms.
+
+Redistribution and use in source and binary forms of the Software, with or
+without modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code of the Software may retain the above
+copyright notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form of the Software may reproduce the above
+copyright notice, this list of conditions and the following disclaimer in
+the documentation and/or materials provided with the distribution.
+
+Neither the name of Intel Corporation nor the names of its contributors
+shall be used to endorse or promote products derived from this Software
+without specific prior written permission.
+
+Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell, offer
+to sell, import and otherwise transfer the Software, if any, in source code
+and object code form. This license shall include changes to the Software
+that are error corrections or other minor changes to the Software that do
+not add functionality or features when the Software is incorporated in any
+version of an operating system that has been distributed under the GNU
+General Public License 2.0 or later. This patent license shall apply to the
+combination of the Software and any operating system licensed under the GNU
+Public License version 2.0 or later if, at the time Intel provides the
+Software to Recipient, such addition of the Software to the then publicly
+available versions of such operating systems available under the GNU Public
+License version 2.0 or later (whether in gold, beta or alpha form) causes
+such combination to be covered by the Licensed Patents. The patent license
+shall not apply to any other combinations which include the Software. NO
+hardware per se is licensed hereunder.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) 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.
+*******************************************************************************/
+
+/**********************************************************************
+* *
+* INTEL CORPORATION *
+* *
+* This software is supplied under the terms of the license included *
+* above. All use of this driver must be in accordance with the terms *
+* of that license. *
+* *
+* Module Name: e100_eeprom.c *
+* *
+* Abstract: This module contains routines to read and write to a *
+* serial EEPROM *
+* *
+* Environment: This file is intended to be specific to the Linux *
+* operating system. *
+* *
+**********************************************************************/
+#include "e100.h"
+
+#define CSR_EEPROM_CONTROL_FIELD(bdp) ((bdp)->scb->scb_eprm_cntrl)
+
+#define CSR_GENERAL_CONTROL2_FIELD(bdp) \
+ ((bdp)->scb->scb_ext.d102_scb.scb_gen_ctrl2)
+
+#define EEPROM_STALL_TIME 4
+#define EEPROM_CHECKSUM ((u16) 0xBABA)
+#define EEPROM_MAX_WORD_SIZE 256
+
+void e100_eeprom_cleanup(struct e100_private *adapter);
+u16 e100_eeprom_calculate_chksum(struct e100_private *adapter);
+static void e100_eeprom_write_word(struct e100_private *adapter, u16 reg,
+ u16 data);
+void e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data,
+ u16 size);
+u16 e100_eeprom_size(struct e100_private *adapter);
+u16 e100_eeprom_read(struct e100_private *adapter, u16 reg);
+
+static void shift_out_bits(struct e100_private *adapter, u16 data, u16 count);
+static u16 shift_in_bits(struct e100_private *adapter);
+static void raise_clock(struct e100_private *adapter, u16 *x);
+static void lower_clock(struct e100_private *adapter, u16 *x);
+static u16 eeprom_wait_cmd_done(struct e100_private *adapter);
+static void eeprom_stand_by(struct e100_private *adapter);
+
+//----------------------------------------------------------------------------------------
+// Procedure: eeprom_set_semaphore
+//
+// Description: This function set (write 1) Gamla EEPROM semaphore bit (bit 23 word 0x1C in the CSR).
+//
+// Arguments:
+// Adapter - Adapter context
+//
+// Returns: true if success
+// else return false
+//
+//----------------------------------------------------------------------------------------
+
+inline u8
+eeprom_set_semaphore(struct e100_private *adapter)
+{
+ u16 data = 0;
+ unsigned long expiration_time = jiffies + HZ / 100 + 1;
+
+ while (time_before(jiffies, expiration_time)) {
+ // Get current value of General Control 2
+ data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
+
+ // Set bit 23 word 0x1C in the CSR.
+ data |= SCB_GCR2_EEPROM_ACCESS_SEMAPHORE;
+ writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter));
+
+ barrier();
+
+ // Check to see if this bit set or not.
+ data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
+
+ if (data & SCB_GCR2_EEPROM_ACCESS_SEMAPHORE) {
+ return true;
+ }
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------------------
+// Procedure: eeprom_reset_semaphore
+//
+// Description: This function reset (write 0) Gamla EEPROM semaphore bit
+// (bit 23 word 0x1C in the CSR).
+//
+// Arguments: struct e100_private * adapter - Adapter context
+//----------------------------------------------------------------------------------------
+
+inline void
+eeprom_reset_semaphore(struct e100_private *adapter)
+{
+ u16 data = 0;
+
+ data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
+ data &= ~(SCB_GCR2_EEPROM_ACCESS_SEMAPHORE);
+ writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter));
+}
+
+//----------------------------------------------------------------------------------------
+// Procedure: e100_eeprom_size
+//
+// Description: This routine determines the size of the EEPROM. This value should be
+// checked for validity - ie. is it too big or too small. The size returned
+// is then passed to the read/write functions.
+//
+// Returns:
+// Size of the eeprom, or zero if an error occured
+//----------------------------------------------------------------------------------------
+u16
+e100_eeprom_size(struct e100_private *adapter)
+{
+ u16 x, size = 1; // must be one to accumulate a product
+
+ // if we've already stored this data, read from memory
+ if (adapter->eeprom_size) {
+ return adapter->eeprom_size;
+ }
+ // otherwise, read from the eeprom
+ // Set EEPROM semaphore.
+ if (adapter->rev_id >= D102_REV_ID) {
+ if (!eeprom_set_semaphore(adapter))
+ return 0;
+ }
+ // enable the eeprom by setting EECS.
+ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
+
+ // write the read opcode
+ shift_out_bits(adapter, EEPROM_READ_OPCODE, 3);
+
+ // experiment to discover the size of the eeprom. request register zero
+ // and wait for the eeprom to tell us it has accepted the entire address.
+ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
+ do {
+ size *= 2; // each bit of address doubles eeprom size
+ x |= EEDO; // set bit to detect "dummy zero"
+ x &= ~EEDI; // address consists of all zeros
+
+ writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
+ udelay(EEPROM_STALL_TIME);
+ raise_clock(adapter, &x);
+ lower_clock(adapter, &x);
+
+ // check for "dummy zero"
+ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
+ if (size > EEPROM_MAX_WORD_SIZE) {
+ size = 0;
+ break;
+ }
+ } while (x & EEDO);
+
+ // read in the value requested
+ (void) shift_in_bits(adapter);
+ e100_eeprom_cleanup(adapter);
+
+ // Clear EEPROM Semaphore.
+ if (adapter->rev_id >= D102_REV_ID) {
+ eeprom_reset_semaphore(adapter);
+ }
+
+ return size;
+}
+
+//----------------------------------------------------------------------------------------
+// Procedure: eeprom_address_size
+//
+// Description: determines the number of bits in an address for the eeprom acceptable
+// values are 64, 128, and 256
+// Arguments: size of the eeprom
+// Returns: bits in an address for that size eeprom
+//----------------------------------------------------------------------------------------
+
+static u16
+eeprom_address_size(u16 size)
+{
+ switch (size) {
+ case 64:
+ return 6;
+ case 128:
+ return 7;
+ case 256:
+ return 8;
+ }
+
+ return 0; //fix compiler warning or error!
+}
+
+//----------------------------------------------------------------------------------------
+// Procedure: e100_eeprom_read
+//
+// Description: This routine serially reads one word out of the EEPROM.
+//
+// Arguments:
+// adapter - our adapter context
+// reg - EEPROM word to read.
+//
+// Returns:
+// Contents of EEPROM word (reg).
+//----------------------------------------------------------------------------------------
+
+u16
+e100_eeprom_read(struct e100_private *adapter, u16 reg)
+{
+ u16 x, data, bits;
+
+ // Set EEPROM semaphore.
+ if (adapter->rev_id >= D102_REV_ID) {
+ if (!eeprom_set_semaphore(adapter))
+ return 0;
+ }
+ // eeprom size is initialized to zero
+ if (!adapter->eeprom_size)
+ adapter->eeprom_size = e100_eeprom_size(adapter);
+
+ bits = eeprom_address_size(adapter->eeprom_size);
+
+ // select EEPROM, reset bits, set EECS
+ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
+
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
+
+ // write the read opcode and register number in that order
+ // The opcode is 3bits in length, reg is 'bits' bits long
+ shift_out_bits(adapter, EEPROM_READ_OPCODE, 3);
+ shift_out_bits(adapter, reg, bits);
+
+ // Now read the data (16 bits) in from the selected EEPROM word
+ data = shift_in_bits(adapter);
+
+ e100_eeprom_cleanup(adapter);
+
+ // Clear EEPROM Semaphore.
+ if (adapter->rev_id >= D102_REV_ID) {
+ eeprom_reset_semaphore(adapter);
+ }
+
+ return data;
+}
+
+//----------------------------------------------------------------------------------------
+// Procedure: shift_out_bits
+//
+// Description: This routine shifts data bits out to the EEPROM.
+//
+// Arguments:
+// data - data to send to the EEPROM.
+// count - number of data bits to shift out.
+//
+// Returns: (none)
+//----------------------------------------------------------------------------------------
+
+static void
+shift_out_bits(struct e100_private *adapter, u16 data, u16 count)
+{
+ u16 x, mask;
+
+ mask = 1 << (count - 1);
+ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
+ x &= ~(EEDO | EEDI);
+
+ do {
+ x &= ~EEDI;
+ if (data & mask)
+ x |= EEDI;
+
+ writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
+ udelay(EEPROM_STALL_TIME);
+ raise_clock(adapter, &x);
+ lower_clock(adapter, &x);
+ mask = mask >> 1;
+ } while (mask);
+
+ x &= ~EEDI;
+ writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter));
+}
+
+//----------------------------------------------------------------------------------------
+// Procedure: raise_clock
+//
+// Description: This routine raises the EEPROM's clock input (EESK)
+//
+// Arguments:
+// x - Ptr to the EEPROM control register's current value
+//
+// Returns: (none)
+//----------------------------------------------------------------------------------------
+
+void
+raise_clock(struct e100_private *adapter, u16 *x)
+{
+ *x = *x | EESK;
+ writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter));
+ udelay(EEPROM_STALL_TIME);
+}
+
+//----------------------------------------------------------------------------------------
+// Procedure: lower_clock
+//
+// Description: This routine lower's the EEPROM's clock input (EESK)
+//
+// Arguments:
+// x - Ptr to the EEPROM control register's current value
+//
+// Returns: (none)
+//----------------------------------------------------------------------------------------
+
+void
+lower_clock(struct e100_private *adapter, u16 *x)
+{
+ *x = *x & ~EESK;
+ writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter));
+ udelay(EEPROM_STALL_TIME);
+}
+
+//----------------------------------------------------------------------------------------
+// Procedure: shift_in_bits
+//
+// Description: This routine shifts data bits in from the EEPROM.
+//
+// Arguments:
+//
+// Returns:
+// The contents of that particular EEPROM word
+//----------------------------------------------------------------------------------------
+
+static u16
+shift_in_bits(struct e100_private *adapter)
+{
+ u16 x, d, i;
+
+ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
+ x &= ~(EEDO | EEDI);
+ d = 0;
+
+ for (i = 0; i < 16; i++) {
+ d <<= 1;
+ raise_clock(adapter, &x);
+
+ x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
+
+ x &= ~EEDI;