aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/removed/raw1394_legacy_isochronous16
-rw-r--r--Documentation/DocBook/kernel-api.tmpl11
-rw-r--r--Documentation/block/barrier.txt16
-rw-r--r--Documentation/feature-removal-schedule.txt10
-rw-r--r--Documentation/kernel-parameters.txt43
-rw-r--r--Documentation/networking/spider_net.txt204
-rw-r--r--Documentation/power_supply_class.txt167
-rw-r--r--Documentation/sched-design-CFS.txt119
-rw-r--r--MAINTAINERS12
-rw-r--r--arch/i386/kernel/smpboot.c12
-rw-r--r--arch/i386/kernel/tsc.c9
-rw-r--r--arch/ia64/kernel/setup.c6
-rw-r--r--arch/mips/Kconfig198
-rw-r--r--arch/mips/Makefile84
-rw-r--r--arch/mips/au1000/common/gpio.c124
-rw-r--r--arch/mips/au1000/common/platform.c2
-rw-r--r--arch/mips/configs/atlas_defconfig4
-rw-r--r--arch/mips/configs/bigsur_defconfig4
-rw-r--r--arch/mips/configs/capcella_defconfig4
-rw-r--r--arch/mips/configs/cobalt_defconfig502
-rw-r--r--arch/mips/configs/db1000_defconfig4
-rw-r--r--arch/mips/configs/db1100_defconfig4
-rw-r--r--arch/mips/configs/db1200_defconfig4
-rw-r--r--arch/mips/configs/db1500_defconfig4
-rw-r--r--arch/mips/configs/db1550_defconfig4
-rw-r--r--arch/mips/configs/ddb5477_defconfig4
-rw-r--r--arch/mips/configs/decstation_defconfig4
-rw-r--r--arch/mips/configs/e55_defconfig4
-rw-r--r--arch/mips/configs/emma2rh_defconfig4
-rw-r--r--arch/mips/configs/ev64120_defconfig985
-rw-r--r--arch/mips/configs/excite_defconfig4
-rw-r--r--arch/mips/configs/fulong_defconfig1765
-rw-r--r--arch/mips/configs/ip22_defconfig4
-rw-r--r--arch/mips/configs/ip27_defconfig4
-rw-r--r--arch/mips/configs/ip32_defconfig4
-rw-r--r--arch/mips/configs/jazz_defconfig4
-rw-r--r--arch/mips/configs/jmr3927_defconfig4
-rw-r--r--arch/mips/configs/lasat200_defconfig1118
-rw-r--r--arch/mips/configs/malta_defconfig4
-rw-r--r--arch/mips/configs/mipssim_defconfig37
-rw-r--r--arch/mips/configs/mpc30x_defconfig4
-rw-r--r--arch/mips/configs/msp71xx_defconfig (renamed from arch/mips/configs/ocelot_3_defconfig)972
-rw-r--r--arch/mips/configs/ocelot_c_defconfig982
-rw-r--r--arch/mips/configs/ocelot_defconfig4
-rw-r--r--arch/mips/configs/pb1100_defconfig4
-rw-r--r--arch/mips/configs/pb1500_defconfig4
-rw-r--r--arch/mips/configs/pb1550_defconfig4
-rw-r--r--arch/mips/configs/pnx8550-jbs_defconfig4
-rw-r--r--arch/mips/configs/pnx8550-stb810_defconfig4
-rw-r--r--arch/mips/configs/qemu_defconfig4
-rw-r--r--arch/mips/configs/rbhma4200_defconfig4
-rw-r--r--arch/mips/configs/rbhma4500_defconfig945
-rw-r--r--arch/mips/configs/rm200_defconfig4
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig4
-rw-r--r--arch/mips/configs/sead_defconfig4
-rw-r--r--arch/mips/configs/tb0219_defconfig4
-rw-r--r--arch/mips/configs/tb0226_defconfig4
-rw-r--r--arch/mips/configs/tb0287_defconfig4
-rw-r--r--arch/mips/configs/workpad_defconfig4
-rw-r--r--arch/mips/configs/wrppmc_defconfig4
-rw-r--r--arch/mips/configs/yosemite_defconfig4
-rw-r--r--arch/mips/ddb5xxx/ddb5477/Makefile3
-rw-r--r--arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c49
-rw-r--r--arch/mips/dec/prom/console.c32
-rw-r--r--arch/mips/dec/prom/init.c5
-rw-r--r--arch/mips/dec/reset.c10
-rw-r--r--arch/mips/defconfig4
-rw-r--r--arch/mips/gt64120/ev64120/Kconfig3
-rw-r--r--arch/mips/gt64120/ev64120/Makefile9
-rw-r--r--arch/mips/gt64120/ev64120/irq.c116
-rw-r--r--arch/mips/gt64120/ev64120/promcon.c48
-rw-r--r--arch/mips/gt64120/ev64120/reset.c45
-rw-r--r--arch/mips/gt64120/ev64120/serialGT.c212
-rw-r--r--arch/mips/gt64120/ev64120/setup.c99
-rw-r--r--arch/mips/gt64120/momenco_ocelot/Makefile2
-rw-r--r--arch/mips/gt64120/momenco_ocelot/ocelot-platform.c46
-rw-r--r--arch/mips/gt64120/wrppmc/setup.c4
-rw-r--r--arch/mips/jazz/Makefile2
-rw-r--r--arch/mips/jazz/jazz-platform.c60
-rw-r--r--arch/mips/kernel/8250-platform.c47
-rw-r--r--arch/mips/kernel/Makefile17
-rw-r--r--arch/mips/kernel/cpu-probe.c30
-rw-r--r--arch/mips/kernel/head.S10
-rw-r--r--arch/mips/kernel/irq-mv6434x.c111
-rw-r--r--arch/mips/kernel/mips-mt-fpaff.c176
-rw-r--r--arch/mips/kernel/mips-mt.c205
-rw-r--r--arch/mips/kernel/proc.c2
-rw-r--r--arch/mips/kernel/process.c4
-rw-r--r--arch/mips/kernel/setup.c16
-rw-r--r--arch/mips/kernel/smp.c13
-rw-r--r--arch/mips/kernel/smtc.c2
-rw-r--r--arch/mips/kernel/syscall.c5
-rw-r--r--arch/mips/kernel/traps.c77
-rw-r--r--arch/mips/kernel/unaligned.c41
-rw-r--r--arch/mips/lasat/Kconfig15
-rw-r--r--arch/mips/lasat/Makefile14
-rw-r--r--arch/mips/lasat/at93c.c148
-rw-r--r--arch/mips/lasat/at93c.h18
-rw-r--r--arch/mips/lasat/ds1603.c183
-rw-r--r--arch/mips/lasat/ds1603.h33
-rw-r--r--arch/mips/lasat/image/Makefile53
-rw-r--r--arch/mips/lasat/image/head.S31
-rw-r--r--arch/mips/lasat/image/romscript.normal23
-rw-r--r--arch/mips/lasat/interrupt.c130
-rw-r--r--arch/mips/lasat/lasat_board.c279
-rw-r--r--arch/mips/lasat/lasat_models.h63
-rw-r--r--arch/mips/lasat/picvue.c240
-rw-r--r--arch/mips/lasat/picvue.h48
-rw-r--r--arch/mips/lasat/picvue_proc.c186
-rw-r--r--arch/mips/lasat/prom.c117
-rw-r--r--arch/mips/lasat/prom.h5
-rw-r--r--arch/mips/lasat/reset.c69
-rw-r--r--arch/mips/lasat/setup.c182
-rw-r--r--arch/mips/lasat/sysctl.c441
-rw-r--r--arch/mips/lasat/sysctl.h24
-rw-r--r--arch/mips/lemote/lm2e/Makefile7
-rw-r--r--arch/mips/lemote/lm2e/bonito-irq.c74
-rw-r--r--arch/mips/lemote/lm2e/dbg_io.c146
-rw-r--r--arch/mips/lemote/lm2e/irq.c145
-rw-r--r--arch/mips/lemote/lm2e/mem.c23
-rw-r--r--arch/mips/lemote/lm2e/pci.c93
-rw-r--r--arch/mips/lemote/lm2e/prom.c104
-rw-r--r--arch/mips/lemote/lm2e/reset.c41
-rw-r--r--arch/mips/lemote/lm2e/setup.c134
-rw-r--r--arch/mips/lib-32/Makefile23
-rw-r--r--arch/mips/lib-32/dump_tlb.c242
-rw-r--r--arch/mips/lib-32/r3k_dump_tlb.c182
-rw-r--r--arch/mips/lib-32/watch.S60
-rw-r--r--arch/mips/lib-64/Makefile23
-rw-r--r--arch/mips/lib-64/dump_tlb.c216
-rw-r--r--arch/mips/lib-64/watch.S57
-rw-r--r--arch/mips/lib/Makefile19
-rw-r--r--arch/mips/lib/dump_tlb.c100
-rw-r--r--arch/mips/lib/r3k_dump_tlb.c62
-rw-r--r--arch/mips/math-emu/cp1emu.c34
-rw-r--r--arch/mips/mips-boards/malta/Makefile3
-rw-r--r--arch/mips/mips-boards/malta/malta_platform.c65
-rw-r--r--arch/mips/mipssim/Makefile (renamed from arch/mips/mips-boards/sim/Makefile)0
-rw-r--r--arch/mips/mipssim/sim_cmdline.c (renamed from arch/mips/mips-boards/sim/sim_cmdline.c)0
-rw-r--r--arch/mips/mipssim/sim_console.c (renamed from arch/mips/mips-boards/sim/sim_console.c)2
-rw-r--r--arch/mips/mipssim/sim_int.c88
-rw-r--r--arch/mips/mipssim/sim_mem.c (renamed from arch/mips/mips-boards/sim/sim_mem.c)2
-rw-r--r--arch/mips/mipssim/sim_platform.c (renamed from arch/mips/mips-boards/sim/sim_platform.c)0
-rw-r--r--arch/mips/mipssim/sim_setup.c (renamed from arch/mips/mips-boards/sim/sim_setup.c)8
-rw-r--r--arch/mips/mipssim/sim_smp.c (renamed from arch/mips/mips-boards/sim/sim_smp.c)18
-rw-r--r--arch/mips/mipssim/sim_time.c (renamed from arch/mips/mips-boards/sim/sim_time.c)30
-rw-r--r--arch/mips/mm/Makefile1
-rw-r--r--arch/mips/mm/c-r4k.c54
-rw-r--r--arch/mips/mm/c-sb1.c2
-rw-r--r--arch/mips/mm/cache.c10
-rw-r--r--arch/mips/mm/tlb-r4k.c23
-rw-r--r--arch/mips/mm/tlbex.c8
-rw-r--r--arch/mips/momentum/ocelot_3/Makefile8
-rw-r--r--arch/mips/momentum/ocelot_3/irq.c109
-rw-r--r--arch/mips/momentum/ocelot_3/platform.c208
-rw-r--r--arch/mips/momentum/ocelot_3/prom.c189
-rw-r--r--arch/mips/momentum/ocelot_3/reset.c59
-rw-r--r--arch/mips/momentum/ocelot_3/setup.c398
-rw-r--r--arch/mips/momentum/ocelot_c/Makefile8
-rw-r--r--arch/mips/momentum/ocelot_c/cpci-irq.c100
-rw-r--r--arch/mips/momentum/ocelot_c/dbg_io.c121
-rw-r--r--arch/mips/momentum/ocelot_c/irq.c107
-rw-r--r--arch/mips/momentum/ocelot_c/platform.c183
-rw-r--r--arch/mips/momentum/ocelot_c/prom.c183
-rw-r--r--arch/mips/momentum/ocelot_c/reset.c58
-rw-r--r--arch/mips/momentum/ocelot_c/setup.c362
-rw-r--r--arch/mips/momentum/ocelot_c/uart-irq.c91
-rw-r--r--arch/mips/pci/Makefile10
-rw-r--r--arch/mips/pci/fixup-atlas.c2
-rw-r--r--arch/mips/pci/fixup-au1000.c2
-rw-r--r--arch/mips/pci/fixup-capcella.c2
-rw-r--r--arch/mips/pci/fixup-cobalt.c2
-rw-r--r--arch/mips/pci/fixup-emma2rh.c2
-rw-r--r--arch/mips/pci/fixup-excite.c2
-rw-r--r--arch/mips/pci/fixup-ip32.c2
-rw-r--r--arch/mips/pci/fixup-jmr3927.c2
-rw-r--r--arch/mips/pci/fixup-lm2e.c242
-rw-r--r--arch/mips/pci/fixup-malta.c2
-rw-r--r--arch/mips/pci/fixup-mpc30x.c2
-rw-r--r--arch/mips/pci/fixup-ocelot-c.c41
-rw-r--r--arch/mips/pci/fixup-ocelot3.c41
-rw-r--r--arch/mips/pci/fixup-pmcmsp.c216
-rw-r--r--arch/mips/pci/fixup-pnx8550.c2
-rw-r--r--arch/mips/pci/fixup-rbtx4927.c2
-rw-r--r--arch/mips/pci/fixup-sni.c2
-rw-r--r--arch/mips/pci/fixup-tb0219.c2
-rw-r--r--arch/mips/pci/fixup-tb0226.c2
-rw-r--r--arch/mips/pci/fixup-tb0287.c2
-rw-r--r--arch/mips/pci/fixup-tx4938.c2
-rw-r--r--arch/mips/pci/fixup-vr4133.c2
-rw-r--r--arch/mips/pci/fixup-wrppmc.c2
-rw-r--r--arch/mips/pci/fixup-yosemite.c2
-rw-r--r--arch/mips/pci/ops-bonito64.c88
-rw-r--r--arch/mips/pci/ops-marvell.c93
-rw-r--r--arch/mips/pci/ops-nile4.c147
-rw-r--r--arch/mips/pci/ops-pmcmsp.c994
-rw-r--r--arch/mips/pci/ops-tx4938.c80
-rw-r--r--arch/mips/pci/pci-bcm1480.c3
-rw-r--r--arch/mips/pci/pci-ddb5477.c2
-rw-r--r--arch/mips/pci/pci-ev64120.c22
-rw-r--r--arch/mips/pci/pci-ip27.c2
-rw-r--r--arch/mips/pci/pci-lasat.c91
-rw-r--r--arch/mips/pci/pci-ocelot-c.c145
-rw-r--r--arch/mips/pci/pci-sb1250.c2
-rw-r--r--arch/mips/philips/pnx8550/common/platform.c2
-rw-r--r--arch/mips/philips/pnx8550/common/proc.c30
-rw-r--r--arch/mips/pmc-sierra/Kconfig46
-rw-r--r--arch/mips/pmc-sierra/msp71xx/Makefile11
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_elb.c (renamed from arch/mips/momentum/ocelot_c/ocelot_c_fpga.h)53
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c179
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_irq.c124
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c134
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c109
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_pci.c (renamed from arch/mips/momentum/ocelot_3/ocelot_3_fpga.h)57
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_prom.c566
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_setup.c256
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_time.c94
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_usb.c150
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-reset.c6
-rw-r--r--arch/mips/sgi-ip27/ip27-berr.c1
-rw-r--r--arch/mips/sgi-ip32/ip32-platform.c52
-rw-r--r--arch/mips/sgi-ip32/ip32-setup.c36
-rw-r--r--arch/mips/sibyte/cfe/setup.c6
-rw-r--r--arch/mips/sni/Makefile2
-rw-r--r--arch/mips/sni/a20r.c31
-rw-r--r--arch/mips/sni/ds1216.c81
-rw-r--r--arch/mips/sni/pcimt.c26
-rw-r--r--arch/mips/sni/pcit.c26
-rw-r--r--arch/mips/sni/rm200.c32
-rw-r--r--arch/mips/sni/sniprom.c5
-rw-r--r--arch/mips/tx4938/common/Makefile2
-rw-r--r--arch/mips/tx4938/common/rtc_rx5c348.c192
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/Makefile2
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/irq.c6
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/setup.c306
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c261
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c164
-rw-r--r--arch/s390/crypto/crypt_s390.h2
-rw-r--r--arch/s390/kernel/early.c45
-rw-r--r--arch/s390/kernel/entry.S7
-rw-r--r--arch/s390/kernel/entry64.S7
-rw-r--r--arch/s390/kernel/ipl.c17
-rw-r--r--arch/s390/kernel/process.c6
-rw-r--r--arch/s390/kernel/smp.c63
-rw-r--r--arch/s390/kernel/time.c4
-rw-r--r--arch/s390/kernel/vtime.c4
-rw-r--r--arch/s390/lib/Makefile4
-rw-r--r--arch/sparc/kernel/smp.c10
-rw-r--r--arch/sparc64/kernel/smp.c27
-rw-r--r--block/Kconfig4
-rw-r--r--block/cfq-iosched.c39
-rw-r--r--block/elevator.c13
-rw-r--r--block/ll_rw_blk.c13
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acorn/block/fd1772.c2
-rw-r--r--drivers/acorn/block/mfmhd.c13
-rw-r--r--drivers/block/Kconfig44
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/acsi.c1825
-rw-r--r--drivers/block/amiflop.c2
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/loop.c64
-rw-r--r--drivers/block/nbd.c2
-rw-r--r--drivers/cdrom/Kconfig213
-rw-r--r--drivers/cdrom/Makefile10
-rw-r--r--drivers/cdrom/aztcd.c2492
-rw-r--r--drivers/cdrom/aztcd.h162
-rw-r--r--drivers/cdrom/cdrom.c216
-rw-r--r--drivers/cdrom/cdu31a.c3251
-rw-r--r--drivers/cdrom/cdu31a.h411
-rw-r--r--drivers/cdrom/cm206.c1594
-rw-r--r--drivers/cdrom/cm206.h171
-rw-r--r--drivers/cdrom/gscd.c1029
-rw-r--r--drivers/cdrom/gscd.h108
-rw-r--r--drivers/cdrom/isp16.c374
-rw-r--r--drivers/cdrom/isp16.h72
-rw-r--r--drivers/cdrom/mcdx.c1943
-rw-r--r--drivers/cdrom/mcdx.h185
-rw-r--r--drivers/cdrom/optcd.c2105
-rw-r--r--drivers/cdrom/optcd.h52
-rw-r--r--drivers/cdrom/sbpcd.c5966
-rw-r--r--drivers/cdrom/sbpcd.h839
-rw-r--r--drivers/cdrom/sjcd.c1815
-rw-r--r--drivers/cdrom/sjcd.h181
-rw-r--r--drivers/cdrom/sonycd535.c1689
-rw-r--r--drivers/cdrom/sonycd535.h183
-rw-r--r--drivers/char/keyboard.c4
-rw-r--r--drivers/char/mem.c9
-rw-r--r--drivers/firewire/fw-card.c7
-rw-r--r--drivers/firewire/fw-cdev.c2
-rw-r--r--drivers/firewire/fw-device.c38
-rw-r--r--drivers/firewire/fw-device.h1
-rw-r--r--drivers/firewire/fw-ohci.c6
-rw-r--r--drivers/firewire/fw-sbp2.c117
-rw-r--r--drivers/firewire/fw-topology.c66
-rw-r--r--drivers/firewire/fw-topology.h25
-rw-r--r--drivers/firewire/fw-transaction.h3
-rw-r--r--drivers/hid/Kconfig10
-rw-r--r--drivers/hid/hid-core.c93
-rw-r--r--drivers/hid/hid-debug.c15
-rw-r--r--drivers/hid/hid-input.c125
-rw-r--r--drivers/hid/usbhid/hid-core.c111
-rw-r--r--drivers/hid/usbhid/hid-lgff.c10
-rw-r--r--drivers/hid/usbhid/hid-pidff.c1
-rw-r--r--drivers/hid/usbhid/hid-quirks.c185
-rw-r--r--drivers/hid/usbhid/hid-tmff.c2
-rw-r--r--drivers/hid/usbhid/hid-zpff.c8
-rw-r--r--drivers/hid/usbhid/hiddev.c2
-rw-r--r--drivers/hid/usbhid/usbkbd.c6
-rw-r--r--drivers/ide/arm/icside.c16
-rw-r--r--drivers/ide/cris/ide-cris.c2
-rw-r--r--drivers/ide/ide-cd.c6
-rw-r--r--drivers/ide/ide-cd.h2
-rw-r--r--drivers/ide/ide-disk.c8
-rw-r--r--drivers/ide/ide-dma.c110
-rw-r--r--drivers/ide/ide-io.c4
-rw-r--r--drivers/ide/ide-iops.c8
-rw-r--r--drivers/ide/ide-probe.c10
-rw-r--r--drivers/ide/ide-proc.c34
-rw-r--r--drivers/ide/ide-timing.h56
-rw-r--r--drivers/ide/ide.c33
-rw-r--r--drivers/ide/legacy/hd.c5
-rw-r--r--drivers/ide/legacy/macide.c14
-rw-r--r--drivers/ide/mips/au1xxx-ide.c24
-rw-r--r--drivers/ide/pci/aec62xx.c119
-rw-r--r--drivers/ide/pci/alim15x3.c78
-rw-r--r--drivers/ide/pci/amd74xx.c127
-rw-r--r--drivers/ide/pci/atiixp.c5
-rw-r--r--drivers/ide/pci/cmd64x.c130
-rw-r--r--drivers/ide/pci/cs5535.c6
-rw-r--r--drivers/ide/pci/hpt366.c170
-rw-r--r--drivers/ide/pci/it8213.c8
-rw-r--r--drivers/ide/pci/it821x.c9
-rw-r--r--drivers/ide/pci/jmicron.c20
-rw-r--r--drivers/ide/pci/pdc202xx_new.c9
-rw-r--r--drivers/ide/pci/pdc202xx_old.c35
-rw-r--r--drivers/ide/pci/piix.c45
-rw-r--r--drivers/ide/pci/scc_pata.c2
-rw-r--r--drivers/ide/pci/serverworks.c103
-rw-r--r--drivers/ide/pci/sgiioc4.c20
-rw-r--r--drivers/ide/pci/siimage.c18
-rw-r--r--drivers/ide/pci/sis5513.c34
-rw-r--r--drivers/ide/pci/sl82c105.c20
-rw-r--r--drivers/ide/pci/slc90e66.c5
-rw-r--r--drivers/ide/pci/tc86c001.c4
-rw-r--r--drivers/ide/pci/via82cxxx.c175
-rw-r--r--drivers/ide/ppc/pmac.c42
-rw-r--r--drivers/ieee1394/dv1394.c8
-rw-r--r--drivers/ieee1394/eth1394.c4
-rw-r--r--drivers/ieee1394/highlevel.c45
-rw-r--r--drivers/ieee1394/highlevel.h16
-rw-r--r--drivers/ieee1394/hosts.c11
-rw-r--r--drivers/ieee1394/hosts.h10
-rw-r--r--drivers/ieee1394/ieee1394_core.c8
-rw-r--r--drivers/ieee1394/ieee1394_core.h15
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c30
-rw-r--r--drivers/ieee1394/ieee1394_transactions.h2
-rw-r--r--drivers/ieee1394/nodemgr.c185
-rw-r--r--drivers/ieee1394/nodemgr.h4
-rw-r--r--drivers/ieee1394/ohci1394.c272
-rw-r--r--drivers/ieee1394/ohci1394.h14
-rw-r--r--drivers/ieee1394/pcilynx.c16
-rw-r--r--drivers/ieee1394/raw1394-private.h5
-rw-r--r--drivers/ieee1394/raw1394.c364
-rw-r--r--drivers/ieee1394/raw1394.h4
-rw-r--r--drivers/ieee1394/sbp2.c15
-rw-r--r--drivers/ieee1394/sbp2.h2
-rw-r--r--drivers/ieee1394/video1394.c10
-rw-r--r--drivers/input/evdev.c84
-rw-r--r--drivers/input/input.c136
-rw-r--r--drivers/input/joydev.c84
-rw-r--r--drivers/input/joystick/Kconfig7
-rw-r--r--drivers/input/joystick/grip_mp.c4
-rw-r--r--drivers/input/joystick/xpad.c281
-rw-r--r--drivers/input/keyboard/atkbd.c4
-rw-r--r--drivers/input/keyboard/pxa27x_keyboard.c2
-rw-r--r--drivers/input/misc/Kconfig6
-rw-r--r--drivers/input/misc/wistron_btns.c359
-rw-r--r--drivers/input/mouse/Kconfig16
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/gpio_mouse.c196
-rw-r--r--drivers/input/mouse/psmouse-base.c29
-rw-r--r--drivers/input/mouse/psmouse.h1
-rw-r--r--drivers/input/mousedev.c242
-rw-r--r--drivers/input/serio/serio_raw.c2
-rw-r--r--drivers/input/tablet/aiptek.c991
-rw-r--r--drivers/input/tablet/wacom.h8
-rw-r--r--drivers/input/tablet/wacom_sys.c6
-rw-r--r--drivers/input/tablet/wacom_wac.c47
-rw-r--r--drivers/input/tablet/wacom_wac.h1
-rw-r--r--drivers/input/touchscreen/Kconfig6
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c33
-rw-r--r--drivers/input/tsdev.c90
-rw-r--r--drivers/misc/Kconfig6
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/eeprom_93cx6.c241
-rw-r--r--drivers/mtd/devices/docprobe.c2
-rw-r--r--drivers/mtd/maps/Kconfig6
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/lasat.c103
-rw-r--r--drivers/mtd/nand/diskonchip.c2
-rw-r--r--drivers/net/8139cp.c11
-rw-r--r--drivers/net/Kconfig174
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/acenic.c4
-rw-r--r--drivers/net/arm/Kconfig12
-rw-r--r--drivers/net/b44.c56
-rw-r--r--drivers/net/b44.h2
-rw-r--r--drivers/net/cxgb3/adapter.h38
-rw-r--r--drivers/net/cxgb3/common.h28
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c43
-rw-r--r--drivers/net/cxgb3/regs.h11
-rw-r--r--drivers/net/cxgb3/sge.c423
-rw-r--r--drivers/net/cxgb3/t3_hw.c128
-rw-r--r--drivers/net/cxgb3/version.h2
-rw-r--r--drivers/net/ehea/ehea.h14
-rw-r--r--drivers/net/ehea/ehea_hw.h24
-rw-r--r--drivers/net/ehea/ehea_main.c32
-rw-r--r--drivers/net/ehea/ehea_qmr.c56
-rw-r--r--drivers/net/fec_8xx/Kconfig2
-rw-r--r--drivers/net/fs_enet/Kconfig2
-rw-r--r--drivers/net/gianfar.c27
-rw-r--r--drivers/net/gianfar.h6
-rw-r--r--drivers/net/gianfar_mii.c55
-rw-r--r--drivers/net/lasi_82596.c1460
-rw-r--r--drivers/net/lib82596.c1434
-rw-r--r--drivers/net/mlx4/qp.c3
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c6
-rw-r--r--drivers/net/pasemi_mac.c2
-rw-r--r--drivers/net/pcmcia/axnet_cs.c7
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c23
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c10
-rw-r--r--drivers/net/phy/Kconfig5
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/icplus.c134
-rw-r--r--drivers/net/phy/marvell.c16
-rwxr-xr-xdrivers/net/qla3xxx.c33
-rw-r--r--drivers/net/r8169.c944
-rw-r--r--drivers/net/s2io.c116
-rw-r--r--drivers/net/s2io.h6
-rw-r--r--drivers/net/sky2.c224
-rw-r--r--drivers/net/sky2.h163
-rw-r--r--drivers/net/sni_82596.c185
-rw-r--r--drivers/net/spider_net.c184
-rw-r--r--drivers/net/spider_net.h21
-rw-r--r--drivers/net/tc35815.c50
-rw-r--r--drivers/net/tulip/Kconfig27
-rw-r--r--drivers/net/tulip/de2104x.c1
-rw-r--r--drivers/net/tulip/de4x5.c98
-rw-r--r--drivers/net/tulip/de4x5.h9
-rw-r--r--drivers/net/usb/usbnet.c76
-rw-r--r--drivers/net/usb/usbnet.h10
-rw-r--r--drivers/net/wireless/Kconfig12
-rw-r--r--drivers/net/wireless/Makefile3
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c34
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c5
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c5
-rw-r--r--drivers/net/wireless/rtl8187.h145
-rw-r--r--drivers/net/wireless/rtl8187_dev.c731
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.c745
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.h44
-rw-r--r--drivers/net/wireless/rtl818x.h226
-rw-r--r--drivers/net/wireless/zd1211rw/Makefile2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.c21
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.h28
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al2230.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al7230b.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_uw2453.c534
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c1
-rw-r--r--drivers/power/Kconfig51
-rw-r--r--drivers/power/Makefile22
-rw-r--r--drivers/power/apm_power.c243
-rw-r--r--drivers/power/ds2760_battery.c470
-rw-r--r--drivers/power/olpc_battery.c352
-rw-r--r--drivers/power/pda_power.c261
-rw-r--r--drivers/power/pmu_battery.c215
-rw-r--r--drivers/power/power_supply.h42
-rw-r--r--drivers/power/power_supply_core.c168
-rw-r--r--drivers/power/power_supply_leds.c176
-rw-r--r--drivers/power/power_supply_sysfs.c299
-rw-r--r--drivers/s390/block/dasd_proc.c4
-rw-r--r--drivers/s390/char/sclp.h12
-rw-r--r--drivers/s390/char/sclp_chp.c4
-rw-r--r--drivers/s390/char/sclp_info.c117
-rw-r--r--drivers/s390/char/vmcp.c13
-rw-r--r--drivers/s390/char/vmlogrdr.c4
-rw-r--r--drivers/s390/char/zcore.c2
-rw-r--r--drivers/s390/cio/device_id.c22
-rw-r--r--drivers/s390/crypto/ap_bus.c98
-rw-r--r--drivers/s390/crypto/ap_bus.h11
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c40
-rw-r--r--drivers/serial/serial_cs.c4
-rw-r--r--drivers/tc/zs.c6
-rw-r--r--drivers/w1/slaves/Kconfig13
-rw-r--r--drivers/w1/slaves/Makefile1
-rw-r--r--drivers/w1/slaves/w1_ds2760.c213
-rw-r--r--drivers/w1/slaves/w1_ds2760.h50
-rw-r--r--drivers/w1/w1_family.h1
-rw-r--r--fs/adfs/file.c2
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/afs/file.c2
-rw-r--r--fs/bad_inode.c7
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/bio.c2
-rw-r--r--fs/block_dev.c1
-rw-r--r--fs/cifs/cifsfs.c8
-rw-r--r--fs/coda/file.c11
-rw-r--r--fs/dlm/Makefile1
-rw-r--r--fs/dlm/config.c25
-rw-r--r--fs/dlm/config.h1
-rw-r--r--fs/dlm/debug_fs.c186
-rw-r--r--fs/dlm/dlm_internal.h17
-rw-r--r--fs/dlm/lock.c470
-rw-r--r--fs/dlm/lock.h13
-rw-r--r--fs/dlm/lockspace.c86
-rw-r--r--fs/dlm/lowcomms.c23
-rw-r--r--fs/dlm/main.c11
-rw-r--r--fs/dlm/member.c11
-rw-r--r--fs/dlm/netlink.c153
-rw-r--r--fs/dlm/rcom.c13
-rw-r--r--fs/dlm/recoverd.c4
-rw-r--r--fs/dlm/user.c129
-rw-r--r--fs/ecryptfs/file.c15
-rw-r--r--fs/ext2/file.c2
-rw-r--r--fs/ext3/file.c1
-rw-r--r--fs/ext4/file.c1
-rw-r--r--fs/fat/file.c2
-rw-r--r--fs/fuse/file.c4
-rw-r--r--fs/gfs2/Makefile2
-rw-r--r--fs/gfs2/bmap.c23
-rw-r--r--fs/gfs2/daemon.c11
-rw-r--r--fs/gfs2/dir.c69
-rw-r--r--fs/gfs2/dir.h9
-rw-r--r--fs/gfs2/eattr.c14
-rw-r--r--fs/gfs2/glock.c123
-rw-r--r--fs/gfs2/glock.h1
-rw-r--r--fs/gfs2/glops.c2
-rw-r--r--fs/gfs2/incore.h81
-rw-r--r--fs/gfs2/inode.c288
-rw-r--r--fs/gfs2/inode.h30
-rw-r--r--fs/gfs2/locking/dlm/lock.c11
-rw-r--r--fs/gfs2/locking/dlm/lock_dlm.h2
-rw-r--r--fs/gfs2/locking/dlm/mount.c2
-rw-r--r--fs/gfs2/locking/dlm/plock.c8
-rw-r--r--fs/gfs2/locking/dlm/thread.c11
-rw-r--r--fs/gfs2/log.c129
-rw-r--r--fs/gfs2/lops.c49
-rw-r--r--fs/gfs2/lops.h23
-rw-r--r--fs/gfs2/meta_io.c8
-rw-r--r--fs/gfs2/meta_io.h2
-rw-r--r--fs/gfs2/mount.c25
-rw-r--r--fs/gfs2/ondisk.c251
-rw-r--r--fs/gfs2/ops_address.c69
-rw-r--r--fs/gfs2/ops_address.h2
-rw-r--r--fs/gfs2/ops_dentry.c24
-rw-r--r--fs/gfs2/ops_export.c65
-rw-r--r--fs/gfs2/ops_export.h22
-rw-r--r--fs/gfs2/ops_file.c5
-rw-r--r--fs/gfs2/ops_fstype.c33
-rw-r--r--fs/gfs2/ops_fstype.h1
-rw-r--r--fs/gfs2/ops_inode.c30
-rw-r--r--fs/gfs2/ops_super.c8
-rw-r--r--fs/gfs2/ops_vm.c2
-rw-r--r--fs/gfs2/quota.c57
-rw-r--r--fs/gfs2/recovery.c22
-rw-r--r--fs/gfs2/rgrp.c377
-rw-r--r--fs/gfs2/rgrp.h1
-rw-r--r--fs/gfs2/super.c79
-rw-r--r--fs/gfs2/super.h2
-rw-r--r--fs/gfs2/util.c6
-rw-r--r--fs/hfs/inode.c2
-rw-r--r--fs/hfsplus/inode.c2
-rw-r--r--fs/hostfs/hostfs_kern.c2
-rw-r--r--fs/hpfs/file.c2
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jfs/endian24.h2
-rw-r--r--fs/jfs/file.c1
-rw-r--r--fs/jfs/jfs_debug.c28
-rw-r--r--fs/jfs/jfs_debug.h2
-rw-r--r--fs/jfs/jfs_dinode.h42
-rw-r--r--fs/jfs/jfs_dmap.c419
-rw-r--r--fs/jfs/jfs_dmap.h118
-rw-r--r--fs/jfs/jfs_dtree.c105
-rw-r--r--fs/jfs/jfs_dtree.h2
-rw-r--r--fs/jfs/jfs_extent.c102
-rw-r--r--fs/jfs/jfs_filsys.h13
-rw-r--r--fs/jfs/jfs_imap.c296
-rw-r--r--fs/jfs/jfs_imap.h98
-rw-r--r--fs/jfs/jfs_incore.h4
-rw-r--r--fs/jfs/jfs_logmgr.c90
-rw-r--r--fs/jfs/jfs_logmgr.h26
-rw-r--r--fs/jfs/jfs_metapage.c3
-rw-r--r--fs/jfs/jfs_mount.c6
-rw-r--r--fs/jfs/jfs_txnmgr.c302
-rw-r--r--fs/jfs/jfs_txnmgr.h2
-rw-r--r--fs/jfs/jfs_types.h20
-rw-r--r--fs/jfs/jfs_umount.c2
-rw-r--r--fs/jfs/jfs_xtree.c428
-rw-r--r--fs/jfs/jfs_xtree.h48
-rw-r--r--fs/jfs/namei.c26
-rw-r--r--fs/jfs/resize.c48
-rw-r--r--fs/jfs/xattr.c9
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/nfs/file.c15
-rw-r--r--fs/nfsd/vfs.c47
-rw-r--r--fs/ntfs/file.c2
-rw-r--r--fs/ocfs2/file.c18
-rw-r--r--fs/partitions/ibm.c167
-rw-r--r--fs/pipe.c70
-rw-r--r--fs/proc/array.c59
-rw-r--r--fs/proc/base.c71
-rw-r--r--fs/qnx4/file.c2
-rw-r--r--fs/ramfs/file-mmu.c2
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/read_write.c20
-rw-r--r--fs/reiserfs/file.c1
-rw-r--r--fs/smbfs/file.c9
-rw-r--r--fs/splice.c413
-rw-r--r--fs/sysv/file.c2
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/ufs/file.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c26
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c44
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h6
-rw-r--r--fs/xfs/xfs_vnodeops.c3
-rw-r--r--include/asm-generic/bitops/sched.h21
-rw-r--r--include/asm-mips/addrspace.h29
-rw-r--r--include/asm-mips/bootinfo.h36
-rw-r--r--include/asm-mips/cacheops.h4
-rw-r--r--include/asm-mips/cpu-features.h4
-rw-r--r--include/asm-mips/cpu.h10
-rw-r--r--include/asm-mips/div64.h9
-rw-r--r--include/asm-mips/gpio.h6
-rw-r--r--include/asm-mips/io.h8
-rw-r--r--include/asm-mips/lasat/ds1603.h18
-rw-r--r--include/asm-mips/lasat/eeprom.h17
-rw-r--r--include/asm-mips/lasat/head.h22
-rw-r--r--include/asm-mips/lasat/lasat.h253
-rw-r--r--include/asm-mips/lasat/lasatint.h12
-rw-r--r--include/asm-mips/lasat/picvue.h15
-rw-r--r--include/asm-mips/lasat/serial.h13
-rw-r--r--include/asm-mips/mach-au1x00/au1xxx_gpio.h20
-rw-r--r--include/asm-mips/mach-au1x00/au1xxx_ide.h28
-rw-r--r--include/asm-mips/mach-au1x00/gpio.h69
-rw-r--r--include/asm-mips/mach-au1x00/ioremap.h11
-rw-r--r--include/asm-mips/mach-cobalt/cobalt.h5
-rw-r--r--include/asm-mips/mach-ev64120/mach-gt64120.h62
-rw-r--r--include/asm-mips/mach-generic/gpio.h15
-rw-r--r--include/asm-mips/mach-generic/ioremap.h11
-rw-r--r--include/asm-mips/mach-generic/spaces.h64
-rw-r--r--include/asm-mips/mach-ip22/spaces.h33
-rw-r--r--include/asm-mips/mach-ip27/spaces.h9
-rw-r--r--include/asm-mips/mach-ip32/spaces.h36
-rw-r--r--include/asm-mips/mach-jmr3927/ioremap.h38
-rw-r--r--include/asm-mips/mach-lasat/mach-gt64120.h27
-rw-r--r--include/asm-mips/mach-lemote/dma-coherence.h42
-rw-r--r--include/asm-mips/mach-lemote/mc146818rtc.h36
-rw-r--r--include/asm-mips/mach-mips/kernel-entry-init.h52
-rw-r--r--include/asm-mips/mach-mipssim/cpu-feature-overrides.h (renamed from include/asm-mips/mach-sim/cpu-feature-overrides.h)0
-rw-r--r--include/asm-mips/mach-ocelot3/cpu-feature-overrides.h48
-rw-r--r--include/asm-mips/mach-tx49xx/ioremap.h42
-rw-r--r--include/asm-mips/mips-boards/bonito64.h7
-rw-r--r--include/asm-mips/mipsregs.h39
-rw-r--r--include/asm-mips/module.h2
-rw-r--r--include/asm-mips/nile4.h310
-rw-r--r--include/asm-mips/page.h21
-rw-r--r--include/asm-mips/pci.h2
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h151
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_int.h43
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_pci.h205
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_prom.h176
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_regops.h236
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_regs.h667
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h141
-rw-r--r--include/asm-mips/processor.h92
-rw-r--r--include/asm-mips/serial.h155
-rw-r--r--include/asm-mips/smp.h7
-rw-r--r--include/asm-mips/sni.h3
-rw-r--r--include/asm-mips/system.h14
-rw-r--r--include/asm-mips/tx4938/rbtx4938.h6
-rw-r--r--include/asm-mips/tx4938/spi.h56
-rw-r--r--include/asm-mips/war.h25
-rw-r--r--include/asm-mips/watch.h35
-rw-r--r--include/asm-s390/atomic.h4
-rw-r--r--include/asm-s390/cmb.h1
-rw-r--r--include/asm-s390/processor.h4
-rw-r--r--include/asm-s390/sclp.h47
-rw-r--r--include/asm-s390/sfp-machine.h6
-rw-r--r--include/asm-s390/sfp-util.h11
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/blkdev.h5
-rw-r--r--include/linux/dlm.h14
-rw-r--r--include/linux/dlm_device.h22
-rw-r--r--include/linux/dlm_netlink.h56
-rw-r--r--include/linux/eeprom_93cx6.h72
-rw-r--r--include/linux/firewire-cdev.h297
-rw-r--r--include/linux/fs.h7
-rw-r--r--include/linux/gfs2_ondisk.h142
-rw-r--r--include/linux/gpio_mouse.h61
-rw-r--r--include/linux/hardirq.h13
-rw-r--r--include/linux/hid.h56
-rw-r--r--include/linux/ide.h18
-rw-r--r--include/linux/input.h20
-rw-r--r--include/linux/ioprio.h6
-rw-r--r--include/linux/mv643xx.h4
-rw-r--r--include/linux/pda_power.h31
-rw-r--r--include/linux/pipe_fs_i.h117
-rw-r--r--include/linux/power_supply.h180
-rw-r--r--include/linux/sched.h251
-rw-r--r--include/linux/splice.h73
-rw-r--r--include/linux/sunrpc/svc.h2
-rw-r--r--include/linux/topology.h12
-rw-r--r--include/linux/usb.h16
-rw-r--r--include/linux/wait.h16
-rw-r--r--include/pcmcia/ciscode.h2
-rw-r--r--init/Kconfig2
-rw-r--r--init/main.c5
-rw-r--r--kernel/delayacct.c10
-rw-r--r--kernel/exit.c5
-rw-r--r--kernel/fork.c4
-rw-r--r--kernel/posix-cpu-timers.c34
-rw-r--r--kernel/relay.c205
-rw-r--r--kernel/sched.c3021
-rw-r--r--kernel/sched_debug.c275
-rw-r--r--kernel/sched_fair.c1131
-rw-r--r--kernel/sched_idletask.c71
-rw-r--r--kernel/sched_rt.c255
-rw-r--r--kernel/sched_stats.h235
-rw-r--r--kernel/softirq.c1
-rw-r--r--kernel/sysctl.c80
-rw-r--r--lib/Kconfig.debug9
-rw-r--r--mm/filemap.c20
-rw-r--r--mm/filemap_xip.c22
-rw-r--r--mm/shmem.c42
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c32
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c2
-rw-r--r--net/sunrpc/svc.c2
-rw-r--r--sound/ppc/beep.c10
752 files changed, 32591 insertions, 51915 deletions
diff --git a/Documentation/ABI/removed/raw1394_legacy_isochronous b/Documentation/ABI/removed/raw1394_legacy_isochronous
new file mode 100644
index 000000000000..1b629622d883
--- /dev/null
+++ b/Documentation/ABI/removed/raw1394_legacy_isochronous
@@ -0,0 +1,16 @@
+What: legacy isochronous ABI of raw1394 (1st generation iso ABI)
+Date: June 2007 (scheduled), removed in kernel v2.6.23
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
+ been deprecated for quite some time. They are very inefficient as they
+ come with high interrupt load and several layers of callbacks for each
+ packet. Because of these deficiencies, the video1394 and dv1394 drivers
+ and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
+
+Users:
+ libraw1394 users via the long deprecated API raw1394_iso_write,
+ raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
+
+ libdc1394, which optionally uses these old libraw1394 calls
+ alternatively to the more efficient video1394 ABI
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 38f88b6ae405..8c5698a8c2e1 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -643,4 +643,15 @@ X!Idrivers/video/console/fonts.c
!Edrivers/spi/spi.c
</chapter>
+ <chapter id="splice">
+ <title>splice API</title>
+ <para>)
+ splice is a method for moving blocks of data around inside the
+ kernel, without continually transferring it between the kernel
+ and user space.
+ </para>
+!Iinclude/linux/splice.h
+!Ffs/splice.c
+ </chapter>
+
</book>
diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt
index a272c3db8094..7d279f2f5bb2 100644
--- a/Documentation/block/barrier.txt
+++ b/Documentation/block/barrier.txt
@@ -82,23 +82,12 @@ including draining and flushing.
typedef void (prepare_flush_fn)(request_queue_t *q, struct request *rq);
int blk_queue_ordered(request_queue_t *q, unsigned ordered,
- prepare_flush_fn *prepare_flush_fn,
- unsigned gfp_mask);
-
-int blk_queue_ordered_locked(request_queue_t *q, unsigned ordered,
- prepare_flush_fn *prepare_flush_fn,
- unsigned gfp_mask);
-
-The only difference between the two functions is whether or not the
-caller is holding q->queue_lock on entry. The latter expects the
-caller is holding the lock.
+ prepare_flush_fn *prepare_flush_fn);
@q : the queue in question
@ordered : the ordered mode the driver/device supports
@prepare_flush_fn : this function should prepare @rq such that it
flushes cache to physical medium when executed
-@gfp_mask : gfp_mask used when allocating data structures
- for ordered processing
For example, SCSI disk driver's prepare_flush_fn looks like the
following.
@@ -106,9 +95,10 @@ following.
static void sd_prepare_flush(request_queue_t *q, struct request *rq)
{
memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->flags |= REQ_BLOCK_PC;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->timeout = SD_TIMEOUT;
rq->cmd[0] = SYNCHRONIZE_CACHE;
+ rq->cmd_len = 10;
}
The following seven ordered modes are supported. The following table
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 7d3f205b0ba5..51b369e7fc70 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -49,16 +49,6 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
-What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
-When: June 2007
-Why: Deprecated in favour of the more efficient and robust rawiso interface.
- Affected are applications which use the deprecated part of libraw1394
- (raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
- raw1394_stop_iso_rcv) or bypass libraw1394.
-Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
-
----------------------------
-
What: old NCR53C9x driver
When: October 2007
Why: Replaced by the much better esp_scsi driver. Actual low-level
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index af50f9bbe68e..4d880b3d1f35 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1014,49 +1014,6 @@ and is between 256 and 4096 characters. It is defined in the file
mga= [HW,DRM]
- migration_cost=
- [KNL,SMP] debug: override scheduler migration costs
- Format: <level-1-usecs>,<level-2-usecs>,...
- This debugging option can be used to override the
- default scheduler migration cost matrix. The numbers
- are indexed by 'CPU domain distance'.
- E.g. migration_cost=1000,2000,3000 on an SMT NUMA
- box will set up an intra-core migration cost of
- 1 msec, an inter-core migration cost of 2 msecs,
- and an inter-node migration cost of 3 msecs.
-
- WARNING: using the wrong values here can break
- scheduler performance, so it's only for scheduler
- development purposes, not production environments.
-
- migration_debug=
- [KNL,SMP] migration cost auto-detect verbosity
- Format=<0|1|2>
- If a system's migration matrix reported at bootup
- seems erroneous then this option can be used to
- increase verbosity of the detection process.
- We default to 0 (no extra messages), 1 will print
- some more information, and 2 will be really
- verbose (probably only useful if you also have a
- serial console attached to the system).
-
- migration_factor=
- [KNL,SMP] multiply/divide migration costs by a factor
- Format=<percent>
- This debug option can be used to proportionally
- increase or decrease the auto-detected migration
- costs for all entries of the migration matrix.
- E.g. migration_factor=150 will increase migration
- costs by 50%. (and thus the scheduler will be less
- eager migrating cache-hot tasks)
- migration_factor=80 will decrease migration costs
- by 20%. (thus the scheduler will be more eager to
- migrate tasks)
-
- WARNING: using the wrong values here can break
- scheduler performance, so it's only for scheduler
- development purposes, not production environments.
-
mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
diff --git a/Documentation/networking/spider_net.txt b/Documentation/networking/spider_net.txt
new file mode 100644
index 000000000000..4b4adb8eb14f
--- /dev/null
+++ b/Documentation/networking/spider_net.txt
@@ -0,0 +1,204 @@
+
+ The Spidernet Device Driver
+ ===========================
+
+Written by Linas Vepstas <linas@austin.ibm.com>
+
+Version of 7 June 2007
+
+Abstract
+========
+This document sketches the structure of portions of the spidernet
+device driver in the Linux kernel tree. The spidernet is a gigabit
+ethernet device built into the Toshiba southbridge commonly used
+in the SONY Playstation 3 and the IBM QS20 Cell blade.
+
+The Structure of the RX Ring.
+=============================
+The receive (RX) ring is a circular linked list of RX descriptors,
+together with three pointers into the ring that are used to manage its
+contents.
+
+The elements of the ring are called "descriptors" or "descrs"; they
+describe the received data. This includes a pointer to a buffer
+containing the received data, the buffer size, and various status bits.
+
+There are three primary states that a descriptor can be in: "empty",
+"full" and "not-in-use". An "empty" or "ready" descriptor is ready
+to receive data from the hardware. A "full" descriptor has data in it,
+and is waiting to be emptied and processed by the OS. A "not-in-use"
+descriptor is neither empty or full; it is simply not ready. It may
+not even have a data buffer in it, or is otherwise unusable.
+
+During normal operation, on device startup, the OS (specifically, the
+spidernet device driver) allocates a set of RX descriptors and RX
+buffers. These are all marked "empty", ready to receive data. This
+ring is handed off to the hardware, which sequentially fills in the
+buffers, and marks them "full". The OS follows up, taking the full
+buffers, processing them, and re-marking them empty.
+
+This filling and emptying is managed by three pointers, the "head"
+and "tail" pointers, managed by the OS, and a hardware current
+descriptor pointer (GDACTDPA). The GDACTDPA points at the descr
+currently being filled. When this descr is filled, the hardware
+marks it full, and advances the GDACTDPA by one. Thus, when there is
+flowing RX traffic, every descr behind it should be marked "full",
+and everything in front of it should be "empty". If the hardware
+discovers that the current descr is not empty, it will signal an
+interrupt, and halt processing.
+
+The tail pointer tails or trails the hardware pointer. When the
+hardware is ahead, the tail pointer will be pointing at a "full"
+descr. The OS will process this descr, and then mark it "not-in-use",
+and advance the tail pointer. Thus, when there is flowing RX traffic,
+all of the descrs in front of the tail pointer should be "full", and
+all of those behind it should be "not-in-use". When RX traffic is not
+flowing, then the tail pointer can catch up to the hardware pointer.
+The OS will then note that the current tail is "empty", and halt
+processing.
+
+The head pointer (somewhat mis-named) follows after the tail pointer.
+When traffic is flowing, then the head pointer will be pointing at
+a "not-in-use" descr. The OS will perform various housekeeping duties
+on this descr. This includes allocating a new data buffer and
+dma-mapping it so as to make it visible to the hardware. The OS will
+then mark the descr as "empty", ready to receive data. Thus, when there
+is flowing RX traffic, everything in front of the head pointer should
+be "not-in-use", and everything behind it should be "empty". If no
+RX traffic is flowing, then the head pointer can catch up to the tail
+pointer, at which point the OS will notice that the head descr is
+"empty", and it will halt processing.
+
+Thus, in an idle system, the GDACTDPA, tail and head pointers will
+all be pointing at the same descr, which should be "empty". All of the
+other descrs in the ring should be "empty" as well.
+
+The show_rx_chain() routine will print out the the locations of the
+GDACTDPA, tail and head pointers. It will also summarize the contents
+of the ring, starting at the tail pointer, and listing the status
+of the descrs that follow.
+
+A typical example of the output, for a nearly idle system, might be
+
+net eth1: Total number of descrs=256
+net eth1: Chain tail located at descr=20
+net eth1: Chain head is at 20
+net eth1: HW curr desc (GDACTDPA) is at 21
+net eth1: Have 1 descrs with stat=x40800101
+net eth1: HW next desc (GDACNEXTDA) is at 22
+net eth1: Last 255 descrs with stat=xa0800000
+
+In the above, the hardware has filled in one descr, number 20. Both
+head and tail are pointing at 20, because it has not yet been emptied.
+Meanwhile, hw is pointing at 21, which is free.
+
+The "Have nnn decrs" refers to the descr starting at the tail: in this
+case, nnn=1 descr, starting at descr 20. The "Last nnn descrs" refers
+to all of the rest of the descrs, from the last status change. The "nnn"
+is a count of how many descrs have exactly the same status.
+
+The status x4... corresponds to "full" and status xa... corresponds
+to "empty". The actual value printed is RXCOMST_A.
+
+In the device driver source code, a different set of names are
+used for these same concepts, so that
+
+"empty" == SPIDER_NET_DESCR_CARDOWNED == 0xa
+"full" == SPIDER_NET_DESCR_FRAME_END == 0x4
+"not in use" == SPIDER_NET_DESCR_NOT_IN_USE == 0xf
+
+
+The RX RAM full bug/feature
+===========================
+
+As long as the OS can empty out the RX buffers at a rate faster than
+the hardware can fill them, there is no problem. If, for some reason,
+the OS fails to empty the RX ring fast enough, the hardware GDACTDPA
+pointer will catch up to the head, notice the not-empty condition,
+ad stop. However, RX packets may still continue arriving on the wire.
+The spidernet chip can save some limited number of these in local RAM.
+When this local ram fills up, the spider chip will issue an interrupt
+indicating this (GHIINT0STS will show ERRINT, and the GRMFLLINT bit
+will be set in GHIINT1STS). When the RX ram full condition occurs,
+a certain bug/feature is triggered that has to be specially handled.
+This section describes the special handling for this condition.
+
+When the OS finally has a chance to run, it will empty out the RX ring.
+In particular, it will clear the descriptor on which the hardware had
+stopped. However, once the hardware has decided that a certain
+descriptor is invalid, it will not restart at that descriptor; instead
+it will restart at the next descr. This potentially will lead to a
+deadlock condition, as the tail pointer will be pointing at this descr,
+which, from the OS point of view, is empty; the OS will be waiting for
+this descr to be filled. However, the hardware has skipped this descr,
+and is filling the next descrs. Since the OS doesn't see this, there
+is a potential deadlock, with the OS waiting for one descr to fill,
+while the hardware is waiting for a different set of descrs to become
+empty.
+
+A call to show_rx_chain() at this point indicates the nature of the
+problem. A typical print when the network is hung shows the following:
+
+net eth1: Spider RX RAM full, incoming packets might be discarded!
+net eth1: Total number of descrs=256
+net eth1: Chain tail located at descr=255
+net eth1: Chain head is at 255
+net eth1: HW curr desc (GDACTDPA) is at 0
+net eth1: Have 1 descrs with stat=xa0800000
+net eth1: HW next desc (GDACNEXTDA) is at 1
+net eth1: Have 127 descrs with stat=x40800101
+net eth1: Have 1 descrs with stat=x40800001
+net eth1: Have 126 descrs with stat=x40800101
+net eth1: Last 1 descrs with stat=xa0800000
+
+Both the tail and head pointers are pointing at descr 255, which is
+marked xa... which is "empty". Thus, from the OS point of view, there
+is nothing to be done. In particular, there is the implicit assumption
+that everything in front of the "empty" descr must surely also be empty,
+as explained in the last section. The OS is waiting for descr 255 to
+become non-empty, which, in this case, will never happen.
+
+The HW pointer is at descr 0. This descr is marked 0x4.. or "full".
+Since its already full, the hardware can do nothing more, and thus has
+halted processing. Notice that descrs 0 through 254 are all marked
+"full", while descr 254 and 255 are empty. (The "Last 1 descrs" is
+descr 254, since tail was at 255.) Thus, the system is deadlocked,
+and there can be no forward progress; the OS thinks there's nothing
+to do, and the hardware has nowhere to put incoming data.
+
+This bug/feature is worked around with the spider_net_resync_head_ptr()
+routine. When the driver receives RX interrupts, but an examination
+of the RX chain seems to show it is empty, then it is probable that
+the hardware has skipped a descr or two (sometimes dozens under heavy
+network conditions). The spider_net_resync_head_ptr() subroutine will
+search the ring for the next full descr, and the driver will resume
+operations there. Since this will leave "holes" in the ring, there
+is also a spider_net_resync_tail_ptr() that will skip over such holes.
+
+As of this writing, the spider_net_resync() strategy seems to work very
+well, even under heavy network loads.
+
+
+The TX ring
+===========
+The TX ring uses a low-watermark interrupt scheme to make sure that
+the TX queue is appropriately serviced for large packet sizes.
+
+For packet sizes greater than about 1KBytes, the kernel can fill
+the TX ring quicker than the device can drain it. Once the ring
+is full, the netdev is stopped. When there is room in the ring,
+the netdev needs to be reawakened, so that more TX packets are placed
+in the ring. The hardware can empty the ring about four times per jiffy,
+so its not appropriate to wait for the poll routine to refill, since
+the poll routine runs only once per jiffy. The low-watermark mechanism
+marks a descr about 1/4th of the way from the bottom of the queue, so
+that an interrupt is generated when the descr is processed. This
+interrupt wakes up the netdev, which can then refill the queue.
+For large packets, this mechanism generates a relatively small number
+of interrupts, about 1K/sec. For smaller packets, this will drop to zero
+interrupts, as the hardware can empty the queue faster than the kernel
+can fill it.
+
+
+ ======= END OF DOCUMENT ========
+
diff --git a/Documentation/power_supply_class.txt b/Documentation/power_supply_class.txt
new file mode 100644
index 000000000000..9758cf433c06
--- /dev/null
+++ b/Documentation/power_supply_class.txt
@@ -0,0 +1,167 @@
+Linux power supply class
+========================
+
+Synopsis
+~~~~~~~~
+Power supply class used to represent battery, UPS, AC or DC power supply
+properties to user-space.
+
+It defines core set of attributes, which should be applicable to (almost)
+every power supply out there. Attributes are available via sysfs and uevent
+interfaces.
+
+Each attribute has well defined meaning, up to unit of measure used. While
+the attributes provided are believed to be universally applicable to any
+power supply, specific monitoring hardware may not be able to provide them
+all, so any of them may be skipped.
+
+Power supply class is extensible, and allows to define drivers own attributes.
+The core attribute set is subject to the standard Linux evolution (i.e.
+if it will be found that some attribute is applicable to many power supply
+types or their drivers, it can be added to the core set).
+
+It also integrates with LED framework, for the purpose of providing
+typically expected feedback of battery charging/fully charged status and
+AC/USB power supply online status. (Note that specific details of the
+indication (including whether to use it at all) are fully controllable by
+user and/or specific machine defaults, per design principles of LED
+framework).
+
+
+Attributes/properties
+~~~~~~~~~~~~~~~~~~~~~
+Power supply class has predefined set of attributes, this eliminates code
+duplication across drivers. Power supply class insist on reusing its
+predefined attributes *and* their units.
+
+So, userspace gets predictable set of attributes and their units for any
+kind of power supply, and can process/present them to a user in consistent
+manner. Results for different power supplies and machines are also directly
+comparable.
+
+See drivers/power/ds2760_battery.c and drivers/power/pda_power.c for the
+example how to declare and handle attributes.
+
+
+Units
+~~~~~
+Quoting include/linux/power_supply.h:
+
+ All voltages, currents, charges, energies, time and temperatures in µV,
+ µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ stated. It's driver's job to convert its raw values to units in which
+ this class operates.
+
+
+Attributes/properties detailed
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+~ ~ ~ ~ ~ ~ ~ Charge/Energy/Capacity - how to not confuse ~ ~ ~ ~ ~ ~ ~
+~ ~
+~ Because both "charge" (µAh) and "energy" (µWh) represents "capacity" ~
+~ of battery, this class distinguish these terms. Don't mix them! ~
+~ ~
+~ CHARGE_* attributes represents capacity in µAh only. ~
+~ ENERGY_* attributes represents capacity in µWh only. ~
+~ CAPACITY attribute represents capacity in *percents*, from 0 to 100. ~
+~ ~
+~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+Postfixes:
+_AVG - *hardware* averaged value, use it if your hardware is really able to
+report averaged values.
+_NOW - momentary/instantaneous values.
+
+STATUS - this attribute represents operating status (charging, full,
+discharging (i.e. powering a load), etc.). This corresponds to
+BATTERY_STATUS_* values, as defined in battery.h.
+
+HEALTH - represents health of the battery, values corresponds to
+POWER_SUPPLY_HEALTH_*, defined in battery.h.
+
+VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and
+minimal power supply voltages. Maximal/minimal means values of voltages
+when battery considered "full"/"empty" at normal conditions. Yes, there is
+no direct relation between voltage and battery capacity, but some dumb
+batteries use voltage for very approximated calculation of capacity.
+Battery driver also can use this attribute just to inform userspace
+about maximal and minimal voltage thresholds of a given battery.
+
+CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when
+battery considered full/empty.
+
+ENERGY_FULL_DESIGN, ENERGY_EMPTY_DESIGN - same as above but for energy.
+
+CHARGE_FULL, CHARGE_EMPTY - These attributes means "last remembered value
+of charge when battery became full/empty". It also could mean "value of
+charge when battery considered full/empty at given conditions (temperature,
+age)". I.e. these attributes represents real thresholds, not design values.
+
+ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
+
+CAPACITY - capacity in percents.
+CAPACITY_LEVEL - capacity level. This corresponds to
+POWER_SUPPLY_CAPACITY_LEVEL_*.
+
+TEMP - temperature of the power supply.
+TEMP_AMBIENT - ambient temperature.
+
+TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
+while battery powers a load)
+TIME_TO_FULL - seconds left for battery to be considered full (i.e.
+while battery is charging)
+
+
+Battery <-> external power supply interaction
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Often power supplies are acting as supplies and supplicants at the same
+time. Batteries are good example. So, batteries usually care if they're
+externally powered or not.
+
+For that case, power supply class implements notification mechanism for
+batteries.
+
+External power supply (AC) lists supplicants (batteries) names in
+"supplied_to" struct member, and each power_supply_changed() call
+issued by external power supply will notify supplicants via
+external_power_changed callback.
+
+
+QA
+~~
+Q: Where is POWER_SUPPLY_PROP_XYZ attribute?
+A: If you cannot find attribute suitable for your driver needs, feel free
+ to add it and send patch along with your driver.
+
+ The attributes available currently are the ones currently provided by the
+ drivers written.
+
+ Good candidates to add in future: model/part#, cycle_time, manufacturer,
+ etc.
+
+
+Q: I have some very specific attribute (e.g. battery color), should I add
+ this attribute to standard ones?
+A: Most likely, no. Such attribute can be placed in the driver itself, if
+ it is useful. Of course, if the attribute in question applicable to
+ large set of batteries, provided by many drivers, and/or comes from
+ some general battery specification/standard, it may be a candidate to
+ be added to the core attribute set.
+
+
+Q: Suppose, my battery monitoring chip/firmware does not provides capacity
+ in percents, but provides charge_{now,full,empty}. Should I calculate
+ percentage capacity manually, inside the driver, and register CAPACITY
+ attribute? The same question about time_to_empty/time_to_full.
+A: Most likely, no. This class is designed to export properties which are
+ directly measurable by the specific hardware available.
+
+ Inferring not available properties using some heuristics or mathematical
+ model is not subject of work for a battery driver. Such functionality
+ should be factored out, and in fact, apm_power, the driver to serve
+ legacy APM API on top of power supply class, uses a simple heuristic of
+ approximating remaining battery capacity based on its charge, current,
+ voltage and so on. But full-fledged battery model is likely not subject
+ for kernel at all, as it would require floating point calculation to deal
+ with things like differential equations and Kalman filters. This is
+ better be handled by batteryd/libbattery, yet to be written.
diff --git a/Documentation/sched-design-CFS.txt b/Documentation/sched-design-CFS.txt
new file mode 100644
index 000000000000..16feebb7bdc0
--- /dev/null
+++ b/Documentation/sched-design-CFS.txt
@@ -0,0 +1,119 @@
+
+This is the CFS scheduler.
+
+80% of CFS's design can be summed up in a single sentence: CFS basically
+models an "ideal, precise multi-tasking CPU" on real hardware.
+
+"Ideal multi-tasking CPU" is a (non-existent :-)) CPU that has 100%
+physical power and which can run each task at precise equal speed, in
+parallel, each at 1/nr_running speed. For example: if there are 2 tasks
+running then it runs each at 50% physical power - totally in parallel.
+
+On real hardware, we can run only a single task at once, so while that
+one task runs, the other tasks that are waiting for the CPU are at a
+disadvantage - the current task gets an unfair amount of CPU time. In
+CFS this fairness imbalance is expressed and tracked via the per-task
+p->wait_runtime (nanosec-unit) value. "wait_runtime" is the amount of
+time the task should now run on the CPU for it to become completely fair
+and balanced.
+
+( small detail: on 'ideal' hardware, the p->wait_runtime value would
+ always be zero - no task would ever get 'out of balance' from the
+ 'ideal' share of CPU time. )
+
+CFS's task picking logic is based on this p->wait_runtime value and it
+is thus very simple: it always tries to run the task with the largest
+p->wait_runtime value. In other words, CFS tries to run the task with
+the 'gravest need' for more CPU time. So CFS always tries to split up
+CPU time between runnable tasks as close to 'ideal multitasking
+hardware' as possible.
+
+Most of the rest of CFS's design just falls out of this really simple
+concept, with a few add-on embellishments like nice levels,
+multiprocessing and various algorithm variants to recognize sleepers.
+
+In practice it works like this: the system runs a task a bit, and when
+the task schedules (or a scheduler tick happens) the task's CPU usage is
+'accounted for': the (small) time it just spent using the physical CPU
+is deducted from p->wait_runtime. [minus the 'fair share' it would have
+gotten anyway]. Once p->wait_runtime gets low enough so that another
+task becomes the 'leftmost task' of the time-ordered rbtree it maintains
+(plus a small amount of 'granularity' distance relative to the leftmost
+task so that we do not over-schedule tasks and trash the cache) then the
+new leftmost task is picked and the current task is preempted.
+
+The rq->fair_clock value tracks the 'CPU time a runnable task would have
+fairly gotten, had it been runnable during that time'. So by using
+rq->fair_clock values we can accurately timestamp and measure the
+'expected CPU time' a task should have gotten. All runnable tasks are
+sorted in the rbtree by the "rq->fair_clock - p->wait_runtime" key, and
+CFS picks the 'leftmost' task and sticks to it. As the system progresses
+forwards, newly woken tasks are put into the tree more and more to the
+right - slowly but surely giving a chance for every task to become the
+'leftmost task' and thus get on the CPU within a deterministic amount of
+time.
+
+Some implementation details:
+
+ - the introduction of Scheduling Classes: an extensible hierarchy of
+ scheduler modules. These modules encapsulate scheduling policy
+ details and are handled by the scheduler core without the core
+ code assuming about them too much.
+
+ - sched_fair.c implements the 'CFS desktop scheduler': it is a
+ replacement for the vanilla scheduler's SCHED_OTHER interactivity
+ code.
+
+ I'd like to give credit to Con Kolivas for the general approach here:
+ he has proven via RSDL/SD that 'fair scheduling' is possible and that
+ it results in better desktop scheduling. Kudos Con!
+
+ The CFS patch uses a completely different approach and implementation
+ from RSDL/SD. My goal was to make CFS's interactivity quality exceed
+ that of RSDL/SD, which is a high standard to meet :-) Testing
+ feedback is welcome to decide this one way or another. [ and, in any
+ case, all of SD's logic could be added via a kernel/sched_sd.c module
+ as well, if Con is interested in such an approach. ]
+
+ CFS's design is quite radical: it does not use runqueues, it uses a
+ time-ordered rbtree to build a 'timeline' of future task execution,
+ and thus has no 'array switch' artifacts (by which both the vanilla
+ scheduler and RSDL/SD are affected).
+
+ CFS uses nanosecond granularity accounting and does not rely on any
+ jiffies or other HZ detail. Thus the CFS scheduler has no notion of
+ 'timeslices' and has no heuristics whatsoever. There is only one
+ central tunable:
+
+ /proc/sys/kernel/sched_granularity_ns
+
+ which can be used to tune the scheduler from 'desktop' (low
+ latencies) to 'server' (good batching) workloads. It defaults to a
+ setting suitable for desktop workloads. SCHED_BATCH is handled by the
+ CFS scheduler module too.
+
+ Due to its design, the CFS scheduler is not prone to any of the
+ 'attacks' that exist today against the heuristics of the stock
+ scheduler: fiftyp.c, thud.c, chew.c, ring-test.c, massive_intr.c all
+ work fine and do not impact interactivity and produce the expected
+ behavior.
+
+ the CFS scheduler has a much stronger handling of nice levels and
+ SCHED_BATCH: both types of workloads should be isolated much more
+ agressively than under the vanilla scheduler.
+
+ ( another detail: due to nanosec accounting and timeline sorting,
+ sched_yield() support is very simple under CFS, and in fact under
+ CFS sched_yield() behaves much better than under any other
+ scheduler i have tested so far. )
+
+ - sched_rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler
+ way than the vanilla scheduler does. It uses 100 runqueues (for all
+ 100 RT priority levels, instead of 140 in the vanilla scheduler)
+ and it needs no expired array.
+
+ - reworked/sanitized SMP load-balancing: the runqueue-walking
+ assumptions are gone from the load-balancing code now, and
+ iterators of the scheduling modules are used. The balancing code got
+ quite a bit simpler as a result.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index df40a4ec87fb..bc272bf0ff97 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1856,7 +1856,7 @@ W: http://www.openib.org/
T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
S: Supported
-INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
+INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
P: Dmitry Torokhov
M: dmitry.torokhov@gmail.com
M: dtor@mail.ru
@@ -3049,6 +3049,16 @@ S: Maintained
RISCOM8 DRIVER
S: Orphan
+RTL818X WIRELESS DRIVER
+P: Michael Wu
+M: flamingice@sourmilk.net
+P: Andrea Merello
+M: andreamrl@tiscali.it
+L: linux-wireless@vger.kernel.org
+W: http://linuxwireless.org/
+T: git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
+S: Maintained
+
S3 SAVAGE FRAMEBUFFER DRIVER
P: Antonino Daplas
M: adaplas@gmail.com
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 88baed1e7e83..0b2954534b8e 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -941,17 +941,6 @@ exit:
}
#endif
-static void smp_tune_scheduling(void)
-{
- if (cpu_khz) {
- /* cache size in kB */
- long cachesize = boot_cpu_data.x86_cache_size;
-
- if (cachesize > 0)
- max_cache_size = cachesize * 1024;
- }
-}
-
/*
* Cycle through the processors sending APIC IPIs to boot each.
*/
@@ -980,7 +969,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
current_thread_info()->cpu = 0;
- smp_tune_scheduling();
set_cpu_sibling_map(0);
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index f64b81f3033b..ea63a30ca3e8 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -4,6 +4,7 @@
* See comments there for proper credits.
*/
+#include <linux/sched.h>
#include <linux/clocksource.h>
#include <linux/workqueue.h>
#include <linux/cpufreq.h>
@@ -106,8 +107,13 @@ unsigned long long sched_clock(void)
/*
* Fall back to jiffies if there's no TSC available:
+ * ( But note that we still use it if the TSC is marked
+ * unstable. We do this because unlike Time Of Day,
+ * the scheduler clock tolerates small errors and it's
+ * very important for it to be as fast as the platform
+ * can achive it. )
*/
- if (unlikely(!tsc_enabled))
+ if (unlikely(!tsc_enabled && !tsc_unstable))
/* No locking but a rare wrong value is not a big deal: */
return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
@@ -277,6 +283,7 @@ static struct clocksource clocksource_tsc = {
void mark_tsc_unstable(char *reason)
{
+ sched_clock_unstable_event();
if (!tsc_unstable) {
tsc_unstable = 1;
tsc_enabled = 0;
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index eaa6a24bc0b6..188fb73c6845 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -805,7 +805,6 @@ static void __cpuinit
get_max_cacheline_size (void)
{
unsigned long line_size, max = 1;
- unsigned int cache_size = 0;
u64 l, levels, unique_caches;
pal_cache_config_info_t cci;
s64 status;
@@ -835,8 +834,6 @@ get_max_cacheline_size (void)
line_size = 1 << cci.pcci_line_size;
if (line_size > max)
max = line_size;
- if (cache_size < cci.pcci_cache_size)
- cache_size = cci.pcci_cache_size;
if (!cci.pcci_unified) {
status = ia64_pal_cache_config_info(l,
/* cache_type (instruction)= */ 1,
@@ -853,9 +850,6 @@ get_max_cacheline_size (void)
ia64_i_cache_stride_shift = cci.pcci_stride;
}
out:
-#ifdef CONFIG_SMP
- max_cache_size = max(max_cache_size, cache_size);
-#endif
if (max > ia64_max_cacheline_size)
ia64_max_cacheline_size = max;
}
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 73455389257a..a00fabe2e4e0 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -15,6 +15,29 @@ choice
prompt "System type"
default SGI_IP22
+config LEMOTE_FULONG
+ bool "Lemote Fulong mini-PC"
+ select ARCH_SPARSEMEM_ENABLE
+ select SYS_HAS_CPU_LOONGSON2
+ select DMA_NONCOHERENT
+ select BOOT_ELF32
+ select BOARD_SCACHE
+ select HAVE_STD_PC_SERIAL_PORT
+ select HW_HAS_PCI
+ select I8259
+ select ISA
+ select IRQ_CPU
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
+ select SYS_HAS_EARLY_PRINTK
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+ select CPU_HAS_WB
+ help
+ Lemote Fulong mini-PC board based on the Chinese Loongson-2E CPU and
+ an FPGA northbridge
+
config MACH_ALCHEMY
bool "Alchemy processor based machines"
@@ -63,7 +86,7 @@ config MACH_DECSTATION
bool "DECstations"
select BOOT_ELF32
select DMA_NONCOHERENT
- select SYS_HAS_EARLY_PRINTK
+ select NO_IOPORT
select IRQ_CPU
select SYS_HAS_CPU_R3000
select SYS_HAS_CPU_R4X00
@@ -88,24 +111,6 @@ config MACH_DECSTATION
otherwise choose R3000.
-config MIPS_EV64120
- bool "Galileo EV64120 Evaluation board (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select PCI_GT64XXX_PCI0
- select SYS_HAS_CPU_R5000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- select SYS_SUPPORTS_KGDB
- help
- This is an evaluation board based on the Galileo GT-64120
- single-chip system controller that contains a MIPS R5000 compatible
- core running at 75/100MHz. Their website is located at
- <http://www.marvell.com/>. Say Y here if you wish to build a
- kernel for this platform.
-
config MACH_JAZZ
bool "Jazz family of machines"
select ARC
@@ -126,20 +131,6 @@ config MACH_JAZZ
Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
Olivetti M700-10 workstations.
-config LASAT
- bool "LASAT Networks platforms"
- select DMA_NONCOHERENT
- select SYS_HAS_EARLY_PRINTK
- select HW_HAS_PCI
- select PCI_GT64XXX_PCI0
- select MIPS_NILE4
- select R5000_CPU_SCACHE
- select SYS_HAS_CPU_R5000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
- select SYS_SUPPORTS_LITTLE_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
-
config MIPS_ATLAS
bool "MIPS Atlas board"
select BOOT_ELF32
@@ -173,7 +164,6 @@ config MIPS_MALTA
bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC
select BOOT_ELF32
- select HAVE_STD_PC_SERIAL_PORT
select DMA_NONCOHERENT
select GENERIC_ISA_DMA
select IRQ_CPU
@@ -246,11 +236,13 @@ config MIPS_SIM
select DMA_NONCOHERENT
select SYS_HAS_EARLY_PRINTK
select IRQ_CPU
+ select BOOT_RAW
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_MIPS32_R2
select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_MULTITHREADING
select SYS_SUPPORTS_LITTLE_ENDIAN
help
This option enables support for MIPS Technologies MIPSsim software
@@ -274,43 +266,6 @@ config MOMENCO_OCELOT
The Ocelot is a MIPS-based Single Board Computer (SBC) made by
Momentum Computer <http://www.momenco.com/>.
-config MOMENCO_OCELOT_3
- bool "Momentum Ocelot-3 board"
- select BOOT_ELF32
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select IRQ_CPU
- select IRQ_CPU_RM7K
- select IRQ_MV64340
- select PCI_MARVELL
- select RM7000_CPU_SCACHE
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_RM9000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- help
- The Ocelot-3 is based off Discovery III System Controller and
- PMC-Sierra Rm79000 core.
-
-config MOMENCO_OCELOT_C
- bool "Momentum Ocelot-C board"
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select IRQ_CPU
- select IRQ_MV64340
- select PCI_MARVELL
- select RM7000_CPU_SCACHE
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_RM7000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
- help
- The Ocelot is a MIPS-based Single Board Computer (SBC) made by
- Momentum Computer <http://www.momenco.com/>.
-
config PNX8550_JBS
bool "Philips PNX8550 based JBS board"
select PNX8550
@@ -346,6 +301,27 @@ config MACH_VR41XX
select SYS_HAS_CPU_VR41XX
select GENERIC_HARDIRQS_NO__DO_IRQ
+config PMC_MSP
+ bool "PMC-Sierra MSP chipsets"
+ depends on EXPERIMENTAL
+ select DMA_NONCOHERENT
+ select SWAP_IO_SPACE
+ select NO_EXCEPT_FILL
+ select BOOT_RAW
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_KGDB
+ select IRQ_CPU
+ select SERIAL_8250
+ select SERIAL_8250_CONSOLE
+ help
+ This adds support for the PMC-Sierra family of Multi-Service
+ Processor System-On-A-Chips. These parts include a number
+ of integrated peripherals, interfaces and DSPs in addition to
+ a variety of MIPS cores.
+
config PMC_YOSEMITE
bool "PMC-Sierra Yosemite eval board"
select DMA_COHERENT
@@ -450,8 +426,7 @@ config SGI_IP27
here.
config SGI_IP32
- bool "SGI IP32 (O2) (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "SGI IP32 (O2)"
select ARC
select ARC32
select BOOT_ELF32
@@ -652,6 +627,7 @@ config TOSHIBA_RBTX4938
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_KGDB
select GENERIC_HARDIRQS_NO__DO_IRQ
+ select GENERIC_GPIO
help
This Toshiba board is based on the TX4938 processor. Say Y here to
support this machine type
@@ -660,9 +636,7 @@ endchoice
source "arch/mips/au1000/Kconfig"
source "arch/mips/ddb5xxx/Kconfig"
-source "arch/mips/gt64120/ev64120/Kconfig"
source "arch/mips/jazz/Kconfig"
-source "arch/mips/lasat/Kconfig"
source "arch/mips/pmc-sierra/Kconfig"
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
@@ -721,6 +695,9 @@ config ARC
config ARCH_MAY_HAVE_PC_FDC
bool
+config BOOT_RAW
+ bool
+
config DMA_COHERENT
bool
@@ -768,16 +745,19 @@ config MIPS_BONITO64
config MIPS_MSC
bool
-config MIPS_NILE4
- bool
-
config MIPS_DISABLE_OBSOLETE_IDE
bool
+config NO_IOPORT
+ def_bool n
+
config GENERIC_ISA_DMA_SUPPORT_BROKEN
bool
select ZONE_DMA
+config GENERIC_GPIO
+ bool
+
#
# Endianess selection. Sufficiently obscure so many users don't know what to
# answer,so we try hard to limit the available choices. Also the use of a
@@ -821,7 +801,10 @@ config IRQ_CPU_RM7K
config IRQ_CPU_RM9K
bool
-config IRQ_MV64340
+config IRQ_MSP_SLP
+ bool
+
+config IRQ_MSP_CIC
bool
config DDB5XXX_COMMON
@@ -834,6 +817,9 @@ config MIPS_BOARDS_GEN
config PCI_GT64XXX_PCI0
bool
+config NO_EXCEPT_FILL
+ bool
+
config MIPS_TX3927
bool
select HAS_TXX9_SERIAL
@@ -841,14 +827,6 @@ config MIPS_TX3927
config MIPS_RM9122
bool
select SERIAL_RM9000
- select GPI_RM9000
- select WDT_RM9000
-
-config PCI_MARVELL
- bool
-
-config SERIAL_RM9000
- bool
config PNX8550
bool
@@ -863,6 +841,7 @@ config SOC_PNX8550
select SYS_SUPPORTS_32BIT_KERNEL
select GENERIC_HARDIRQS_NO__DO_IRQ
select SYS_SUPPORTS_KGDB
+ select GENERIC_GPIO
config SWAP_IO_SPACE
bool
@@ -875,31 +854,17 @@ config EMMA2RH
config SERIAL_RM9000
bool
-config GPI_RM9000
- bool
-
-config WDT_RM9000
- bool
-
#
# Unfortunately not all GT64120 systems run the chip at the same clock.
# As the user for the clock rate and try to minimize the available options.
#
choice
prompt "Galileo Chip Clock"
- #default SYSCLK_83 if MIPS_EV64120
- depends on MIPS_EV64120 || MOMENCO_OCELOT
- default SYSCLK_83 if MIPS_EV64120
+ depends on MOMENCO_OCELOT
default SYSCLK_100 if MOMENCO_OCELOT
-config SYSCLK_75
- bool "75" if MIPS_EV64120
-
-config SYSCLK_83
- bool "83.3" if MIPS_EV64120
-
config SYSCLK_100
- bool "100" if MIPS_EV64120 || MOMENCO_OCELOT
+ bool "100" if MOMENCO_OCELOT
endchoice
@@ -911,8 +876,9 @@ config BOOT_ELF32
config MIPS_L1_CACHE_SHIFT
int
- default "4" if MACH_DECSTATION || SNI_RM
- default "7" if SGI_IP27
+ default "4" if MACH_DECSTATION
+ default "7" if SGI_IP27 || SNI_RM
+ default "4" if PMC_MSP4200_EVAL
default "5"
config HAVE_STD_PC_SERIAL_PORT
@@ -944,6 +910,16 @@ choice
prompt "CPU type"
default CPU_R4X00
+config CPU_LOONGSON2
+ bool "Loongson 2"
+ depends on SYS_HAS_CPU_LOONGSON2
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
+ select CPU_SUPPORTS_HIGHMEM
+ help
+ The Loongson 2E processor implements the MIPS III instruction set
+ with many extensions.
+
config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
@@ -1154,6 +1130,9 @@ config CPU_SB1
endchoice
+config SYS_HAS_CPU_LOONGSON2
+ bool
+
config SYS_HAS_CPU_MIPS32_R1
bool
@@ -1488,6 +1467,15 @@ config CPU_HAS_SMARTMIPS
config CPU_HAS_WB
bool
+config 64BIT_CONTEXT
+ bool "Save 64bit integer registers"
+ depends on 32BIT && CPU_LOONGSON2
+ help
+ Loongson2 CPU is 64bit , when used in 32BIT mode, its integer
+ registers can still be accessed as 64bit, mainly for multimedia
+ instructions. We must have all 64bit save/restored to make sure
+ those instructions to get correct result.
+
#
# Vectored interrupt mode is an R2 feature
#
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index f450066b6241..20d19c9b7761 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -118,6 +118,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap
cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap
cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
+cflags-$(CONFIG_CPU_LOONGSON2) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
@@ -283,14 +284,6 @@ load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000
CLEAN_FILES += drivers/tc/lk201-map.c
#
-# Galileo EV64120 Board
-#
-core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/ev64120/
-core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/common/
-cflags-$(CONFIG_MIPS_EV64120) += -Iinclude/asm-mips/mach-ev64120
-load-$(CONFIG_MIPS_EV64120) += 0xffffffff80100000
-
-#
# Wind River PPMC Board (4KC + GT64120)
#
core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/
@@ -298,6 +291,13 @@ cflags-$(CONFIG_WR_PPMC) += -Iinclude/asm-mips/mach-wrppmc
load-$(CONFIG_WR_PPMC) += 0xffffffff80100000
#
+# lemote fulong mini-PC board
+#
+core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/
+load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000
+cflags-$(CONFIG_LEMOTE_FULONG) += -Iinclude/asm-mips/mach-lemote
+
+#
# For all MIPS, Inc. eval boards
#
core-$(CONFIG_MIPS_BOARDS_GEN) += arch/mips/mips-boards/generic/
@@ -327,7 +327,7 @@ load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000
#
# MIPS SIM
#
-core-$(CONFIG_MIPS_SIM) += arch/mips/mips-boards/sim/
+core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/
cflags-$(CONFIG_MIPS_SIM) += -Iinclude/asm-mips/mach-sim
load-$(CONFIG_MIPS_SIM) += 0x80100000
@@ -343,12 +343,12 @@ cflags-$(CONFIG_MOMENCO_OCELOT) += -Iinclude/asm-mips/mach-ocelot
load-$(CONFIG_MOMENCO_OCELOT) += 0xffffffff80100000
#
-# Momentum Ocelot-C and -CS boards
+# PMC-Sierra MSP SOCs
#
-# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the
-# mips_io_port_base.
-core-$(CONFIG_MOMENCO_OCELOT_C) += arch/mips/momentum/ocelot_c/
-load-$(CONFIG_MOMENCO_OCELOT_C) += 0xffffffff80100000
+core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/
+cflags-$(CONFIG_PMC_MSP) += -Iinclude/asm-mips/pmc-sierra/msp71xx \
+ -mno-branch-likely
+load-$(CONFIG_PMC_MSP) += 0xffffffff80100000
#
# PMC-Sierra Yosemite
@@ -365,13 +365,6 @@ cflags-$(CONFIG_QEMU) += -Iinclude/asm-mips/mach-qemu
load-$(CONFIG_QEMU) += 0xffffffff80010000
#
-# Momentum Ocelot-3
-#
-core-$(CONFIG_MOMENCO_OCELOT_3) += arch/mips/momentum/ocelot_3/
-cflags-$(CONFIG_MOMENCO_OCELOT_3) += -Iinclude/asm-mips/mach-ocelot3
-load-$(CONFIG_MOMENCO_OCELOT_3) += 0xffffffff80100000
-
-#
# Basler eXcite
#
core-$(CONFIG_BASLER_EXCITE) += arch/mips/basler/excite/
@@ -389,10 +382,6 @@ core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/
core-$(CONFIG_DDB5477) += arch/mips/ddb5xxx/ddb5477/
load-$(CONFIG_DDB5477) += 0xffffffff80100000
-core-$(CONFIG_LASAT) += arch/mips/lasat/
-cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat
-load-$(CONFIG_LASAT) += 0xffffffff80000000
-
#
# Common VR41xx
#
@@ -580,6 +569,7 @@ load-$(CONFIG_TOSHIBA_JMR3927) += 0xffffffff80050000
#
core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/toshiba_rbtx4927/
core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/common/
+cflags-$(CONFIG_TOSHIBA_RBTX4927) += -Iinclude/asm-mips/mach-tx49xx
load-$(CONFIG_TOSHIBA_RBTX4927) += 0xffffffff80020000
#
@@ -587,6 +577,7 @@ load-$(CONFIG_TOSHIBA_RBTX4927) += 0xffffffff80020000
#
core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/toshiba_rbtx4938/
core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/common/
+cflags-$(CONFIG_TOSHIBA_RBTX4938) += -Iinclude/asm-mips/mach-tx49xx
load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000
cflags-y += -Iinclude/asm-mips/mach-generic
@@ -603,7 +594,8 @@ JIFFIES = jiffies_64
endif
AFLAGS += $(cflags-y)
-CFLAGS += $(cflags-y)
+CFLAGS += $(cflags-y) \
+ -D"VMLINUX_LOAD_ADDRESS=$(load-y)"
LDFLAGS += -m $(ld-emul)
@@ -633,18 +625,11 @@ CPPFLAGS_vmlinux.lds := \
head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
libs-y += arch/mips/lib/
-libs-$(CONFIG_32BIT) += arch/mips/lib-32/
-libs-$(CONFIG_64BIT) += arch/mips/lib-64/
core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/
drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/
-ifdef CONFIG_LASAT
-rom.bin rom.sw: vmlinux
- $(Q)$(MAKE) $(build)=arch/mips/lasat/image $@
-endif
-
#
# Some machines like the Indy need 32-bit ELF binaries for booting purposes.
# Other need ECOFF, so we build a 32-bit ELF binary for them which we then
@@ -702,32 +687,19 @@ vmlinux.srec: $(vmlinux-32)
CLEAN_FILES += vmlinux.ecoff \
vmlinux.srec
+archprepare:
+ifdef CONFIG_MIPS32_N32
+ @echo ' Checking missing-syscalls for N32'
+ $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32"
+endif
+ifdef CONFIG_MIPS32_O32
+ @echo ' Checking missing-syscalls for O32'
+ $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32"
+endif
+
archclean:
@$(MAKE) $(clean)=arch/mips/boot
- @$(MAKE) $(clean)=arch/mips/lasat
CLEAN_FILES += vmlinux.32 \
vmlinux.64 \
vmlinux.ecoff
-
-quiet_cmd_syscalls_n32 = CALL-N32 $<
- cmd_syscalls_n32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=n32
-
-quiet_cmd_syscalls_o32 = CALL-O32 $<
- cmd_syscalls_o32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=32
-
-PHONY += missing-syscalls-n32 missing-syscalls-o32
-
-missing-syscalls-n32: scripts/checksyscalls.sh FORCE
- $(call cmd,syscalls_n32)
-
-missing-syscalls-o32: scripts/checksyscalls.sh FORCE
- $(call cmd,syscalls_o32)
-
-archprepare:
-ifdef CONFIG_MIPS32_N32
- $(Q)$(MAKE) $(build)=arch/mips missing-syscalls-n32
-endif
-ifdef CONFIG_MIPS32_O32
- $(Q)$(MAKE) $(build)=arch/mips missing-syscalls-o32
-endif
diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
index ce55297dcb8c..7abe42099439 100644
--- a/arch/mips/au1000/common/gpio.c
+++ b/arch/mips/au1000/common/gpio.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ * Architecture specific GPIO support
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -18,101 +21,136 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Notes :
+ * au1000 SoC have only one GPIO line : GPIO1
+ * others have a second one : GPIO2
*/
+
+#include <linux/autoconf.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
#include <linux/module.h>
-#include <au1000.h>
-#include <au1xxx_gpio.h>
+
+#include <asm/addrspace.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/gpio.h>
#define gpio1 sys
#if !defined(CONFIG_SOC_AU1000)
-static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE;
-#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
+static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE;
+#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
-int au1xxx_gpio2_read(int signal)
+static int au1xxx_gpio2_read(unsigned gpio)
{
- signal -= 200;
-/* gpio2->dir &= ~(0x01 << signal); //Set GPIO to input */
- return ((gpio2->pinstate >> signal) & 0x01);
+ gpio -= AU1XXX_GPIO_BASE;
+ return ((gpio2->pinstate >> gpio) & 0x01);
}
-void au1xxx_gpio2_write(int signal, int value)
+static void au1xxx_gpio2_write(unsigned gpio, int value)
{
- signal -= 200;
+ gpio -= AU1XXX_GPIO_BASE;
- gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) |
- (value << signal);
+ gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio);
}
-void au1xxx_gpio2_tristate(int signal)
+static int au1xxx_gpio2_direction_input(unsigned gpio)
{
- signal -= 200;
- gpio2->dir &= ~(0x01 << signal); /* Set GPIO to input */
+ gpio -= AU1XXX_GPIO_BASE;
+ gpio2->dir &= ~(0x01 << gpio);
+ return 0;
}
-#endif
-int au1xxx_gpio1_read(int signal)
+static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
+{
+ gpio -= AU1XXX_GPIO_BASE;
+ gpio2->dir = (0x01 << gpio) | (value << gpio);
+ return 0;
+}
+
+#endif /* !defined(CONFIG_SOC_AU1000) */
+
+static int au1xxx_gpio1_read(unsigned gpio)
{
-/* gpio1->trioutclr |= (0x01 << signal); */
- return ((gpio1->pinstaterd >> signal) & 0x01);
+ return ((gpio1->pinstaterd >> gpio) & 0x01);
}
-void au1xxx_gpio1_write(int signal, int value)
+static void au1xxx_gpio1_write(unsigned gpio, int value)
{
- if(value)
- gpio1->outputset = (0x01 << signal);
+ if (value)
+ gpio1->outputset = (0x01 << gpio);
else
- gpio1->outputclr = (0x01 << signal); /* Output a Zero */
+ /* Output a zero */
+ gpio1->outputclr = (0x01 << gpio);
}
-void au1xxx_gpio1_tristate(int signal)
+static int au1xxx_gpio1_direction_input(unsigned gpio)
{
- gpio1->trioutclr = (0x01 << signal); /* Tristate signal */
+ gpio1->pininputen = (0x01 << gpio);
+ return 0;
}
+static int au1xxx_gpio1_direction_output(unsigned gpio, int value)
+{
+ gpio1->trioutclr = (0x01 & gpio);
+ return 0;
+}
-int au1xxx_gpio_read(int signal)
+int au1xxx_gpio_get_value(unsigned gpio)
{
- if(signal >= 200)
+ if (gpio >= AU1XXX_GPIO_BASE)
#if defined(CONFIG_SOC_AU1000)
return 0;
#else
- return au1xxx_gpio2_read(signal);
+ return au1xxx_gpio2_read(gpio);
#endif
else
- return au1xxx_gpio1_read(signal);
+ return au1xxx_gpio1_read(gpio);
}
-void au1xxx_gpio_write(int signal, int value)
+EXPORT_SYMBOL(au1xxx_gpio_get_value);
+
+void au1xxx_gpio_set_value(unsigned gpio, int value)
{
- if(signal >= 200)
+ if (gpio >= AU1XXX_GPIO_BASE)
#if defined(CONFIG_SOC_AU1000)
;
#else
- au1xxx_gpio2_write(signal, value);
+ au1xxx_gpio2_write(gpio, value);
#endif
else
- au1xxx_gpio1_write(signal, value);
+ au1xxx_gpio1_write(gpio, value);
}
-void au1xxx_gpio_tristate(int signal)
+EXPORT_SYMBOL(au1xxx_gpio_set_value);
+
+int au1xxx_gpio_direction_input(unsigned gpio)
{
- if(signal >= 200)
+ if (gpio >= AU1XXX_GPIO_BASE)
#if defined(CONFIG_SOC_AU1000)
;
#else
- au1xxx_gpio2_tristate(signal);
+ return au1xxx_gpio2_direction_input(gpio);
#endif
else
- au1xxx_gpio1_tristate(signal);
+ return au1xxx_gpio1_direction_input(gpio);
}
-void au1xxx_gpio1_set_inputs(void)
+EXPORT_SYMBOL(au1xxx_gpio_direction_input);
+
+int au1xxx_gpio_direction_output(unsigned gpio, int value)
{
- gpio1->pininputen = 0;
+ if (gpio >= AU1XXX_GPIO_BASE)
+#if defined(CONFIG_SOC_AU1000)
+ ;
+#else
+ return au1xxx_gpio2_direction_output(gpio, value);
+#endif
+ else
+ return au1xxx_gpio1_direction_output(gpio, value);
}
-EXPORT_SYMBOL(au1xxx_gpio1_set_inputs);
-EXPORT_SYMBOL(au1xxx_gpio_tristate);
-EXPORT_SYMBOL(au1xxx_gpio_write);
-EXPORT_SYMBOL(au1xxx_gpio_read);
+EXPORT_SYMBOL(au1xxx_gpio_direction_output);
diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
index 8fd203d4a339..d51e18fb789b 100644
--- a/arch/mips/au1000/common/platform.c
+++ b/arch/mips/au1000/common/platform.c
@@ -289,7 +289,7 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
#endif
};
-int au1xxx_platform_init(void)
+int __init au1xxx_platform_init(void)
{
return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices));
}
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 39e251300c64..129e2c961fec 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
CONFIG_MIPS_ATLAS=y
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_MIPS_ATLAS=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 4713a13211ce..dc3e1bf4e42e 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 5e7ae56b1f3c..4c7031222e64 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 631b2138ad68..c8c05785a86d 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,44 +1,24 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc7
-# Wed Apr 18 14:25:45 2007
+# Linux kernel version: 2.6.22-rc2
+# Fri May 25 11:17:29 2007
#
CONFIG_MIPS=y
#
# Machine selection
#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
CONFIG_MIPS_COBALT=y
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_DDB5477 is not set
@@ -138,7 +118,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+CONFIG_ZONE_DMA_FLAG=0
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
@@ -178,6 +158,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
# CONFIG_BLK_DEV_INITRD is not set
@@ -193,14 +174,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -233,16 +219,13 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_MMU=y
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -268,7 +251,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -300,11 +282,11 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
@@ -345,13 +327,16 @@ CONFIG_NETWORK_SECMARK=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -370,10 +355,6 @@ CONFIG_FW_LOADER=y
#
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -418,7 +399,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -445,16 +425,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -479,87 +456,145 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-CONFIG_SGI_IOC4=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=y
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_BLK_DEV_TC86C001=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
#
# SCSI device support
#
CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+CONFIG_PATA_VIA=y
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
#
# Multi-device support (RAID and LVM)
@@ -570,10 +605,14 @@ CONFIG_RAID_ATTRS=y
# Fusion MPT device support
#
# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -594,24 +633,7 @@ CONFIG_NETDEVICES=y
# ARCnet devices
#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
@@ -639,35 +661,8 @@ CONFIG_TULIP=y
# CONFIG_ULI526X is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
#
# Token Ring devices
@@ -675,18 +670,16 @@ CONFIG_NETXEN_NIC=y
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
@@ -711,10 +704,7 @@ CONFIG_INPUT=y
#
# Userland interfaces
#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
@@ -726,18 +716,23 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_COBALT_BTNS=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_INPUT_POLLDEV=y
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
@@ -754,7 +749,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_PCI is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -773,16 +768,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
CONFIG_COBALT_LCD=y
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_DRM is not set
@@ -792,10 +782,7 @@ CONFIG_COBALT_LCD=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -808,12 +795,7 @@ CONFIG_COBALT_LCD=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
# Multifunction device drivers
@@ -824,16 +806,19 @@ CONFIG_COBALT_LCD=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
#
@@ -868,10 +853,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -912,18 +893,30 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
#
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
#
CONFIG_RTC_DRV_CMOS=y
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+
+#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
@@ -937,14 +930,6 @@ CONFIG_RTC_DRV_CMOS=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -952,8 +937,13 @@ CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
@@ -969,7 +959,7 @@ CONFIG_INOTIFY_USER=y
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
+# CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
#
@@ -1003,7 +993,6 @@ CONFIG_CONFIGFS_FS=y
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -1021,13 +1010,23 @@ CONFIG_CONFIGFS_FS=y
# Network File Systems
#
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1051,10 +1050,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Distributed Lock Manager
#
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
#
# Profiling support
@@ -1072,72 +1068,30 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 10f6af43753d..ec60beb888b2 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1000=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1000=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 4b0862927748..f3c25f08bfad 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1100=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1100=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 820659e810dc..6d400befbacc 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1200=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1200=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 4050b9b91bcb..82aea6e08823 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1500=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1500=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 7b3519058ab8..82697714a9e3 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1550=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1550=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 5b502a2013fb..a42ab9ae7d4b 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 4bbdab078ff1..d6e3fffbc80d 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
CONFIG_MACH_DECSTATION=y
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_MACH_DECSTATION=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index b5714a6a5398..78f5004fb721 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
index 2e3e155b4c55..b29bff0f56c3 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
deleted file mode 100644
index c10e4e063226..000000000000
--- a/arch/mips/configs/ev64120_defconfig
+++ /dev/null
@@ -1,985 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:30 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-CONFIG_MIPS_EV64120=y
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-# CONFIG_EVB_PCI1 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_MIPS_GT64120=y
-# CONFIG_SYSCLK_75 is not set
-# CONFIG_SYSCLK_83 is not set
-CONFIG_SYSCLK_100=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_KMOD is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-CONFIG_SLHC=y
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
-CONFIG_SYS_SUPPORTS_KGDB=y
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=m
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
index 460d7a26a8ba..69810592aa6b 100644
--- a/arch/mips/configs/excite_defconfig
+++ b/arch/mips/configs/excite_defconfig
@@ -26,9 +26,7 @@ CONFIG_BASLER_EXCITE=y
# CONFIG_BASLER_EXCITE_PROTOTYPE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_BASLER_EXCITE=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/fulong_defconfig b/arch/mips/configs/fulong_defconfig
new file mode 100644
index 000000000000..6ab94d8cf08b
--- /dev/null
+++ b/arch/mips/configs/fulong_defconfig
@@ -0,0 +1,1765 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Mon Jun 11 00:23:51 2007
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_LEMOTE_FULONG=y
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_LOONGSON2=y
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_LOONGSON2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+# CONFIG_PAGE_SIZE_4KB is not set
+# CONFIG_PAGE_SIZE_8KB is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_BOARD_SCACHE=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_CPU_HAS_WB=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION="lm32"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_ISA=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_IEEE80211_SOFTMAC is not set
+# CONFIG_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x1fc00000
+CONFIG_MTD_PHYSMAP_LEN=0x80000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# Misc devices
+#
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TC35815 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_IVTV is not set
+# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=y
+# CONFIG_FB_RADEON_I2C is not set
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_VIA82XX=m
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=y
+CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=936
+CONFIG_FAT_DEFAULT_IOCHARSET="utf8"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp936"
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_DEBUG2=y
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+CONFIG_NLS_CODEPAGE_936=y
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 7ec618f3c8b9..405c9f505a77 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 9ddc3eff4793..a9dcbcf563cb 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 8fc18809d5ff..a040459bec11 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 9331cb0a19b1..dd04eece9fd3 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
CONFIG_MACH_JAZZ=y
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_MACH_JAZZ=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 1b364cf69140..9a25e770abd8 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
deleted file mode 100644
index fd4272c1458a..000000000000
--- a/arch/mips/configs/lasat200_defconfig
+++ /dev/null
@@ -1,1118 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:34 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-CONFIG_LASAT=y
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_PICVUE=y
-CONFIG_PICVUE_PROC=y
-CONFIG_DS1603=y
-CONFIG_LASAT_SYSCTL=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_MIPS_NILE4=y
-# CONFIG_CPU_BIG_ENDIAN is not set
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
-CONFIG_MIPS_GT64120=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_R5000_CPU_SCACHE=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_LASAT=y
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=m
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 1f64d7632a03..546cb243fd09 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
CONFIG_MIPS_MALTA=y
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_MIPS_MALTA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index a2db5c201216..6abad6f88313 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
CONFIG_MIPS_SIM=y
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
@@ -496,36 +492,23 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_SIM_NET=y
+# CONFIG_DM9000 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index ad5c0bf87b2b..4981ce425d82 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/msp71xx_defconfig
index 28547313ce13..adca5f7ba533 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:35 2007
+# Linux kernel version: 2.6.21-rc4
+# Thu Apr 26 18:11:29 2007
#
CONFIG_MIPS=y
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,14 +33,13 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-CONFIG_MOMENCO_OCELOT_3=y
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_DDB5477 is not set
# CONFIG_MACH_VR41XX is not set
+CONFIG_PMC_MSP=y
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_QEMU is not set
# CONFIG_MARKEINS is not set
@@ -62,6 +59,16 @@ CONFIG_MOMENCO_OCELOT_3=y
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_PMC_MSP4200_EVAL is not set
+# CONFIG_PMC_MSP4200_GW is not set
+# CONFIG_PMC_MSP7120_EVAL is not set
+CONFIG_PMC_MSP7120_GW=y
+# CONFIG_PMC_MSP7120_FPGA is not set
+
+#
+# Options for PMC-Sierra MSP chipsets
+#
+CONFIG_PMC_MSP_EMBEDDED_ROOTFS=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -71,24 +78,24 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
+CONFIG_BOOT_RAW=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_NO_EXCEPT_FILL=y
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
+CONFIG_IRQ_MSP_CIC=y
+CONFIG_MSP_USB=y
CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
#
# CPU selection
#
# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
+CONFIG_CPU_MIPS32_R2=y
# CONFIG_CPU_MIPS64_R1 is not set
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
@@ -104,14 +111,14 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_R10000 is not set
# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_RM9000=y
+# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM9000=y
-CONFIG_WEAK_ORDERING=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
@@ -122,13 +129,12 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
# CONFIG_64BIT_PHYS_ADDR is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
@@ -149,15 +155,16 @@ CONFIG_ZONE_DMA_FLAG=1
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_BKL is not set
# CONFIG_KEXEC is not set
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
@@ -168,14 +175,15 @@ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
-CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION="-pmc"
CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
+# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
@@ -184,15 +192,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
+# CONFIG_IKCONFIG is not set
CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -201,11 +210,11 @@ CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_SHMEM=y
+# CONFIG_SHMEM is not set
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
+CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -232,8 +241,8 @@ CONFIG_BLOCK=y
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_DEADLINE is not set
# CONFIG_DEFAULT_CFQ is not set
@@ -245,6 +254,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
CONFIG_MMU=y
#
@@ -267,10 +277,7 @@ CONFIG_TRAD_SIGNALS=y
#
# Power management options
#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_PM is not set
#
# Networking
@@ -281,17 +288,16 @@ CONFIG_NET=y
# Networking options
#
# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
+# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
@@ -300,122 +306,92 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
#
# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-CONFIG_IPV6_MIP6=y
+# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
#
# Core Netfilter Configuration
#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
#
# IP: Netfilter Configuration
#
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
# CONFIG_IP_NF_ARPTABLES is not set
#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+# Bridge: Netfilter Configuration
#
-CONFIG_NF_CONNTRACK_IPV6=m
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
#
# DCCP Configuration (EXPERIMENTAL)
@@ -432,9 +408,10 @@ CONFIG_NF_CONNTRACK_IPV6=m
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
+CONFIG_BRIDGE=y
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
+CONFIG_LLC=y
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
@@ -447,7 +424,6 @@ CONFIG_NF_CONNTRACK_IPV6=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -456,14 +432,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+# CONFIG_IEEE80211 is not set
CONFIG_WIRELESS_EXT=y
-CONFIG_FIB_RULES=y
#
# Device Drivers
@@ -473,19 +443,101 @@ CONFIG_FIB_RULES=y
# Generic Driver Options
#
CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
+# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
#
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PMC_MSP_EVM=y
+CONFIG_MSP_FLASH_MAP_LIMIT_32M=y
+CONFIG_MSP_FLASH_MAP_LIMIT=0x02000000
+CONFIG_MTD_PMC_MSP_RAMROOT=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
#
# Parallel port support
@@ -505,19 +557,21 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-CONFIG_SGI_IOC4=m
+# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
#
@@ -528,16 +582,16 @@ CONFIG_SGI_IOC4=m
#
# SCSI device support
#
-CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
-CONFIG_SCSI_NETLINK=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
# SCSI support type (disk, tape, CD-ROM)
#
-# CONFIG_BLK_DEV_SD is not set
+CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
@@ -550,22 +604,21 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
-CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
-CONFIG_SCSI_FC_ATTRS=m
-CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SCSI_SAS_ATTRS=m
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
#
-CONFIG_ISCSI_TCP=m
+# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -573,8 +626,7 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_AIC94XX=m
-# CONFIG_AIC94XX_DEBUG is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
@@ -630,10 +682,10 @@ CONFIG_SCSI_AIC94XX=m
# Network device support
#
CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
+# CONFIG_TUN is not set
#
# ARCnet devices
@@ -643,26 +695,16 @@ CONFIG_TUN=m
#
# PHY device support
#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+CONFIG_MSPETH=y
+CONFIG_MSPETH_NAPI=y
+# CONFIG_MSPETH_SKB_RECYCLE is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
@@ -674,26 +716,7 @@ CONFIG_MII=y
#
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-CONFIG_E100=y
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_SC92031 is not set
+# CONFIG_NET_PCI is not set
#
# Ethernet (1000 Mbit)
@@ -709,22 +732,20 @@ CONFIG_E100=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-CONFIG_MV643XX_ETH=y
-CONFIG_QLA3XXX=m
+# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -734,7 +755,29 @@ CONFIG_NETXEN_NIC=m
#
# Wireless LAN (non-hamradio)
#
-# CONFIG_NET_RADIO is not set
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
#
# Wan interfaces
@@ -742,17 +785,17 @@ CONFIG_NETXEN_NIC=m
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
-CONFIG_PPP=m
+CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
# CONFIG_SLIP is not set
-CONFIG_SLHC=m
+CONFIG_SLHC=y
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
@@ -796,31 +839,24 @@ CONFIG_INPUT=y
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_PMCMSP_GPIO=y
#
# Serial drivers
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -830,8 +866,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
#
# IPMI
@@ -843,7 +878,8 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -858,7 +894,58 @@ CONFIG_RTC=y
#
# I2C support
#
-# CONFIG_I2C is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_PMCMSP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+CONFIG_PMCTWILED=y
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
#
# SPI support
@@ -874,8 +961,57 @@ CONFIG_RTC=y
#
# Hardware Monitoring support
#
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
@@ -886,62 +1022,13 @@ CONFIG_RTC=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
#
# Sound
@@ -960,13 +1047,134 @@ CONFIG_HID=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -1030,37 +1238,22 @@ CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
+# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -1071,22 +1264,25 @@ CONFIG_GENERIC_ACL=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
+# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -1097,8 +1293,21 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
-CONFIG_EFS_FS=y
-CONFIG_CRAMFS=y
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_SQUASHFS_VMALLOC=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -1108,26 +1317,9 @@ CONFIG_CRAMFS=y
#
# Network File Systems
#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -1143,9 +1335,9 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=m
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
@@ -1169,7 +1361,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
@@ -1187,10 +1379,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Distributed Lock Manager
#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
#
# Profiling support
@@ -1203,14 +1392,40 @@ CONFIG_DLM_TCP=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="ip=any root=nfs"
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
#
# Security options
@@ -1223,41 +1438,40 @@ CONFIG_CMDLINE="ip=any root=nfs"
#
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
+# CONFIG_CRYPTO_XCBC is not set
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
@@ -1268,16 +1482,12 @@ CONFIG_CRYPTO_CAMELLIA=m
# Library routines
#
CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
+CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
deleted file mode 100644
index 82ff6fc0cd41..000000000000
--- a/arch/mips/configs/ocelot_c_defconfig
+++ /dev/null
@@ -1,982 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:36 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-CONFIG_MOMENCO_OCELOT_C=y
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM7000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-# CONFIG_32BIT is not set
-CONFIG_64BIT=y
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_BUILD_ELF64 is not set
-CONFIG_MIPS32_COMPAT=y
-CONFIG_COMPAT=y
-CONFIG_SYSVIPC_COMPAT=y
-CONFIG_MIPS32_O32=y
-CONFIG_MIPS32_N32=y
-CONFIG_BINFMT_ELF32=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=y
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 15a027e00eec..e1db1fb80cd0 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
CONFIG_MOMENCO_OCELOT=y
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 37d696c64541..0028aef0af9d 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_PB1100=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_PB1100=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index b11f0e8b6059..8a1d5888739c 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_PB1500=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_PB1500=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 2927f38f4907..5581ad2ca411 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_PB1550=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_PB1550=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index fae16c5ec521..821c1cee5639 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
CONFIG_PNX8550_JBS=y
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
index cd821e52181d..0e8bd92b38cf 100644
--- a/arch/mips/configs/pnx8550-stb810_defconfig
+++ b/arch/mips/configs/pnx8550-stb810_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 8e8d03157954..6cca105832ca 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/rbhma4200_defconfig b/arch/mips/configs/rbhma4200_defconfig
index 35d64260917e..20a38526d483 100644
--- a/arch/mips/configs/rbhma4200_defconfig
+++ b/arch/mips/configs/rbhma4200_defconfig
@@ -24,17 +24,13 @@ CONFIG_MIPS=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 41011f770a67..5dbb250f71c7 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:39 2007
+# Linux kernel version: 2.6.22-rc5
+# Fri Jun 22 21:39:45 2007
#
CONFIG_MIPS=y
@@ -9,40 +9,23 @@ CONFIG_MIPS=y
# Machine selection
#
CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_DDB5477 is not set
# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_MSP is not set
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_QEMU is not set
# CONFIG_MARKEINS is not set
@@ -82,6 +65,8 @@ CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
@@ -93,6 +78,7 @@ CONFIG_HAVE_STD_PC_SERIAL_PORT=y
#
# CPU selection
#
+# CONFIG_CPU_LOONGSON2 is not set
# CONFIG_CPU_MIPS32_R1 is not set
# CONFIG_CPU_MIPS32_R2 is not set
# CONFIG_CPU_MIPS64_R1 is not set
@@ -149,12 +135,12 @@ CONFIG_ZONE_DMA_FLAG=1
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
@@ -186,28 +172,35 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
+# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -244,17 +237,12 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_MMU=y
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
@@ -266,10 +254,7 @@ CONFIG_TRAD_SIGNALS=y
#
# Power management options
#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_PM is not set
#
# Networking
@@ -279,14 +264,9 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -294,7 +274,7 @@ CONFIG_IP_MULTICAST=y
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
@@ -305,130 +285,23 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-CONFIG_IPV6_MIP6=y
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
-#
-CONFIG_NF_CONNTRACK_IPV6=m
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -446,7 +319,6 @@ CONFIG_NF_CONNTRACK_IPV6=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -455,15 +327,16 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-CONFIG_FIB_RULES=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -474,94 +347,13 @@ CONFIG_FIB_RULES=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
#
# Parallel port support
@@ -583,93 +375,30 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-CONFIG_SGI_IOC4=m
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=m
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
#
# SCSI device support
#
-CONFIG_RAID_ATTRS=m
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -685,6 +414,7 @@ CONFIG_RAID_ATTRS=m
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -699,36 +429,15 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
+# CONFIG_TUN is not set
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
@@ -747,6 +456,7 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
+CONFIG_TC35815=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
@@ -761,91 +471,20 @@ CONFIG_NET_PCI=y
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-CONFIG_IPW2200=m
-# CONFIG_IPW2200_MONITOR is not set
-# CONFIG_IPW2200_QOS is not set
-# CONFIG_IPW2200_DEBUG is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_BCM43XX is not set
-# CONFIG_ZD1211RW is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
+# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-CONFIG_SLHC=m
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
@@ -864,57 +503,18 @@ CONFIG_SLHC=m
#
# Input device support
#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -926,11 +526,12 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_TXX9=y
CONFIG_HAS_TXX9_SERIAL=y
CONFIG_SERIAL_TXX9_NR_UARTS=6
-# CONFIG_SERIAL_TXX9_CONSOLE is not set
-# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+CONFIG_SERIAL_TXX9_CONSOLE=y
+CONFIG_SERIAL_TXX9_STDSERIAL=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
@@ -940,15 +541,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_DRM is not set
@@ -958,108 +554,61 @@ CONFIG_LEGACY_PTY_COUNT=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
#
-# I2C support
+# SPI Master Controller Drivers
#
-# CONFIG_I2C is not set
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_TXX9=y
#
-# SPI support
+# SPI Protocol Masters
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI_AT25=y
+# CONFIG_SPI_SPIDEV is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
# Graphics support
#
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-CONFIG_FB_ATY=y
-CONFIG_FB_ATY_CT=y
-# CONFIG_FB_ATY_GENERIC_LCD is not set
-# CONFIG_FB_ATY_GX is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Sound
+# Display device support
#
-# CONFIG_SOUND is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
#
-# HID Devices
+# Sound
#
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
+# CONFIG_SOUND is not set
#
# USB support
@@ -1067,148 +616,80 @@ CONFIG_HID=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_OHCI_HCD is not set
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
+# CONFIG_USB is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
-# may also be needed; see USB_STORAGE Help for more information
-#
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-CONFIG_USB_YEALINK=m
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=y
-
-#
-# USB port drivers
+# USB Gadget Support
#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
#
-# USB Serial Converter support
+# LED devices
#
-# CONFIG_USB_SERIAL is not set
+# CONFIG_NEW_LEDS is not set
#
-# USB Miscellaneous drivers
+# LED drivers
#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
#
-# USB DSL modem support
+# LED Triggers
#
#
-# USB Gadget Support
+# InfiniBand support
#
-# CONFIG_USB_GADGET is not set
+# CONFIG_INFINIBAND is not set
#
-# MMC/SD Card support
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
-# CONFIG_MMC is not set
#
-# LED devices
+# Real Time Clock
#
-# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
#
-# LED drivers
+# RTC interfaces
#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
#
-# LED Triggers
+# I2C RTC drivers
#
#
-# InfiniBand support
+# SPI RTC drivers
#
-# CONFIG_INFINIBAND is not set
+CONFIG_RTC_DRV_RS5C348=y
+# CONFIG_RTC_DRV_MAX6902 is not set
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+# Platform RTC drivers
#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
#
-# Real Time Clock
+# on-CPU RTC drivers
#
-# CONFIG_RTC_CLASS is not set
#
# DMA Engine support
@@ -1224,38 +705,15 @@ CONFIG_USB_MON=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
+# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
@@ -1265,26 +723,21 @@ CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
#
# CD-ROM/DVD Filesystems
#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
-CONFIG_FAT_FS=y
# CONFIG_MSDOS_FS is not set
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -1298,7 +751,7 @@ CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -1310,16 +763,7 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -1334,19 +778,16 @@ CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -1362,54 +803,12 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
#
# Distributed Lock Manager
#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
#
# Profiling support
@@ -1427,7 +826,6 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
CONFIG_SYS_SUPPORTS_KGDB=y
@@ -1441,62 +839,17 @@ CONFIG_SYS_SUPPORTS_KGDB=y
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
+# CONFIG_LIBCRC32C is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 5593cde9f74c..1a67a85aabbb 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 6c4f09a381e2..98a914092258 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 988b9cdef01f..69c08b24c82a 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
CONFIG_MIPS_SEAD=y
@@ -35,8 +33,6 @@ CONFIG_MIPS_SEAD=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig
index 8b1675c07ec4..5d4fc0e4f729 100644
--- a/arch/mips/configs/tb0219_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index b5be8b74d896..1b92b48de051 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 8bb6be4342b6..5b77c7a5d83a 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 8f019ffcc71b..94a4f94a8b24 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index 52b48c0715d3..e38bd9b0eadc 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_WR_PPMC=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 6824606309e5..f1cdb12f7925 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index 23fd3b81fe1a..4864b8a659c7 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,8 @@
# Makefile for NEC DDB-Vrc5477 board
#
-obj-y += irq.o irq_5477.o setup.o lcd44780.o
+obj-y += ddb5477-platform.o irq.o irq_5477.o setup.o \
+ lcd44780.o
obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
obj-$(CONFIG_KGDB) += kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c b/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c
new file mode 100644
index 000000000000..c16020ad54c2
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c
@@ -0,0 +1,49 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ddb5xxx/ddb5477.h>
+
+#define DDB_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+#define DDB5477_PORT(base, int) \
+{ \
+ .mapbase = base, \
+ .irq = int, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_MEM, \
+ .flags = DDB_UART_FLAGS, \
+ .regshift = 3, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ DDB5477_PORT(0xbfa04200, VRC5477_IRQ_UART0),
+ DDB5477_PORT(0xbfa04240, VRC5477_IRQ_UART1),
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the NEC DDB5477");
diff --git a/arch/mips/dec/prom/console.c b/arch/mips/dec/prom/console.c
index 65419bf32441..078e1a12421d 100644
--- a/arch/mips/dec/prom/console.c
+++ b/arch/mips/dec/prom/console.c
@@ -3,7 +3,7 @@
*
* DECstation PROM-based early console support.
*
- * Copyright (C) 2004 Maciej W. Rozycki
+ * Copyright (C) 2004, 2007 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -13,15 +13,35 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <asm/dec/prom.h>
-void prom_putchar(char c)
+static void __init prom_console_write(struct console *con, const char *s,
+ unsigned int c)
{
- char s[2];
+ char buf[81];
+ unsigned int chunk = sizeof(buf) - 1;
- s[0] = c;
- s[1] = '\0';
+ while (c > 0) {
+ if (chunk > c)
+ chunk = c;
+ memcpy(buf, s, chunk);
+ buf[chunk] = '\0';
+ prom_printf("%s", buf);
+ s += chunk;
+ c -= chunk;
+ }
+}
+
+static struct console promcons __initdata = {
+ .name = "prom",
+ .write = prom_console_write,
+ .flags = CON_BOOT | CON_PRINTBUFFER,
+ .index = -1,
+};
- prom_printf( s);
+void __init register_prom_console(void)
+{
+ register_console(&promcons);
}
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
index a217aafe59f6..808c182fd3fa 100644
--- a/arch/mips/dec/prom/init.c
+++ b/arch/mips/dec/prom/init.c
@@ -86,7 +86,7 @@ void __init which_prom(s32 magic, s32 *prom_vec)
void __init prom_init(void)
{
- extern void ATTRIB_NORET dec_machine_halt(void);
+ extern void dec_machine_halt(void);
static char cpu_msg[] __initdata =
"Sorry, this kernel is compiled for a wrong CPU type!\n";
s32 argc = fw_arg0;
@@ -103,6 +103,9 @@ void __init prom_init(void)
if (prom_is_rex(magic))
rex_clear_cache();
+ /* Register the early console. */
+ register_prom_console();
+
/* Were we compiled with the right CPU option? */
#if defined(CONFIG_CPU_R3000)
if ((current_cpu_data.cputype == CPU_R4000SC) ||
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
index 56397227adb0..c15a879046e5 100644
--- a/arch/mips/dec/reset.c
+++ b/arch/mips/dec/reset.c
@@ -9,26 +9,26 @@
#include <asm/addrspace.h>
-typedef void ATTRIB_NORET (* noret_func_t)(void);
+typedef void __noreturn (* noret_func_t)(void);
-static inline void ATTRIB_NORET back_to_prom(void)
+static inline void __noreturn back_to_prom(void)
{
noret_func_t func = (void *)CKSEG1ADDR(0x1fc00000);
func();
}
-void ATTRIB_NORET dec_machine_restart(char *command)
+void __noreturn dec_machine_restart(char *command)
{
back_to_prom();
}
-void ATTRIB_NORET dec_machine_halt(void)
+void __noreturn dec_machine_halt(void)
{
back_to_prom();
}
-void ATTRIB_NORET dec_machine_power_off(void)
+void __noreturn dec_machine_power_off(void)
{
/* DECstations don't have a software power switch */
back_to_prom();
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 41211f8b7738..b3b6e58058f6 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/gt64120/ev64120/Kconfig b/arch/mips/gt64120/ev64120/Kconfig
deleted file mode 100644
index d691762cb0f7..000000000000
--- a/arch/mips/gt64120/ev64120/Kconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-config EVB_PCI1
- bool "Enable Second PCI (PCI1)"
- depends on MIPS_EV64120
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
deleted file mode 100644
index 323b2cebc691..000000000000
--- a/arch/mips/gt64120/ev64120/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Copyright 2000 RidgeRun, Inc.
-# Author: RidgeRun, Inc.
-# glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
-#
-# Makefile for the Galileo EV64120 board.
-#
-
-obj-y += irq.o promcon.o reset.o serialGT.o setup.o
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
deleted file mode 100644
index 64e4c80b6139..000000000000
--- a/arch/mips/gt64120/ev64120/irq.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Code to handle irqs on GT64120A boards
- * Derived from mips/orion and Cort <cort@fsmlabs.com>
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/gt64120.h>
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-
- if (pending & STATUSF_IP4) /* int2 hardware line (timer) */
- do_IRQ(4);
- else if (pending & STATUSF_IP2) /* int0 hardware line */
- do_IRQ(GT_INTA);
- else if (pending & STATUSF_IP5) /* int3 hardware line */
- do_IRQ(GT_INTD);
- else if (pending & STATUSF_IP6) /* int4 hardware line */
- do_IRQ(6);
- else if (pending & STATUSF_IP7) /* compare int */
- do_IRQ(7);
- else
- spurious_interrupt();
-}
-
-static void disable_ev64120_irq(unsigned int irq_nr)
-{
- if (irq_nr >= 8) { // All PCI interrupts are on line 5 or 2
- clear_c0_status(9 << 10);
- } else {
- clear_c0_status(1 << (irq_nr + 8));
- }
-}
-
-static void enable_ev64120_irq(unsigned int irq_nr)
-{
- if (irq_nr >= 8) // All PCI interrupts are on line 5 or 2
- set_c0_status(9 << 10);
- else
- set_c0_status(1 << (irq_nr + 8));
-}
-
-static void end_ev64120_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_ev64120_irq(irq);
-}
-
-static struct irq_chip ev64120_irq_type = {
- .name = "EV64120",
- .ack = disable_ev64120_irq,
- .mask = disable_ev64120_irq,
- .mask_ack = disable_ev64120_irq,
- .unmask = enable_ev64120_irq,
- .end = end_ev64120_irq,
-};
-
-void gt64120_irq_setup(void)
-{
- /*
- * Clear all of the interrupts while we change the able around a bit.
- */
- clear_c0_status(ST0_IM);
-
- /*
- * Enable timer. Other interrupts will be enabled as they are
- * registered.
- */
- set_c0_status(IE_IRQ2);
-}
-
-void __init arch_init_irq(void)
-{
- gt64120_irq_setup();
-}
diff --git a/arch/mips/gt64120/ev64120/promcon.c b/arch/mips/gt64120/ev64120/promcon.c
deleted file mode 100644
index 6e0ecfed9640..000000000000
--- a/arch/mips/gt64120/ev64120/promcon.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Wrap-around code for a console using the
- * SGI PROM io-routines.
- *
- * Copyright (c) 1999 Ulf Carlsson
- *
- * Derived from DECstation promcon.c
- * Copyright (c) 1998 Harald Koerfgen
- */
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-static void prom_console_write(struct console *co, const char *s,
- unsigned count)
-{
- extern int CONSOLE_CHANNEL; // The default serial port
- unsigned i;
-
- for (i = 0; i < count; i++) {
- if (*s == 10)
- serial_putc(CONSOLE_CHANNEL, 13);
- serial_putc(CONSOLE_CHANNEL, *s++);
- }
-}
-
-static struct console sercons = {
- .name = "ttyS",
- .write = prom_console_write,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/*
- * Register console.
- */
-
-static int gal_serial_console_init(void)
-{
- // serial_init();
- //serial_set(115200);
-
- register_console(&sercons);
-
- return 0;
-}
-
-console_initcall(gal_serial_console_init);
diff --git a/arch/mips/gt64120/ev64120/reset.c b/arch/mips/gt64120/ev64120/reset.c
deleted file mode 100644
index 7b9f5e5bf21f..000000000000
--- a/arch/mips/gt64120/ev64120/reset.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1997 Ralf Baechle
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void galileo_machine_restart(char *command)
-{
- *(volatile char *) 0xbc000000 = 0x0f;
- /*
- * Ouch, we're still alive ... This time we take the silver bullet ...
- * ... and find that we leave the hardware in a state in which the
- * kernel in the flush locks up somewhen during of after the PCI
- * detection stuff.
- */
- set_c0_status(ST0_BEV | ST0_ERL);
- change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
- flush_cache_all();
- write_c0_wired(0);
- __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-}
-
-void galileo_machine_halt(void)
-{
- printk(KERN_NOTICE "You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-
-}
-
-void galileo_machine_power_off(void)
-{
- galileo_machine_halt();
-}
diff --git a/arch/mips/gt64120/ev64120/serialGT.c b/arch/mips/gt64120/ev64120/serialGT.c
deleted file mode 100644
index 8f0d835491ff..000000000000
--- a/arch/mips/gt64120/ev64120/serialGT.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * serialGT.c
- *
- * BRIEF MODULE DESCRIPTION
- * Low Level Serial Port control for use
- * with the Galileo EVB64120A MIPS eval board and
- * its on board two channel 16552 Uart.
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-// Note:
-// Serial CHANNELS - 0 is the bottom connector of evb64120A.
-// (The one that maps to the "B" channel of the
-// board's uart)
-// 1 is the top connector of evb64120A.
-// (The one that maps to the "A" channel of the
-// board's uart)
-int DEBUG_CHANNEL = 0; // See Note Above
-int CONSOLE_CHANNEL = 1; // See Note Above
-
-#define DUART 0xBD000000 /* Base address of Uart. */
-#define CHANNELOFFSET 0x20 /* DUART+CHANNELOFFSET gets you to the ChanA
- register set of the 16552 Uart device.
- DUART+0 gets you to the ChanB register set.
- */
-#define DUART_DELTA 0x4
-#define FIFO_ENABLE 0x07
-#define INT_ENABLE 0x04 /* default interrupt mask */
-
-#define RBR 0x00
-#define THR 0x00
-#define DLL 0x00
-#define IER 0x01
-#define DLM 0x01
-#define IIR 0x02
-#define FCR 0x02
-#define LCR 0x03
-#define MCR 0x04
-#define LSR 0x05
-#define MSR 0x06
-#define SCR 0x07
-
-#define LCR_DLAB 0x80
-#define XTAL 1843200
-#define LSR_THRE 0x20
-#define LSR_BI 0x10
-#define LSR_DR 0x01
-#define MCR_LOOP 0x10
-#define ACCESS_DELAY 0x10000
-
-/******************************
- Routine:
- Description:
- ******************************/
-int inreg(int channel, int reg)
-{
- int val;
- val =
- *((volatile unsigned char *) DUART +
- (channel * CHANNELOFFSET) + (reg * DUART_DELTA));
- return val;
-}
-
-/******************************
- Routine:
- Description:
- ******************************/
-void outreg(int channel, int reg, unsigned char val)
-{
- *((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
- + (reg * DUART_DELTA)) = val;
-}
-
-/******************************
- Routine:
- Description:
- Initialize the device driver.
- ******************************/
-void serial_init(int channel)
-{
- /*
- * Configure active port, (CHANNELOFFSET already set.)
- *
- * Set 8 bits, 1 stop bit, no parity.
- *
- * LCR<7> 0 divisor latch access bit
- * LCR<6> 0 break control (1=send break)
- * LCR<5> 0 stick parity (0=space, 1=mark)
- * LCR<4> 0 parity even (0=odd, 1=even)
- * LCR<3> 0 parity enable (1=enabled)
- * LCR<2> 0 # stop bits (0=1, 1=1.5)
- * LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8)
- */
- outreg(channel, LCR, 0x3);
-
- outreg(channel, FCR, FIFO_ENABLE); /* Enable the FIFO */
-
- outreg(channel, IER, INT_ENABLE); /* Enable appropriate interrupts */
-}
-
-/******************************
- Routine:
- Description:
- Set the baud rate.
- ******************************/
-void serial_set(int channel, unsigned long baud)
-{
- unsigned char sav_lcr;
-
- /*
- * Enable access to the divisor latches by setting DLAB in LCR.
- *
- */
- sav_lcr = inreg(channel, LCR);
-
-#if 0
- /*
- * Set baud rate
- */
- outreg(channel, LCR, LCR_DLAB | sav_lcr);
- // outreg(DLL,(XTAL/(16*2*(baud))-2));
- outreg(channel, DLL, XTAL / (16 * baud));
- // outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
- outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
-#else
- /*
- * Note: Set baud rate, hardcoded here for rate of 115200
- * since became unsure of above "baud rate" algorithm (??).
- */
- outreg(channel, LCR, 0x83);
- outreg(channel, DLM, 0x00); // See note above
- outreg(channel, DLL, 0x02); // See note above.
- outreg(channel, LCR, 0x03);
-#endif
-
- /*
- * Restore line control register
- */
- outreg(channel, LCR, sav_lcr);
-}
-
-
-/******************************
- Routine:
- Description:
- Transmit a character.
- ******************************/
-void serial_putc(int channel, int c)
-{
- while ((inreg(channel, LSR) & LSR_THRE) == 0);
- outreg(channel, THR, c);
-}
-
-/******************************
- Routine:
- Description:
- Read a received character if one is
- available. Return -1 otherwise.
- ******************************/
-int serial_getc(int channel)
-{
- if (inreg(channel, LSR) & LSR_DR) {
- return inreg(channel, RBR);
- }
- return -1;
-}
-
-/******************************
- Routine:
- Description:
- Used by embedded gdb client. (example; gdb-stub.c)
- ******************************/
-char getDebugChar()
-{
- int val;
- while ((val = serial_getc(DEBUG_CHANNEL)) == -1); // loop until we get a character in.
- return (char) val;
-}
-
-/******************************
- Routine:
- Description:
- Used by embedded gdb target. (example; gdb-stub.c)
- ******************************/
-void putDebugChar(char c)
-{
- serial_putc(DEBUG_CHANNEL, (int) c);
-}
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
deleted file mode 100644
index 477848c22a2c..000000000000
--- a/arch/mips/gt64120/ev64120/setup.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/pm.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/time.h>
-#include <asm/reboot.h>
-#include <asm/traps.h>
-#include <linux/bootmem.h>
-
-unsigned long gt64120_base = KSEG1ADDR(0x14000000);
-
-/* These functions are used for rebooting or halting the machine*/
-extern void galileo_machine_restart(char *command);
-extern void galileo_machine_halt(void);
-extern void galileo_machine_power_off(void);
-/*
- *This structure holds pointers to the pci configuration space accesses
- *and interrupts allocating routine for device over the PCI
- */
-extern struct pci_ops galileo_pci_ops;
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-/*
- * Initializes basic routines and structures pointers, memory size (as
- * given by the bios and saves the command line.
- */
-
-void __init plat_mem_setup(void)
-{
- _machine_restart = galileo_machine_restart;
- _machine_halt = galileo_machine_halt;
- pm_power_off = galileo_machine_power_off;
-
- set_io_port_base(KSEG1);
-}
-
-const char *get_system_type(void)
-{
- return "Galileo EV64120A";
-}
-
-/*
- * Kernel arguments passed by the firmware
- *
- * $a0 - nothing
- * $a1 - holds a pointer to the eprom parameters
- * $a2 - nothing
- */
-
-void __init prom_init(void)
-{
- mips_machgroup = MACH_GROUP_GALILEO;
- mips_machtype = MACH_EV64120A;
-
- add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
index 9f9a33fc76b9..1df5fe23c642 100644
--- a/arch/mips/gt64120/momenco_ocelot/Makefile
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -2,6 +2,6 @@
# Makefile for Momentum's Ocelot board.
#
-obj-y += irq.o prom.o reset.o setup.o
+obj-y += irq.o ocelot-platform.o prom.o reset.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c b/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c
new file mode 100644
index 000000000000..81d9031a5a2a
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c
@@ -0,0 +1,46 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * A NS16552 DUART with a 20MHz crystal.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define OCELOT_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+ {
+ .mapbase = 0xe0001020,
+ .irq = 4,
+ .uartclk = 20000000,
+ .iotype = UPIO_MEM,
+ .flags = OCELOT_UART_FLAGS,
+ .regshift = 2,
+ },
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Momenco Ocelot");
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
index 121188d5ec4a..ea965529e5e0 100644
--- a/arch/mips/gt64120/wrppmc/setup.c
+++ b/arch/mips/gt64120/wrppmc/setup.c
@@ -158,8 +158,8 @@ const char *get_system_type(void)
*/
void __init prom_init(void)
{
- mips_machgroup = MACH_GROUP_GALILEO;
- mips_machtype = MACH_EV64120A;
+ mips_machgroup = MACH_GROUP_WINDRIVER;
+ mips_machtype = MACH_WRPPMC;
add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM);
add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA);
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index dd9d99bfcf7a..ae4c402b5004 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -2,4 +2,4 @@
# Makefile for the Jazz family specific parts of the kernel
#
-obj-y := irq.o jazzdma.o reset.o setup.o
+obj-y := irq.o jazzdma.o jazz-platform.o reset.o setup.o
diff --git a/arch/mips/jazz/jazz-platform.c b/arch/mips/jazz/jazz-platform.c
new file mode 100644
index 000000000000..fd736703eef2
--- /dev/null
+++ b/arch/mips/jazz/jazz-platform.c
@@ -0,0 +1,60 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+
+#include <asm/jazz.h>
+
+/*
+ * Confusion ... It seems the original Microsoft Jazz machine used to have a
+ * 4.096MHz clock for its UART while the MIPS Magnum and Millenium systems
+ * had 8MHz. The Olivetti M700-10 and the Acer PICA have 1.8432MHz like PCs.
+ */
+#ifdef CONFIG_OLIVETTI_M700
+#define JAZZ_BASE_BAUD 1843200
+#else
+#define JAZZ_BASE_BAUD 8000000 /* 3072000 */
+#endif
+
+#define JAZZ_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+#define JAZZ_PORT(base, int) \
+{ \
+ .mapbase = base, \
+ .irq = int, \
+ .uartclk = JAZZ_BASE_BAUD, \
+ .iotype = UPIO_MEM, \
+ .flags = JAZZ_UART_FLAGS, \
+ .regshift = 0, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ JAZZ_PORT(JAZZ_SERIAL1_BASE, JAZZ_SERIAL1_IRQ),
+ JAZZ_PORT(JAZZ_SERIAL2_BASE, JAZZ_SERIAL2_IRQ),
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Jazz family");
diff --git a/arch/mips/kernel/8250-platform.c b/arch/mips/kernel/8250-platform.c
new file mode 100644
index 000000000000..cbf3fe20ad17
--- /dev/null
+++ b/arch/mips/kernel/8250-platform.c
@@ -0,0 +1,47 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(base, int) \
+{ \
+ .iobase = base, \
+ .irq = int, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
+ .regshift = 0, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ PORT(0x3F8, 4),
+ PORT(0x2F8, 3),
+ PORT(0x3E8, 4),
+ PORT(0x2E8, 3),
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250 UART probe driver");
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 49246264cc7c..961594cb5214 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -14,14 +14,15 @@ binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
+obj-$(CONFIG_CPU_LOONGSON2) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R8000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o
@@ -29,13 +30,14 @@ obj-$(CONFIG_CPU_RM9000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_NEVADA) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R10000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
+obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_MIPS_MT) += mips-mt.o
+obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o
obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.o
obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
@@ -47,7 +49,6 @@ obj-$(CONFIG_I8259) += i8259.o
obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
obj-$(CONFIG_IRQ_CPU_RM9K) += irq-rm9000.o
-obj-$(CONFIG_IRQ_MV64340) += irq-mv6434x.o
obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.o
obj-$(CONFIG_32BIT) += scall32-o32.o
@@ -68,3 +69,5 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
+
+obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index b12eeee0e974..c6b8b074a81a 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -186,9 +186,29 @@ static inline void check_wait(void)
}
}
+static inline void check_errata(void)
+{
+ struct cpuinfo_mips *c = &current_cpu_data;
+
+ switch (c->cputype) {
+ case CPU_34K:
+ /*
+ * Erratum "RPS May Cause Incorrect Instruction Execution"
+ * This code only handles VPE0, any SMP/SMTC/RTOS code
+ * making use of VPE1 will be responsable for that VPE.
+ */
+ if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2)
+ write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS);
+ break;
+ default:
+ break;
+ }
+}
+
void __init check_bugs32(void)
{
check_wait();
+ check_errata();
}
/*
@@ -485,6 +505,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
MIPS_CPU_LLSC;
c->tlbsize = 64;
break;
+ case PRID_IMP_LOONGSON2:
+ c->cputype = CPU_LOONGSON2;
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS |
+ MIPS_CPU_FPU | MIPS_CPU_LLSC |
+ MIPS_CPU_32FPR;
+ c->tlbsize = 64;
+ break;
}
}
@@ -588,6 +616,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
c->options |= MIPS_CPU_VEIC;
if (config3 & MIPS_CONF3_MT)
c->ases |= MIPS_ASE_MIPSMT;
+ if (config3 & MIPS_CONF3_ULRI)
+ c->options |= MIPS_CPU_ULRI;
return config3 & MIPS_CONF_M;
}
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 6f57ca44291f..f78538eceef7 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/threads.h>
+#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/irqflags.h>
@@ -129,24 +130,25 @@
#endif
.endm
+#ifndef CONFIG_NO_EXCEPT_FILL
/*
* Reserved space for exception handlers.
* Necessary for machines which link their kernels at KSEG0.
*/
.fill 0x400
+#endif
EXPORT(stext) # used for profiling
EXPORT(_stext)
-#ifdef CONFIG_MIPS_SIM
+#ifdef CONFIG_BOOT_RAW
/*
* Give us a fighting chance of running if execution beings at the
* kernel load address. This is needed because this platform does
* not have a ELF loader yet.
*/
- j kernel_entry
-#endif
__INIT
+#endif
NESTED(kernel_entry, 16, sp) # kernel entry point
@@ -197,9 +199,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
j start_kernel
END(kernel_entry)
-#ifdef CONFIG_QEMU
__INIT
-#endif
#ifdef CONFIG_SMP
/*
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
deleted file mode 100644
index 3dd561832e4c..000000000000
--- a/arch/mips/kernel/irq-mv6434x.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/mv643xx.h>
-#include <linux/sched.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/marvell.h>
-
-static unsigned int irq_base;
-
-static inline int ls1bit32(unsigned int x)
-{
- int b = 31, s;
-
- s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
- s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
- s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
- s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
- s = 1; if (x << 1 == 0) s = 0; b -= s;
-
- return b;
-}
-
-/* mask off an interrupt -- 1 is enable, 0 is disable */
-static inline void mask_mv64340_irq(unsigned int irq)
-{
- uint32_t value;
-
- if (irq < (irq_base + 32)) {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- value &= ~(1 << (irq - irq_base));
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
- } else {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- value &= ~(1 << (irq - irq_base - 32));
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
- }
-}
-
-/* unmask an interrupt -- 1 is enable, 0 is disable */
-static inline void unmask_mv64340_irq(unsigned int irq)
-{
- uint32_t value;
-
- if (irq < (irq_base + 32)) {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- value |= 1 << (irq - irq_base);
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
- } else {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- value |= 1 << (irq - irq_base - 32);
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
- }
-}
-
-/*
- * Interrupt handler for interrupts coming from the Marvell chip.
- * It could be built in ethernet ports etc...
- */
-void ll_mv64340_irq(void)
-{
- unsigned int irq_src_low, irq_src_high;
- unsigned int irq_mask_low, irq_mask_high;
-
- /* read the interrupt status registers */
- irq_mask_low = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- irq_mask_high = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- irq_src_low = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW);
- irq_src_high = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH);
-
- /* mask for just the interrupts we want */
- irq_src_low &= irq_mask_low;
- irq_src_high &= irq_mask_high;
-
- if (irq_src_low)
- do_IRQ(ls1bit32(irq_src_low) + irq_base);
- else
- do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
-}
-
-struct irq_chip mv64340_irq_type = {
- .name = "MV-64340",
- .ack = mask_mv64340_irq,
- .mask = mask_mv64340_irq,
- .mask_ack = mask_mv64340_irq,
- .unmask = unmask_mv64340_irq,
-};
-
-void __init mv64340_irq_init(unsigned int base)
-{
- int i;
-
- for (i = base; i < base + 64; i++)
- set_irq_chip_and_handler(i, &mv64340_irq_type,
- handle_level_irq);
-
- irq_base = base;
-}
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
new file mode 100644
index 000000000000..ede5d73d652e
--- /dev/null
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -0,0 +1,176 @@
+/*
+ * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/security.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+
+/*
+ * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
+ */
+cpumask_t mt_fpu_cpumask;
+
+static int fpaff_threshold = -1;
+unsigned long mt_fpemul_threshold = 0;
+
+/*
+ * Replacement functions for the sys_sched_setaffinity() and
+ * sys_sched_getaffinity() system calls, so that we can integrate
+ * FPU affinity with the user's requested processor affinity.
+ * This code is 98% identical with the sys_sched_setaffinity()
+ * and sys_sched_getaffinity() system calls, and should be
+ * updated when kernel/sched.c changes.
+ */
+
+/*
+ * find_process_by_pid - find a process with a matching PID value.
+ * used in sys_sched_set/getaffinity() in kernel/sched.c, so
+ * cloned here.
+ */
+static inline struct task_struct *find_process_by_pid(pid_t pid)
+{
+ return pid ? find_task_by_pid(pid) : current;
+}
+
+
+/*
+ * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+ unsigned long __user *user_mask_ptr)
+{
+ cpumask_t new_mask;
+ cpumask_t effective_mask;
+ int retval;
+ struct task_struct *p;
+
+ if (len < sizeof(new_mask))
+ return -EINVAL;
+
+ if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+ return -EFAULT;
+
+ lock_cpu_hotplug();
+ read_lock(&tasklist_lock);
+
+ p = find_process_by_pid(pid);
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ unlock_cpu_hotplug();
+ return -ESRCH;
+ }
+
+ /*
+ * It is not safe to call set_cpus_allowed with the
+ * tasklist_lock held. We will bump the task_struct's
+ * usage count and drop tasklist_lock before invoking
+ * set_cpus_allowed.
+ */
+ get_task_struct(p);
+
+ retval = -EPERM;
+ if ((current->euid != p->euid) && (current->euid != p->uid) &&
+ !capable(CAP_SYS_NICE)) {
+ read_unlock(&tasklist_lock);
+ goto out_unlock;
+ }
+
+ retval = security_task_setscheduler(p, 0, NULL);
+ if (retval)
+ goto out_unlock;
+
+ /* Record new user-specified CPU set for future reference */
+ p->thread.user_cpus_allowed = new_mask;
+
+ /* Unlock the task list */
+ read_unlock(&tasklist_lock);
+
+ /* Compute new global allowed CPU set if necessary */
+ if ((p->thread.mflags & MF_FPUBOUND)
+ && cpus_intersects(new_mask, mt_fpu_cpumask)) {
+ cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
+ retval = set_cpus_allowed(p, effective_mask);
+ } else {
+ p->thread.mflags &= ~MF_FPUBOUND;
+ retval = set_cpus_allowed(p, new_mask);
+ }
+
+
+out_unlock:
+ put_task_struct(p);
+ unlock_cpu_hotplug();
+ return retval;
+}
+
+/*
+ * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
+ unsigned long __user *user_mask_ptr)
+{
+ unsigned int real_len;
+ cpumask_t mask;
+ int retval;
+ struct task_struct *p;
+
+ real_len = sizeof(mask);
+ if (len < real_len)
+ return -EINVAL;
+
+ lock_cpu_hotplug();
+ read_lock(&tasklist_lock);
+
+ retval = -ESRCH;
+ p = find_process_by_pid(pid);
+ if (!p)
+ goto out_unlock;
+ retval = security_task_getscheduler(p);
+ if (retval)
+ goto out_unlock;
+
+ cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+
+out_unlock:
+ read_unlock(&tasklist_lock);
+ unlock_cpu_hotplug();
+ if (retval)
+ return retval;
+ if (copy_to_user(user_mask_ptr, &mask, real_len))
+ return -EFAULT;
+ return real_len;
+}
+
+
+static int __init fpaff_thresh(char *str)
+{
+ get_option(&str, &fpaff_threshold);
+ return 1;
+}
+__setup("fpaff=", fpaff_thresh);
+
+/*
+ * FPU Use Factor empirically derived from experiments on 34K
+ */
+#define FPUSEFACTOR 333
+
+static __init int mt_fp_affinity_init(void)
+{
+ if (fpaff_threshold >= 0) {
+ mt_fpemul_threshold = fpaff_threshold;
+ } else {
+ mt_fpemul_threshold =
+ (FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
+ }
+ printk(KERN_DEBUG "FPU Affinity set after %ld emulations\n",
+ mt_fpemul_threshold);
+
+ return 0;
+}
+arch_initcall(mt_fp_affinity_init);
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index ba01800b6018..1a7d89231299 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -6,7 +6,6 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/sched.h>
-#include <linux/cpumask.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/security.h>
@@ -23,149 +22,6 @@
#include <asm/cacheflush.h>
/*
- * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
- */
-
-cpumask_t mt_fpu_cpumask;
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-
-#include <linux/cpu.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-
-unsigned long mt_fpemul_threshold = 0;
-
-/*
- * Replacement functions for the sys_sched_setaffinity() and
- * sys_sched_getaffinity() system calls, so that we can integrate
- * FPU affinity with the user's requested processor affinity.
- * This code is 98% identical with the sys_sched_setaffinity()
- * and sys_sched_getaffinity() system calls, and should be
- * updated when kernel/sched.c changes.
- */
-
-/*
- * find_process_by_pid - find a process with a matching PID value.
- * used in sys_sched_set/getaffinity() in kernel/sched.c, so
- * cloned here.
- */
-static inline struct task_struct *find_process_by_pid(pid_t pid)
-{
- return pid ? find_task_by_pid(pid) : current;
-}
-
-
-/*
- * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
- */
-asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
- unsigned long __user *user_mask_ptr)
-{
- cpumask_t new_mask;
- cpumask_t effective_mask;
- int retval;
- struct task_struct *p;
-
- if (len < sizeof(new_mask))
- return -EINVAL;
-
- if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
- return -EFAULT;
-
- lock_cpu_hotplug();
- read_lock(&tasklist_lock);
-
- p = find_process_by_pid(pid);
- if (!p) {
- read_unlock(&tasklist_lock);
- unlock_cpu_hotplug();
- return -ESRCH;
- }
-
- /*
- * It is not safe to call set_cpus_allowed with the
- * tasklist_lock held. We will bump the task_struct's
- * usage count and drop tasklist_lock before invoking
- * set_cpus_allowed.
- */
- get_task_struct(p);
-
- retval = -EPERM;
- if ((current->euid != p->euid) && (current->euid != p->uid) &&
- !capable(CAP_SYS_NICE)) {
- read_unlock(&tasklist_lock);
- goto out_unlock;
- }
-
- retval = security_task_setscheduler(p, 0, NULL);
- if (retval)
- goto out_unlock;
-
- /* Record new user-specified CPU set for future reference */
- p->thread.user_cpus_allowed = new_mask;
-
- /* Unlock the task list */
- read_unlock(&tasklist_lock);
-
- /* Compute new global allowed CPU set if necessary */
- if( (p->thread.mflags & MF_FPUBOUND)
- && cpus_intersects(new_mask, mt_fpu_cpumask)) {
- cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
- retval = set_cpus_allowed(p, effective_mask);
- } else {
- p->thread.mflags &= ~MF_FPUBOUND;
- retval = set_cpus_allowed(p, new_mask);
- }
-
-
-out_unlock:
- put_task_struct(p);
- unlock_cpu_hotplug();
- return retval;
-}
-
-/*
- * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
- */
-asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
- unsigned long __user *user_mask_ptr)
-{
- unsigned int real_len;
- cpumask_t mask;
- int retval;
- struct task_struct *p;
-
- real_len = sizeof(mask);
- if (len < real_len)
- return -EINVAL;
-
- lock_cpu_hotplug();
- read_lock(&tasklist_lock);
-
- retval = -ESRCH;
- p = find_process_by_pid(pid);
- if (!p)
- goto out_unlock;
- retval = security_task_getscheduler(p);
- if (retval)
- goto out_unlock;
-
- cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
-
-out_unlock:
- read_unlock(&tasklist_lock);
- unlock_cpu_hotplug();
- if (retval)
- return retval;
- if (copy_to_user(user_mask_ptr, &mask, real_len))
- return -EFAULT;
- return real_len;
-}
-
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
-/*
* Dump new MIPS MT state for the core. Does not leave TCs halted.
* Takes an argument which taken to be a pre-call MVPControl value.
*/
@@ -195,27 +51,31 @@ void mips_mt_regdump(unsigned long mvpctl)
nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
printk("-- per-VPE State --\n");
- for(i = 0; i < nvpe; i++) {
- for(tc = 0; tc < ntc; tc++) {
+ for (i = 0; i < nvpe; i++) {
+ for (tc = 0; tc < ntc; tc++) {
settc(tc);
- if((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
- printk(" VPE %d\n", i);
- printk(" VPEControl : %08lx\n", read_vpe_c0_vpecontrol());
- printk(" VPEConf0 : %08lx\n", read_vpe_c0_vpeconf0());
- printk(" VPE%d.Status : %08lx\n",
- i, read_vpe_c0_status());
- printk(" VPE%d.EPC : %08lx\n", i, read_vpe_c0_epc());
- printk(" VPE%d.Cause : %08lx\n", i, read_vpe_c0_cause());
- printk(" VPE%d.Config7 : %08lx\n",
- i, read_vpe_c0_config7());
- break; /* Next VPE */
+ if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
+ printk(" VPE %d\n", i);
+ printk(" VPEControl : %08lx\n",
+ read_vpe_c0_vpecontrol());
+ printk(" VPEConf0 : %08lx\n",
+ read_vpe_c0_vpeconf0());
+ printk(" VPE%d.Status : %08lx\n",
+ i, read_vpe_c0_status());
+ printk(" VPE%d.EPC : %08lx\n",
+ i, read_vpe_c0_epc());
+ printk(" VPE%d.Cause : %08lx\n",
+ i, read_vpe_c0_cause());
+ printk(" VPE%d.Config7 : %08lx\n",
+ i, read_vpe_c0_config7());
+ break; /* Next VPE */
+ }
}
- }
}
printk("-- per-TC State --\n");
- for(tc = 0; tc < ntc; tc++) {
+ for (tc = 0; tc < ntc; tc++) {
settc(tc);
- if(read_tc_c0_tcbind() == read_c0_tcbind()) {
+ if (read_tc_c0_tcbind() == read_c0_tcbind()) {
/* Are we dumping ourself? */
haltval = 0; /* Then we're not halted, and mustn't be */
tcstatval = flags; /* And pre-dump TCStatus is flags */
@@ -310,17 +170,6 @@ static int __init ndflush(char *s)
return 1;
}
__setup("ndflush=", ndflush);
-#ifdef CONFIG_MIPS_MT_FPAFF
-static int fpaff_threshold = -1;
-
-static int __init fpaff_thresh(char *str)
-{
- get_option(&str, &fpaff_threshold);
- return 1;
-}
-
-__setup("fpaff=", fpaff_thresh);
-#endif /* CONFIG_MIPS_MT_FPAFF */
static unsigned int itc_base = 0;
@@ -376,20 +225,6 @@ void mips_mt_set_cpuoptions(void)
if (mt_n_dflushes != 1)
printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes);
-#ifdef CONFIG_MIPS_MT_FPAFF
- /* FPU Use Factor empirically derived from experiments on 34K */
-#define FPUSEFACTOR 333
-
- if (fpaff_threshold >= 0) {
- mt_fpemul_threshold = fpaff_threshold;
- } else {
- mt_fpemul_threshold =
- (FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
- }
- printk("FPU Affinity set after %ld emulations\n",
- mt_fpemul_threshold);
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
if (itc_base != 0) {
/*
* Configure ITC mapping. This code is very
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 5ddc2e9deecf..ec04f5a1a5ea 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -14,7 +14,6 @@
#include <asm/cpu-features.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
-#include <asm/watch.h>
unsigned int vced_count, vcei_count;
@@ -84,6 +83,7 @@ static const char *cpu_name[] = {
[CPU_VR4181A] = "NEC VR4181A",
[CPU_SR71000] = "Sandcraft SR71000",
[CPU_PR4450] = "Philips PR4450",
+ [CPU_LOONGSON2] = "ICT Loongson-2",
};
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 6bdfb5a9fa1a..8f4cf27c7157 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -46,7 +46,7 @@
* power and have a low exit latency (ie sit in a loop waiting for somebody to
* say that they'd like to reschedule)
*/
-ATTRIB_NORET void cpu_idle(void)
+void __noreturn cpu_idle(void)
{
/* endless idle loop with no priority at all */
while (1) {
@@ -213,7 +213,7 @@ int dump_task_fpu (struct task_struct *t, elf_fpregset_t *fpr)
/*
* Create a kernel thread
*/
-static ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
+static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
{
do_exit(fn(arg));
}
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 4975da0bfb63..316685fca059 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -20,6 +20,7 @@
#include <linux/highmem.h>
#include <linux/console.h>
#include <linux/pfn.h>
+#include <linux/debugfs.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
@@ -574,3 +575,18 @@ __setup("nodsp", dsp_disable);
unsigned long kernelsp[NR_CPUS];
unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *mips_debugfs_dir;
+static int __init debugfs_mips(void)
+{
+ struct dentry *d;
+
+ d = debugfs_create_dir("mips", NULL);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ mips_debugfs_dir = d;
+ return 0;
+}
+arch_initcall(debugfs_mips);
+#endif
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 67edfa7ed93a..be7362bc2c9a 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -51,18 +51,8 @@ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
EXPORT_SYMBOL(phys_cpu_present_map);
EXPORT_SYMBOL(cpu_online_map);
-/* This happens early in bootup, can't really do it better */
-static void smp_tune_scheduling (void)
-{
- struct cache_desc *cd = &current_cpu_data.scache;
- unsigned long cachesize = cd->linesz * cd->sets * cd->ways;
-
- if (cachesize > max_cache_size)
- max_cache_size = cachesize;
-}
-
extern void __init calibrate_delay(void);
-extern ATTRIB_NORET void cpu_idle(void);
+extern void cpu_idle(void);
/*
* First C code run on the secondary CPUs after being started up by
@@ -228,7 +218,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
{
init_new_context(current, &init_mm);
current_thread_info()->cpu = 0;
- smp_tune_scheduling();
plat_prepare_cpus(max_cpus);
#ifndef CONFIG_HOTPLUG_CPU
cpu_present_map = cpu_possible_map;
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 046b03b1705a..342d873b2ecc 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1104,7 +1104,7 @@ void smtc_idle_loop_hook(void)
mtflags = dmt();
pdb_msg = &id_ho_db_msg[0];
im = read_c0_status();
- vpe = cpu_data[smp_processor_id()].vpe_id;
+ vpe = current_cpu_data.vpe_id;
for (bit = 0; bit < 8; bit++) {
/*
* In current prototype, I/O interrupts
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 9dd5a2df8eac..b947c61c0cc8 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -272,9 +272,8 @@ asmlinkage int sys_set_thread_area(unsigned long addr)
struct thread_info *ti = task_thread_info(current);
ti->tp_value = addr;
-
- /* If some future MIPS implementation has this register in hardware,
- * we will need to update it here (and in context switches). */
+ if (cpu_has_userlocal)
+ write_c0_userlocal(addr);
return 0;
}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 3ea7863c4519..80ea4fa95bd9 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -39,7 +39,6 @@
#include <asm/traps.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
-#include <asm/watch.h>
#include <asm/types.h>
#include <asm/stacktrace.h>
@@ -70,6 +69,7 @@ extern asmlinkage void handle_reserved(void);
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx, int has_fpu);
+void (*board_watchpoint_handler)(struct pt_regs *regs);
void (*board_be_init)(void);
int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
void (*board_nmi_handler_setup)(void);
@@ -311,7 +311,7 @@ void show_registers(struct pt_regs *regs)
static DEFINE_SPINLOCK(die_lock);
-NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
+void __noreturn die(const char * str, struct pt_regs * regs)
{
static int die_counter;
#ifdef CONFIG_MIPS_MT_SMTC
@@ -753,6 +753,33 @@ asmlinkage void do_ri(struct pt_regs *regs)
force_sig(SIGILL, current);
}
+/*
+ * MIPS MT processors may have fewer FPU contexts than CPU threads. If we've
+ * emulated more than some threshold number of instructions, force migration to
+ * a "CPU" that has FP support.
+ */
+static void mt_ase_fp_affinity(void)
+{
+#ifdef CONFIG_MIPS_MT_FPAFF
+ if (mt_fpemul_threshold > 0 &&
+ ((current->thread.emulated_fp++ > mt_fpemul_threshold))) {
+ /*
+ * If there's no FPU present, or if the application has already
+ * restricted the allowed set to exclude any CPUs with FPUs,
+ * we'll skip the procedure.
+ */
+ if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {
+ cpumask_t tmask;
+
+ cpus_and(tmask, current->thread.user_cpus_allowed,
+ mt_fpu_cpumask);
+ set_cpus_allowed(current, tmask);
+ current->thread.mflags |= MF_FPUBOUND;
+ }
+ }
+#endif /* CONFIG_MIPS_MT_FPAFF */
+}
+
asmlinkage void do_cpu(struct pt_regs *regs)
{
unsigned int cpid;
@@ -786,36 +813,8 @@ asmlinkage void do_cpu(struct pt_regs *regs)
&current->thread.fpu, 0);
if (sig)
force_sig(sig, current);
-#ifdef CONFIG_MIPS_MT_FPAFF
- else {
- /*
- * MIPS MT processors may have fewer FPU contexts
- * than CPU threads. If we've emulated more than
- * some threshold number of instructions, force
- * migration to a "CPU" that has FP support.
- */
- if(mt_fpemul_threshold > 0
- && ((current->thread.emulated_fp++
- > mt_fpemul_threshold))) {
- /*
- * If there's no FPU present, or if the
- * application has already restricted
- * the allowed set to exclude any CPUs
- * with FPUs, we'll skip the procedure.
- */
- if (cpus_intersects(current->cpus_allowed,
- mt_fpu_cpumask)) {
- cpumask_t tmask;
-
- cpus_and(tmask,
- current->thread.user_cpus_allowed,
- mt_fpu_cpumask);
- set_cpus_allowed(current, tmask);
- current->thread.mflags |= MF_FPUBOUND;
- }
- }
- }
-#endif /* CONFIG_MIPS_MT_FPAFF */
+ else
+ mt_ase_fp_affinity();
}
return;
@@ -835,6 +834,11 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
asmlinkage void do_watch(struct pt_regs *regs)
{
+ if (board_watchpoint_handler) {
+ (*board_watchpoint_handler)(regs);
+ return;
+ }
+
/*
* We use the watch exception where available to detect stack
* overflows.
@@ -1343,7 +1347,14 @@ void __init per_cpu_trap_init(void)
set_c0_status(ST0_MX);
#ifdef CONFIG_CPU_MIPSR2
- write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
+ if (cpu_has_mips_r2) {
+ unsigned int enable = 0x0000000f;
+
+ if (cpu_has_userlocal)
+ enable |= (1 << 29);
+
+ write_c0_hwrena(enable);
+ }
#endif
#ifdef CONFIG_MIPS_MT_SMTC
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 18c4a3c45a31..8b9c34ffae18 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -77,6 +77,7 @@
#include <linux/signal.h>
#include <linux/smp.h>
#include <linux/sched.h>
+#include <linux/debugfs.h>
#include <asm/asm.h>
#include <asm/branch.h>
#include <asm/byteorder.h>
@@ -87,9 +88,18 @@
#define STR(x) __STR(x)
#define __STR(x) #x
-#ifdef CONFIG_PROC_FS
-unsigned long unaligned_instructions;
+enum {
+ UNALIGNED_ACTION_QUIET,
+ UNALIGNED_ACTION_SIGNAL,
+ UNALIGNED_ACTION_SHOW,
+};
+#ifdef CONFIG_DEBUG_FS
+static u32 unaligned_instructions;
+static u32 unaligned_action;
+#else
+#define unaligned_action UNALIGNED_ACTION_QUIET
#endif
+extern void show_registers(struct pt_regs *regs);
static inline int emulate_load_store_insn(struct pt_regs *regs,
void __user *addr, unsigned int __user *pc,
@@ -459,7 +469,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
goto sigill;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_DEBUG_FS
unaligned_instructions++;
#endif
@@ -516,6 +526,10 @@ asmlinkage void do_ade(struct pt_regs *regs)
pc = (unsigned int __user *) exception_epc(regs);
if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0)
goto sigbus;
+ if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
+ goto sigbus;
+ else if (unaligned_action == UNALIGNED_ACTION_SHOW)
+ show_registers(regs);
/*
* Do branch emulation only if we didn't forward the exception.
@@ -546,3 +560,24 @@ sigbus:
* XXX On return from the signal handler we should advance the epc
*/
}
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_unaligned(void)
+{
+ struct dentry *d;
+
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+ d = debugfs_create_u32("unaligned_instructions", S_IRUGO,
+ mips_debugfs_dir, &unaligned_instructions);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR,
+ mips_debugfs_dir, &unaligned_action);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ return 0;
+}
+__initcall(debugfs_unaligned);
+#endif
diff --git a/arch/mips/lasat/Kconfig b/arch/mips/lasat/Kconfig
deleted file mode 100644
index 1d2ee8a9be13..000000000000
--- a/arch/mips/lasat/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config PICVUE
- tristate "PICVUE LCD display driver"
- depends on LASAT
-
-config PICVUE_PROC
- tristate "PICVUE LCD display driver /proc interface"
- depends on PICVUE
-
-config DS1603
- bool "DS1603 RTC driver"
- depends on LASAT
-
-config LASAT_SYSCTL
- bool "LASAT sysctl interface"
- depends on LASAT
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
deleted file mode 100644
index 99f5046fdf49..000000000000
--- a/arch/mips/lasat/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the LASAT specific kernel interface routines under Linux.
-#
-
-obj-y += reset.o setup.o prom.o lasat_board.o \
- at93c.o interrupt.o
-
-obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o
-obj-$(CONFIG_DS1603) += ds1603.o
-obj-$(CONFIG_PICVUE) += picvue.o
-obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o
-
-clean:
- make -C image clean
diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c
deleted file mode 100644
index ca26e554615e..000000000000
--- a/arch/mips/lasat/at93c.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Atmel AT93C46 serial eeprom driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/lasat/lasat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "at93c.h"
-
-#define AT93C_ADDR_SHIFT 7
-#define AT93C_ADDR_MAX ((1 << AT93C_ADDR_SHIFT) - 1)
-#define AT93C_RCMD (0x6 << AT93C_ADDR_SHIFT)
-#define AT93C_WCMD (0x5 << AT93C_ADDR_SHIFT)
-#define AT93C_WENCMD 0x260
-#define AT93C_WDSCMD 0x200
-
-struct at93c_defs *at93c;
-
-static void at93c_reg_write(u32 val)
-{
- *at93c->reg = val;
-}
-
-static u32 at93c_reg_read(void)
-{
- u32 tmp = *at93c->reg;
- return tmp;
-}
-
-static u32 at93c_datareg_read(void)
-{
- u32 tmp = *at93c->rdata_reg;
- return tmp;
-}
-
-static void at93c_cycle_clk(u32 data)
-{
- at93c_reg_write(data | at93c->clk);
- lasat_ndelay(250);
- at93c_reg_write(data & ~at93c->clk);
- lasat_ndelay(250);
-}
-
-static void at93c_write_databit(u8 bit)
-{
- u32 data = at93c_reg_read();
- if (bit)
- data |= 1 << at93c->wdata_shift;
- else
- data &= ~(1 << at93c->wdata_shift);
-
- at93c_reg_write(data);
- lasat_ndelay(100);
- at93c_cycle_clk(data);
-}
-
-static unsigned int at93c_read_databit(void)
-{
- u32 data;
-
- at93c_cycle_clk(at93c_reg_read());
- data = (at93c_datareg_read() >> at93c->rdata_shift) & 1;
- return data;
-}
-
-static u8 at93c_read_byte(void)
-{
- int i;
- u8 data = 0;
-
- for (i = 0; i<=7; i++) {
- data <<= 1;
- data |= at93c_read_databit();
- }
- return data;
-}
-
-static void at93c_write_bits(u32 data, int size)
-{
- int i;
- int shift = size - 1;
- u32 mask = (1 << shift);
-
- for (i = 0; i < size; i++) {
- at93c_write_databit((data & mask) >> shift);
- data <<= 1;
- }
-}
-
-static void at93c_init_op(void)
-{
- at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift));
- lasat_ndelay(50);
-}
-
-static void at93c_end_op(void)
-{
- at93c_reg_write(at93c_reg_read() & ~at93c->cs);
- lasat_ndelay(250);
-}
-
-static void at93c_wait(void)
-{
- at93c_init_op();
- while (!at93c_read_databit())
- ;
- at93c_end_op();
-};
-
-static void at93c_disable_wp(void)
-{
- at93c_init_op();
- at93c_write_bits(AT93C_WENCMD, 10);
- at93c_end_op();
-}
-
-static void at93c_enable_wp(void)
-{
- at93c_init_op();
- at93c_write_bits(AT93C_WDSCMD, 10);
- at93c_end_op();
-}
-
-u8 at93c_read(u8 addr)
-{
- u8 byte;
- at93c_init_op();
- at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10);
- byte = at93c_read_byte();
- at93c_end_op();
- return byte;
-}
-
-void at93c_write(u8 addr, u8 data)
-{
- at93c_disable_wp();
- at93c_init_op();
- at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10);
- at93c_write_bits(data, 8);
- at93c_end_op();
- at93c_wait();
- at93c_enable_wp();
-}
diff --git a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h
deleted file mode 100644
index cfe2f99b1d44..000000000000
--- a/arch/mips/lasat/at93c.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Atmel AT93C46 serial eeprom driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-
-extern struct at93c_defs {
- volatile u32 *reg;
- volatile u32 *rdata_reg;
- int rdata_shift;
- int wdata_shift;
- u32 cs;
- u32 clk;
-} *at93c;
-
-u8 at93c_read(u8 addr);
-void at93c_write(u8 addr, u8 data);
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
deleted file mode 100644
index 7dced67c55eb..000000000000
--- a/arch/mips/lasat/ds1603.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#include <linux/kernel.h>
-#include <asm/lasat/lasat.h>
-#include <linux/delay.h>
-#include <asm/lasat/ds1603.h>
-#include <asm/time.h>
-
-#include "ds1603.h"
-
-#define READ_TIME_CMD 0x81
-#define SET_TIME_CMD 0x80
-#define TRIMMER_SET_CMD 0xC0
-#define TRIMMER_VALUE_MASK 0x38
-#define TRIMMER_SHIFT 3
-
-struct ds_defs *ds1603 = NULL;
-
-/* HW specific register functions */
-static void rtc_reg_write(unsigned long val)
-{
- *ds1603->reg = val;
-}
-
-static unsigned long rtc_reg_read(void)
-{
- unsigned long tmp = *ds1603->reg;
- return tmp;
-}
-
-static unsigned long rtc_datareg_read(void)
-{
- unsigned long tmp = *ds1603->data_reg;
- return tmp;
-}
-
-static void rtc_nrst_high(void)
-{
- rtc_reg_write(rtc_reg_read() | ds1603->rst);
-}
-
-static void rtc_nrst_low(void)
-{
- rtc_reg_write(rtc_reg_read() & ~ds1603->rst);
-}
-
-static void rtc_cycle_clock(unsigned long data)
-{
- data |= ds1603->clk;
- rtc_reg_write(data);
- lasat_ndelay(250);
- if (ds1603->data_reversed)
- data &= ~ds1603->data;
- else
- data |= ds1603->data;
- data &= ~ds1603->clk;
- rtc_reg_write(data);
- lasat_ndelay(250 + ds1603->huge_delay);
-}
-
-static void rtc_write_databit(unsigned int bit)
-{
- unsigned long data = rtc_reg_read();
- if (ds1603->data_reversed)
- bit = !bit;
- if (bit)
- data |= ds1603->data;
- else
- data &= ~ds1603->data;
-
- rtc_reg_write(data);
- lasat_ndelay(50 + ds1603->huge_delay);
- rtc_cycle_clock(data);
-}
-
-static unsigned int rtc_read_databit(void)
-{
- unsigned int data;
-
- data = (rtc_datareg_read() & (1 << ds1603->data_read_shift))
- >> ds1603->data_read_shift;
- rtc_cycle_clock(rtc_reg_read());
- return data;
-}
-
-static void rtc_write_byte(unsigned int byte)
-{
- int i;
-
- for (i = 0; i<=7; i++) {
- rtc_write_databit(byte & 1L);
- byte >>= 1;
- }
-}
-
-static void rtc_write_word(unsigned long word)
-{
- int i;
-
- for (i = 0; i<=31; i++) {
- rtc_write_databit(word & 1L);
- word >>= 1;
- }
-}
-
-static unsigned long rtc_read_word(void)
-{
- int i;
- unsigned long word = 0;
- unsigned long shift = 0;
-
- for (i = 0; i<=31; i++) {
- word |= rtc_read_databit() << shift;
- shift++;
- }
- return word;
-}
-
-static void rtc_init_op(void)
-{
- rtc_nrst_high();
-
- rtc_reg_write(rtc_reg_read() & ~ds1603->clk);
-
- lasat_ndelay(50);
-}
-
-static void rtc_end_op(void)
-{
- rtc_nrst_low();
- lasat_ndelay(1000);
-}
-
-/* interface */
-unsigned long ds1603_read(void)
-{
- unsigned long word;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- rtc_init_op();
- rtc_write_byte(READ_TIME_CMD);
- word = rtc_read_word();
- rtc_end_op();
- spin_unlock_irqrestore(&rtc_lock, flags);
- return word;
-}
-
-int ds1603_set(unsigned long time)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- rtc_init_op();
- rtc_write_byte(SET_TIME_CMD);
- rtc_write_word(time);
- rtc_end_op();
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return 0;
-}
-
-void ds1603_set_trimmer(unsigned int trimval)
-{
- rtc_init_op();
- rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK)
- | (TRIMMER_SET_CMD));
- rtc_end_op();
-}
-
-void ds1603_disable(void)
-{
- ds1603_set_trimmer(TRIMMER_DISABLE_RTC);
-}
-
-void ds1603_enable(void)
-{
- ds1603_set_trimmer(TRIMMER_DEFAULT);
-}
diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h
deleted file mode 100644
index c2e5c76a379d..000000000000
--- a/arch/mips/lasat/ds1603.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#ifndef __DS1603_H
-#define __DS1603_H
-
-struct ds_defs {
- volatile u32 *reg;
- volatile u32 *data_reg;
- u32 rst;
- u32 clk;
- u32 data;
- u32 data_read_shift;
- char data_reversed;
- u32 huge_delay;
-};
-
-extern struct ds_defs *ds1603;
-
-unsigned long ds1603_read(void);
-int ds1603_set(unsigned long);
-void ds1603_set_trimmer(unsigned int);
-void ds1603_enable(void);
-void ds1603_disable(void);
-void ds1603_init(struct ds_defs *);
-
-#define TRIMMER_DEFAULT 3
-#define TRIMMER_DISABLE_RTC 0
-
-#endif
diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile
deleted file mode 100644
index 35ecd6483ef6..000000000000
--- a/arch/mips/lasat/image/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER
-#
-# i-data Networks
-#
-# Author: Thomas Horsten <thh@i-data.com>
-#
-
-ifndef Version
- Version = "$(USER)-test"
-endif
-
-MKLASATIMG = mklasatimg
-MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200
-KERNEL_IMAGE = $(TOPDIR)/vmlinux
-KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ )
-KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ )
-
-LDSCRIPT= -L$(obj) -Tromscript.normal
-
-HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \
- -D_kernel_entry=0x$(KERNEL_ENTRY) \
- -D VERSION="\"$(Version)\"" \
- -D TIMESTAMP=$(shell date +%s)
-
-$(obj)/head.o: $(obj)/head.S $(KERNEL_IMAGE)
- $(CC) -fno-pic $(HEAD_DEFINES) -I$(TOPDIR)/include -c -o $@ $<
-
-OBJECTS = head.o kImage.o
-
-rom.sw: $(obj)/rom.sw
-
-$(obj)/rom.sw: $(obj)/rom.bin
- $(MKLASATIMG) -o $@ -k $^ -m $(MKLASATIMG_ARCH)
-
-$(obj)/rom.bin: $(obj)/rom
- $(OBJCOPY) -O binary -S $^ $@
-
-# Rule to make the bootloader
-$(obj)/rom: $(addprefix $(obj)/,$(OBJECTS))
- $(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^
-
-$(obj)/%.o: $(obj)/%.gz
- $(LD) -r -o $@ -b binary $<
-
-$(obj)/%.gz: $(obj)/%.bin
- gzip -cf -9 $< > $@
-
-$(obj)/kImage.bin: $(KERNEL_IMAGE)
- $(OBJCOPY) -O binary -S $^ $@
-
-clean:
- rm -f rom rom.bin rom.sw kImage.bin kImage.o
diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S
deleted file mode 100644
index efb95f2609c2..000000000000
--- a/arch/mips/lasat/image/head.S
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <asm/lasat/head.h>
-
- .text
- .section .text.start, "ax"
- .set noreorder
- .set mips3
-
- /* Magic words identifying a software image */
- .word LASAT_K_MAGIC0_VAL
- .word LASAT_K_MAGIC1_VAL
-
- /* Image header version */
- .word 0x00000002
-
- /* image start and size */
- .word _image_start
- .word _image_size
-
- /* start of kernel and entrypoint in uncompressed image */
- .word _kernel_start
- .word _kernel_entry
-
- /* Here we have room for future flags */
-
- .org 0x40
-reldate:
- .word TIMESTAMP
-
- .org 0x50
-release:
- .string VERSION
diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal
deleted file mode 100644
index 988f8ad189cb..000000000000
--- a/arch/mips/lasat/image/romscript.normal
+++ /dev/null
@@ -1,23 +0,0 @@
-OUTPUT_ARCH(mips)
-
-SECTIONS
-{
- .text :
- {
- *(.text.start)
- }
-
- /* Data in ROM */
-
- .data ALIGN(0x10) :
- {
- *(.data)
- }
- _image_start = ADDR(.data);
- _image_size = SIZEOF(.data);
-
- .other :
- {
- *(.*)
- }
-}
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
deleted file mode 100644
index 9a622b9a1051..000000000000
--- a/arch/mips/lasat/interrupt.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines for generic manipulation of the interrupts found on the
- * Lasat boards.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/lasat/lasatint.h>
-#include <asm/time.h>
-#include <asm/gdb-stub.h>
-
-static volatile int *lasat_int_status = NULL;
-static volatile int *lasat_int_mask = NULL;
-static volatile int lasat_int_mask_shift;
-
-void disable_lasat_irq(unsigned int irq_nr)
-{
- *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
-}
-
-void enable_lasat_irq(unsigned int irq_nr)
-{
- *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
-}
-
-static struct irq_chip lasat_irq_type = {
- .name = "Lasat",
- .ack = disable_lasat_irq,
- .mask = disable_lasat_irq,
- .mask_ack = disable_lasat_irq,
- .unmask = enable_lasat_irq,
-};
-
-static inline int ls1bit32(unsigned int x)
-{
- int b = 31, s;
-
- s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
- s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
- s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
- s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
- s = 1; if (x << 1 == 0) s = 0; b -= s;
-
- return b;
-}
-
-static unsigned long (* get_int_status)(void);
-
-static unsigned long get_int_status_100(void)
-{
- return *lasat_int_status & *lasat_int_mask;
-}
-
-static unsigned long get_int_status_200(void)
-{
- unsigned long int_status;
-
- int_status = *lasat_int_status;
- int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff;
- return int_status;
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned long int_status;
- unsigned int cause = read_c0_cause();
- int irq;
-
- if (cause & CAUSEF_IP7) { /* R4000 count / compare IRQ */
- ll_timer_interrupt(7);
- return;
- }
-
- int_status = get_int_status();
-
- /* if int_status == 0, then the interrupt has already been cleared */
- if (int_status) {
- irq = ls1bit32(int_status);
-
- do_IRQ(irq);
- }
-}
-
-void __init arch_init_irq(void)
-{
- int i;
-
- switch (mips_machtype) {
- case MACH_LASAT_100:
- lasat_int_status = (void *)LASAT_INT_STATUS_REG_100;
- lasat_int_mask = (void *)LASAT_INT_MASK_REG_100;
- lasat_int_mask_shift = LASATINT_MASK_SHIFT_100;
- get_int_status = get_int_status_100;
- *lasat_int_mask = 0;
- break;
- case MACH_LASAT_200:
- lasat_int_status = (void *)LASAT_INT_STATUS_REG_200;
- lasat_int_mask = (void *)LASAT_INT_MASK_REG_200;
- lasat_int_mask_shift = LASATINT_MASK_SHIFT_200;
- get_int_status = get_int_status_200;
- *lasat_int_mask &= 0xffff;
- break;
- default:
- panic("arch_init_irq: mips_machtype incorrect");
- }
-
- for (i = 0; i <= LASATINT_END; i++)
- set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c
deleted file mode 100644
index fbe9a87bd0ad..000000000000
--- a/arch/mips/lasat/lasat_board.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines specific to the LASAT boards
- */
-#include <linux/types.h>
-#include <linux/crc32.h>
-#include <asm/lasat/lasat.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <asm/bootinfo.h>
-#include <asm/addrspace.h>
-#include "at93c.h"
-/* New model description table */
-#include "lasat_models.h"
-
-#define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len))
-
-struct lasat_info lasat_board_info;
-
-void update_bcastaddr(void);
-
-int EEPROMRead(unsigned int pos, unsigned char *data, int len)
-{
- int i;
-
- for (i=0; i<len; i++)
- *data++ = at93c_read(pos++);
-
- return 0;
-}
-int EEPROMWrite(unsigned int pos, unsigned char *data, int len)
-{
- int i;
-
- for (i=0; i<len; i++)
- at93c_write(pos++, *data++);
-
- return 0;
-}
-
-static void init_flash_sizes(void)
-{
- int i;
- unsigned long *lb = lasat_board_info.li_flashpart_base;
- unsigned long *ls = lasat_board_info.li_flashpart_size;
-
- ls[LASAT_MTD_BOOTLOADER] = 0x40000;
- ls[LASAT_MTD_SERVICE] = 0xC0000;
- ls[LASAT_MTD_NORMAL] = 0x100000;
-
- if (mips_machtype == MACH_LASAT_100) {
- lasat_board_info.li_flash_base = 0x1e000000;
-
- lb[LASAT_MTD_BOOTLOADER] = 0x1e400000;
-
- if (lasat_board_info.li_flash_size > 0x200000) {
- ls[LASAT_MTD_CONFIG] = 0x100000;
- ls[LASAT_MTD_FS] = 0x500000;
- }
- } else {
- lasat_board_info.li_flash_base = 0x10000000;
-
- if (lasat_board_info.li_flash_size < 0x1000000) {
- lb[LASAT_MTD_BOOTLOADER] = 0x10000000;
- ls[LASAT_MTD_CONFIG] = 0x100000;
- if (lasat_board_info.li_flash_size >= 0x400000) {
- ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000;
- }
- }
- }
-
- for (i = 1; i < LASAT_MTD_LAST; i++)
- lb[i] = lb[i-1] + ls[i-1];
-}
-
-int lasat_init_board_info(void)
-{
- int c;
- unsigned long crc;
- unsigned long cfg0, cfg1;
- const product_info_t *ppi;
- int i_n_base_models = N_BASE_MODELS;
- const char * const * i_txt_base_models = txt_base_models;
- int i_n_prids = N_PRIDS;
-
- memset(&lasat_board_info, 0, sizeof(lasat_board_info));
-
- /* First read the EEPROM info */
- EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
- sizeof(struct lasat_eeprom_struct));
-
- /* Check the CRC */
- crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
- sizeof(struct lasat_eeprom_struct) - 4);
-
- if (crc != lasat_board_info.li_eeprom_info.crc32) {
- printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM CRC does "
- "not match calculated, attempting to soldier on...\n");
- }
-
- if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) {
- printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM version "
- "%d, wanted version %d, attempting to soldier on...\n",
- (unsigned int)lasat_board_info.li_eeprom_info.version,
- LASAT_EEPROM_VERSION);
- }
-
- cfg0 = lasat_board_info.li_eeprom_info.cfg[0];
- cfg1 = lasat_board_info.li_eeprom_info.cfg[1];
-
- if ( LASAT_W0_DSCTYPE(cfg0) != 1) {
- printk(KERN_WARNING "WARNING...\nWARNING...\n"
- "Invalid configuration read from EEPROM, attempting to "
- "soldier on...");
- }
- /* We have a valid configuration */
-
- switch (LASAT_W0_SDRAMBANKSZ(cfg0)) {
- case 0:
- lasat_board_info.li_memsize = 0x0800000;
- break;
- case 1:
- lasat_board_info.li_memsize = 0x1000000;
- break;
- case 2:
- lasat_board_info.li_memsize = 0x2000000;
- break;
- case 3:
- lasat_board_info.li_memsize = 0x4000000;
- break;
- case 4:
- lasat_board_info.li_memsize = 0x8000000;
- break;
- default:
- lasat_board_info.li_memsize = 0;
- }
-
- switch (LASAT_W0_SDRAMBANKS(cfg0)) {
- case 0:
- break;
- case 1:
- lasat_board_info.li_memsize *= 2;
- break;
- default:
- break;
- }
-
- switch (LASAT_W0_BUSSPEED(cfg0)) {
- case 0x0:
- lasat_board_info.li_bus_hz = 60000000;
- break;
- case 0x1:
- lasat_board_info.li_bus_hz = 66000000;
- break;
- case 0x2:
- lasat_board_info.li_bus_hz = 66666667;
- break;
- case 0x3:
- lasat_board_info.li_bus_hz = 80000000;
- break;
- case 0x4:
- lasat_board_info.li_bus_hz = 83333333;
- break;
- case 0x5:
- lasat_board_info.li_bus_hz = 100000000;
- break;
- }
-
- switch (LASAT_W0_CPUCLK(cfg0)) {
- case 0x0:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz;
- break;
- case 0x1:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz +
- (lasat_board_info.li_bus_hz >> 1);
- break;
- case 0x2:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz +
- lasat_board_info.li_bus_hz;
- break;
- case 0x3:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz +
- lasat_board_info.li_bus_hz +
- (lasat_board_info.li_bus_hz >> 1);
- break;
- case 0x4:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz +
- lasat_board_info.li_bus_hz +
- lasat_board_info.li_bus_hz;
- break;
- }
-
- /* Flash size */
- switch (LASAT_W1_FLASHSIZE(cfg1)) {
- case 0:
- lasat_board_info.li_flash_size = 0x200000;
- break;
- case 1:
- lasat_board_info.li_flash_size = 0x400000;
- break;
- case 2:
- lasat_board_info.li_flash_size = 0x800000;
- break;
- case 3:
- lasat_board_info.li_flash_size = 0x1000000;
- break;
- case 4:
- lasat_board_info.li_flash_size = 0x2000000;
- break;
- }
-
- init_flash_sizes();
-
- lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0);
- lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid;
- if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0)
- lasat_board_info.li_prid = lasat_board_info.li_bmid;
-
- /* Base model stuff */
- if (lasat_board_info.li_bmid > i_n_base_models)
- lasat_board_info.li_bmid = i_n_base_models;
- strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]);
-
- /* Product ID dependent values */
- c = lasat_board_info.li_prid;
- if (c >= i_n_prids) {
- strcpy(lasat_board_info.li_namestr, "Unknown Model");
- strcpy(lasat_board_info.li_typestr, "Unknown Type");
- } else {
- ppi = &vendor_info_table[0].vi_product_info[c];
- strcpy(lasat_board_info.li_namestr, ppi->pi_name);
- if (ppi->pi_type)
- strcpy(lasat_board_info.li_typestr, ppi->pi_type);
- else
- sprintf(lasat_board_info.li_typestr, "%d",10*c);
- }
-
-#if defined(CONFIG_INET) && defined(CONFIG_SYSCTL)
- update_bcastaddr();
-#endif
-
- return 0;
-}
-
-void lasat_write_eeprom_info(void)
-{
- unsigned long crc;
-
- /* Generate the CRC */
- crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
- sizeof(struct lasat_eeprom_struct) - 4);
- lasat_board_info.li_eeprom_info.crc32 = crc;
-
- /* Write the EEPROM info */
- EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
- sizeof(struct lasat_eeprom_struct));
-}
-
diff --git a/arch/mips/lasat/lasat_models.h b/arch/mips/lasat/lasat_models.h
deleted file mode 100644
index ae0c5d0bd403..000000000000
--- a/arch/mips/lasat/lasat_models.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Model description tables
- */
-
-typedef struct product_info_t {
- const char *pi_name;
- const char *pi_type;
-} product_info_t;
-
-typedef struct vendor_info_t {
- const char *vi_name;
- const product_info_t *vi_product_info;
-} vendor_info_t;
-
-/*
- * Base models
- */
-static const char * const txt_base_models[] = {
- "MQ 2", "MQ Pro", "SP 25", "SP 50", "SP 100", "SP 5000", "SP 7000", "SP 1000", "Unknown"
-};
-#define N_BASE_MODELS (sizeof(txt_base_models)/sizeof(char*)-1)
-
-/*
- * Eicon Networks
- */
-static const char txt_en_mq[] = "Masquerade";
-static const char txt_en_sp[] = "Safepipe";
-
-static const product_info_t product_info_eicon[] = {
- { txt_en_mq, "II" }, /* 0 */
- { txt_en_mq, "Pro" }, /* 1 */
- { txt_en_sp, "25" }, /* 2 */
- { txt_en_sp, "50" }, /* 3 */
- { txt_en_sp, "100" }, /* 4 */
- { txt_en_sp, "5000" }, /* 5 */
- { txt_en_sp, "7000" }, /* 6 */
- { txt_en_sp, "30" }, /* 7 */
- { txt_en_sp, "5100" }, /* 8 */
- { txt_en_sp, "7100" }, /* 9 */
- { txt_en_sp, "1110" }, /* 10 */
- { txt_en_sp, "3020" }, /* 11 */
- { txt_en_sp, "3030" }, /* 12 */
- { txt_en_sp, "5020" }, /* 13 */
- { txt_en_sp, "5030" }, /* 14 */
- { txt_en_sp, "1120" }, /* 15 */
- { txt_en_sp, "1130" }, /* 16 */
- { txt_en_sp, "6010" }, /* 17 */
- { txt_en_sp, "6110" }, /* 18 */
- { txt_en_sp, "6210" }, /* 19 */
- { txt_en_sp, "1020" }, /* 20 */
- { txt_en_sp, "1040" }, /* 21 */
- { txt_en_sp, "1050" }, /* 22 */
- { txt_en_sp, "1060" }, /* 23 */
-};
-#define N_PRIDS (sizeof(product_info_eicon)/sizeof(product_info_t))
-
-/*
- * The vendor table
- */
-static vendor_info_t const vendor_info_table[] = {
- { "Eicon Networks", product_info_eicon },
-};
-#define N_VENDORS (sizeof(vendor_info_table)/sizeof(vendor_info_t))
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c
deleted file mode 100644
index 9ae82c3ffb07..000000000000
--- a/arch/mips/lasat/picvue.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/bootinfo.h>
-#include <asm/lasat/lasat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include "picvue.h"
-
-#define PVC_BUSY 0x80
-#define PVC_NLINES 2
-#define PVC_DISPMEM 80
-#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES
-
-struct pvc_defs *picvue = NULL;
-
-DECLARE_MUTEX(pvc_sem);
-
-static void pvc_reg_write(u32 val)
-{
- *picvue->reg = val;
-}
-
-static u32 pvc_reg_read(void)
-{
- u32 tmp = *picvue->reg;
- return tmp;
-}
-
-static void pvc_write_byte(u32 data, u8 byte)
-{
- data |= picvue->e;
- pvc_reg_write(data);
- data &= ~picvue->data_mask;
- data |= byte << picvue->data_shift;
- pvc_reg_write(data);
- ndelay(220);
- pvc_reg_write(data & ~picvue->e);
- ndelay(220);
-}
-
-static u8 pvc_read_byte(u32 data)
-{
- u8 byte;
-
- data |= picvue->e;
- pvc_reg_write(data);
- ndelay(220);
- byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift;
- data &= ~picvue->e;
- pvc_reg_write(data);
- ndelay(220);
- return byte;
-}
-
-static u8 pvc_read_data(void)
-{
- u32 data = pvc_reg_read();
- u8 byte;
- data |= picvue->rw;
- data &= ~picvue->rs;
- pvc_reg_write(data);
- ndelay(40);
- byte = pvc_read_byte(data);
- data |= picvue->rs;
- pvc_reg_write(data);
- return byte;
-}
-
-#define TIMEOUT 1000
-static int pvc_wait(void)
-{
- int i = TIMEOUT;
- int err = 0;
-
- while ((pvc_read_data() & PVC_BUSY) && i)
- i--;
- if (i == 0)
- err = -ETIME;
-
- return err;
-}
-
-#define MODE_INST 0
-#define MODE_DATA 1
-static void pvc_write(u8 byte, int mode)
-{
- u32 data = pvc_reg_read();
- data &= ~picvue->rw;
- if (mode == MODE_DATA)
- data |= picvue->rs;
- else
- data &= ~picvue->rs;
- pvc_reg_write(data);
- ndelay(40);
- pvc_write_byte(data, byte);
- if (mode == MODE_DATA)
- data &= ~picvue->rs;
- else
- data |= picvue->rs;
- pvc_reg_write(data);
- pvc_wait();
-}
-
-void pvc_write_string(const unsigned char *str, u8 addr, int line)
-{
- int i = 0;
-
- if (line > 0 && (PVC_NLINES > 1))
- addr += 0x40 * line;
- pvc_write(0x80 | addr, MODE_INST);
-
- while (*str != 0 && i < PVC_LINELEN) {
- pvc_write(*str++, MODE_DATA);
- i++;
- }
-}
-
-void pvc_write_string_centered(const unsigned char *str, int line)
-{
- int len = strlen(str);
- u8 addr;
-
- if (len > PVC_VISIBLE_CHARS)
- addr = 0;
- else
- addr = (PVC_VISIBLE_CHARS - strlen(str))/2;
-
- pvc_write_string(str, addr, line);
-}
-
-void pvc_dump_string(const unsigned char *str)
-{
- int len = strlen(str);
-
- pvc_write_string(str, 0, 0);
- if (len > PVC_VISIBLE_CHARS)
- pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1);
-}
-
-#define BM_SIZE 8
-#define MAX_PROGRAMMABLE_CHARS 8
-int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE])
-{
- int i;
- int addr;
-
- if (charnum > MAX_PROGRAMMABLE_CHARS)
- return -ENOENT;
-
- addr = charnum * 8;
- pvc_write(0x40 | addr, MODE_INST);
-
- for (i=0; i<BM_SIZE; i++)
- pvc_write(bitmap[i], MODE_DATA);
- return 0;
-}
-
-#define FUNC_SET_CMD 0x20
-#define EIGHT_BYTE (1 << 4)
-#define FOUR_BYTE 0
-#define TWO_LINES (1 << 3)
-#define ONE_LINE 0
-#define LARGE_FONT (1 << 2)
-#define SMALL_FONT 0
-static void pvc_funcset(u8 cmd)
-{
- pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)), MODE_INST);
-}
-
-#define ENTRYMODE_CMD 0x4
-#define AUTO_INC (1 << 1)
-#define AUTO_DEC 0
-#define CURSOR_FOLLOWS_DISP (1 << 0)
-static void pvc_entrymode(u8 cmd)
-{
- pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)), MODE_INST);
-}
-
-#define DISP_CNT_CMD 0x08
-#define DISP_OFF 0
-#define DISP_ON (1 << 2)
-#define CUR_ON (1 << 1)
-#define CUR_BLINK (1 << 0)
-void pvc_dispcnt(u8 cmd)
-{
- pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST);
-}
-
-#define MOVE_CMD 0x10
-#define DISPLAY (1 << 3)
-#define CURSOR 0
-#define RIGHT (1 << 2)
-#define LEFT 0
-void pvc_move(u8 cmd)
-{
- pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST);
-}
-
-#define CLEAR_CMD 0x1
-void pvc_clear(void)
-{
- pvc_write(CLEAR_CMD, MODE_INST);
-}
-
-#define HOME_CMD 0x2
-void pvc_home(void)
-{
- pvc_write(HOME_CMD, MODE_INST);
-}
-
-int pvc_init(void)
-{
- u8 cmd = EIGHT_BYTE;
-
- if (PVC_NLINES == 2)
- cmd |= (SMALL_FONT|TWO_LINES);
- else
- cmd |= (LARGE_FONT|ONE_LINE);
- pvc_funcset(cmd);
- pvc_dispcnt(DISP_ON);
- pvc_entrymode(AUTO_INC);
-
- pvc_clear();
- pvc_write_string_centered("Display", 0);
- pvc_write_string_centered("Initialized", 1);
-
- return 0;
-}
-
-module_init(pvc_init);
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/picvue.h b/arch/mips/lasat/picvue.h
deleted file mode 100644
index 2a96bf971897..000000000000
--- a/arch/mips/lasat/picvue.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <asm/semaphore.h>
-
-struct pvc_defs {
- volatile u32 *reg;
- u32 data_shift;
- u32 data_mask;
- u32 e;
- u32 rw;
- u32 rs;
-};
-
-extern struct pvc_defs *picvue;
-
-#define PVC_NLINES 2
-#define PVC_DISPMEM 80
-#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES
-#define PVC_VISIBLE_CHARS 16
-
-void pvc_write_string(const unsigned char *str, u8 addr, int line);
-void pvc_write_string_centered(const unsigned char *str, int line);
-void pvc_dump_string(const unsigned char *str);
-
-#define BM_SIZE 8
-#define MAX_PROGRAMMABLE_CHARS 8
-int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]);
-
-void pvc_dispcnt(u8 cmd);
-#define DISP_OFF 0
-#define DISP_ON (1 << 2)
-#define CUR_ON (1 << 1)
-#define CUR_BLINK (1 << 0)
-
-void pvc_move(u8 cmd);
-#define DISPLAY (1 << 3)
-#define CURSOR 0
-#define RIGHT (1 << 2)
-#define LEFT 0
-
-void pvc_clear(void);
-void pvc_home(void);
-
-extern struct semaphore pvc_sem;
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
deleted file mode 100644
index cce7cddcdb08..000000000000
--- a/arch/mips/lasat/picvue_proc.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-
-#include <linux/timer.h>
-
-#include "picvue.h"
-
-static char pvc_lines[PVC_NLINES][PVC_LINELEN+1];
-static int pvc_linedata[PVC_NLINES];
-static struct proc_dir_entry *pvc_display_dir;
-static char *pvc_linename[PVC_NLINES] = {"line1", "line2"};
-#define DISPLAY_DIR_NAME "display"
-static int scroll_dir = 0, scroll_interval = 0;
-
-static struct timer_list timer;
-
-static void pvc_display(unsigned long data) {
- int i;
-
- pvc_clear();
- for (i=0; i<PVC_NLINES; i++)
- pvc_write_string(pvc_lines[i], 0, i);
-}
-
-static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
-
-static int pvc_proc_read_line(char *page, char **start,
- off_t off, int count,
- int *eof, void *data)
-{
- char *origpage = page;
- int lineno = *(int *)data;
-
- if (lineno < 0 || lineno > PVC_NLINES) {
- printk("proc_read_line: invalid lineno %d\n", lineno);
- return 0;
- }
-
- down(&pvc_sem);
- page += sprintf(page, "%s\n", pvc_lines[lineno]);
- up(&pvc_sem);
-
- return page - origpage;
-}
-
-static int pvc_proc_write_line(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- int origcount = count;
- int lineno = *(int *)data;
-
- if (lineno < 0 || lineno > PVC_NLINES) {
- printk("proc_write_line: invalid lineno %d\n", lineno);
- return origcount;
- }
-
- if (count > PVC_LINELEN)
- count = PVC_LINELEN;
-
- if (buffer[count-1] == '\n')
- count--;
-
- down(&pvc_sem);
- strncpy(pvc_lines[lineno], buffer, count);
- pvc_lines[lineno][count] = '\0';
- up(&pvc_sem);
-
- tasklet_schedule(&pvc_display_tasklet);
-
- return origcount;
-}
-
-static int pvc_proc_write_scroll(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- int origcount = count;
- int cmd = simple_strtol(buffer, NULL, 10);
-
- down(&pvc_sem);
- if (scroll_interval != 0)
- del_timer(&timer);
-
- if (cmd == 0) {
- scroll_dir = 0;
- scroll_interval = 0;
- } else {
- if (cmd < 0) {
- scroll_dir = -1;
- scroll_interval = -cmd;
- } else {
- scroll_dir = 1;
- scroll_interval = cmd;
- }
- add_timer(&timer);
- }
- up(&pvc_sem);
-
- return origcount;
-}
-
-static int pvc_proc_read_scroll(char *page, char **start,
- off_t off, int count,
- int *eof, void *data)
-{
- char *origpage = page;
-
- down(&pvc_sem);
- page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
- up(&pvc_sem);
-
- return page - origpage;
-}
-
-
-void pvc_proc_timerfunc(unsigned long data)
-{
- if (scroll_dir < 0)
- pvc_move(DISPLAY|RIGHT);
- else if (scroll_dir > 0)
- pvc_move(DISPLAY|LEFT);
-
- timer.expires = jiffies + scroll_interval;
- add_timer(&timer);
-}
-
-static void pvc_proc_cleanup(void)
-{
- int i;
- for (i=0; i<PVC_NLINES; i++)
- remove_proc_entry(pvc_linename[i], pvc_display_dir);
- remove_proc_entry("scroll", pvc_display_dir);
- remove_proc_entry(DISPLAY_DIR_NAME, NULL);
-
- del_timer(&timer);
-}
-
-static int __init pvc_proc_init(void)
-{
- struct proc_dir_entry *proc_entry;
- int i;
-
- pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL);
- if (pvc_display_dir == NULL)
- goto error;
-
- for (i=0; i<PVC_NLINES; i++) {
- strcpy(pvc_lines[i], "");
- pvc_linedata[i] = i;
- }
- for (i=0; i<PVC_NLINES; i++) {
- proc_entry = create_proc_entry(pvc_linename[i], 0644, pvc_display_dir);
- if (proc_entry == NULL)
- goto error;
- proc_entry->read_proc = pvc_proc_read_line;
- proc_entry->write_proc = pvc_proc_write_line;
- proc_entry->data = &pvc_linedata[i];
- }
- proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir);
- if (proc_entry == NULL)
- goto error;
- proc_entry->write_proc = pvc_proc_write_scroll;
- proc_entry->read_proc = pvc_proc_read_scroll;
-
- init_timer(&timer);
- timer.function = pvc_proc_timerfunc;
-
- return 0;
-error:
- pvc_proc_cleanup();
- return -ENOMEM;
-}
-
-module_init(pvc_proc_init);
-module_exit(pvc_proc_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
deleted file mode 100644
index 812c6ac366be..000000000000
--- a/arch/mips/lasat/prom.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * PROM interface routines.
- */
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/ioport.h>
-#include <asm/bootinfo.h>
-#include <asm/lasat/lasat.h>
-#include <asm/cpu.h>
-
-#include "at93c.h"
-#include <asm/lasat/eeprom.h>
-#include "prom.h"
-
-#define RESET_VECTOR 0xbfc00000
-#define PROM_JUMP_TABLE_ENTRY(n) (*((u32 *)(RESET_VECTOR + 0x20) + n))
-#define PROM_DISPLAY_ADDR PROM_JUMP_TABLE_ENTRY(0)
-#define PROM_PUTC_ADDR PROM_JUMP_TABLE_ENTRY(1)
-#define PROM_MONITOR_ADDR PROM_JUMP_TABLE_ENTRY(2)
-
-static void null_prom_display(const char *string, int pos, int clear)
-{
-}
-
-static void null_prom_monitor(void)
-{
-}
-
-static void null_prom_putc(char c)
-{
-}
-
-/* these are functions provided by the bootloader */
-static void (* __prom_putc)(char c) = null_prom_putc;
-
-void prom_putchar(char c)
-{
- __prom_putc(c);
-}
-
-void (* prom_display)(const char *string, int pos, int clear) =
- null_prom_display;
-void (* prom_monitor)(void) = null_prom_monitor;
-
-unsigned int lasat_ndelay_divider;
-
-static void setup_prom_vectors(void)
-{
- u32 version = *(u32 *)(RESET_VECTOR + 0x90);
-
- if (version >= 307) {
- prom_display = (void *)PROM_DISPLAY_ADDR;
- __prom_putc = (void *)PROM_PUTC_ADDR;
- prom_monitor = (void *)PROM_MONITOR_ADDR;
- }
- printk("prom vectors set up\n");
-}
-
-static struct at93c_defs at93c_defs[N_MACHTYPES] = {
- {(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100,
- AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100},
- {(void *)AT93C_REG_200, (void *)AT93C_RDATA_REG_200, AT93C_RDATA_SHIFT_200,
- AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200},
-};
-
-void __init prom_init(void)
-{
- int argc = fw_arg0;
- char **argv = (char **) fw_arg1;
-
- setup_prom_vectors();
-
- if (current_cpu_data.cputype == CPU_R5000) {
- printk("LASAT 200 board\n");
- mips_machtype = MACH_LASAT_200;
- lasat_ndelay_divider = LASAT_200_DIVIDER;
- } else {
- printk("LASAT 100 board\n");
- mips_machtype = MACH_LASAT_100;
- lasat_ndelay_divider = LASAT_100_DIVIDER;
- }
-
- at93c = &at93c_defs[mips_machtype];
-
- lasat_init_board_info(); /* Read info from EEPROM */
-
- mips_machgroup = MACH_GROUP_LASAT;
-
- /* Get the command line */
- if (argc > 0) {
- strncpy(arcs_cmdline, argv[0], CL_SIZE-1);
- arcs_cmdline[CL_SIZE-1] = '\0';
- }
-
- /* Set the I/O base address */
- set_io_port_base(KSEG1);
-
- /* Set memory regions */
- ioport_resource.start = 0;
- ioport_resource.end = 0xffffffff; /* Wrong, fixme. */
-
- add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM);
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-const char *get_system_type(void)
-{
- return lasat_board_info.li_bmstr;
-}
diff --git a/arch/mips/lasat/prom.h b/arch/mips/lasat/prom.h
deleted file mode 100644
index 019d45fbd268..000000000000
--- a/arch/mips/lasat/prom.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef PROM_H
-#define PROM_H
-extern void (* prom_display)(const char *string, int pos, int clear);
-extern void (* prom_monitor)(void);
-#endif
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c
deleted file mode 100644
index 9e22acf03083..000000000000
--- a/arch/mips/lasat/reset.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Reset the LASAT board.
- */
-#include <linux/kernel.h>
-#include <linux/pm.h>
-
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/lasat/lasat.h>
-
-#include "picvue.h"
-#include "prom.h"
-
-static void lasat_machine_restart(char *command);
-static void lasat_machine_halt(void);
-
-/* Used to set machine to boot in service mode via /proc interface */
-int lasat_boot_to_service = 0;
-
-static void lasat_machine_restart(char *command)
-{
- local_irq_disable();
-
- if (lasat_boot_to_service) {
- printk("machine_restart: Rebooting to service mode\n");
- *(volatile unsigned int *)0xa0000024 = 0xdeadbeef;
- *(volatile unsigned int *)0xa00000fc = 0xfedeabba;
- }
- *lasat_misc->reset_reg = 0xbedead;
- for (;;) ;
-}
-
-#define MESSAGE "System halted"
-static void lasat_machine_halt(void)
-{
- local_irq_disable();
-
- /* Disable interrupts and loop forever */
- printk(KERN_NOTICE MESSAGE "\n");
-#ifdef CONFIG_PICVUE
- pvc_clear();
- pvc_write_string(MESSAGE, 0, 0);
-#endif
- prom_monitor();
- for (;;) ;
-}
-
-void lasat_reboot_setup(void)
-{
- _machine_restart = lasat_machine_restart;
- _machine_halt = lasat_machine_halt;
- pm_power_off = lasat_machine_halt;
-}
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
deleted file mode 100644
index 488007f13988..000000000000
--- a/arch/mips/lasat/setup.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved.
- *
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * Brian Murphy <brian@murphy.dk>
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Lasat specific setup.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-
-#include <asm/time.h>
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/lasat/lasat.h>
-#include <asm/lasat/serial.h>
-
-#ifdef CONFIG_PICVUE
-#include <linux/notifier.h>
-#endif
-
-#include "ds1603.h"
-#include <asm/lasat/ds1603.h>
-#include <asm/lasat/picvue.h>
-#include <asm/lasat/eeprom.h>
-
-#include "prom.h"
-
-int lasat_command_line = 0;
-void lasatint_init(void);
-
-extern void lasat_reboot_setup(void);
-extern void pcisetup(void);
-extern void edhac_init(void *, void *, void *);
-extern void addrflt_init(void);
-
-struct lasat_misc lasat_misc_info[N_MACHTYPES] = {
- {(void *)KSEG1ADDR(0x1c840000), (void *)KSEG1ADDR(0x1c800000), 2},
- {(void *)KSEG1ADDR(0x11080000), (void *)KSEG1ADDR(0x11000000), 6}
-};
-
-struct lasat_misc *lasat_misc = NULL;
-
-#ifdef CONFIG_DS1603
-static struct ds_defs ds_defs[N_MACHTYPES] = {
- { (void *)DS1603_REG_100, (void *)DS1603_REG_100,
- DS1603_RST_100, DS1603_CLK_100, DS1603_DATA_100,
- DS1603_DATA_SHIFT_100, 0, 0 },
- { (void *)DS1603_REG_200, (void *)DS1603_DATA_REG_200,
- DS1603_RST_200, DS1603_CLK_200, DS1603_DATA_200,
- DS1603_DATA_READ_SHIFT_200, 1, 2000 }
-};
-#endif
-
-#ifdef CONFIG_PICVUE
-#include "picvue.h"
-static struct pvc_defs pvc_defs[N_MACHTYPES] = {
- { (void *)PVC_REG_100, PVC_DATA_SHIFT_100, PVC_DATA_M_100,
- PVC_E_100, PVC_RW_100, PVC_RS_100 },
- { (void *)PVC_REG_200, PVC_DATA_SHIFT_200, PVC_DATA_M_200,
- PVC_E_200, PVC_RW_200, PVC_RS_200 }
-};
-#endif
-
-static int lasat_panic_display(struct notifier_block *this,
- unsigned long event, void *ptr)
-{
-#ifdef CONFIG_PICVUE
- unsigned char *string = ptr;
- if (string == NULL)
- string = "Kernel Panic";
- pvc_dump_string(string);
-#endif
- return NOTIFY_DONE;
-}
-
-static int lasat_panic_prom_monitor(struct notifier_block *this,
- unsigned long event, void *ptr)
-{
- prom_monitor();
- return NOTIFY_DONE;
-}
-
-static struct notifier_block lasat_panic_block[] =
-{
- { lasat_panic_display, NULL, INT_MAX },
- { lasat_panic_prom_monitor, NULL, INT_MIN }
-};
-
-static void lasat_time_init(void)
-{
- mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
-}
-
-#define DYNAMIC_SERIAL_INIT
-#ifdef DYNAMIC_SERIAL_INIT
-void __init serial_init(void)
-{
-#ifdef CONFIG_SERIAL_8250
- struct uart_port s;
-
- memset(&s, 0, sizeof(s));
-
- s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
- s.iotype = UPIO_MEM;
-
- if (mips_machtype == MACH_LASAT_100) {
- s.uartclk = LASAT_BASE_BAUD_100 * 16;
- s.irq = LASATINT_UART_100;
- s.regshift = LASAT_UART_REGS_SHIFT_100;
- s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_100);
- } else {
- s.uartclk = LASAT_BASE_BAUD_200 * 16;
- s.irq = LASATINT_UART_200;
- s.regshift = LASAT_UART_REGS_SHIFT_200;
- s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_200);
- }
-
- if (early_serial_setup(&s) != 0)
- printk(KERN_ERR "Serial setup failed!\n");
-#endif
-}
-#endif
-
-void __init plat_mem_setup(void)
-{
- int i;
- lasat_misc = &lasat_misc_info[mips_machtype];
-#ifdef CONFIG_PICVUE
- picvue = &pvc_defs[mips_machtype];
-#endif
-
- /* Set up panic notifier */
- for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
- atomic_notifier_chain_register(&panic_notifier_list,
- &lasat_panic_block[i]);
-
- lasat_reboot_setup();
-
- board_time_init = lasat_time_init;
-
-#ifdef CONFIG_DS1603
- ds1603 = &ds_defs[mips_machtype];
- rtc_mips_get_time = ds1603_read;
- rtc_mips_set_time = ds1603_set;
-#endif
-
-#ifdef DYNAMIC_SERIAL_INIT
- serial_init();
-#endif
- /* Switch from prom exception handler to normal mode */
- change_c0_status(ST0_BEV,0);
-
- pr_info("Lasat specific initialization complete\n");
-}
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
deleted file mode 100644
index 699ab1886ceb..000000000000
--- a/arch/mips/lasat/sysctl.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines specific to the LASAT boards
- */
-#include <linux/types.h>
-#include <asm/lasat/lasat.h>
-
-#include <linux/module.h>
-#include <linux/sysctl.h>
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/net.h>
-#include <linux/inet.h>
-#include <linux/mutex.h>
-#include <asm/uaccess.h>
-
-#include "sysctl.h"
-#include "ds1603.h"
-
-static DEFINE_MUTEX(lasat_info_mutex);
-
-/* Strategy function to write EEPROM after changing string entry */
-int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = sysctl_string(table, name,
- nlen, oldval, oldlenp, newval, newlen);
- if (r < 0) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- if (newval && newlen) {
- lasat_write_eeprom_info();
- }
- mutex_unlock(&lasat_info_mutex);
- return 1;
-}
-
-
-/* And the same for proc */
-int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = proc_dostring(table, write, filp, buffer, lenp, ppos);
- if ( (!write) || r) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- lasat_write_eeprom_info();
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-
-/* proc function to write EEPROM after changing int entry */
-int proc_dolasatint(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
- if ( (!write) || r) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- lasat_write_eeprom_info();
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-
-static int rtctmp;
-
-#ifdef CONFIG_DS1603
-/* proc function to read/write RealTime Clock */
-int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- if (!write) {
- rtctmp = ds1603_read();
- /* check for time < 0 and set to 0 */
- if (rtctmp < 0)
- rtctmp = 0;
- }
- r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
- if ( (!write) || r) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- ds1603_set(rtctmp);
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-#endif
-
-/* Sysctl for setting the IP addresses */
-int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
- if (r < 0) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- if (newval && newlen) {
- lasat_write_eeprom_info();
- }
- mutex_unlock(&lasat_info_mutex);
- return 1;
-}
-
-#ifdef CONFIG_DS1603
-/* Same for RTC */
-int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- rtctmp = ds1603_read();
- if (rtctmp < 0)
- rtctmp = 0;
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
- if (r < 0) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- if (newval && newlen) {
- ds1603_set(rtctmp);
- }
- mutex_unlock(&lasat_info_mutex);
- return 1;
-}
-#endif
-
-#ifdef CONFIG_INET
-static char lasat_bcastaddr[16];
-
-void update_bcastaddr(void)
-{
- unsigned int ip;
-
- ip = (lasat_board_info.li_eeprom_info.ipaddr &
- lasat_board_info.li_eeprom_info.netmask) |
- ~lasat_board_info.li_eeprom_info.netmask;
-
- sprintf(lasat_bcastaddr, "%d.%d.%d.%d",
- (ip ) & 0xff,
- (ip >> 8) & 0xff,
- (ip >> 16) & 0xff,
- (ip >> 24) & 0xff);
-}
-
-static char proc_lasat_ipbuf[32];
-/* Parsing of IP address */
-int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int len;
- unsigned int ip;
- char *p, c;
-
- if (!table->data || !table->maxlen || !*lenp ||
- (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
-
- mutex_lock(&lasat_info_mutex);
- if (write) {
- len = 0;
- p = buffer;
- while (len < *lenp) {
- if(get_user(c, p++)) {
- mutex_unlock(&lasat_info_mutex);
- return -EFAULT;
- }
- if (c == 0 || c == '\n')
- break;
- len++;
- }
- if (len >= sizeof(proc_lasat_ipbuf)-1)
- len = sizeof(proc_lasat_ipbuf) - 1;
- if (copy_from_user(proc_lasat_ipbuf, buffer, len))
- {
- mutex_unlock(&lasat_info_mutex);
- return -EFAULT;
- }
- proc_lasat_ipbuf[len] = 0;
- *ppos += *lenp;
- /* Now see if we can convert it to a valid IP */
- ip = in_aton(proc_lasat_ipbuf);
- *(unsigned int *)(table->data) = ip;
- lasat_write_eeprom_info();
- } else {
- ip = *(unsigned int *)(table->data);
- sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d",
- (ip ) & 0xff,
- (ip >> 8) & 0xff,
- (ip >> 16) & 0xff,
- (ip >> 24) & 0xff);
- len = strlen(proc_lasat_ipbuf);
- if (len > *lenp)
- len = *lenp;
- if (len)
- if(copy_to_user(buffer, proc_lasat_ipbuf, len)) {
- mutex_unlock(&lasat_info_mutex);
- return -EFAULT;
- }
- if (len < *lenp) {
- if(put_user('\n', ((char *) buffer) + len)) {
- mutex_unlock(&lasat_info_mutex);
- return -EFAULT;
- }
- len++;
- }
- *lenp = len;
- *ppos += len;
- }
- update_bcastaddr();
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-#endif /* defined(CONFIG_INET) */
-
-static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen)
-{
- int r;
-
- mutex_lock(&lasat_info_mutex);
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
- if (r < 0) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
-
- if (newval && newlen)
- {
- if (name && *name == LASAT_PRID)
- lasat_board_info.li_eeprom_info.prid = *(int*)newval;
-
- lasat_write_eeprom_info();
- lasat_init_board_info();
- }
- mutex_unlock(&lasat_info_mutex);
-
- return 0;
-}
-
-int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
- if ( (!write) || r) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- if (filp && filp->f_path.dentry)
- {
- if (!strcmp(filp->f_path.dentry->d_name.name, "prid"))
- lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid;
- if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess"))
- lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
- }
- lasat_write_eeprom_info();
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-
-extern int lasat_boot_to_service;
-
-#ifdef CONFIG_SYSCTL
-
-static ctl_table lasat_table[] = {
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "cpu-hz",
- .data = &lasat_board_info.li_cpu_hz,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "bus-hz",
- .data = &lasat_board_info.li_bus_hz,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "bmid",
- .data = &lasat_board_info.li_bmid,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "prid",
- .data = &lasat_board_info.li_prid,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_lasat_eeprom_value,
- .strategy = &sysctl_lasat_eeprom_value
- },
-#ifdef CONFIG_INET
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "ipaddr",
- .data = &lasat_board_info.li_eeprom_info.ipaddr,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_lasat_ip,
- .strategy = &sysctl_lasat_intvec
- },
- {
- .ctl_name = LASAT_NETMASK,
- .procname = "netmask",
- .data = &lasat_board_info.li_eeprom_info.netmask,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_lasat_ip,
- .strategy = &sysctl_lasat_intvec
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "bcastaddr",
- .data = &lasat_bcastaddr,
- .maxlen = sizeof(lasat_bcastaddr),
- .mode = 0600,
- .proc_handler = &proc_dostring,
- .strategy = &sysctl_string
- },
-#endif
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "passwd_hash",
- .data = &lasat_board_info.li_eeprom_info.passwd_hash,
- .maxlen = sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
- .mode = 0600,
- .proc_handler = &proc_dolasatstring,
- .strategy = &sysctl_lasatstring
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "boot-service",
- .data = &lasat_boot_to_service,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec
- },
-#ifdef CONFIG_DS1603
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "rtc",
- .data = &rtctmp,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dolasatrtc,
- .strategy = &sysctl_lasat_rtc
- },
-#endif
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "namestr",
- .data = &lasat_board_info.li_namestr,
- .maxlen = sizeof(lasat_board_info.li_namestr),
- .mode = 0444,
- .proc_handler = &proc_dostring,
- .strategy = &sysctl_string
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "typestr",
- .data = &lasat_board_info.li_typestr,
- .maxlen = sizeof(lasat_board_info.li_typestr),
- .mode = 0444,
- .proc_handler = &proc_dostring,
- .strategy = &sysctl_string
- },
- {}
-};
-
-static ctl_table lasat_root_table[] = {
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "lasat",
- .mode = 0555,
- .child = lasat_table
- },
- {}
-};
-
-static int __init lasat_register_sysctl(void)
-{
- struct ctl_table_header *lasat_table_header;
-
- lasat_table_header =
- register_sysctl_table(lasat_root_table);
-
- return 0;
-}
-
-__initcall(lasat_register_sysctl);
-#endif /* CONFIG_SYSCTL */
diff --git a/arch/mips/lasat/sysctl.h b/arch/mips/lasat/sysctl.h
deleted file mode 100644
index 4d139d2adbdf..000000000000
--- a/arch/mips/lasat/sysctl.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * LASAT sysctl values
- */
-
-#ifndef _LASAT_SYSCTL_H
-#define _LASAT_SYSCTL_H
-
-/* /proc/sys/lasat */
-enum {
- LASAT_CPU_HZ=1,
- LASAT_BUS_HZ,
- LASAT_MODEL,
- LASAT_PRID,
- LASAT_IPADDR,
- LASAT_NETMASK,
- LASAT_BCAST,
- LASAT_PASSWORD,
- LASAT_SBOOT,
- LASAT_RTC,
- LASAT_NAMESTR,
- LASAT_TYPESTR,
-};
-
-#endif /* _LASAT_SYSCTL_H */
diff --git a/arch/mips/lemote/lm2e/Makefile b/arch/mips/lemote/lm2e/Makefile
new file mode 100644
index 000000000000..fb1b48c48cb3
--- /dev/null
+++ b/arch/mips/lemote/lm2e/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Lemote Fulong mini-PC board.
+#
+
+obj-y += setup.o prom.o reset.o irq.o pci.o bonito-irq.o dbg_io.o mem.o
+EXTRA_AFLAGS := $(CFLAGS)
+
diff --git a/arch/mips/lemote/lm2e/bonito-irq.c b/arch/mips/lemote/lm2e/bonito-irq.c
new file mode 100644
index 000000000000..8fc3bce7075b
--- /dev/null
+++ b/arch/mips/lemote/lm2e/bonito-irq.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+
+static inline void bonito_irq_enable(unsigned int irq)
+{
+ BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE));
+ mmiowb();
+}
+
+static inline void bonito_irq_disable(unsigned int irq)
+{
+ BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE));
+ mmiowb();
+}
+
+static struct irq_chip bonito_irq_type = {
+ .name = "bonito_irq",
+ .ack = bonito_irq_disable,
+ .mask = bonito_irq_disable,
+ .mask_ack = bonito_irq_disable,
+ .unmask = bonito_irq_enable,
+};
+
+static struct irqaction dma_timeout_irqaction = {
+ .handler = no_action,
+ .name = "dma_timeout",
+};
+
+void bonito_irq_init(void)
+{
+ u32 i;
+
+ for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++) {
+ set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
+ }
+
+ setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction);
+}
diff --git a/arch/mips/lemote/lm2e/dbg_io.c b/arch/mips/lemote/lm2e/dbg_io.c
new file mode 100644
index 000000000000..6c95da3ca76f
--- /dev/null
+++ b/arch/mips/lemote/lm2e/dbg_io.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <asm/serial.h>
+
+#define UART16550_BAUD_2400 2400
+#define UART16550_BAUD_4800 4800
+#define UART16550_BAUD_9600 9600
+#define UART16550_BAUD_19200 19200
+#define UART16550_BAUD_38400 38400
+#define UART16550_BAUD_57600 57600
+#define UART16550_BAUD_115200 115200
+
+#define UART16550_PARITY_NONE 0
+#define UART16550_PARITY_ODD 0x08
+#define UART16550_PARITY_EVEN 0x18
+#define UART16550_PARITY_MARK 0x28
+#define UART16550_PARITY_SPACE 0x38
+
+#define UART16550_DATA_5BIT 0x0
+#define UART16550_DATA_6BIT 0x1
+#define UART16550_DATA_7BIT 0x2
+#define UART16550_DATA_8BIT 0x3
+
+#define UART16550_STOP_1BIT 0x0
+#define UART16550_STOP_2BIT 0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+#ifdef CONFIG_64BIT
+#define BASE (0xffffffffbfd003f8)
+#else
+#define BASE (0xbfd003f8)
+#endif
+
+#define MAX_BAUD BASE_BAUD
+/* === END OF CONFIG === */
+
+#define REG_OFFSET 1
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) readb((char *)BASE + (y))
+#define UART16550_WRITE(y, z) writeb(z, (char *)BASE + (y))
+
+void debugInit(u32 baud, u8 data, u8 parity, u8 stop)
+{
+ u32 divisor;
+
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized;
+
+u8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_115200,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0) ;
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+int putDebugChar(u8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ /*
+ debugInit(UART16550_BAUD_115200,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT); */
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0) ;
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
diff --git a/arch/mips/lemote/lm2e/irq.c b/arch/mips/lemote/lm2e/irq.c
new file mode 100644
index 000000000000..05693bceaeaf
--- /dev/null
+++ b/arch/mips/lemote/lm2e/irq.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+#include <asm/mips-boards/bonito64.h>
+
+
+/*
+ * the first level int-handler will jump here if it is a bonito irq
+ */
+static void bonito_irqdispatch(void)
+{
+ u32 int_status;
+ int i;
+
+ /* workaround the IO dma problem: let cpu looping to allow DMA finish */
+ int_status = BONITO_INTISR;
+ if (int_status & (1 << 10)) {
+ while (int_status & (1 << 10)) {
+ udelay(1);
+ int_status = BONITO_INTISR;
+ }
+ }
+
+ /* Get pending sources, masked by current enables */
+ int_status = BONITO_INTISR & BONITO_INTEN;
+
+ if (int_status != 0) {
+ i = __ffs(int_status);
+ int_status &= ~(1 << i);
+ do_IRQ(BONITO_IRQ_BASE + i);
+ }
+}
+
+static void i8259_irqdispatch(void)
+{
+ int irq;
+
+ irq = i8259_irq();
+ if (irq >= 0) {
+ do_IRQ(irq);
+ } else {
+ spurious_interrupt();
+ }
+
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP7) {
+ do_IRQ(MIPS_CPU_IRQ_BASE + 7);
+ } else if (pending & CAUSEF_IP5) {
+ i8259_irqdispatch();
+ } else if (pending & CAUSEF_IP2) {
+ bonito_irqdispatch();
+ } else {
+ spurious_interrupt();
+ }
+}
+
+static struct irqaction cascade_irqaction = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
+
+void __init arch_init_irq(void)
+{
+ extern void bonito_irq_init(void);
+
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ * int-handler is not on bootstrap
+ */
+ clear_c0_status(ST0_IM | ST0_BEV);
+ local_irq_disable();
+
+ /* most bonito irq should be level triggered */
+ BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR |
+ BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES;
+ BONITO_INTSTEER = 0;
+
+ /*
+ * Mask out all interrupt by writing "1" to all bit position in
+ * the interrupt reset reg.
+ */
+ BONITO_INTENCLR = ~0;
+
+ /* init all controller
+ * 0-15 ------> i8259 interrupt
+ * 16-23 ------> mips cpu interrupt
+ * 32-63 ------> bonito irq
+ */
+
+ /* Sets the first-level interrupt dispatcher. */
+ mips_cpu_irq_init();
+ init_i8259_irqs();
+ bonito_irq_init();
+
+ /*
+ printk("GPIODATA=%x, GPIOIE=%x\n", BONITO_GPIODATA, BONITO_GPIOIE);
+ printk("INTEN=%x, INTSET=%x, INTCLR=%x, INTISR=%x\n",
+ BONITO_INTEN, BONITO_INTENSET,
+ BONITO_INTENCLR, BONITO_INTISR);
+ */
+
+ /* bonito irq at IP2 */
+ setup_irq(MIPS_CPU_IRQ_BASE + 2, &cascade_irqaction);
+ /* 8259 irq at IP5 */
+ setup_irq(MIPS_CPU_IRQ_BASE + 5, &cascade_irqaction);
+
+}
diff --git a/arch/mips/lemote/lm2e/mem.c b/arch/mips/lemote/lm2e/mem.c
new file mode 100644
index 000000000000..16cd21587d34
--- /dev/null
+++ b/arch/mips/lemote/lm2e/mem.c
@@ -0,0 +1,23 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+
+/* override of arch/mips/mm/cache.c: __uncached_access */
+int __uncached_access(struct file *file, unsigned long addr)
+{
+ if (file->f_flags & O_SYNC)
+ return 1;
+
+ /*
+ * On the Lemote Loongson 2e system, the peripheral registers
+ * reside between 0x1000:0000 and 0x2000:0000.
+ */
+ return addr >= __pa(high_memory) ||
+ ((addr >= 0x10000000) && (addr < 0x20000000));
+}
diff --git a/arch/mips/lemote/lm2e/pci.c b/arch/mips/lemote/lm2e/pci.c
new file mode 100644
index 000000000000..1ade1cef3899
--- /dev/null
+++ b/arch/mips/lemote/lm2e/pci.c
@@ -0,0 +1,93 @@
+/*
+ * pci.c
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/mips-boards/bonito64.h>
+
+extern struct pci_ops bonito64_pci_ops;
+
+static struct resource loongson2e_pci_mem_resource = {
+ .name = "LOONGSON2E PCI MEM",
+ .start = 0x14000000UL,
+ .end = 0x1fffffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource loongson2e_pci_io_resource = {
+ .name = "LOONGSON2E PCI IO MEM",
+ .start = 0x00004000UL,
+ .end = IO_SPACE_LIMIT,
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller loongson2e_pci_controller = {
+ .pci_ops = &bonito64_pci_ops,
+ .io_resource = &loongson2e_pci_io_resource,
+ .mem_resource = &loongson2e_pci_mem_resource,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static void __init ict_pcimap(void)
+{
+ /*
+ * local to PCI mapping: [256M,512M] -> [256M,512M]; differ from PMON
+ *
+ * CPU address space [256M,448M] is window for accessing pci space
+ * we set pcimap_lo[0,1,2] to map it to pci space [256M,448M]
+ * pcimap: bit18,pcimap_2; bit[17-12],lo2;bit[11-6],lo1;bit[5-0],lo0
+ */
+ /* 1,00 0110 ,0001 01,00 0000 */
+ BONITO_PCIMAP = 0x46140;
+
+ /* 1, 00 0010, 0000,01, 00 0000 */
+ /* BONITO_PCIMAP = 0x42040; */
+
+ /*
+ * PCI to local mapping: [2G,2G+256M] -> [0,256M]
+ */
+ BONITO_PCIBASE0 = 0x80000000;
+ BONITO_PCIBASE1 = 0x00800000;
+ BONITO_PCIBASE2 = 0x90000000;
+
+}
+
+static int __init pcibios_init(void)
+{
+ extern int pci_probe_only;
+ pci_probe_only = 0;
+
+ ict_pcimap();
+ register_pci_controller(&loongson2e_pci_controller);
+
+ return 0;
+}
+
+arch_initcall(pcibios_init);
diff --git a/arch/mips/lemote/lm2e/prom.c b/arch/mips/lemote/lm2e/prom.c
new file mode 100644
index 000000000000..67312d7acf2a
--- /dev/null
+++ b/arch/mips/lemote/lm2e/prom.c
@@ -0,0 +1,104 @@
+/*
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright 2003 ICT CAS
+ * Author: Michael Guo <guoyi@ict.ac.cn>
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+extern unsigned long bus_clock;
+extern unsigned long cpu_clock;
+extern unsigned int memsize, highmemsize;
+extern int putDebugChar(unsigned char byte);
+
+static int argc;
+/* pmon passes arguments in 32bit pointers */
+static int *arg;
+static int *env;
+
+const char *get_system_type(void)
+{
+ return "lemote-fulong";
+}
+
+void __init prom_init_cmdline(void)
+{
+ int i;
+ long l;
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+ for (i = 1; i < argc; i++) {
+ l = (long)arg[i];
+ if (strlen(arcs_cmdline) + strlen(((char *)l) + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, ((char *)l));
+ strcat(arcs_cmdline, " ");
+ }
+}
+
+void __init prom_init(void)
+{
+ long l;
+ argc = fw_arg0;
+ arg = (int *)fw_arg1;
+ env = (int *)fw_arg2;
+
+ mips_machgroup = MACH_GROUP_LEMOTE;
+ mips_machtype = MACH_LEMOTE_FULONG;
+
+ prom_init_cmdline();
+
+ if ((strstr(arcs_cmdline, "console=")) == NULL)
+ strcat(arcs_cmdline, " console=ttyS0,115200");
+ if ((strstr(arcs_cmdline, "root=")) == NULL)
+ strcat(arcs_cmdline, " root=/dev/hda1");
+
+#define parse_even_earlier(res, option, p) \
+do { \
+ if (strncmp(option, (char *)p, strlen(option)) == 0) \
+ res = simple_strtol((char *)p + strlen(option"="), \
+ NULL, 10); \
+} while (0)
+
+ l = (long)*env;
+ while (l != 0) {
+ parse_even_earlier(bus_clock, "busclock", l);
+ parse_even_earlier(cpu_clock, "cpuclock", l);
+ parse_even_earlier(memsize, "memsize", l);
+ parse_even_earlier(highmemsize, "highmemsize", l);
+ env++;
+ l = (long)*env;
+ }
+ if (memsize == 0)
+ memsize = 256;
+
+ pr_info("busclock=%ld, cpuclock=%ld,memsize=%d,highmemsize=%d\n",
+ bus_clock, cpu_clock, memsize, highmemsize);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void prom_putchar(char c)
+{
+ putDebugChar(c);
+}
diff --git a/arch/mips/lemote/lm2e/reset.c b/arch/mips/lemote/lm2e/reset.c
new file mode 100644
index 000000000000..099387a3827a
--- /dev/null
+++ b/arch/mips/lemote/lm2e/reset.c
@@ -0,0 +1,41 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ */
+#include <linux/pm.h>
+
+#include <asm/reboot.h>
+
+static void loongson2e_restart(char *command)
+{
+#ifdef CONFIG_32BIT
+ *(unsigned long *)0xbfe00104 &= ~(1 << 2);
+ *(unsigned long *)0xbfe00104 |= (1 << 2);
+#else
+ *(unsigned long *)0xffffffffbfe00104 &= ~(1 << 2);
+ *(unsigned long *)0xffffffffbfe00104 |= (1 << 2);
+#endif
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+static void loongson2e_halt(void)
+{
+ while (1) ;
+}
+
+static void loongson2e_power_off(void)
+{
+ loongson2e_halt();
+}
+
+void mips_reboot_setup(void)
+{
+ _machine_restart = loongson2e_restart;
+ _machine_halt = loongson2e_halt;
+ pm_power_off = loongson2e_power_off;
+}
diff --git a/arch/mips/lemote/lm2e/setup.c b/arch/mips/lemote/lm2e/setup.c
new file mode 100644
index 000000000000..0e4d1fa572b5
--- /dev/null
+++ b/arch/mips/lemote/lm2e/setup.c
@@ -0,0 +1,134 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * setup.c - board dependent boot routines
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/time.h>
+#include <asm/wbflush.h>
+
+#ifdef CONFIG_VT
+#include <linux/console.h>
+#include <linux/screen_info.h>
+#endif
+
+extern void mips_reboot_setup(void);
+
+#ifdef CONFIG_64BIT
+#define PTR_PAD(p) ((0xffffffff00000000)|((unsigned long long)(p)))
+#else
+#define PTR_PAD(p) (p)
+#endif
+
+unsigned long cpu_clock;
+unsigned long bus_clock;
+unsigned int memsize;
+unsigned int highmemsize = 0;
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+ setup_irq(MIPS_CPU_IRQ_BASE + 7, irq);
+}
+
+static void __init loongson2e_time_init(void)
+{
+ /* setup mips r4k timer */
+ mips_hpt_frequency = cpu_clock / 2;
+}
+
+static unsigned long __init mips_rtc_get_time(void)
+{
+ return mc146818_get_cmos_time();
+}
+
+void (*__wbflush)(void);
+EXPORT_SYMBOL(__wbflush);
+
+static void wbflush_loongson2e(void)
+{
+ asm(".set\tpush\n\t"
+ ".set\tnoreorder\n\t"
+ ".set mips3\n\t"
+ "sync\n\t"
+ "nop\n\t"
+ ".set\tpop\n\t"
+ ".set mips0\n\t");
+}
+
+void __init plat_mem_setup(void)
+{
+ set_io_port_base(PTR_PAD(0xbfd00000));
+
+ mips_reboot_setup();
+
+ board_time_init = loongson2e_time_init;
+ rtc_mips_get_time = mips_rtc_get_time;
+
+ __wbflush = wbflush_loongson2e;
+
+ add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
+#ifdef CONFIG_64BIT
+ if (highmemsize > 0) {
+ add_memory_region(0x20000000, highmemsize << 20, BOOT_MEM_RAM);
+ }
+#endif
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+
+ screen_info = (struct screen_info) {
+ 0, 25, /* orig-x, orig-y */
+ 0, /* unused */
+ 0, /* orig-video-page */
+ 0, /* orig-video-mode */
+ 80, /* orig-video-cols */
+ 0, 0, 0, /* ega_ax, ega_bx, ega_cx */
+ 25, /* orig-video-lines */
+ VIDEO_TYPE_VGAC, /* orig-video-isVGA */
+ 16 /* orig-video-points */
+ };
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
+#endif
+
+}
diff --git a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile
deleted file mode 100644
index 8b94d4cc5a30..000000000000
--- a/arch/mips/lib-32/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for MIPS-specific library files..
-#
-
-lib-y += watch.o
-
-obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
-obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
-obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
-obj-$(CONFIG_CPU_R10000) += dump_tlb.o
-obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
-obj-$(CONFIG_CPU_R4300) += dump_tlb.o
-obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
-obj-$(CONFIG_CPU_R5000) += dump_tlb.o
-obj-$(CONFIG_CPU_R5432) += dump_tlb.o
-obj-$(CONFIG_CPU_R6000) +=
-obj-$(CONFIG_CPU_R8000) +=
-obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
-obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
-obj-$(CONFIG_CPU_SB1) += dump_tlb.o
-obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
-obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
-obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
deleted file mode 100644
index 6a68deb51aae..000000000000
--- a/arch/mips/lib-32/dump_tlb.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Dump R4x00 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-static inline const char *msk2str(unsigned int mask)
-{
- switch (mask) {
- case PM_4K:
- return "4kb";
- case PM_16K:
- return "16kb";
- case PM_64K:
- return "64kb";
- case PM_256K:
- return "256kb";
-#ifndef CONFIG_CPU_VR41XX
- case PM_1M:
- return "1Mb";
- case PM_4M:
- return "4Mb";
- case PM_16M:
- return "16Mb";
- case PM_64M:
- return "64Mb";
- case PM_256M:
- return "256Mb";
-#endif
- }
-
- return "unknown";
-}
-
-#define BARRIER() \
- __asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- "nop;nop;nop;nop;nop;nop;nop\n\t" \
- ".set\treorder");
-
-void dump_tlb(int first, int last)
-{
- unsigned int pagemask, c0, c1, asid;
- unsigned long long entrylo0, entrylo1;
- unsigned long entryhi;
- int i;
-
- asid = read_c0_entryhi() & 0xff;
-
- printk("\n");
- for (i = first; i <= last; i++) {
- write_c0_index(i);
- BARRIER();
- tlb_read();
- BARRIER();
- pagemask = read_c0_pagemask();
- entryhi = read_c0_entryhi();
- entrylo0 = read_c0_entrylo0();
- entrylo1 = read_c0_entrylo1();
-
- /* Unused entries have a virtual address in KSEG0. */
- if ((entryhi & 0xf0000000) != 0x80000000
- && (entryhi & 0xff) == asid) {
- /*
- * Only print entries in use
- */
- printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
-
- c0 = (entrylo0 >> 3) & 7;
- c1 = (entrylo1 >> 3) & 7;
-
- printk("va=%08lx asid=%02lx\n",
- (entryhi & 0xffffe000), (entryhi & 0xff));
- printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
- (entrylo0 << 6) & PAGE_MASK, c0,
- (entrylo0 & 4) ? 1 : 0,
- (entrylo0 & 2) ? 1 : 0, (entrylo0 & 1));
- printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
- (entrylo1 << 6) & PAGE_MASK, c1,
- (entrylo1 & 4) ? 1 : 0,
- (entrylo1 & 2) ? 1 : 0, (entrylo1 & 1));
- printk("\n");
- }
- }
-
- write_c0_entryhi(asid);
-}
-
-void dump_tlb_all(void)
-{
- dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
- int wired;
-
- wired = read_c0_wired();
- printk("Wired: %d", wired);
- dump_tlb(0, read_c0_wired());
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
- unsigned int flags, oldpid;
- int index;
-
- local_irq_save(flags);
- oldpid = read_c0_entryhi() & 0xff;
- BARRIER();
- write_c0_entryhi((addr & PAGE_MASK) | oldpid);
- BARRIER();
- tlb_probe();
- BARRIER();
- index = read_c0_index();
- write_c0_entryhi(oldpid);
- local_irq_restore(flags);
-
- if (index < 0) {
- printk("No entry for address 0x%08lx in TLB\n", addr);
- return;
- }
-
- printk("Entry %d maps address 0x%08lx\n", index, addr);
- dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
- dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
- pgd_t *page_dir, *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte, page;
- unsigned long addr, val;
-
- addr = (unsigned long) address;
-
- printk("Addr == %08lx\n", addr);
- printk("task == %8p\n", t);
- printk("task->mm == %8p\n", t->mm);
- //printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
-
- if (addr > KSEG0) {
- page_dir = pgd_offset_k(0);
- pgd = pgd_offset_k(addr);
- } else if (t->mm) {
- page_dir = pgd_offset(t->mm, 0);
- pgd = pgd_offset(t->mm, addr);
- } else {
- printk("Current thread has no mm\n");
- return;
- }
- printk("page_dir == %08x\n", (unsigned int) page_dir);
- printk("pgd == %08x, ", (unsigned int) pgd);
- pud = pud_offset(pgd, addr);
- printk("pud == %08x, ", (unsigned int) pud);
-
- pmd = pmd_offset(pud, addr);
- printk("pmd == %08x, ", (unsigned int) pmd);
-
- pte = pte_offset(pmd, addr);
- printk("pte == %08x, ", (unsigned int) pte);
-
- page = *pte;
-#ifdef CONFIG_64BIT_PHYS_ADDR
- printk("page == %08Lx\n", pte_val(page));
-#else
- printk("page == %08lx\n", pte_val(page));
-#endif
-
- val = pte_val(page);
- if (val & _PAGE_PRESENT)
- printk("present ");
- if (val & _PAGE_READ)
- printk("read ");
- if (val & _PAGE_WRITE)
- printk("write ");
- if (val & _PAGE_ACCESSED)
- printk("accessed ");
- if (val & _PAGE_MODIFIED)
- printk("modified ");
- if (val & _PAGE_R4KBUG)
- printk("r4kbug ");
- if (val & _PAGE_GLOBAL)
- printk("global ");
- if (val & _PAGE_VALID)
- printk("valid ");
- printk("\n");
-}
-
-void dump_list_current(void *address)
-{
- dump_list_process(current, address);
-}
-
-unsigned int vtop(void *address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned int addr, paddr;
-
- addr = (unsigned long) address;
- pgd = pgd_offset(current->mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- pte = pte_offset(pmd, addr);
- paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
- paddr |= (addr & ~PAGE_MASK);
-
- return paddr;
-}
-
-void dump16(unsigned long *p)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- printk("*%08lx == %08lx, ", (unsigned long) p, *p);
- p++;
- printk("*%08lx == %08lx\n", (unsigned long) p, *p);
- p++;
- }
-}
diff --git a/arch/mips/lib-32/r3k_dump_tlb.c b/arch/mips/lib-32/r3k_dump_tlb.c
deleted file mode 100644
index 4f2cb74f0766..000000000000
--- a/arch/mips/lib-32/r3k_dump_tlb.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Dump R3000 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- * Copyright (C) 1999 by Harald Koerfgen
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
-
-void dump_tlb(int first, int last)
-{
- int i;
- unsigned int asid;
- unsigned long entryhi, entrylo0;
-
- asid = read_c0_entryhi() & 0xfc0;
-
- for (i = first; i <= last; i++) {
- write_c0_index(i<<8);
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- "tlbr\n\t"
- "nop\n\t"
- ".set\treorder");
- entryhi = read_c0_entryhi();
- entrylo0 = read_c0_entrylo0();
-
- /* Unused entries have a virtual address of KSEG0. */
- if ((entryhi & 0xffffe000) != 0x80000000
- && (entryhi & 0xfc0) == asid) {
- /*
- * Only print entries in use
- */
- printk("Index: %2d ", i);
-
- printk("va=%08lx asid=%08lx"
- " [pa=%06lx n=%d d=%d v=%d g=%d]",
- (entryhi & 0xffffe000),
- entryhi & 0xfc0,
- entrylo0 & PAGE_MASK,
- (entrylo0 & (1 << 11)) ? 1 : 0,
- (entrylo0 & (1 << 10)) ? 1 : 0,
- (entrylo0 & (1 << 9)) ? 1 : 0,
- (entrylo0 & (1 << 8)) ? 1 : 0);
- }
- }
- printk("\n");
-
- write_c0_entryhi(asid);
-}
-
-void dump_tlb_all(void)
-{
- dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
- int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
-
- printk("Wired: %d", wired);
- dump_tlb(0, wired - 1);
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
- unsigned long flags, oldpid;
- int index;
-
- local_irq_save(flags);
- oldpid = read_c0_entryhi() & 0xff;
- write_c0_entryhi((addr & PAGE_MASK) | oldpid);
- tlb_probe();
- index = read_c0_index();
- write_c0_entryhi(oldpid);
- local_irq_restore(flags);
-
- if (index < 0) {
- printk("No entry for address 0x%08lx in TLB\n", addr);
- return;
- }
-
- printk("Entry %d maps address 0x%08lx\n", index, addr);
- dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
- int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
- dump_tlb(wired, current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
- pgd_t *page_dir, *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte, page;
- unsigned int addr;
- unsigned long val;
-
- addr = (unsigned int) address;
-
- printk("Addr == %08x\n", addr);
- printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
-
- page_dir = pgd_offset(t->mm, 0);
- printk("page_dir == %08x\n", (unsigned int) page_dir);
-
- pgd = pgd_offset(t->mm, addr);
- printk("pgd == %08x, ", (unsigned int) pgd);
-
- pud = pud_offset(pgd, addr);
- printk("pud == %08x, ", (unsigned int) pud);
-
- pmd = pmd_offset(pud, addr);
- printk("pmd == %08x, ", (unsigned int) pmd);
-
- pte = pte_offset(pmd, addr);
- printk("pte == %08x, ", (unsigned int) pte);
-
- page = *pte;
- printk("page == %08x\n", (unsigned int) pte_val(page));
-
- val = pte_val(page);
- if (val & _PAGE_PRESENT) printk("present ");
- if (val & _PAGE_READ) printk("read ");
- if (val & _PAGE_WRITE) printk("write ");
- if (val & _PAGE_ACCESSED) printk("accessed ");
- if (val & _PAGE_MODIFIED) printk("modified ");
- if (val & _PAGE_GLOBAL) printk("global ");
- if (val & _PAGE_VALID) printk("valid ");
- printk("\n");
-}
-
-void dump_list_current(void *address)
-{
- dump_list_process(current, address);
-}
-
-unsigned int vtop(void *address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned int addr, paddr;
-
- addr = (unsigned long) address;
- pgd = pgd_offset(current->mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- pte = pte_offset(pmd, addr);
- paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
- paddr |= (addr & ~PAGE_MASK);
-
- return paddr;
-}
-
-void dump16(unsigned long *p)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- printk("*%08lx == %08lx, ", (unsigned long)p, *p);
- p++;
- printk("*%08lx == %08lx\n", (unsigned long)p, *p);
- p++;
- }
-}
diff --git a/arch/mips/lib-32/watch.S b/arch/mips/lib-32/watch.S
deleted file mode 100644
index 808b3af1a605..000000000000
--- a/arch/mips/lib-32/watch.S
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Kernel debug stuff to use the Watch registers.
- * Useful to find stack overflows, dangling pointers etc.
- *
- * Copyright (C) 1995, 1996, 1999 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-
- .set noreorder
-/*
- * Parameter: a0 - logic address to watch
- * Currently only KSEG0 addresses are allowed!
- * a1 - set bit #1 to trap on load references
- * bit #0 to trap on store references
- * Results : none
- */
- LEAF(__watch_set)
- li t0, 0x80000000
- subu a0, t0
- ori a0, 7
- xori a0, 7
- or a0, a1
- mtc0 a0, CP0_WATCHLO
- sw a0, watch_savelo
-
- jr ra
- mtc0 zero, CP0_WATCHHI
- END(__watch_set)
-
-/*
- * Parameter: none
- * Results : none
- */
- LEAF(__watch_clear)
- jr ra
- mtc0 zero, CP0_WATCHLO
- END(__watch_clear)
-
-/*
- * Parameter: none
- * Results : none
- */
- LEAF(__watch_reenable)
- lw t0, watch_savelo
- jr ra
- mtc0 t0, CP0_WATCHLO
- END(__watch_reenable)
-
-/*
- * Saved value of the c0_watchlo register for watch_reenable()
- */
- .data
-watch_savelo: .word 0
- .text
diff --git a/arch/mips/lib-64/Makefile b/arch/mips/lib-64/Makefile
deleted file mode 100644
index 8b94d4cc5a30..000000000000
--- a/arch/mips/lib-64/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for MIPS-specific library files..
-#
-
-lib-y += watch.o
-
-obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
-obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
-obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
-obj-$(CONFIG_CPU_R10000) += dump_tlb.o
-obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
-obj-$(CONFIG_CPU_R4300) += dump_tlb.o
-obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
-obj-$(CONFIG_CPU_R5000) += dump_tlb.o
-obj-$(CONFIG_CPU_R5432) += dump_tlb.o
-obj-$(CONFIG_CPU_R6000) +=
-obj-$(CONFIG_CPU_R8000) +=
-obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
-obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
-obj-$(CONFIG_CPU_SB1) += dump_tlb.o
-obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
-obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
-obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
deleted file mode 100644
index 594df1a05ecc..000000000000
--- a/arch/mips/lib-64/dump_tlb.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Dump R4x00 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-static inline const char *msk2str(unsigned int mask)
-{
- switch (mask) {
- case PM_4K: return "4kb";
- case PM_16K: return "16kb";
- case PM_64K: return "64kb";
- case PM_256K: return "256kb";
-#ifndef CONFIG_CPU_VR41XX
- case PM_1M: return "1Mb";
- case PM_4M: return "4Mb";
- case PM_16M: return "16Mb";
- case PM_64M: return "64Mb";
- case PM_256M: return "256Mb";
-#endif
- }
-
- return "unknown";
-}
-
-#define BARRIER() \
- __asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- "nop;nop;nop;nop;nop;nop;nop\n\t" \
- ".set\treorder");
-
-void dump_tlb(int first, int last)
-{
- unsigned long s_entryhi, entryhi, entrylo0, entrylo1, asid;
- unsigned int s_index, pagemask, c0, c1, i;
-
- s_entryhi = read_c0_entryhi();
- s_index = read_c0_index();
- asid = s_entryhi & 0xff;
-
- for (i = first; i <= last; i++) {
- write_c0_index(i);
- BARRIER();
- tlb_read();
- BARRIER();
- pagemask = read_c0_pagemask();
- entryhi = read_c0_entryhi();
- entrylo0 = read_c0_entrylo0();
- entrylo1 = read_c0_entrylo1();
-
- /* Unused entries have a virtual address of CKSEG0. */
- if ((entryhi & ~0x1ffffUL) != CKSEG0
- && (entryhi & 0xff) == asid) {
- /*
- * Only print entries in use
- */
- printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
-
- c0 = (entrylo0 >> 3) & 7;
- c1 = (entrylo1 >> 3) & 7;
-
- printk("va=%011lx asid=%02lx\n",
- (entryhi & ~0x1fffUL),
- entryhi & 0xff);
- printk("\t[pa=%011lx c=%d d=%d v=%d g=%ld] ",
- (entrylo0 << 6) & PAGE_MASK, c0,
- (entrylo0 & 4) ? 1 : 0,
- (entrylo0 & 2) ? 1 : 0,
- (entrylo0 & 1));
- printk("[pa=%011lx c=%d d=%d v=%d g=%ld]\n",
- (entrylo1 << 6) & PAGE_MASK, c1,
- (entrylo1 & 4) ? 1 : 0,
- (entrylo1 & 2) ? 1 : 0,
- (entrylo1 & 1));
- }
- }
- printk("\n");
-
- write_c0_entryhi(s_entryhi);
- write_c0_index(s_index);
-}
-
-void dump_tlb_all(void)
-{
- dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
- int wired;
-
- wired = read_c0_wired();
- printk("Wired: %d", wired);
- dump_tlb(0, read_c0_wired());
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
- unsigned int flags, oldpid;
- int index;
-
- local_irq_save(flags);
- oldpid = read_c0_entryhi() & 0xff;
- BARRIER();
- write_c0_entryhi((addr & PAGE_MASK) | oldpid);
- BARRIER();
- tlb_probe();
- BARRIER();
- index = read_c0_index();
- write_c0_entryhi(oldpid);
- local_irq_restore(flags);
-
- if (index < 0) {
- printk("No entry for address 0x%08lx in TLB\n", addr);
- return;
- }
-
- printk("Entry %d maps address 0x%08lx\n", index, addr);
- dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
- dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
- pgd_t *page_dir, *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte, page;
- unsigned long addr, val;
-
- addr = (unsigned long) address;
-
- printk("Addr == %08lx\n", addr);
- printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd);
-
- page_dir = pgd_offset(t->mm, 0UL);
- printk("page_dir == %016lx\n", (unsigned long) page_dir);
-
- pgd = pgd_offset(t->mm, addr);
- printk("pgd == %016lx\n", (unsigned long) pgd);
-
- pud = pud_offset(pgd, addr);
- printk("pud == %016lx\n", (unsigned long) pud);
-
- pmd = pmd_offset(pud, addr);
- printk("pmd == %016lx\n", (unsigned long) pmd);
-
- pte = pte_offset(pmd, addr);
- printk("pte == %016lx\n", (unsigned long) pte);
-
- page = *pte;
- printk("page == %08lx\n", pte_val(page));
-
- val = pte_val(page);
- if (val & _PAGE_PRESENT) printk("present ");
- if (val & _PAGE_READ) printk("read ");
- if (val & _PAGE_WRITE) printk("write ");
- if (val & _PAGE_ACCESSED) printk("accessed ");
- if (val & _PAGE_MODIFIED) printk("modified ");
- if (val & _PAGE_R4KBUG) printk("r4kbug ");
- if (val & _PAGE_GLOBAL) printk("global ");
- if (val & _PAGE_VALID) printk("valid ");
- printk("\n");
-}
-
-void dump_list_current(void *address)
-{
- dump_list_process(current, address);
-}
-
-unsigned long vtop(void *address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long addr, paddr;
-
- addr = (unsigned long) address;
- pgd = pgd_offset(current->mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- pte = pte_offset(pmd, addr);
- paddr = (CKSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
- paddr |= (addr & ~PAGE_MASK);
-
- return paddr;
-}
-
-void dump16(unsigned long *p)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- printk("*%08lx == %08lx, ", (unsigned long)p, *p);
- p++;
- printk("*%08lx == %08lx\n", (unsigned long)p, *p);
- p++;
- }
-}
diff --git a/arch/mips/lib-64/watch.S b/arch/mips/lib-64/watch.S
deleted file mode 100644
index f91434013695..000000000000
--- a/arch/mips/lib-64/watch.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Kernel debug stuff to use the Watch registers.
- * Useful to find stack overflows, dangling pointers etc.
- *
- * Copyright (C) 1995, 1996, 1999, 2001 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-
- .set noreorder
-/*
- * Parameter: a0 - physical address to watch
- * a1 - set bit #1 to trap on load references
- * bit #0 to trap on store references
- * Results : none
- */
- LEAF(__watch_set)
- ori a0, 7
- xori a0, 7
- or a0, a1
- mtc0 a0, CP0_WATCHLO
- sd a0, watch_savelo
- dsrl32 a0, a0, 0
-
- jr ra
- mtc0 zero, CP0_WATCHHI
- END(__watch_set)
-
-/*
- * Parameter: none
- * Results : none
- */
- LEAF(__watch_clear)
- jr ra
- mtc0 zero, CP0_WATCHLO
- END(__watch_clear)
-
-/*
- * Parameter: none
- * Results : none
- */
- LEAF(__watch_reenable)
- ld t0, watch_savelo
- jr ra
- mtc0 t0, CP0_WATCHLO
- END(__watch_reenable)
-
-/*
- * Saved value of the c0_watchlo register for watch_reenable()
- */
- .local watch_savelo
- .comm watch_savelo, 8, 8
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 1c1aa9f92f6c..91ed1eb33102 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -8,5 +8,24 @@ lib-y += csum_partial.o memcpy.o memcpy-inatomic.o memset.o strlen_user.o \
obj-y += iomap.o
obj-$(CONFIG_PCI) += iomap-pci.o
+obj-$(CONFIG_CPU_LOONGSON2) += dump_tlb.o
+obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
+obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
+obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
+obj-$(CONFIG_CPU_R10000) += dump_tlb.o
+obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
+obj-$(CONFIG_CPU_R4300) += dump_tlb.o
+obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
+obj-$(CONFIG_CPU_R5000) += dump_tlb.o
+obj-$(CONFIG_CPU_R5432) += dump_tlb.o
+obj-$(CONFIG_CPU_R6000) +=
+obj-$(CONFIG_CPU_R8000) +=
+obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
+obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
+obj-$(CONFIG_CPU_SB1) += dump_tlb.o
+obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
+obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
+obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
+
# libgcc-style stuff needed in the kernel
obj-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
new file mode 100644
index 000000000000..1a4db7dc77cb
--- /dev/null
+++ b/arch/mips/lib/dump_tlb.c
@@ -0,0 +1,100 @@
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+static inline const char *msk2str(unsigned int mask)
+{
+ switch (mask) {
+ case PM_4K: return "4kb";
+ case PM_16K: return "16kb";
+ case PM_64K: return "64kb";
+ case PM_256K: return "256kb";
+#ifndef CONFIG_CPU_VR41XX
+ case PM_1M: return "1Mb";
+ case PM_4M: return "4Mb";
+ case PM_16M: return "16Mb";
+ case PM_64M: return "64Mb";
+ case PM_256M: return "256Mb";
+#endif
+ }
+ return "";
+}
+
+#define BARRIER() \
+ __asm__ __volatile__( \
+ ".set\tnoreorder\n\t" \
+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
+ ".set\treorder");
+
+static void dump_tlb(int first, int last)
+{
+ unsigned long s_entryhi, entryhi, asid;
+ unsigned long long entrylo0, entrylo1;
+ unsigned int s_index, pagemask, c0, c1, i;
+
+ s_entryhi = read_c0_entryhi();
+ s_index = read_c0_index();
+ asid = s_entryhi & 0xff;
+
+ for (i = first; i <= last; i++) {
+ write_c0_index(i);
+ BARRIER();
+ tlb_read();
+ BARRIER();
+ pagemask = read_c0_pagemask();
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+ entrylo1 = read_c0_entrylo1();
+
+ /* Unused entries have a virtual address of CKSEG0. */
+ if ((entryhi & ~0x1ffffUL) != CKSEG0
+ && (entryhi & 0xff) == asid) {
+#ifdef CONFIG_32BIT
+ int width = 8;
+#else
+ int width = 11;
+#endif
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
+
+ c0 = (entrylo0 >> 3) & 7;
+ c1 = (entrylo1 >> 3) & 7;
+
+ printk("va=%0*lx asid=%02lx\n",
+ width, (entryhi & ~0x1fffUL),
+ entryhi & 0xff);
+ printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
+ width,
+ (entrylo0 << 6) & PAGE_MASK, c0,
+ (entrylo0 & 4) ? 1 : 0,
+ (entrylo0 & 2) ? 1 : 0,
+ (entrylo0 & 1) ? 1 : 0);
+ printk("[pa=%0*llx c=%d d=%d v=%d g=%d]\n",
+ width,
+ (entrylo1 << 6) & PAGE_MASK, c1,
+ (entrylo1 & 4) ? 1 : 0,
+ (entrylo1 & 2) ? 1 : 0,
+ (entrylo1 & 1) ? 1 : 0);
+ }
+ }
+ printk("\n");
+
+ write_c0_entryhi(s_entryhi);
+ write_c0_index(s_index);
+}
+
+void dump_tlb_all(void)
+{
+ dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c
new file mode 100644
index 000000000000..52f87795ecc3
--- /dev/null
+++ b/arch/mips/lib/r3k_dump_tlb.c
@@ -0,0 +1,62 @@
+/*
+ * Dump R3000 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 1999 by Harald Koerfgen
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
+
+static void dump_tlb(int first, int last)
+{
+ int i;
+ unsigned int asid;
+ unsigned long entryhi, entrylo0;
+
+ asid = read_c0_entryhi() & 0xfc0;
+
+ for (i = first; i <= last; i++) {
+ write_c0_index(i<<8);
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ "tlbr\n\t"
+ "nop\n\t"
+ ".set\treorder");
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+
+ /* Unused entries have a virtual address of KSEG0. */
+ if ((entryhi & 0xffffe000) != 0x80000000
+ && (entryhi & 0xfc0) == asid) {
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d ", i);
+
+ printk("va=%08lx asid=%08lx"
+ " [pa=%06lx n=%d d=%d v=%d g=%d]",
+ (entryhi & 0xffffe000),
+ entryhi & 0xfc0,
+ entrylo0 & PAGE_MASK,
+ (entrylo0 & (1 << 11)) ? 1 : 0,
+ (entrylo0 & (1 << 10)) ? 1 : 0,
+ (entrylo0 & (1 << 9)) ? 1 : 0,
+ (entrylo0 & (1 << 8)) ? 1 : 0);
+ }
+ }
+ printk("\n");
+
+ write_c0_entryhi(asid);
+}
+
+void dump_tlb_all(void)
+{
+ dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 80531b35cd61..d7f05b0abe17 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -35,6 +35,7 @@
* better performance by compiling with -msoft-float!
*/
#include <linux/sched.h>
+#include <linux/debugfs.h>
#include <asm/inst.h>
#include <asm/bootinfo.h>
@@ -1277,3 +1278,36 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return sig;
}
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_fpuemu(void)
+{
+ struct dentry *d, *dir;
+ int i;
+ static struct {
+ const char *name;
+ unsigned int *v;
+ } vars[] __initdata = {
+ { "emulated", &fpuemustats.emulated },
+ { "loads", &fpuemustats.loads },
+ { "stores", &fpuemustats.stores },
+ { "cp1ops", &fpuemustats.cp1ops },
+ { "cp1xops", &fpuemustats.cp1xops },
+ { "errors", &fpuemustats.errors },
+ };
+
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+ dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
+ for (i = 0; i < ARRAY_SIZE(vars); i++) {
+ d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ }
+ return 0;
+}
+__initcall(debugfs_fpuemu);
+#endif
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index 377d9e8f250a..a242b0fc377d 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -19,6 +19,7 @@
# under Linux.
#
-obj-y := malta_int.o malta_setup.o
+obj-y := malta_int.o malta_platform.o malta_setup.o
+
obj-$(CONFIG_MTD) += malta_mtd.o
obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
diff --git a/arch/mips/mips-boards/malta/malta_platform.c b/arch/mips/mips-boards/malta/malta_platform.c
new file mode 100644
index 000000000000..83b9bab3cd3f
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_platform.c
@@ -0,0 +1,65 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ * written by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Probe driver for the Malta's UART ports:
+ *
+ * o 2 ports in the SMC SuperIO
+ * o 1 port in the CBUS UART, a discrete 16550 which normally is only used
+ * for bringups.
+ *
+ * We don't use 8250_platform.c on Malta as it would result in the CBUS
+ * UART becoming ttyS0.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define SMC_PORT(base, int) \
+{ \
+ .iobase = base, \
+ .irq = int, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
+ .regshift = 0, \
+}
+
+#define CBUS_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+ SMC_PORT(0x3F8, 4),
+ SMC_PORT(0x2F8, 3),
+ {
+ .mapbase = 0x1f000900, /* The CBUS UART */
+ .irq = MIPS_CPU_IRQ_BASE + 2,
+ .uartclk = 3686400, /* Twice the usual clk! */
+ .iotype = UPIO_MEM32,
+ .flags = CBUS_UART_FLAGS,
+ .regshift = 3,
+ },
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM2,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Malta CBUS UART");
diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mipssim/Makefile
index dc0bfda11427..dc0bfda11427 100644
--- a/arch/mips/mips-boards/sim/Makefile
+++ b/arch/mips/mipssim/Makefile
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c
index c63021a5dc6c..c63021a5dc6c 100644
--- a/arch/mips/mips-boards/sim/sim_cmdline.c
+++ b/arch/mips/mipssim/sim_cmdline.c
diff --git a/arch/mips/mips-boards/sim/sim_console.c b/arch/mips/mipssim/sim_console.c
index de595a9ccb27..a2f41672cd5d 100644
--- a/arch/mips/mips-boards/sim/sim_console.c
+++ b/arch/mips/mipssim/sim_console.c
@@ -18,8 +18,8 @@
* written by Ralf Baechle
*/
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/serial_reg.h>
-#include <asm/io.h>
static inline unsigned int serial_in(int offset)
{
diff --git a/arch/mips/mipssim/sim_int.c b/arch/mips/mipssim/sim_int.c
new file mode 100644
index 000000000000..d86b37235cf6
--- /dev/null
+++ b/arch/mips/mipssim/sim_int.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 1999, 2005 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <asm/mips-boards/simint.h>
+#include <asm/irq_cpu.h>
+
+static inline int clz(unsigned long x)
+{
+ __asm__ (
+ " .set push \n"
+ " .set mips32 \n"
+ " clz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ return -clz(pending) + 31 - CAUSEB_IP;
+#else
+ unsigned int a0 = 7;
+ unsigned int t0;
+
+ t0 = s0 & 0xf000;
+ t0 = t0 < 1;
+ t0 = t0 << 2;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0xc000;
+ t0 = t0 < 1;
+ t0 = t0 << 1;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0x8000;
+ t0 = t0 < 1;
+ /* t0 = t0 << 2; */
+ a0 = a0 - t0;
+ /* s0 = s0 << t0; */
+
+ return a0;
+#endif
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+
+ if (irq > 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq);
+ else
+ spurious_interrupt();
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init();
+}
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mipssim/sim_mem.c
index e408ef0bcd6e..2312483eb838 100644
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ b/arch/mips/mipssim/sim_mem.c
@@ -95,7 +95,7 @@ void __init prom_meminit(void)
size = p->size;
add_memory_region(base, size, type);
- p++;
+ p++;
}
}
diff --git a/arch/mips/mips-boards/sim/sim_platform.c b/arch/mips/mipssim/sim_platform.c
index 53210a8c5dec..53210a8c5dec 100644
--- a/arch/mips/mips-boards/sim/sim_platform.c
+++ b/arch/mips/mipssim/sim_platform.c
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
index b705f09e57c3..3643582bdade 100644
--- a/arch/mips/mips-boards/sim/sim_setup.c
+++ b/arch/mips/mipssim/sim_setup.c
@@ -19,18 +19,18 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/ioport.h>
+#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <asm/cpu.h>
#include <asm/bootinfo.h>
-#include <asm/irq.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/prom.h>
-#include <asm/serial.h>
-#include <asm/io.h>
#include <asm/time.h>
#include <asm/mips-boards/sim.h>
#include <asm/mips-boards/simint.h>
@@ -62,7 +62,7 @@ void __init plat_mem_setup(void)
#endif
}
-void prom_init(void)
+void __init prom_init(void)
{
set_io_port_base(0xbfd00000);
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mipssim/sim_smp.c
index cb47863ecf10..38fa807b99f9 100644
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ b/arch/mips/mipssim/sim_smp.c
@@ -22,13 +22,13 @@
#include <linux/sched.h>
#include <linux/cpumask.h>
#include <linux/interrupt.h>
+#include <linux/smp.h>
+
#include <asm/atomic.h>
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/system.h>
-#include <asm/hardirq.h>
#include <asm/mmu_context.h>
-#include <asm/smp.h>
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/smtc_ipi.h>
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -73,11 +73,19 @@ void prom_init_secondary(void)
#endif /* CONFIG_MIPS_MT_SMTC */
}
+void plat_smp_setup(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (read_c0_config3() & (1 << 2))
+ mipsmt_build_cpu_map(0);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
/*
* Platform SMP pre-initialization
*/
-void prom_prepare_cpus(unsigned int max_cpus)
+void plat_prepare_cpus(unsigned int max_cpus)
{
#ifdef CONFIG_MIPS_MT_SMTC
/*
@@ -85,8 +93,8 @@ void prom_prepare_cpus(unsigned int max_cpus)
* but it may be multithreaded.
*/
- if (read_c0_config3() & (1<<2)) {
- mipsmt_prepare_cpus(max_cpus);
+ if (read_c0_config3() & (1 << 2)) {
+ mipsmt_prepare_cpus();
}
#endif /* CONFIG_MIPS_MT_SMTC */
}
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mipssim/sim_time.c
index 7224ffe31d36..874a18e8ac24 100644
--- a/arch/mips/mips-boards/sim/sim_time.c
+++ b/arch/mips/mipssim/sim_time.c
@@ -5,10 +5,10 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>
+#include <linux/mipsregs.h>
+#include <linux/smp.h>
#include <linux/timex.h>
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
#include <asm/hardirq.h>
#include <asm/div64.h>
#include <asm/cpu.h>
@@ -16,7 +16,6 @@
#include <asm/irq.h>
#include <asm/mc146818-time.h>
#include <asm/msc01_ic.h>
-#include <asm/smp.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/prom.h>
@@ -37,8 +36,7 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
#ifndef CONFIG_MIPS_MT_SMTC
if (cpu == 0) {
timer_interrupt(irq, dev_id);
- }
- else {
+ } else {
/* Everyone else needs to reset the timer int here as
ll_local_timer_interrupt doesn't */
/*
@@ -76,8 +74,10 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
irq_enable_hazard();
evpe(vpflags);
- if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id);
- else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+ if (cpu_data[cpu].vpe_id == 0)
+ timer_interrupt(irq, dev_id);
+ else
+ write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
smtc_timer_broadcast(cpu_data[cpu].vpe_id);
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -85,7 +85,8 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
/*
* every CPU should do profiling and process accounting
*/
- local_timer_interrupt (irq, dev_id);
+ local_timer_interrupt (irq, dev_id);
+
return IRQ_HANDLED;
#else
return timer_interrupt (irq, dev_id);
@@ -152,17 +153,15 @@ void __init sim_time_init(void)
local_irq_save(flags);
-
- /* Set Data mode - binary. */
+ /* Set Data mode - binary. */
CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
-
est_freq = estimate_cpu_frequency ();
- printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
- (est_freq%1000000)*100/1000000);
+ printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
+ (est_freq % 1000000) * 100 / 1000000);
- cpu_khz = est_freq / 1000;
+ cpu_khz = est_freq / 1000;
local_irq_restore(flags);
}
@@ -180,8 +179,7 @@ void __init plat_timer_setup(struct irqaction *irq)
if (cpu_has_veic) {
set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
- }
- else {
+ } else {
if (cpu_has_vint)
set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 293697b15603..19a0e544c4e9 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
obj-$(CONFIG_64BIT) += pgtable-64.o
obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_CPU_LOONGSON2) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index df04a315d830..be96231dccb6 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -335,6 +335,10 @@ static void r4k_flush_cache_all(void)
static inline void local_r4k___flush_cache_all(void * args)
{
+#if defined(CONFIG_CPU_LOONGSON2)
+ r4k_blast_scache();
+ return;
+#endif
r4k_blast_dcache();
r4k_blast_icache();
@@ -848,6 +852,24 @@ static void __init probe_pcache(void)
c->options |= MIPS_CPU_PREFETCH;
break;
+ case CPU_LOONGSON2:
+ icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ if (prid & 0x3)
+ c->icache.ways = 4;
+ else
+ c->icache.ways = 2;
+ c->icache.waybit = 0;
+
+ dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ if (prid & 0x3)
+ c->dcache.ways = 4;
+ else
+ c->dcache.ways = 2;
+ c->dcache.waybit = 0;
+ break;
+
default:
if (!(config & MIPS_CONF_M))
panic("Don't know how to probe P-caches on this cpu.");
@@ -963,6 +985,14 @@ static void __init probe_pcache(void)
break;
}
+#ifdef CONFIG_CPU_LOONGSON2
+ /*
+ * LOONGSON2 has 4 way icache, but when using indexed cache op,
+ * one op will act on all 4 ways
+ */
+ c->icache.ways = 1;
+#endif
+
printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
icache_size >> 10,
cpu_has_vtag_icache ? "virtually tagged" : "physically tagged",
@@ -1036,6 +1066,24 @@ static int __init probe_scache(void)
return 1;
}
+#if defined(CONFIG_CPU_LOONGSON2)
+static void __init loongson2_sc_init(void)
+{
+ struct cpuinfo_mips *c = &current_cpu_data;
+
+ scache_size = 512*1024;
+ c->scache.linesz = 32;
+ c->scache.ways = 4;
+ c->scache.waybit = 0;
+ c->scache.waysize = scache_size / (c->scache.ways);
+ c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
+ pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
+ scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+
+ c->options |= MIPS_CPU_INCLUSIVE_CACHES;
+}
+#endif
+
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
extern int mips_sc_init(void);
@@ -1085,6 +1133,12 @@ static void __init setup_scache(void)
#endif
return;
+#if defined(CONFIG_CPU_LOONGSON2)
+ case CPU_LOONGSON2:
+ loongson2_sc_init();
+ return;
+#endif
+
default:
if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
c->isa_level == MIPS_CPU_ISA_M32R2 ||
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 9ea460b16bda..6f9bd7fbd481 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -476,7 +476,7 @@ static __init void probe_cache_sizes(void)
* memory management function pointers, as well as initialize
* the caches and tlbs
*/
-void sb1_cache_init(void)
+void __init sb1_cache_init(void)
{
extern char except_vec2_sb1;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index abf99b1eba13..81f925a9a731 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -6,6 +6,8 @@
* Copyright (C) 1994 - 2003, 07 by Ralf Baechle (ralf@linux-mips.org)
* Copyright (C) 2007 MIPS Technologies, Inc.
*/
+#include <linux/fs.h>
+#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -164,3 +166,11 @@ void __init cpu_cache_init(void)
panic(cache_panic);
}
+
+int __weak __uncached_access(struct file *file, unsigned long addr)
+{
+ if (file->f_flags & O_SYNC)
+ return 1;
+
+ return addr >= __pa(high_memory);
+}
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 65160d4984d9..dcd6913dc1ff 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -48,6 +48,22 @@ extern void build_tlb_refill_handler(void);
#endif /* CONFIG_MIPS_MT_SMTC */
+#if defined(CONFIG_CPU_LOONGSON2)
+/*
+ * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
+ * unfortrunately, itlb is not totally transparent to software.
+ */
+#define FLUSH_ITLB write_c0_diag(4);
+
+#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC) write_c0_diag(4); }
+
+#else
+
+#define FLUSH_ITLB
+#define FLUSH_ITLB_VM(vma)
+
+#endif
+
void local_flush_tlb_all(void)
{
unsigned long flags;
@@ -73,6 +89,7 @@ void local_flush_tlb_all(void)
}
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
+ FLUSH_ITLB;
EXIT_CRITICAL(flags);
}
@@ -136,6 +153,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
} else {
drop_mmu_context(mm, cpu);
}
+ FLUSH_ITLB;
EXIT_CRITICAL(flags);
}
}
@@ -178,6 +196,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
} else {
local_flush_tlb_all();
}
+ FLUSH_ITLB;
EXIT_CRITICAL(flags);
}
@@ -210,6 +229,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
finish:
write_c0_entryhi(oldpid);
+ FLUSH_ITLB_VM(vma);
EXIT_CRITICAL(flags);
}
}
@@ -241,7 +261,7 @@ void local_flush_tlb_one(unsigned long page)
tlbw_use_hazard();
}
write_c0_entryhi(oldpid);
-
+ FLUSH_ITLB;
EXIT_CRITICAL(flags);
}
@@ -293,6 +313,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
else
tlb_write_indexed();
tlbw_use_hazard();
+ FLUSH_ITLB_VM(vma);
EXIT_CRITICAL(flags);
}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index e7149290d1cb..4ec0964b8394 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -893,6 +893,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
case CPU_4KSC:
case CPU_20KC:
case CPU_25KF:
+ case CPU_LOONGSON2:
tlbw(p);
break;
@@ -1276,7 +1277,8 @@ static void __init build_r4000_tlb_refill_handler(void)
* need three, with the second nop'ed and the third being
* unused.
*/
-#ifdef CONFIG_32BIT
+ /* Loongson2 ebase is different than r4k, we have more space */
+#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
if ((p - tlb_handler) > 64)
panic("TLB refill handler space exceeded");
#else
@@ -1289,7 +1291,7 @@ static void __init build_r4000_tlb_refill_handler(void)
/*
* Now fold the handler in the TLB refill handler space.
*/
-#ifdef CONFIG_32BIT
+#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
f = final_handler;
/* Simplest case, just copy the handler. */
copy_handler(relocs, labels, tlb_handler, p, f);
@@ -1336,7 +1338,7 @@ static void __init build_r4000_tlb_refill_handler(void)
final_len);
f = final_handler;
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2)
if (final_len > 32)
final_len = 64;
else
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
deleted file mode 100644
index d5a090a85a15..000000000000
--- a/arch/mips/momentum/ocelot_3/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-3 board.
-#
-# 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).
-#
-obj-y += irq.o platform.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
deleted file mode 100644
index 3862d1d1add4..000000000000
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-static struct irqaction cascade_mv64340 = {
- no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
-};
-
-void __init arch_init_irq(void)
-{
- /*
- * Clear all of the interrupts while we change the able around a bit.
- * int-handler is not on bootstrap
- */
- clear_c0_status(ST0_IM | ST0_BEV);
-
- rm7k_cpu_irq_init();
-
- /* set up the cascading interrupts */
- setup_irq(8, &cascade_mv64340); /* unmask intControl IM8, IRQ 9 */
- mv64340_irq_init(16);
-
- set_c0_status(ST0_IM); /* IE in the status register */
-
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_cause() & read_c0_status();
-
- if (pending & STATUSF_IP0)
- do_IRQ(0);
- else if (pending & STATUSF_IP1)
- do_IRQ(1);
- else if (pending & STATUSF_IP2)
- do_IRQ(2);
- else if (pending & STATUSF_IP3)
- do_IRQ(3);
- else if (pending & STATUSF_IP4)
- do_IRQ(4);
- else if (pending & STATUSF_IP5)
- do_IRQ(5);
- else if (pending & STATUSF_IP6)
- do_IRQ(6);
- else if (pending & STATUSF_IP7)
- do_IRQ(7);
- else {
- /*
- * Now look at the extended interrupts
- */
- pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
-
- if (pending & STATUSF_IP8)
- ll_mv64340_irq();
- else
- spurious_interrupt();
- }
-}
diff --git a/arch/mips/momentum/ocelot_3/platform.c b/arch/mips/momentum/ocelot_3/platform.c
deleted file mode 100644
index 44e4c3fc7403..000000000000
--- a/arch/mips/momentum/ocelot_3/platform.c
+++ /dev/null
@@ -1,208 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "ocelot_3_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
- [0] = {
- .name = "ethernet shared base",
- .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
- .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
- MV643XX_ETH_SHARED_REGS_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
- .name = MV643XX_ETH_SHARED_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
- .resource = mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE 0xfe000000UL
-#define MV_SRAM_SIZE (256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-#define MV64x60_IRQ_ETH_2 50
-
-static struct resource mv64x60_eth0_resources[] = {
- [0] = {
- .name = "eth0 irq",
- .start = MV64x60_IRQ_ETH_0,
- .end = MV64x60_IRQ_ETH_0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
- .port_number = 0,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH0,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
- .name = MV643XX_ETH_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv64x60_eth0_resources),
- .resource = mv64x60_eth0_resources,
- .dev = {
- .platform_data = &eth0_pd,
- },
-};
-
-static struct resource mv64x60_eth1_resources[] = {
- [0] = {
- .name = "eth1 irq",
- .start = MV64x60_IRQ_ETH_1,
- .end = MV64x60_IRQ_ETH_1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
- .port_number = 1,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH1,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
- .name = MV643XX_ETH_NAME,
- .id = 1,
- .num_resources = ARRAY_SIZE(mv64x60_eth1_resources),
- .resource = mv64x60_eth1_resources,
- .dev = {
- .platform_data = &eth1_pd,
- },
-};
-
-static struct resource mv64x60_eth2_resources[] = {
- [0] = {
- .name = "eth2 irq",
- .start = MV64x60_IRQ_ETH_2,
- .end = MV64x60_IRQ_ETH_2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth2_pd = {
- .port_number = 2,
-};
-
-static struct platform_device eth2_device = {
- .name = MV643XX_ETH_NAME,
- .id = 2,
- .num_resources = ARRAY_SIZE(mv64x60_eth2_resources),
- .resource = mv64x60_eth2_resources,
- .dev = {
- .platform_data = &eth2_pd,
- },
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
- &mv643xx_eth_shared_device,
- &eth0_device,
- &eth1_device,
- &eth2_device,
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
- /* place the data */
- OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock on */
- OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock off and read-strobe */
- OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
- /* return the data */
- return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
- u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int i,j;
-
- for (i = 0; i < 12; i++)
- exchange_bit(read_opcode[i], 1);
-
- for (j = 0; j < 6; j++) {
- dest[j] = 0;
- for (i = 0; i < 8; i++) {
- dest[j] <<= 1;
- dest[j] |= exchange_bit(0, 1);
- }
- }
-
- /* turn off CS */
- exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
- unsigned int add)
-{
- int i;
-
- BUG_ON(add >= 256);
-
- for (i = ETH_ALEN; i >= 0; i--) {
- dst[i] = src[i] + add;
- add = dst[i] < src[i]; /* compute carry */
- }
-
- WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
- unsigned char mac[ETH_ALEN];
- int ret;
-
- get_mac(mac);
- eth_mac_add(eth0_pd.mac_addr, mac, 0);
- eth_mac_add(eth1_pd.mac_addr, mac, 1);
- eth_mac_add(eth2_pd.mac_addr, mac, 2);
- ret = platform_add_devices(mv643xx_eth_pd_devs,
- ARRAY_SIZE(mv643xx_eth_pd_devs));
-
- return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c
deleted file mode 100644
index 8e02df63578a..000000000000
--- a/arch/mips/momentum/ocelot_3/prom.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- */
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-#include "ocelot_3_fpga.h"
-
-struct callvectors* debug_vectors;
-extern unsigned long marvell_base;
-extern unsigned long cpu_clock;
-
-const char *get_system_type(void)
-{
- return "Momentum Ocelot-3";
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
- addr &= 0xffffffff;
- return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
- unsigned long ul;
- unsigned char *puc, uc;
-
- args += (arc * 4);
- ul = (unsigned long)signext(args);
- puc = (unsigned char *)ul;
- if (puc == 0)
- return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
- uc = *puc++;
- ul = (unsigned long)uc;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 24);
-#else /* CONFIG_CPU_LITTLE_ENDIAN */
- uc = *puc++;
- ul = ((unsigned long)uc) << 24;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= ((unsigned long)uc);
-#endif /* CONFIG_CPU_LITTLE_ENDIAN */
- ul = signext(ul);
- return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
- unsigned long args;
- char *p;
-
- args = signext(addrin);
- p = (char *)get_arg(args, arg_index);
-
- return p;
-}
-#endif /* CONFIG_64BIT */
-
-void __init prom_init(void)
-{
- int argc = fw_arg0;
- char **arg = (char **) fw_arg1;
- char **env = (char **) fw_arg2;
- struct callvectors *cv = (struct callvectors *) fw_arg3;
- int i;
-
-#ifdef CONFIG_64BIT
- char *ptr;
- printk("prom_init - MIPS64\n");
-
- /* save the PROM vectors for debugging use */
- debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
-
- for (i = 1; i < argc; i++) {
- ptr = (char *)arg64((unsigned long)arg, i);
- if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
- sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, ptr);
- strcat(arcs_cmdline, " ");
- }
- i = 0;
-
- while (1) {
- ptr = (char *)arg64((unsigned long)env, i);
- if (! ptr)
- break;
-
- if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(ptr + strlen("gtbase="),
- NULL, 16);
-
- if ((marvell_base & 0xffffffff00000000) == 0)
- marvell_base |= 0xffffffff00000000;
-
- printk("marvell_base set to 0x%016lx\n", marvell_base);
- }
- if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
- NULL, 10);
- printk("cpu_clock set to %d\n", cpu_clock);
- }
- i++;
- }
- printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else /* CONFIG_64BIT */
-
- /* save the PROM vectors for debugging use */
- debug_vectors = cv;
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
- for (i = 1; i < argc; i++) {
- if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
- >= sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, arg[i]);
- strcat(arcs_cmdline, " ");
- }
-
- while (*env) {
- if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(*env + strlen("gtbase="),
- NULL, 16);
- }
- if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(*env + strlen("cpuclock="),
- NULL, 10);
- }
- env++;
- }
-#endif /* CONFIG_64BIT */
-
- mips_machgroup = MACH_GROUP_MOMENCO;
- mips_machtype = MACH_MOMENCO_OCELOT_3;
-
-#ifndef CONFIG_64BIT
- debug_vectors->printf("Booting Linux kernel...\n");
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-}
diff --git a/arch/mips/momentum/ocelot_3/reset.c b/arch/mips/momentum/ocelot_3/reset.c
deleted file mode 100644
index 9d86d2468376..000000000000
--- a/arch/mips/momentum/ocelot_3/reset.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 01, 05 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void momenco_ocelot_restart(char *command)
-{
- /* base address of timekeeper portion of part */
- void *nvram = (void *) 0xfc807000L;
-
- /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
- writeb(0x84, nvram + 0xff7);
-
- /* wait for the watchdog to go off */
- mdelay(100+(1000/16));
-
- /* if the watchdog fails for some reason, let people know */
- printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
- printk(KERN_NOTICE "\n** You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
- momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
deleted file mode 100644
index ff0829f81116..000000000000
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * setup.c
- *
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-3 board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 01, 05 - 06 Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- * mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mc146818rtc.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-#include <linux/pm.h>
-#include <linux/bcd.h>
-
-#include <asm/time.h>
-#include <asm/page.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/mc146818rtc.h>
-#include <asm/tlbflush.h>
-#include "ocelot_3_fpga.h"
-
-/* Marvell Discovery Register Base */
-unsigned long marvell_base = (signed)0xf4000000;
-
-/* CPU clock */
-unsigned long cpu_clock;
-
-/* RTC/NVRAM */
-unsigned char* rtc_base = (unsigned char*)(signed)0xfc800000;
-
-/* FPGA Base */
-unsigned long ocelot_fpga_base = (signed)0xfc000000;
-
-/* Serial base */
-unsigned long uart_base = (signed)0xfd000000;
-
-/*
- * Marvell Discovery SRAM. This is one place where Ethernet
- * Tx and Rx descriptors can be placed to improve performance
- */
-extern unsigned long mv64340_sram_base;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-void momenco_time_init(void);
-static char reset_reason;
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
- unsigned long entryhi, unsigned long pagemask);
-
-static inline unsigned long ENTRYLO(unsigned long paddr)
-{
- return ((paddr & PAGE_MASK) |
- (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
- _CACHE_UNCACHED)) >> 6;
-}
-
-void __init bus_error_init(void)
-{
- /* nothing */
-}
-
-/*
- * setup code for a handoff from a version 2 PMON 2000 PROM
- */
-void setup_wired_tlb_entries(void)
-{
- write_c0_wired(0);
- local_flush_tlb_all();
-
- /* marvell and extra space */
- add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), (signed)0xf4000000, PM_64K);
-
- /* fpga, rtc, and uart */
- add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M);
-}
-
-unsigned long m48t37y_get_time(void)
-{
- unsigned int year, month, day, hour, min, sec;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* stop the update */
- rtc_base[0x7ff8] = 0x40;
-
- year = BCD2BIN(rtc_base[0x7fff]);
- year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
- month = BCD2BIN(rtc_base[0x7ffe]);
-
- day = BCD2BIN(rtc_base[0x7ffd]);
-
- hour = BCD2BIN(rtc_base[0x7ffb]);
- min = BCD2BIN(rtc_base[0x7ffa]);
- sec = BCD2BIN(rtc_base[0x7ff9]);
-
- /* start the update */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
- struct rtc_time tm;
- unsigned long flags;
-
- /* convert to a more useful format -- note months count from 0 */
- to_tm(sec, &tm);
- tm.tm_mon += 1;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* enable writing */
- rtc_base[0x7ff8] = 0x80;
-
- /* year */
- rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
- rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
- /* month */
- rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
- /* day */
- rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
- /* hour/min/sec */
- rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
- rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
- rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
- /* day of week -- not really used, but let's keep it up-to-date */
- rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
- /* disable writing */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(7, irq); /* Timer interrupt, unmask status IM7 */
-}
-
-void momenco_time_init(void)
-{
- setup_wired_tlb_entries();
-
- /*
- * Ocelot-3 board has been built with both
- * the Rm7900 and the Rm7065C
- */
- mips_hpt_frequency = cpu_clock / 2;
-
- rtc_mips_get_time = m48t37y_get_time;
- rtc_mips_set_time = m48t37y_set_time;
-}
-
-/*
- * PCI Support for Ocelot-3
- */
-
-/* Bus #0 IO and MEM space */
-#define OCELOT_3_PCI_IO_0_START 0xe0000000
-#define OCELOT_3_PCI_IO_0_SIZE 0x08000000
-#define OCELOT_3_PCI_MEM_0_START 0xc0000000
-#define OCELOT_3_PCI_MEM_0_SIZE 0x10000000
-
-/* Bus #1 IO and MEM space */
-#define OCELOT_3_PCI_IO_1_START 0xe8000000
-#define OCELOT_3_PCI_IO_1_SIZE 0x08000000
-#define OCELOT_3_PCI_MEM_1_START 0xd0000000
-#define OCELOT_3_PCI_MEM_1_SIZE 0x10000000
-
-static struct resource mv_pci_io_mem0_resource = {
- .name = "MV64340 PCI0 IO MEM",
- .start = OCELOT_3_PCI_IO_0_START,
- .end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE - 1,
- .flags = IORESOURCE_IO,
-};
-
-static struct resource mv_pci_io_mem1_resource = {
- .name = "MV64340 PCI1 IO MEM",
- .start = OCELOT_3_PCI_IO_1_START,
- .end = OCELOT_3_PCI_IO_1_START + OCELOT_3_PCI_IO_1_SIZE - 1,
- .flags = IORESOURCE_IO,
-};
-
-static struct resource mv_pci_mem0_resource = {
- .name = "MV64340 PCI0 MEM",
- .start = OCELOT_3_PCI_MEM_0_START,
- .end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct resource mv_pci_mem1_resource = {
- .name = "MV64340 PCI1 MEM",
- .start = OCELOT_3_PCI_MEM_1_START,
- .end = OCELOT_3_PCI_MEM_1_START + OCELOT_3_PCI_MEM_1_SIZE - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem0_resource,
- .io_resource = &mv_pci_io_mem0_resource,
- },
- .config_addr = MV64340_PCI_0_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem1_resource,
- .io_resource = &mv_pci_io_mem1_resource,
- },
- .config_addr = MV64340_PCI_1_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init int __init ja_pci_init(void)
-{
- uint32_t enable;
- extern int pci_probe_only;
-
- /* PMON will assign PCI resources */
- pci_probe_only = 1;
-
- enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
- /*
- * We require at least one enabled I/O or PCI memory window or we
- * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
- */
- if (enable & (0x01 << 9) || enable & (0x01 << 10))
- register_pci_controller(&mv_bus0_controller.pcic);
-
- if (enable & (0x01 << 14) || enable & (0x01 << 15))
- register_pci_controller(&mv_bus1_controller.pcic);
-
- ioport_resource.end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE +
- OCELOT_3_PCI_IO_1_SIZE - 1;
-
- iomem_resource.end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE +
- OCELOT_3_PCI_MEM_1_SIZE - 1;
-
- set_io_port_base(OCELOT_3_PCI_IO_0_START); /* mips_io_port_base */
-
- return 0;
-}
-
-arch_initcall(ja_pci_init);
-
-void __init plat_mem_setup(void)
-{
- unsigned int tmpword;
-
- board_time_init = momenco_time_init;
-
- _machine_restart = momenco_ocelot_restart;
- _machine_halt = momenco_ocelot_halt;
- pm_power_off = momenco_ocelot_power_off;
-
- /* Wired TLB entries */
- setup_wired_tlb_entries();
-
- /* shut down ethernet ports, just to be sure our memory doesn't get
- * corrupted by random ethernet traffic.
- */
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
- do {}
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-
- /* Turn off the Bit-Error LED */
- OCELOT_FPGA_WRITE(0x80, CLR);
-
- tmpword = OCELOT_FPGA_READ(BOARDREV);
- if (tmpword < 26)
- printk("Momenco Ocelot-3: Board Assembly Rev. %c\n",
- 'A'+tmpword);
- else
- printk("Momenco Ocelot-3: Board Assembly Revision #0x%x\n",
- tmpword);
-
- tmpword = OCELOT_FPGA_READ(FPGA_REV);
- printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
- tmpword = OCELOT_FPGA_READ(RESET_STATUS);
- printk("Reset reason: 0x%x\n", tmpword);
- switch (tmpword) {
- case 0x1:
- printk(" - Power-up reset\n");
- break;
- case 0x2:
- printk(" - Push-button reset\n");
- break;
- case 0x4:
- printk(" - cPCI bus reset\n");
- break;
- case 0x8:
- printk(" - Watchdog reset\n");
- break;
- case 0x10:
- printk(" - Software reset\n");
- break;
- default:
- printk(" - Unknown reset cause\n");
- }
- reset_reason = tmpword;
- OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
-
- tmpword = OCELOT_FPGA_READ(CPCI_ID);
- printk("cPCI ID register: 0x%02x\n", tmpword);
- printk(" - Slot number: %d\n", tmpword & 0x1f);
- printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
- printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
-
- tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
- printk("Board Status register: 0x%02x\n", tmpword);
- printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
- printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
- printk(" - L3 cache size: %d MB\n", (1<<((tmpword&12) >> 2))&~1);
-
- /* Support for 128 MB memory */
- add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
deleted file mode 100644
index d69161aa1675..000000000000
--- a/arch/mips/momentum/ocelot_c/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-C and -CS boards.
-#
-
-obj-y += cpci-irq.o irq.o platform.o prom.o reset.o \
- setup.o uart-irq.o
-
-obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
deleted file mode 100644
index 186a140fd2a9..000000000000
--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_c/cpci-irq.c
- * Interrupt routines for cpci. Interrupt numbers are assigned from
- * CPCI_IRQ_BASE to CPCI_IRQ_BASE+8 (8 interrupt sources).
- *
- * Note that the high-level software will need to be careful about using
- * these interrupts. If this board is asserting a cPCI interrupt, it will
- * also see the asserted interrupt. Care must be taken to avoid an
- * interrupt flood.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include "ocelot_c_fpga.h"
-
-#define CPCI_IRQ_BASE 8
-
-static inline int ls1bit8(unsigned int x)
-{
- int b = 7, s;
-
- s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s;
- s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s;
- s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s;
-
- return b;
-}
-
-/* mask off an interrupt -- 0 is enable, 1 is disable */
-static inline void mask_cpci_irq(unsigned int irq)
-{
- uint32_t value;
-
- value = OCELOT_FPGA_READ(INTMASK);
- value |= 1 << (irq - CPCI_IRQ_BASE);
- OCELOT_FPGA_WRITE(value, INTMASK);
-
- /* read the value back to assure that it's really been written */
- value = OCELOT_FPGA_READ(INTMASK);
-}
-
-/* unmask an interrupt -- 0 is enable, 1 is disable */
-static inline void unmask_cpci_irq(unsigned int irq)
-{
- uint32_t value;
-
- value = OCELOT_FPGA_READ(INTMASK);
- value &= ~(1 << (irq - CPCI_IRQ_BASE));
- OCELOT_FPGA_WRITE(value, INTMASK);
-
- /* read the value back to assure that it's really been written */
- value = OCELOT_FPGA_READ(INTMASK);
-}
-
-/*
- * Interrupt handler for interrupts coming from the FPGA chip.
- * It could be built in ethernet ports etc...
- */
-void ll_cpci_irq(void)
-{
- unsigned int irq_src, irq_mask;
-
- /* read the interrupt status registers */
- irq_src = OCELOT_FPGA_READ(INTSTAT);
- irq_mask = OCELOT_FPGA_READ(INTMASK);
-
- /* mask for just the interrupts we want */
- irq_src &= ~irq_mask;
-
- do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE);
-}
-
-struct irq_chip cpci_irq_type = {
- .name = "CPCI/FPGA",
- .ack = mask_cpci_irq,
- .mask = mask_cpci_irq,
- .mask_ack = mask_cpci_irq,
- .unmask = unmask_cpci_irq,
-};
-
-void cpci_irq_init(void)
-{
- int i;
-
- for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++)
- set_irq_chip_and_handler(i, &cpci_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c
deleted file mode 100644
index 32d6fb4ee679..000000000000
--- a/arch/mips/momentum/ocelot_c/dbg_io.c
+++ /dev/null
@@ -1,121 +0,0 @@
-
-#include <asm/serial.h> /* For the serial port location and base baud */
-
-/* --- CONFIG --- */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-/* --- END OF CONFIG --- */
-
-#define UART16550_BAUD_2400 2400
-#define UART16550_BAUD_4800 4800
-#define UART16550_BAUD_9600 9600
-#define UART16550_BAUD_19200 19200
-#define UART16550_BAUD_38400 38400
-#define UART16550_BAUD_57600 57600
-#define UART16550_BAUD_115200 115200
-
-#define UART16550_PARITY_NONE 0
-#define UART16550_PARITY_ODD 0x08
-#define UART16550_PARITY_EVEN 0x18
-#define UART16550_PARITY_MARK 0x28
-#define UART16550_PARITY_SPACE 0x38
-
-#define UART16550_DATA_5BIT 0x0
-#define UART16550_DATA_6BIT 0x1
-#define UART16550_DATA_7BIT 0x2
-#define UART16550_DATA_8BIT 0x3
-
-#define UART16550_STOP_1BIT 0x0
-#define UART16550_STOP_2BIT 0x4
-
-/* ----------------------------------------------------- */
-
-/* === CONFIG === */
-
-/* [jsun] we use the second serial port for kdb */
-#define BASE OCELOT_SERIAL1_BASE
-#define MAX_BAUD OCELOT_BASE_BAUD
-
-/* === END OF CONFIG === */
-
-#define REG_OFFSET 4
-
-/* register offset */
-#define OFS_RCV_BUFFER 0
-#define OFS_TRANS_HOLD 0
-#define OFS_SEND_BUFFER 0
-#define OFS_INTR_ENABLE (1*REG_OFFSET)
-#define OFS_INTR_ID (2*REG_OFFSET)
-#define OFS_DATA_FORMAT (3*REG_OFFSET)
-#define OFS_LINE_CONTROL (3*REG_OFFSET)
-#define OFS_MODEM_CONTROL (4*REG_OFFSET)
-#define OFS_RS232_OUTPUT (4*REG_OFFSET)
-#define OFS_LINE_STATUS (5*REG_OFFSET)
-#define OFS_MODEM_STATUS (6*REG_OFFSET)
-#define OFS_RS232_INPUT (6*REG_OFFSET)
-#define OFS_SCRATCH_PAD (7*REG_OFFSET)
-
-#define OFS_DIVISOR_LSB (0*REG_OFFSET)
-#define OFS_DIVISOR_MSB (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
-#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
- /* disable interrupts */
- UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
- /* set up baud rate */
- {
- uint32 divisor;
-
- /* set DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
- /* set divisor */
- divisor = MAX_BAUD / baud;
- UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
- UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
- /* clear DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
- }
-
- /* set data format */
- UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-static int remoteDebugInitialized = 0;
-
-uint8 getDebugChar(void)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(UART16550_BAUD_38400,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
- return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(UART16550_BAUD_38400,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
- UART16550_WRITE(OFS_SEND_BUFFER, byte);
- return 1;
-}
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
deleted file mode 100644
index 844d566c9de3..000000000000
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <linux/mv643xx.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-extern void uart_irq_init(void);
-extern void cpci_irq_init(void);
-
-static struct irqaction cascade_fpga = {
- no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via FPGA", NULL, NULL
-};
-
-static struct irqaction cascade_mv64340 = {
- no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
-};
-
-extern void ll_uart_irq(void);
-extern void ll_cpci_irq(void);
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-
- if (pending & STATUSF_IP0)
- do_IRQ(0);
- else if (pending & STATUSF_IP1)
- do_IRQ(1);
- else if (pending & STATUSF_IP2)
- do_IRQ(2);
- else if (pending & STATUSF_IP3)
- ll_uart_irq();
- else if (pending & STATUSF_IP4)
- do_IRQ(4);
- else if (pending & STATUSF_IP5)
- ll_cpci_irq();
- else if (pending & STATUSF_IP6)
- ll_mv64340_irq();
- else if (pending & STATUSF_IP7)
- do_IRQ(7);
- else
- spurious_interrupt();
-}
-
-void __init arch_init_irq(void)
-{
- /*
- * Clear all of the interrupts while we change the able around a bit.
- * int-handler is not on bootstrap
- */
- clear_c0_status(ST0_IM);
-
- mips_cpu_irq_init();
-
- /* set up the cascading interrupts */
- setup_irq(3, &cascade_fpga);
- setup_irq(5, &cascade_fpga);
- setup_irq(6, &cascade_mv64340);
-
- mv64340_irq_init(16);
- uart_irq_init();
- cpci_irq_init();
-}
diff --git a/arch/mips/momentum/ocelot_c/platform.c b/arch/mips/momentum/ocelot_c/platform.c
deleted file mode 100644
index 7780aa0c6555..000000000000
--- a/arch/mips/momentum/ocelot_c/platform.c
+++ /dev/null
@@ -1,183 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "ocelot_c_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
- [0] = {
- .name = "ethernet shared base",
- .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
- .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
- MV643XX_ETH_SHARED_REGS_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
- .name = MV643XX_ETH_SHARED_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
- .resource = mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE 0xfe000000UL
-#define MV_SRAM_SIZE (256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-
-static struct resource mv64x60_eth0_resources[] = {
- [0] = {
- .name = "eth0 irq",
- .start = MV64x60_IRQ_ETH_0,
- .end = MV64x60_IRQ_ETH_0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
- .port_number = 0,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH0,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
- .name = MV643XX_ETH_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv64x60_eth0_resources),
- .resource = mv64x60_eth0_resources,
- .dev = {
- .platform_data = &eth0_pd,
- },
-};
-
-static struct resource mv64x60_eth1_resources[] = {
- [0] = {
- .name = "eth1 irq",
- .start = MV64x60_IRQ_ETH_1,
- .end = MV64x60_IRQ_ETH_1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
- .port_number = 1,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH1,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
- .name = MV643XX_ETH_NAME,
- .id = 1,
- .num_resources = ARRAY_SIZE(mv64x60_eth1_resources),
- .resource = mv64x60_eth1_resources,
- .dev = {
- .platform_data = &eth1_pd,
- },
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
- &mv643xx_eth_shared_device,
- &eth0_device,
- &eth1_device,
- /* The third port is not wired up on the Ocelot C */
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
- /* place the data */
- OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock on */
- OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock off and read-strobe */
- OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
- /* return the data */
- return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
- u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int i,j;
-
- for (i = 0; i < 12; i++)
- exchange_bit(read_opcode[i], 1);
-
- for (j = 0; j < 6; j++) {
- dest[j] = 0;
- for (i = 0; i < 8; i++) {
- dest[j] <<= 1;
- dest[j] |= exchange_bit(0, 1);
- }
- }
-
- /* turn off CS */
- exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
- unsigned int add)
-{
- int i;
-
- BUG_ON(add >= 256);
-
- for (i = ETH_ALEN; i >= 0; i--) {
- dst[i] = src[i] + add;
- add = dst[i] < src[i]; /* compute carry */
- }
-
- WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
- unsigned char mac[ETH_ALEN];
- int ret;
-
- get_mac(mac);
- eth_mac_add(eth0_pd.mac_addr, mac, 0);
- eth_mac_add(eth1_pd.mac_addr, mac, 1);
- ret = platform_add_devices(mv643xx_eth_pd_devs,
- ARRAY_SIZE(mv643xx_eth_pd_devs));
-
- return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
deleted file mode 100644
index b689ceea8cfb..000000000000
--- a/arch/mips/momentum/ocelot_c/prom.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-
-#include "ocelot_c_fpga.h"
-
-struct callvectors* debug_vectors;
-
-extern unsigned long marvell_base;
-extern unsigned int cpu_clock;
-
-const char *get_system_type(void)
-{
-#ifdef CONFIG_CPU_SR71000
- return "Momentum Ocelot-CS";
-#else
- return "Momentum Ocelot-C";
-#endif
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
- addr &= 0xffffffff;
- return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
- unsigned long ul;
- unsigned char *puc, uc;
-
- args += (arc * 4);
- ul = (unsigned long)signext(args);
- puc = (unsigned char *)ul;
- if (puc == 0)
- return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
- uc = *puc++;
- ul = (unsigned long)uc;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 24);
-#else /* CONFIG_CPU_LITTLE_ENDIAN */
- uc = *puc++;
- ul = ((unsigned long)uc) << 24;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= ((unsigned long)uc);
-#endif /* CONFIG_CPU_LITTLE_ENDIAN */
- ul = signext(ul);
- return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
- unsigned long args;
- char *p;
- args = signext(addrin);
- p = (char *)get_arg(args, arg_index);
- return p;
-}
-#endif /* CONFIG_64BIT */
-
-
-void __init prom_init(void)
-{
- int argc = fw_arg0;
- char **arg = (char **) fw_arg1;
- char **env = (char **) fw_arg2;
- struct callvectors *cv = (struct callvectors *) fw_arg3;
- int i;
-
-#ifdef CONFIG_64BIT
- char *ptr;
-
- printk("prom_init - MIPS64\n");
- /* save the PROM vectors for debugging use */
- debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
-
- for (i = 1; i < argc; i++) {
- ptr = (char *)arg64((unsigned long)arg, i);
- if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
- sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, ptr);
- strcat(arcs_cmdline, " ");
- }
- i = 0;
- while (1) {
- ptr = (char *)arg64((unsigned long)env, i);
- if (! ptr)
- break;
-
- if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(ptr + strlen("gtbase="),
- NULL, 16);
-
- if ((marvell_base & 0xffffffff00000000) == 0)
- marvell_base |= 0xffffffff00000000;
-
- printk("marvell_base set to 0x%016lx\n", marvell_base);
- }
- if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
- NULL, 10);
- printk("cpu_clock set to %d\n", cpu_clock);
- }
- i++;
- }
- printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else /* CONFIG_64BIT */
- /* save the PROM vectors for debugging use */
- debug_vectors = cv;
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
- for (i = 1; i < argc; i++) {
- if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
- >= sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, arg[i]);
- strcat(arcs_cmdline, " ");
- }
-
- while (*env) {
- if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(*env + strlen("gtbase="),
- NULL, 16);
- }
- if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(*env + strlen("cpuclock="),
- NULL, 10);
- }
- env++;
- }
-#endif /* CONFIG_64BIT */
-
- mips_machgroup = MACH_GROUP_MOMENCO;
- mips_machtype = MACH_MOMENCO_OCELOT_C;
-
-#ifndef CONFIG_64BIT
- debug_vectors->printf("Booting Linux kernel...\n");
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
diff --git a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c
deleted file mode 100644
index 3fdcb64ff1e6..000000000000
--- a/arch/mips/momentum/ocelot_c/reset.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-
-void momenco_ocelot_restart(char *command)
-{
- /* base address of timekeeper portion of part */
- void *nvram = (void *)
-#ifdef CONFIG_64BIT
- 0xfffffffffc807000;
-#else
- 0xfc807000;
-#endif
-
- /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
- writeb(0x84, nvram + 0xff7);
-
- /* wait for the watchdog to go off */
- mdelay(100+(1000/16));
-
- /* if the watchdog fails for some reason, let people know */
- printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
- printk(KERN_NOTICE "\n** You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
- momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
deleted file mode 100644
index 0b6b2338cfb4..000000000000
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-C and -CS board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 2001 Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- * mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-#include <linux/timex.h>
-#include <linux/vmalloc.h>
-#include <linux/mv643xx.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/marvell.h>
-#include <linux/bootmem.h>
-#include <linux/blkdev.h>
-#include "ocelot_c_fpga.h"
-
-unsigned long marvell_base;
-unsigned int cpu_clock;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-void momenco_time_init(void);
-
-static char reset_reason;
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask);
-
-static unsigned long ENTRYLO(unsigned long paddr)
-{
- return ((paddr & PAGE_MASK) |
- (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
- _CACHE_UNCACHED)) >> 6;
-}
-
-/* setup code for a handoff from a version 2 PMON 2000 PROM */
-void PMON_v2_setup(void)
-{
- /* Some wired TLB entries for the MV64340 and perhiperals. The
- MV64340 is going to be hit on every IRQ anyway - there's
- absolutely no point in letting it be a random TLB entry, as
- it'll just cause needless churning of the TLB. And we use
- the other half for the serial port, which is just a PITA
- otherwise :)
-
- Device Physical Virtual
- MV64340 Internal Regs 0xf4000000 0xf4000000
- Ocelot-C[S] PLD (CS0) 0xfc000000 0xfc000000
- NVRAM (CS1) 0xfc800000 0xfc800000
- UARTs (CS2) 0xfd000000 0xfd000000
- Internal SRAM 0xfe000000 0xfe000000
- M-Systems DOC (CS3) 0xff000000 0xff000000
- */
- printk("PMON_v2_setup\n");
-
-#ifdef CONFIG_64BIT
- /* marvell and extra space */
- add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K);
- /* fpga, rtc, and uart */
- add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M);
- /* m-sys and internal SRAM */
- add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M);
-
- marvell_base = 0xfffffffff4000000;
-#else
- /* marvell and extra space */
- add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K);
- /* fpga, rtc, and uart */
- add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfc000000, PM_16M);
- /* m-sys and internal SRAM */
- add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M);
-
- marvell_base = 0xf4000000;
-#endif
-}
-
-unsigned long m48t37y_get_time(void)
-{
-#ifdef CONFIG_64BIT
- unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
-#else
- unsigned char* rtc_base = (unsigned char*)0xfc800000;
-#endif
- unsigned int year, month, day, hour, min, sec;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* stop the update */
- rtc_base[0x7ff8] = 0x40;
-
- year = BCD2BIN(rtc_base[0x7fff]);
- year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
- month = BCD2BIN(rtc_base[0x7ffe]);
-
- day = BCD2BIN(rtc_base[0x7ffd]);
-
- hour = BCD2BIN(rtc_base[0x7ffb]);
- min = BCD2BIN(rtc_base[0x7ffa]);
- sec = BCD2BIN(rtc_base[0x7ff9]);
-
- /* start the update */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
-#ifdef CONFIG_64BIT
- unsigned char* rtc_base = (unsigned char*)0xfffffffffc800000;
-#else
- unsigned char* rtc_base = (unsigned char*)0xfc800000;
-#endif
- struct rtc_time tm;
- unsigned long flags;
-
- /* convert to a more useful format -- note months count from 0 */
- to_tm(sec, &tm);
- tm.tm_mon += 1;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* enable writing */
- rtc_base[0x7ff8] = 0x80;
-
- /* year */
- rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
- rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
- /* month */
- rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
- /* day */
- rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
- /* hour/min/sec */
- rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
- rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
- rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
- /* day of week -- not really used, but let's keep it up-to-date */
- rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
- /* disable writing */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(7, irq);
-}
-
-void momenco_time_init(void)
-{
-#ifdef CONFIG_CPU_SR71000
- mips_hpt_frequency = cpu_clock;
-#elif defined(CONFIG_CPU_RM7000)
- mips_hpt_frequency = cpu_clock / 2;
-#else
-#error Unknown CPU for this board
-#endif
- printk("momenco_time_init cpu_clock=%d\n", cpu_clock);
-
- rtc_mips_get_time = m48t37y_get_time;
- rtc_mips_set_time = m48t37y_set_time;
-}
-
-void __init plat_mem_setup(void)
-{
- unsigned int tmpword;
-
- board_time_init = momenco_time_init;
-
- _machine_restart = momenco_ocelot_restart;
- _machine_halt = momenco_ocelot_halt;
- pm_power_off = momenco_ocelot_power_off;
-
- /*
- * initrd_start = (unsigned long)ocelot_initrd_start;
- * initrd_end = (unsigned long)ocelot_initrd_start + (ulong)ocelot_initrd_size;
- * initrd_below_start_ok = 1;
- */
-
- /* do handoff reconfiguration */
- PMON_v2_setup();
-
- /* shut down ethernet ports, just to be sure our memory doesn't get
- * corrupted by random ethernet traffic.
- */
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
- do {}
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-
- /* Turn off the Bit-Error LED */
- OCELOT_FPGA_WRITE(0x80, CLR);
-
- tmpword = OCELOT_FPGA_READ(BOARDREV);
-#ifdef CONFIG_CPU_SR71000
- if (tmpword < 26)
- printk("Momenco Ocelot-CS: Board Assembly Rev. %c\n",
- 'A'+tmpword);
- else
- printk("Momenco Ocelot-CS: Board Assembly Revision #0x%x\n",
- tmpword);
-#else
- if (tmpword < 26)
- printk("Momenco Ocelot-C: Board Assembly Rev. %c\n",
- 'A'+tmpword);
- else
- printk("Momenco Ocelot-C: Board Assembly Revision #0x%x\n",
- tmpword);
-#endif
-
- tmpword = OCELOT_FPGA_READ(FPGA_REV);
- printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
- tmpword = OCELOT_FPGA_READ(RESET_STATUS);
- printk("Reset reason: 0x%x\n", tmpword);
- switch (tmpword) {
- case 0x1:
- printk(" - Power-up reset\n");
- break;
- case 0x2:
- printk(" - Push-button reset\n");
- break;
- case 0x4:
- printk(" - cPCI bus reset\n");
- break;
- case 0x8:
- printk(" - Watchdog reset\n");
- break;
- case 0x10:
- printk(" - Software reset\n");
- break;
- default:
- printk(" - Unknown reset cause\n");
- }
- reset_reason = tmpword;
- OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
-
- tmpword = OCELOT_FPGA_READ(CPCI_ID);
- printk("cPCI ID register: 0x%02x\n", tmpword);
- printk(" - Slot number: %d\n", tmpword & 0x1f);
- printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
- printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
-
- tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
- printk("Board Status register: 0x%02x\n", tmpword);
- printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
- printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
- printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
- printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
-
- switch(tmpword &3) {
- case 3:
- /* 512MiB */
- add_memory_region(0x0, 0x200<<20, BOOT_MEM_RAM);
- break;
- case 2:
- /* 256MiB */
- add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
- break;
- case 1:
- /* 128MiB */
- add_memory_region(0x0, 0x80<<20, BOOT_MEM_RAM);
- break;
- case 0:
- /* 1GiB -- needs CONFIG_HIGHMEM */
- add_memory_region(0x0, 0x400<<20, BOOT_MEM_RAM);
- break;
- }
-}
-
-/*
- * This needs to be one of the first initcalls, because no I/O port access
- * can work before this
- */
-static int io_base_ioremap(void)
-{
- void __iomem * io_remap_range = ioremap(0xc0000000UL, 0x10000);
-
- if (!io_remap_range)
- panic("Could not ioremap I/O port range");
-
- set_io_port_base((unsigned long) io_remap_range);
-
- return 0;
-}
-
-module_init(io_base_ioremap);
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
deleted file mode 100644
index de1a31ee52f3..000000000000
--- a/arch/mips/momentum/ocelot_c/uart-irq.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_c/uart-irq.c
- * Interrupt routines for UARTs. Interrupt numbers are assigned from
- * 80 to 81 (2 interrupt sources).
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "ocelot_c_fpga.h"
-
-static inline int ls1bit8(unsigned int x)
-{
- int b = 7, s;
-
- s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s;
- s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s;
- s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s;
-
- return b;
-}
-
-/* mask off an interrupt -- 0 is enable, 1 is disable */
-static inline void mask_uart_irq(unsigned int irq)
-{
- uint8_t value;
-
- value = OCELOT_FPGA_READ(UART_INTMASK);
- value |= 1 << (irq - 74);
- OCELOT_FPGA_WRITE(value, UART_INTMASK);
-
- /* read the value back to assure that it's really been written */
- value = OCELOT_FPGA_READ(UART_INTMASK);
-}
-
-/* unmask an interrupt -- 0 is enable, 1 is disable */
-static inline void unmask_uart_irq(unsigned int irq)
-{
- uint8_t value;
-
- value = OCELOT_FPGA_READ(UART_INTMASK);
- value &= ~(1 << (irq - 74));
- OCELOT_FPGA_WRITE(value, UART_INTMASK);
-
- /* read the value back to assure that it's really been written */
- value = OCELOT_FPGA_READ(UART_INTMASK);
-}
-
-/*
- * Interrupt handler for interrupts coming from the FPGA chip.
- */
-void ll_uart_irq(void)
-{
- unsigned int irq_src, irq_mask;
-
- /* read the interrupt status registers */
- irq_src = OCELOT_FPGA_READ(UART_INTSTAT);
- irq_mask = OCELOT_FPGA_READ(UART_INTMASK);
-
- /* mask for just the interrupts we want */
- irq_src &= ~irq_mask;
-
- do_IRQ(ls1bit8(irq_src) + 74);
-}
-
-struct irq_chip uart_irq_type = {
- .name = "UART/FPGA",
- .ack = mask_uart_irq,
- .mask = mask_uart_irq,
- .mask_ack = mask_uart_irq,
- .unmask = unmask_uart_irq,
-};
-
-void uart_irq_init(void)
-{
- set_irq_chip_and_handler(80, &uart_irq_type, handle_level_irq);
- set_irq_chip_and_handler(81, &uart_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index aba3dbf47eda..f26ede001a0b 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -9,9 +9,7 @@ obj-y += pci.o pci-dac.o
#
obj-$(CONFIG_MIPS_BONITO64) += ops-bonito64.o
obj-$(CONFIG_PCI_GT64XXX_PCI0) += ops-gt64xxx_pci0.o
-obj-$(CONFIG_PCI_MARVELL) += ops-marvell.o
obj-$(CONFIG_MIPS_MSC) += ops-msc.o
-obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o
obj-$(CONFIG_MIPS_TX3927) += ops-tx3927.o
obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o
obj-$(CONFIG_NEC_CMBVR4133) += fixup-vr4133.o
@@ -22,17 +20,17 @@ obj-$(CONFIG_MARKEINS) += ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o
#
obj-$(CONFIG_BASLER_EXCITE) += ops-titan.o pci-excite.o fixup-excite.o
obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
-obj-$(CONFIG_LASAT) += pci-lasat.o
obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o
obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
-obj-$(CONFIG_MIPS_EV64120) += pci-ev64120.o
obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o
+obj-$(CONFIG_LEMOTE_FULONG) += fixup-lm2e.o ops-bonito64.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o
obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o
-obj-$(CONFIG_MOMENCO_OCELOT_3) += fixup-ocelot3.o
-obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.o
+obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
+obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
+obj-$(CONFIG_PMC_MSP7120_FPGA) += fixup-pmcmsp.o ops-pmcmsp.o
obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \
pci-yosemite.o
obj-$(CONFIG_SGI_IP27) += ops-bridge.o pci-ip27.o
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
index c6cd6e9cdfbc..45224fd2c7ba 100644
--- a/arch/mips/pci/fixup-atlas.c
+++ b/arch/mips/pci/fixup-atlas.c
@@ -58,7 +58,7 @@ static char irq_tab[][5] __initdata = {
{0, 0, 0, 0, 0 } /* 21: Unused */
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab[slot][pin];
}
diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
index c2f8304fe55b..ca0276c8070a 100644
--- a/arch/mips/pci/fixup-au1000.c
+++ b/arch/mips/pci/fixup-au1000.c
@@ -35,7 +35,7 @@
extern char irq_tab_alchemy[][5];
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_alchemy[slot][pin];
}
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
index 1e530751936c..1416bca6d1a3 100644
--- a/arch/mips/pci/fixup-capcella.c
+++ b/arch/mips/pci/fixup-capcella.c
@@ -38,7 +38,7 @@ static char irq_tab_capcella[][5] __initdata = {
[14] = { -1, INTA, INTB, INTC, INTD }
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_capcella[slot][pin];
}
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index d57ffd7242ca..7fc475f7eae5 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -161,7 +161,7 @@ static char irq_tab_raq2[] __initdata = {
[COBALT_PCICONF_ETH1] = COBALT_ETH1_IRQ
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (cobalt_board_id < COBALT_BRD_ID_QUBE2)
return irq_tab_qube1[slot];
diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c
index 7abcfd175d43..a2705895561d 100644
--- a/arch/mips/pci/fixup-emma2rh.c
+++ b/arch/mips/pci/fixup-emma2rh.c
@@ -89,7 +89,7 @@ static void __devinit emma2rh_pci_host_fixup(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
emma2rh_pci_host_fixup);
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_map[slot][pin];
}
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
index 1da696d43f00..cd64d9f177c4 100644
--- a/arch/mips/pci/fixup-excite.c
+++ b/arch/mips/pci/fixup-excite.c
@@ -21,7 +21,7 @@
#include <linux/pci.h>
#include <excite.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (pin == 0)
return -1;
diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c
index 3e66b0aa63ca..190fffd08d3e 100644
--- a/arch/mips/pci/fixup-ip32.c
+++ b/arch/mips/pci/fixup-ip32.c
@@ -39,7 +39,7 @@ static char irq_tab_mace[][5] __initdata = {
* irqs. I suppose a device without a pin A will thank us for doing it
* right if there exists such a broken piece of crap.
*/
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_mace[slot][pin];
}
diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c
index 73d18503517c..e974394be7bc 100644
--- a/arch/mips/pci/fixup-jmr3927.c
+++ b/arch/mips/pci/fixup-jmr3927.c
@@ -33,7 +33,7 @@
#include <asm/jmr3927/jmr3927.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char irq = pin;
diff --git a/arch/mips/pci/fixup-lm2e.c b/arch/mips/pci/fixup-lm2e.c
new file mode 100644
index 000000000000..e18ae4f574c1
--- /dev/null
+++ b/arch/mips/pci/fixup-lm2e.c
@@ -0,0 +1,242 @@
+/*
+ * fixup-lm2e.c
+ *
+ * Copyright (C) 2004 ICT CAS
+ * Author: Li xiaoyu, ICT CAS
+ * lixy@ict.ac.cn
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mips-boards/bonito64.h>
+
+/* South bridge slot number is set by the pci probe process */
+static u8 sb_slot = 5;
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq = 0;
+
+ if (slot == sb_slot) {
+ switch (PCI_FUNC(dev->devfn)) {
+ case 2:
+ irq = 10;
+ break;
+ case 3:
+ irq = 11;
+ break;
+ case 5:
+ irq = 9;
+ break;
+ }
+ } else {
+ irq = BONITO_IRQ_BASE + 25 + pin;
+ }
+ return irq;
+
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+static void __init loongson2e_nec_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+
+ /* Configues port 1, 2, 3, 4 to be validate*/
+ pci_read_config_dword(pdev, 0xe0, &val);
+ pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x4);
+
+ /* System clock is 48-MHz Oscillator. */
+ pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+
+static void __init loongson2e_686b_func0_fixup(struct pci_dev *pdev)
+{
+ unsigned char c;
+
+ sb_slot = PCI_SLOT(pdev->devfn);
+
+ printk(KERN_INFO "via686b fix: ISA bridge\n");
+
+ /* Enable I/O Recovery time */
+ pci_write_config_byte(pdev, 0x40, 0x08);
+
+ /* Enable ISA refresh */
+ pci_write_config_byte(pdev, 0x41, 0x01);
+
+ /* disable ISA line buffer */
+ pci_write_config_byte(pdev, 0x45, 0x00);
+
+ /* Gate INTR, and flush line buffer */
+ pci_write_config_byte(pdev, 0x46, 0xe0);
+
+ /* Disable PCI Delay Transaction, Enable EISA ports 4D0/4D1. */
+ /* pci_write_config_byte(pdev, 0x47, 0x20); */
+
+ /*
+ * enable PCI Delay Transaction, Enable EISA ports 4D0/4D1.
+ * enable time-out timer
+ */
+ pci_write_config_byte(pdev, 0x47, 0xe6);
+
+ /*
+ * enable level trigger on pci irqs: 9,10,11,13
+ * important! without this PCI interrupts won't work
+ */
+ outb(0x2e, 0x4d1);
+
+ /* 512 K PCI Decode */
+ pci_write_config_byte(pdev, 0x48, 0x01);
+
+ /* Wait for PGNT before grant to ISA Master/DMA */
+ pci_write_config_byte(pdev, 0x4a, 0x84);
+
+ /*
+ * Plug'n'Play
+ *
+ * Parallel DRQ 3, Floppy DRQ 2 (default)
+ */
+ pci_write_config_byte(pdev, 0x50, 0x0e);
+
+ /*
+ * IRQ Routing for Floppy and Parallel port
+ *
+ * IRQ 6 for floppy, IRQ 7 for parallel port
+ */
+ pci_write_config_byte(pdev, 0x51, 0x76);
+
+ /* IRQ Routing for serial ports (take IRQ 3 and 4) */
+ pci_write_config_byte(pdev, 0x52, 0x34);
+
+ /* All IRQ's level triggered. */
+ pci_write_config_byte(pdev, 0x54, 0x00);
+
+ /* route PIRQA-D irq */
+ pci_write_config_byte(pdev, 0x55, 0x90); /* bit 7-4, PIRQA */
+ pci_write_config_byte(pdev, 0x56, 0xba); /* bit 7-4, PIRQC; */
+ /* 3-0, PIRQB */
+ pci_write_config_byte(pdev, 0x57, 0xd0); /* bit 7-4, PIRQD */
+
+ /* enable function 5/6, audio/modem */
+ pci_read_config_byte(pdev, 0x85, &c);
+ c &= ~(0x3 << 2);
+ pci_write_config_byte(pdev, 0x85, c);
+
+ printk(KERN_INFO"via686b fix: ISA bridge done\n");
+}
+
+static void __init loongson2e_686b_func1_fixup(struct pci_dev *pdev)
+{
+ printk(KERN_INFO"via686b fix: IDE\n");
+
+ /* Modify IDE controller setup */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 48);
+ pci_write_config_byte(pdev, PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+ pci_write_config_byte(pdev, 0x40, 0x0b);
+ /* legacy mode */
+ pci_write_config_byte(pdev, 0x42, 0x09);
+
+#if 1/* play safe, otherwise we may see notebook's usb keyboard lockup */
+ /* disable read prefetch/write post buffers */
+ pci_write_config_byte(pdev, 0x41, 0x02);
+
+ /* use 3/4 as fifo thresh hold */
+ pci_write_config_byte(pdev, 0x43, 0x0a);
+ pci_write_config_byte(pdev, 0x44, 0x00);
+
+ pci_write_config_byte(pdev, 0x45, 0x00);
+#else
+ pci_write_config_byte(pdev, 0x41, 0xc2);
+ pci_write_config_byte(pdev, 0x43, 0x35);
+ pci_write_config_byte(pdev, 0x44, 0x1c);
+
+ pci_write_config_byte(pdev, 0x45, 0x10);
+#endif
+
+ printk(KERN_INFO"via686b fix: IDE done\n");
+}
+
+static void __init loongson2e_686b_func2_fixup(struct pci_dev *pdev)
+{
+ /* irq routing */
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 10);
+}
+
+static void __init loongson2e_686b_func3_fixup(struct pci_dev *pdev)
+{
+ /* irq routing */
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 11);
+}
+
+static void __init loongson2e_686b_func5_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+ unsigned char c;
+
+ /* enable IO */
+ pci_write_config_byte(pdev, PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+ pci_read_config_dword(pdev, 0x4, &val);
+ pci_write_config_dword(pdev, 0x4, val | 1);
+
+ /* route ac97 IRQ */
+ pci_write_config_byte(pdev, 0x3c, 9);
+
+ pci_read_config_byte(pdev, 0x8, &c);
+
+ /* link control: enable link & SGD PCM output */
+ pci_write_config_byte(pdev, 0x41, 0xcc);
+
+ /* disable game port, FM, midi, sb, enable write to reg2c-2f */
+ pci_write_config_byte(pdev, 0x42, 0x20);
+
+ /* we are using Avance logic codec */
+ pci_write_config_word(pdev, 0x2c, 0x1005);
+ pci_write_config_word(pdev, 0x2e, 0x4710);
+ pci_read_config_dword(pdev, 0x2c, &val);
+
+ pci_write_config_byte(pdev, 0x42, 0x0);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686,
+ loongson2e_686b_func0_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+ loongson2e_686b_func1_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2,
+ loongson2e_686b_func2_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3,
+ loongson2e_686b_func3_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5,
+ loongson2e_686b_func5_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+ loongson2e_nec_fixup);
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index bf2c41d1e9c5..0f48498bc231 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -36,7 +36,7 @@ static char irq_tab[][5] __initdata = {
{0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int virq;
virq = irq_tab[slot][pin];
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
index 3c9ae41f7517..591159625722 100644
--- a/arch/mips/pci/fixup-mpc30x.c
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -34,7 +34,7 @@ static const int irq_tab_mpc30x[] __initdata = {
[29] = MQ200_IRQ,
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (slot == 30)
return internal_func_irqs[PCI_FUNC(dev->devfn)];
diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c
deleted file mode 100644
index d45494807a33..000000000000
--- a/arch/mips/pci/fixup-ocelot-c.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work for the Linux port to the Ocelot board, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/momentum/ocelot_g/pci.c
- * Board-specific PCI routines for mv64340 controller.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int bus = dev->bus->number;
-
- if (bus == 0 && slot == 1)
- return 2; /* PCI-X A */
- if (bus == 1 && slot == 1)
- return 12; /* PCI-X B */
- if (bus == 1 && slot == 2)
- return 4; /* PCI B */
-
-return 0;
- panic("Whooops in pcibios_map_irq");
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/fixup-ocelot3.c b/arch/mips/pci/fixup-ocelot3.c
deleted file mode 100644
index ececc03ec620..000000000000
--- a/arch/mips/pci/fixup-ocelot3.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 Montavista Software Inc.
- * Author: Manish Lachwani (mlachwani@mvista.com)
- *
- * Looking at the schematics for the Ocelot-3 board, there are
- * two PCI busses and each bus has two PCI slots.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/mipsregs.h>
-
-/*
- * Do platform specific device initialization at
- * pci_enable_device() time
- */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int bus = dev->bus->number;
-
- if (bus == 0 && slot == 1)
- return 2; /* PCI-X A */
- if (bus == 0 && slot == 2)
- return 3; /* PCI-X B */
- if (bus == 1 && slot == 1)
- return 4; /* PCI A */
- if (bus == 1 && slot == 2)
- return 5; /* PCI B */
-
-return 0;
- panic("Whooops in pcibios_map_irq");
-}
diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c
new file mode 100644
index 000000000000..00261211dbfa
--- /dev/null
+++ b/arch/mips/pci/fixup-pmcmsp.c
@@ -0,0 +1,216 @@
+/*
+ * PMC-Sierra MSP board specific pci fixups.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2005-2007 PMC-Sierra, Inc
+ *
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+
+#include <msp_pci.h>
+#include <msp_cic_int.h>
+
+/* PCI interrupt pins */
+#define IRQ4 MSP_INT_EXT4
+#define IRQ5 MSP_INT_EXT5
+#define IRQ6 MSP_INT_EXT6
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+/* Garibaldi Board IRQ wiring to PCI slots */
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */
+ {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */
+ {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */
+ {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */
+ {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */
+ {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */
+ {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */
+ {0, 0, 0, 0, 0 }, /* 6 (AD[16]): Unused */
+ {0, 0, 0, 0, 0 }, /* 7 (AD[17]): Unused */
+ {0, 0, 0, 0, 0 }, /* 8 (AD[18]): Unused */
+ {0, 0, 0, 0, 0 }, /* 9 (AD[19]): Unused */
+ {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */
+ {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */
+ {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */
+ {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */
+ {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */
+ {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */
+ {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */
+ {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */
+ {0, IRQ4, IRQ4, 0, 0 }, /* 18 (AD[28]): slot 0 */
+ {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */
+ {0, IRQ5, IRQ5, 0, 0 }, /* 20 (AD[30]): slot 1 */
+ {0, IRQ6, IRQ6, 0, 0 } /* 21 (AD[31]): slot 2 */
+};
+
+#elif defined(CONFIG_PMC_MSP7120_EVAL)
+
+/* MSP7120 Eval Board IRQ wiring to PCI slots */
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */
+ {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */
+ {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */
+ {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */
+ {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */
+ {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */
+ {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */
+ {0, IRQ6, IRQ6, 0, 0 }, /* 6 (AD[16]): slot 3 (mini) */
+ {0, IRQ5, IRQ5, 0, 0 }, /* 7 (AD[17]): slot 2 (mini) */
+ {0, IRQ4, IRQ4, IRQ4, IRQ4}, /* 8 (AD[18]): slot 0 (PCI) */
+ {0, IRQ5, IRQ5, IRQ5, IRQ5}, /* 9 (AD[19]): slot 1 (PCI) */
+ {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */
+ {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */
+ {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */
+ {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */
+ {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */
+ {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */
+ {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */
+ {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */
+ {0, 0, 0, 0, 0 }, /* 18 (AD[28]): Unused */
+ {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */
+ {0, 0, 0, 0, 0 }, /* 20 (AD[30]): Unused */
+ {0, 0, 0, 0, 0 } /* 21 (AD[31]): Unused */
+};
+
+#else
+
+/* Unknown board -- don't assign any IRQs */
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */
+ {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */
+ {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */
+ {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */
+ {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */
+ {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */
+ {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */
+ {0, 0, 0, 0, 0 }, /* 6 (AD[16]): Unused */
+ {0, 0, 0, 0, 0 }, /* 7 (AD[17]): Unused */
+ {0, 0, 0, 0, 0 }, /* 8 (AD[18]): Unused */
+ {0, 0, 0, 0, 0 }, /* 9 (AD[19]): Unused */
+ {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */
+ {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */
+ {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */
+ {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */
+ {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */
+ {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */
+ {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */
+ {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */
+ {0, 0, 0, 0, 0 }, /* 18 (AD[28]): Unused */
+ {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */
+ {0, 0, 0, 0, 0 }, /* 20 (AD[30]): Unused */
+ {0, 0, 0, 0, 0 } /* 21 (AD[31]): Unused */
+};
+#endif
+
+/*****************************************************************************
+ *
+ * FUNCTION: pcibios_plat_dev_init
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Perform platform specific device initialization at
+ * pci_enable_device() time.
+ * None are needed for the MSP7120 PCI Controller.
+ *
+ * INPUTS: dev - structure describing the PCI device
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL
+ *
+ ****************************************************************************/
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: pcibios_map_irq
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Perform board supplied PCI IRQ mapping routine.
+ *
+ * INPUTS: dev - unused
+ * slot - PCI slot. Identified by which bit of the AD[] bus
+ * drives the IDSEL line. AD[10] is 0, AD[31] is
+ * slot 21.
+ * pin - numbered using the scheme of the PCI_INTERRUPT_PIN
+ * field of the config header.
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: IRQ number
+ *
+ ****************************************************************************/
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+#if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL)
+ printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n");
+#endif
+ printk(KERN_WARNING "PCI: irq_tab returned %d for slot=%d pin=%d\n",
+ irq_tab[slot][pin], slot, pin);
+
+ return irq_tab[slot][pin];
+}
+
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/pci/fixup-pnx8550.c b/arch/mips/pci/fixup-pnx8550.c
index 50546dab6689..96857ac63bf5 100644
--- a/arch/mips/pci/fixup-pnx8550.c
+++ b/arch/mips/pci/fixup-pnx8550.c
@@ -45,7 +45,7 @@ void __init pcibios_fixup(void)
/* nothing to do here */
}
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return pnx8550_irq_tab[slot][pin];
}
diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c
index ceeb1860895a..3cdbecb8e714 100644
--- a/arch/mips/pci/fixup-rbtx4927.c
+++ b/arch/mips/pci/fixup-rbtx4927.c
@@ -119,7 +119,7 @@ int pci_get_irq(struct pci_dev *dev, int pin)
return irq;
}
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char irq;
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index 36e5fb1b3786..a45bedd17233 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -120,7 +120,7 @@ static inline int is_rm300_revd(void)
return (csmsr & 0xa0) == 0x20;
}
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
switch (sni_brd_type) {
case SNI_BRD_PCI_TOWER:
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index 734f2b71e164..720a2b720c5c 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -23,7 +23,7 @@
#include <asm/vr41xx/tb0219.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = -1;
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
index c9e7cb4361a1..e3eedf4bf9bd 100644
--- a/arch/mips/pci/fixup-tb0226.c
+++ b/arch/mips/pci/fixup-tb0226.c
@@ -23,7 +23,7 @@
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/tb0226.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = -1;
diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c
index fbe6bcb28199..267ab3dc3d42 100644
--- a/arch/mips/pci/fixup-tb0287.c
+++ b/arch/mips/pci/fixup-tb0287.c
@@ -22,7 +22,7 @@
#include <asm/vr41xx/tb0287.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char bus;
int irq = -1;
diff --git a/arch/mips/pci/fixup-tx4938.c b/arch/mips/pci/fixup-tx4938.c
index f455520ada88..2485f47dfe6f 100644
--- a/arch/mips/pci/fixup-tx4938.c
+++ b/arch/mips/pci/fixup-tx4938.c
@@ -69,7 +69,7 @@ int pci_get_irq(struct pci_dev *dev, int pin)
return irq;
}
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char irq = 0;
diff --git a/arch/mips/pci/fixup-vr4133.c b/arch/mips/pci/fixup-vr4133.c
index a8d9d22b13df..de5e5f6bbf4c 100644
--- a/arch/mips/pci/fixup-vr4133.c
+++ b/arch/mips/pci/fixup-vr4133.c
@@ -169,7 +169,7 @@ void i8259_init(void)
}
#endif
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
extern int pci_probe_only;
pci_probe_only = 1;
diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c
index 3357c1300bb1..3d277549d5df 100644
--- a/arch/mips/pci/fixup-wrppmc.c
+++ b/arch/mips/pci/fixup-wrppmc.c
@@ -25,7 +25,7 @@ static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = {
[6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0},
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return pci_irq_tab[slot][pin];
}
diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c
index 81d77a587a51..fdafb13a793b 100644
--- a/arch/mips/pci/fixup-yosemite.c
+++ b/arch/mips/pci/fixup-yosemite.c
@@ -26,7 +26,7 @@
#include <linux/init.h>
#include <linux/pci.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (pin == 0)
return -1;
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
index dc35270b65a2..f742c51acf0d 100644
--- a/arch/mips/pci/ops-bonito64.c
+++ b/arch/mips/pci/ops-bonito64.c
@@ -29,83 +29,60 @@
#define PCI_ACCESS_READ 0
#define PCI_ACCESS_WRITE 1
-/*
- * PCI configuration cycle AD bus definition
- */
-/* Type 0 */
-#define PCI_CFG_TYPE0_REG_SHF 0
-#define PCI_CFG_TYPE0_FUNC_SHF 8
+#ifdef CONFIG_LEMOTE_FULONG
+#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(BONITO_PCICFG_BASE | (offset))
+#define ID_SEL_BEGIN 11
+#else
+#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset))
+#define ID_SEL_BEGIN 10
+#endif
+#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
-/* Type 1 */
-#define PCI_CFG_TYPE1_REG_SHF 0
-#define PCI_CFG_TYPE1_FUNC_SHF 8
-#define PCI_CFG_TYPE1_DEV_SHF 11
-#define PCI_CFG_TYPE1_BUS_SHF 16
static int bonito64_pcibios_config_access(unsigned char access_type,
struct pci_bus *bus,
unsigned int devfn, int where,
u32 * data)
{
- unsigned char busnum = bus->number;
+ u32 busnum = bus->number;
+ u32 addr, type;
u32 dummy;
- u64 pci_addr;
-
- /* Algorithmics Bonito64 system controller. */
+ void *addrp;
+ int device = PCI_SLOT(devfn);
+ int function = PCI_FUNC(devfn);
+ int reg = where & ~3;
- if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) {
- /* We number bus 0 devices from 0..21 */
- return -1;
- }
-
- /* Clear cause register bits */
- BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
- BONITO_PCICMD_MTABORT_CLR);
-
- /*
- * Setup pattern to be used as PCI "address" for
- * Type 0 cycle
- */
if (busnum == 0) {
- /* IDSEL */
- pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10);
- } else {
- /* Bus number */
- pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF;
-
- /* Device number */
- pci_addr |=
- PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF;
- }
-
- /* Function (same for Type 0/1) */
- pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF;
-
- /* Register number (same for Type 0/1) */
- pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
+ /* Type 0 configuration for onboard PCI bus */
+ if (device > MAX_DEV_NUM)
+ return -1;
- if (busnum == 0) {
- /* Type 0 */
- BONITO_PCIMAP_CFG = pci_addr >> 16;
+ addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
+ type = 0;
} else {
- /* Type 1 */
- BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
+ /* Type 1 configuration for offboard PCI bus */
+ addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+ type = 0x10000;
}
- pci_addr &= 0xffff;
+ /* Clear aborts */
+ BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR;
+
+ BONITO_PCIMAP_CFG = (addr >> 16) | type;
/* Flush Bonito register block */
dummy = BONITO_PCIMAP_CFG;
- iob(); /* sync */
+ mmiowb();
- /* Perform access */
+ addrp = CFG_SPACE_REG(addr & 0xffff);
if (access_type == PCI_ACCESS_WRITE) {
- *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data;
-
+ writel(cpu_to_le32(*data), addrp);
+#ifndef CONFIG_LEMOTE_FULONG
/* Wait till done */
while (BONITO_PCIMSTAT & 0xF);
+#endif
} else {
- *(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr);
+ *data = le32_to_cpu(readl(addrp));
}
/* Detect Master/Target abort */
@@ -121,6 +98,7 @@ static int bonito64_pcibios_config_access(unsigned char access_type,
}
return 0;
+
}
diff --git a/arch/mips/pci/ops-marvell.c b/arch/mips/pci/ops-marvell.c
deleted file mode 100644
index 1ac5c59199d1..000000000000
--- a/arch/mips/pci/ops-marvell.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/marvell.h>
-
-static int mv_read_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 * val)
-{
- struct mv_pci_controller *mvbc = bus->sysdata;
- unsigned long address_reg, data_reg;
- u32 address;
-
- address_reg = mvbc->config_addr;
- data_reg = mvbc->config_vreg;
-
- /* Accessing device 31 crashes those Marvells. Since years.
- Will they ever make sane controllers ... */
- if (PCI_SLOT(devfn) == 31)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- address = (bus->number << 16) | (devfn << 8) |
- (where & 0xfc) | 0x80000000;
-
- /* start the configuration cycle */
- MV_WRITE(address_reg, address);
-
- switch (size) {
- case 1:
- *val = MV_READ_8(data_reg + (where & 0x3));
- break;
-
- case 2:
- *val = MV_READ_16(data_reg + (where & 0x3));
- break;
-
- case 4:
- *val = MV_READ(data_reg);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int mv_write_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- struct mv_pci_controller *mvbc = bus->sysdata;
- unsigned long address_reg, data_reg;
- u32 address;
-
- address_reg = mvbc->config_addr;
- data_reg = mvbc->config_vreg;
-
- /* Accessing device 31 crashes those Marvells. Since years.
- Will they ever make sane controllers ... */
- if (PCI_SLOT(devfn) == 31)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- address = (bus->number << 16) | (devfn << 8) |
- (where & 0xfc) | 0x80000000;
-
- /* start the configuration cycle */
- MV_WRITE(address_reg, address);
-
- switch (size) {
- case 1:
- MV_WRITE_8(data_reg + (where & 0x3), val);
- break;
-
- case 2:
- MV_WRITE_16(data_reg + (where & 0x3), val);
- break;
-
- case 4:
- MV_WRITE(data_reg, val);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops mv_pci_ops = {
- .read = mv_read_config,
- .write = mv_write_config
-};
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
deleted file mode 100644
index a8d38dc8c504..000000000000
--- a/arch/mips/pci/ops-nile4.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/bootinfo.h>
-
-#include <asm/lasat/lasat.h>
-#include <asm/gt64120.h>
-#include <asm/nile4.h>
-
-#define PCI_ACCESS_READ 0
-#define PCI_ACCESS_WRITE 1
-
-#define LO(reg) (reg / 4)
-#define HI(reg) (reg / 4 + 1)
-
-volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
-
-static DEFINE_SPINLOCK(nile4_pci_lock);
-
-static int nile4_pcibios_config_access(unsigned char access_type,
- struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
-{
- unsigned char busnum = bus->number;
- u32 adr, mask, err;
-
- if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
- /* The addressing scheme chosen leaves room for just
- * 8 devices on the first busnum (besides the PCI
- * controller itself) */
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
- /* Access controller registers directly */
- if (access_type == PCI_ACCESS_WRITE) {
- vrc_pciregs[(0x200 + where) >> 2] = *val;
- } else {
- *val = vrc_pciregs[(0x200 + where) >> 2];
- }
- return PCIBIOS_SUCCESSFUL;
- }
-
- /* Temporarily map PCI Window 1 to config space */
- mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
- vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0);
-
- /* Clear PCI Error register. This also clears the Error Type
- * bits in the Control register */
- vrc_pciregs[LO(NILE4_PCIERR)] = 0;
- vrc_pciregs[HI(NILE4_PCIERR)] = 0;
-
- /* Setup address */
- if (busnum == 0)
- adr =
- KSEG1ADDR(PCI_WINDOW1) +
- ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
- | (where & ~3));
- else
- adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) |
- (where & ~3);
-
- if (access_type == PCI_ACCESS_WRITE)
- *(u32 *) adr = *val;
- else
- *val = *(u32 *) adr;
-
- /* Check for master or target abort */
- err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
-
- /* Restore PCI Window 1 */
- vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
-
- if (err)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 * val)
-{
- unsigned long flags;
- u32 data = 0;
- int err;
-
- if ((size == 2) && (where & 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
- else if ((size == 4) && (where & 3))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- spin_lock_irqsave(&nile4_pci_lock, flags);
- err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
- &data);
- spin_unlock_irqrestore(&nile4_pci_lock, flags);
-
- if (err)
- return err;
-
- if (size == 1)
- *val = (data >> ((where & 3) << 3)) & 0xff;
- else if (size == 2)
- *val = (data >> ((where & 3) << 3)) & 0xffff;
- else
- *val = data;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- unsigned long flags;
- u32 data = 0;
- int err;
-
- if ((size == 2) && (where & 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
- else if ((size == 4) && (where & 3))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- spin_lock_irqsave(&nile4_pci_lock, flags);
- err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
- &data);
- spin_unlock_irqrestore(&nile4_pci_lock, flags);
-
- if (err)
- return err;
-
- if (size == 1)
- data = (data & ~(0xff << ((where & 3) << 3))) |
- (val << ((where & 3) << 3));
- else if (size == 2)
- data = (data & ~(0xffff << ((where & 3) << 3))) |
- (val << ((where & 3) << 3));
- else
- data = val;
-
- if (nile4_pcibios_config_access
- (PCI_ACCESS_WRITE, bus, devfn, where, &data))
- return -1;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops nile4_pci_ops = {
- .read = nile4_pcibios_read,
- .write = nile4_pcibios_write,
-};
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c
new file mode 100644
index 000000000000..09fa007c1d1b
--- /dev/null
+++ b/arch/mips/pci/ops-pmcmsp.c
@@ -0,0 +1,994 @@
+/*
+ * PMC-Sierra MSP board specific pci_ops
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2005-2007 PMC-Sierra, Inc
+ *
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#define PCI_COUNTERS 1
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+#include <asm/mipsmtregs.h>
+#endif
+
+#include <msp_prom.h>
+#include <msp_cic_int.h>
+#include <msp_pci.h>
+#include <msp_regs.h>
+#include <msp_regops.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+static char proc_init;
+extern struct proc_dir_entry *proc_bus_pci_dir;
+unsigned int pci_int_count[32];
+
+static void pci_proc_init(void);
+
+/*****************************************************************************
+ *
+ * FUNCTION: read_msp_pci_counts
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Prints the count of how many times each PCI
+ * interrupt has asserted. Can be invoked by the
+ * /proc filesystem.
+ *
+ * INPUTS: page - part of STDOUT calculation
+ * off - part of STDOUT calculation
+ * count - part of STDOUT calculation
+ * data - unused
+ *
+ * OUTPUTS: start - new start location
+ * eof - end of file pointer
+ *
+ * RETURNS: len - STDOUT length
+ *
+ ****************************************************************************/
+static int read_msp_pci_counts(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int i;
+ int len = 0;
+ unsigned int intcount, total = 0;
+
+ for (i = 0; i < 32; ++i) {
+ intcount = pci_int_count[i];
+ if (intcount != 0) {
+ len += sprintf(page + len, "[%d] = %u\n", i, intcount);
+ total += intcount;
+ }
+ }
+
+ len += sprintf(page + len, "total = %u\n", total);
+ if (len <= off+count)
+ *eof = 1;
+
+ *start = page + off;
+ len -= off;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: gen_pci_cfg_wr
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Generates a configuration write cycle for debug purposes.
+ * The IDSEL line asserted and location and data written are
+ * immaterial. Just want to be able to prove that a
+ * configuration write can be correctly generated on the
+ * PCI bus. Intent is that this function by invocable from
+ * the /proc filesystem.
+ *
+ * INPUTS: page - part of STDOUT calculation
+ * off - part of STDOUT calculation
+ * count - part of STDOUT calculation
+ * data - unused
+ *
+ * OUTPUTS: start - new start location
+ * eof - end of file pointer
+ *
+ * RETURNS: len - STDOUT length
+ *
+ ****************************************************************************/
+static int gen_pci_cfg_wr(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ unsigned char where = 0; /* Write to static Device/Vendor ID */
+ unsigned char bus_num = 0; /* Bus 0 */
+ unsigned char dev_fn = 0xF; /* Arbitrary device number */
+ u32 wr_data = 0xFF00AA00; /* Arbitrary data */
+ struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+ int len = 0;
+ unsigned long value;
+ int intr;
+
+ len += sprintf(page + len, "PMC MSP PCI: Beginning\n");
+
+ if (proc_init == 0) {
+ pci_proc_init();
+ proc_init = ~0;
+ }
+
+ len += sprintf(page + len, "PMC MSP PCI: Before Cfg Wr\n");
+
+ /*
+ * Generate PCI Configuration Write Cycle
+ */
+
+ /* Clear cause register bits */
+ preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+ /* Setup address that is to appear on PCI bus */
+ preg->config_addr = BPCI_CFGADDR_ENABLE |
+ (bus_num << BPCI_CFGADDR_BUSNUM_SHF) |
+ (dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |
+ (where & 0xFC);
+
+ value = cpu_to_le32(wr_data);
+
+ /* Launch the PCI configuration write cycle */
+ *PCI_CONFIG_SPACE_REG = value;
+
+ /*
+ * Check if the PCI configuration cycle (rd or wr) succeeded, by
+ * checking the status bits for errors like master or target abort.
+ */
+ intr = preg->if_status;
+
+ len += sprintf(page + len, "PMC MSP PCI: After Cfg Wr\n");
+
+ /* Handle STDOUT calculations */
+ if (len <= off+count)
+ *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: pci_proc_init
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Create entries in the /proc filesystem for debug access.
+ *
+ * INPUTS: none
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: none
+ *
+ ****************************************************************************/
+static void pci_proc_init(void)
+{
+ create_proc_read_entry("pmc_msp_pci_rd_cnt", 0, NULL,
+ read_msp_pci_counts, NULL);
+ create_proc_read_entry("pmc_msp_pci_cfg_wr", 0, NULL,
+ gen_pci_cfg_wr, NULL);
+}
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+spinlock_t bpci_lock = SPIN_LOCK_UNLOCKED;
+
+/*****************************************************************************
+ *
+ * STRUCT: pci_io_resource
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Defines the address range that pciauto() will use to
+ * assign to the I/O BARs of PCI devices.
+ *
+ * Use the start and end addresses of the MSP7120 PCI Host
+ * Controller I/O space, in the form that they appear on the
+ * PCI bus AFTER MSP7120 has performed address translation.
+ *
+ * For I/O accesses, MSP7120 ignores OATRAN and maps I/O
+ * accesses into the bottom 0xFFF region of address space,
+ * so that is the range to put into the pci_io_resource
+ * struct.
+ *
+ * In MSP4200, the start address was 0x04 instead of the
+ * expected 0x00. Will just assume there was a good reason
+ * for this!
+ *
+ * NOTES: Linux, by default, will assign I/O space to the lowest
+ * region of address space. Since MSP7120 and Linux,
+ * by default, have no offset in between how they map, the
+ * io_offset element of pci_controller struct should be set
+ * to zero.
+ * ELEMENTS:
+ * name - String used for a meaningful name.
+ *
+ * start - Start address of MSP7120's I/O space, as MSP7120 presents
+ * the address on the PCI bus.
+ *
+ * end - End address of MSP7120's I/O space, as MSP7120 presents
+ * the address on the PCI bus.
+ *
+ * flags - Attributes indicating the type of resource. In this case,
+ * indicate I/O space.
+ *
+ ****************************************************************************/
+static struct resource pci_io_resource = {
+ .name = "pci IO space",
+ .start = 0x04,
+ .end = 0x0FFF,
+ .flags = IORESOURCE_IO /* I/O space */
+};
+
+/*****************************************************************************
+ *
+ * STRUCT: pci_mem_resource
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Defines the address range that pciauto() will use to
+ * assign to the memory BARs of PCI devices.
+ *
+ * The .start and .end values are dependent upon how address
+ * translation is performed by the OATRAN regiser.
+ *
+ * The values to use for .start and .end are the values
+ * in the form they appear on the PCI bus AFTER MSP7120 has
+ * performed OATRAN address translation.
+ *
+ * ELEMENTS:
+ * name - String used for a meaningful name.
+ *
+ * start - Start address of MSP7120's memory space, as MSP7120 presents
+ * the address on the PCI bus.
+ *
+ * end - End address of MSP7120's memory space, as MSP7120 presents
+ * the address on the PCI bus.
+ *
+ * flags - Attributes indicating the type of resource. In this case,
+ * indicate memory space.
+ *
+ ****************************************************************************/
+static struct resource pci_mem_resource = {
+ .name = "pci memory space",
+ .start = MSP_PCI_SPACE_BASE,
+ .end = MSP_PCI_SPACE_END,
+ .flags = IORESOURCE_MEM /* memory space */
+};
+
+/*****************************************************************************
+ *
+ * FUNCTION: bpci_interrupt
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: PCI status interrupt handler. Updates the count of how
+ * many times each status bit has been set, then clears
+ * the status bits. If the appropriate macros are defined,
+ * these counts can be viewed via the /proc filesystem.
+ *
+ * INPUTS: irq - unused
+ * dev_id - unused
+ * pt_regs - unused
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ *
+ ****************************************************************************/
+static int bpci_interrupt(int irq, void *dev_id)
+{
+ struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+ unsigned int stat = preg->if_status;
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+ int i;
+ for (i = 0; i < 32; ++i) {
+ if ((1 << i) & stat)
+ ++pci_int_count[i];
+ }
+#endif /* PROC_FS && PCI_COUNTERS */
+
+ /* printk("PCI ISR: Status=%08X\n", stat); */
+
+ /* write to clear all asserted interrupts */
+ preg->if_status = stat;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_config_access
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Performs a PCI configuration access (rd or wr), then
+ * checks that the access succeeded by querying MSP7120's
+ * PCI status bits.
+ *
+ * INPUTS:
+ * access_type - kind of PCI configuration cycle to perform
+ * (read or write). Legal values are
+ * PCI_ACCESS_WRITE and PCI_ACCESS_READ.
+ *
+ * bus - pointer to the bus number of the device to
+ * be targetted for the configuration cycle.
+ * The only element of the pci_bus structure
+ * used is bus->number. This argument determines
+ * if the configuration access will be Type 0 or
+ * Type 1. Since MSP7120 assumes itself to be the
+ * PCI Host, any non-zero bus->number generates
+ * a Type 1 access.
+ *
+ * devfn - this is an 8-bit field. The lower three bits
+ * specify the function number of the device to
+ * be targetted for the configuration cycle, with
+ * all three-bit combinations being legal. The
+ * upper five bits specify the device number,
+ * with legal values being 10 to 31.
+ *
+ * where - address within the Configuration Header
+ * space to access.
+ *
+ * data - for write accesses, contains the data to
+ * write.
+ *
+ * OUTPUTS:
+ * data - for read accesses, contains the value read.
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - access failure
+ *
+ ****************************************************************************/
+int msp_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus,
+ unsigned int devfn,
+ unsigned char where,
+ u32 *data)
+{
+ struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+ unsigned char bus_num = bus->number;
+ unsigned char dev_fn = (unsigned char)devfn;
+ unsigned long flags;
+ unsigned long intr;
+ unsigned long value;
+ static char pciirqflag;
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+ unsigned int vpe_status;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+ if (proc_init == 0) {
+ pci_proc_init();
+ proc_init = ~0;
+ }
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+ /*
+ * Just the first time this function invokes, allocate
+ * an interrupt line for PCI host status interrupts. The
+ * allocation assigns an interrupt handler to the interrupt.
+ */
+ if (pciirqflag == 0) {
+ request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */
+ bpci_interrupt,
+ SA_SHIRQ | SA_INTERRUPT,
+ "PMC MSP PCI Host",
+ preg);
+ pciirqflag = ~0;
+ }
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+ local_irq_save(flags);
+ vpe_status = dvpe();
+#else
+ spin_lock_irqsave(&bpci_lock, flags);
+#endif
+
+ /*
+ * Clear PCI cause register bits.
+ *
+ * In Polo, the PCI Host had a dedicated DMA called the
+ * Block Copy (not to be confused with the general purpose Block
+ * Copy Engine block). There appear to have been special interrupts
+ * for this Block Copy, called Block Copy 0 Fault (BC0F) and
+ * Block Copy 1 Fault (BC1F). MSP4200 and MSP7120 don't have this
+ * dedicated Block Copy block, so these two interrupts are now
+ * marked reserved. In case the Block Copy is resurrected in a
+ * future design, maintain the code that treats these two interrupts
+ * specially.
+ *
+ * Write to clear all interrupts in the PCI status register, aside
+ * from BC0F and BC1F.
+ */
+ preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+ /* Setup address that is to appear on PCI bus */
+ preg->config_addr = BPCI_CFGADDR_ENABLE |
+ (bus_num << BPCI_CFGADDR_BUSNUM_SHF) |
+ (dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |
+ (where & 0xFC);
+
+ /* IF access is a PCI configuration write */
+ if (access_type == PCI_ACCESS_WRITE) {
+ value = cpu_to_le32(*data);
+ *PCI_CONFIG_SPACE_REG = value;
+ } else {
+ /* ELSE access is a PCI configuration read */
+ value = le32_to_cpu(*PCI_CONFIG_SPACE_REG);
+ *data = value;
+ }
+
+ /*
+ * Check if the PCI configuration cycle (rd or wr) succeeded, by
+ * checking the status bits for errors like master or target abort.
+ */
+ intr = preg->if_status;
+
+ /* Clear config access */
+ preg->config_addr = 0;
+
+ /* IF error occurred */
+ if (intr & ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F)) {
+ /* Clear status bits */
+ preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+ evpe(vpe_status);
+ local_irq_restore(flags);
+#else
+ spin_unlock_irqrestore(&bpci_lock, flags);
+#endif
+
+ return -1;
+ }
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+ evpe(vpe_status);
+ local_irq_restore(flags);
+#else
+ spin_unlock_irqrestore(&bpci_lock, flags);
+#endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_read_config_byte
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Read a byte from PCI configuration address spac
+ * Since the hardware can't address 8 bit chunks
+ * directly, read a 32-bit chunk, then mask off extraneous
+ * bits.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the read is destined for.
+ * devfn - device/function combination that the read is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ *
+ * OUTPUTS val - read data
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_byte(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u32 *val)
+{
+ u32 data = 0;
+
+ /*
+ * If the config access did not complete normally (e.g., underwent
+ * master abort) do the PCI compliant thing, which is to supply an
+ * all ones value.
+ */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data)) {
+ *val = 0xFFFFFFFF;
+ return -1;
+ }
+
+ *val = (data >> ((where & 3) << 3)) & 0x0ff;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_read_config_word
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Read a word (16 bits) from PCI configuration address space.
+ * Since the hardware can't address 16 bit chunks
+ * directly, read a 32-bit chunk, then mask off extraneous
+ * bits.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the read is destined for.
+ * devfn - device/function combination that the read is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ *
+ * OUTPUTS val - read data
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * PCIBIOS_BAD_REGISTER_NUMBER - bad register address
+ * -1 - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_word(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u32 *val)
+{
+ u32 data = 0;
+
+ /* if (where & 1) */ /* Commented out non-compliant code.
+ * Should allow word access to configuration
+ * registers, with only exception being when
+ * the word access would wrap around into
+ * the next dword.
+ */
+ if ((where & 3) == 3) {
+ *val = 0xFFFFFFFF;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ /*
+ * If the config access did not complete normally (e.g., underwent
+ * master abort) do the PCI compliant thing, which is to supply an
+ * all ones value.
+ */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data)) {
+ *val = 0xFFFFFFFF;
+ return -1;
+ }
+
+ *val = (data >> ((where & 3) << 3)) & 0x0ffff;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_read_config_dword
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Read a double word (32 bits) from PCI configuration
+ * address space.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the read is destined for.
+ * devfn - device/function combination that the read is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ *
+ * OUTPUTS val - read data
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * PCIBIOS_BAD_REGISTER_NUMBER - bad register address
+ * -1 - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_dword(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u32 *val)
+{
+ u32 data = 0;
+
+ /* Address must be dword aligned. */
+ if (where & 3) {
+ *val = 0xFFFFFFFF;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ /*
+ * If the config access did not complete normally (e.g., underwent
+ * master abort) do the PCI compliant thing, which is to supply an
+ * all ones value.
+ */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data)) {
+ *val = 0xFFFFFFFF;
+ return -1;
+ }
+
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_write_config_byte
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Write a byte to PCI configuration address space.
+ * Since the hardware can't address 8 bit chunks
+ * directly, a read-modify-write is performed.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * val - value to write
+ *
+ * OUTPUTS none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_byte(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u8 val)
+{
+ u32 data = 0;
+
+ /* read config space */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return -1;
+
+ /* modify the byte within the dword */
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ /* write back the full dword */
+ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+ where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_write_config_word
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Write a word (16-bits) to PCI configuration address space.
+ * Since the hardware can't address 16 bit chunks
+ * directly, a read-modify-write is performed.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * val - value to write
+ *
+ * OUTPUTS none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * PCIBIOS_BAD_REGISTER_NUMBER - bad register address
+ * -1 - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_word(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u16 val)
+{
+ u32 data = 0;
+
+ /* Fixed non-compliance: if (where & 1) */
+ if ((where & 3) == 3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ /* read config space */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return -1;
+
+ /* modify the word within the dword */
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ /* write back the full dword */
+ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+ where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_write_config_dword
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Write a double word (32-bits) to PCI configuration address
+ * space.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * val - value to write
+ *
+ * OUTPUTS none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * PCIBIOS_BAD_REGISTER_NUMBER - bad register address
+ * -1 - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_dword(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u32 val)
+{
+ /* check that address is dword aligned */
+ if (where & 3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ /* perform write */
+ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+ where, &val))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_read_config
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Interface the PCI configuration read request with
+ * the appropriate function, based on how many bytes
+ * the read request is.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * size - in units of bytes, should be 1, 2, or 4.
+ *
+ * OUTPUTS val - value read, with any extraneous bytes masked
+ * to zero.
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - failure
+ *
+ ****************************************************************************/
+int
+msp_pcibios_read_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ int size,
+ u32 *val)
+{
+ if (size == 1) {
+ if (msp_pcibios_read_config_byte(bus, devfn, where, val)) {
+ return -1;
+ }
+ } else if (size == 2) {
+ if (msp_pcibios_read_config_word(bus, devfn, where, val)) {
+ return -1;
+ }
+ } else if (size == 4) {
+ if (msp_pcibios_read_config_dword(bus, devfn, where, val)) {
+ return -1;
+ }
+ } else {
+ *val = 0xFFFFFFFF;
+ return -1;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_write_config
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Interface the PCI configuration write request with
+ * the appropriate function, based on how many bytes
+ * the read request is.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * size - in units of bytes, should be 1, 2, or 4.
+ * val - value to write
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - failure
+ *
+ ****************************************************************************/
+int
+msp_pcibios_write_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ int size,
+ u32 val)
+{
+ if (size == 1) {
+ if (msp_pcibios_write_config_byte(bus, devfn,
+ where, (u8)(0xFF & val))) {
+ return -1;
+ }
+ } else if (size == 2) {
+ if (msp_pcibios_write_config_word(bus, devfn,
+ where, (u16)(0xFFFF & val))) {
+ return -1;
+ }
+ } else if (size == 4) {
+ if (msp_pcibios_write_config_dword(bus, devfn, where, val)) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * STRUCTURE: msp_pci_ops
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: structure to abstract the hardware specific PCI
+ * configuration accesses.
+ *
+ * ELEMENTS:
+ * read - function for Linux to generate PCI Configuration reads.
+ * write - function for Linux to generate PCI Configuration writes.
+ *
+ ****************************************************************************/
+struct pci_ops msp_pci_ops = {
+ .read = msp_pcibios_read_config,
+ .write = msp_pcibios_write_config
+};
+
+/*****************************************************************************
+ *
+ * STRUCTURE: msp_pci_controller
+ * _________________________________________________________________________
+ *
+ * Describes the attributes of the MSP7120 PCI Host Controller
+ *
+ * ELEMENTS:
+ * pci_ops - abstracts the hardware specific PCI configuration
+ * accesses.
+ *
+ * mem_resource - address range pciauto() uses to assign to PCI device
+ * memory BARs.
+ *
+ * mem_offset - offset between how MSP7120 outbound PCI memory
+ * transaction addresses appear on the PCI bus and how Linux
+ * wants to configure memory BARs of the PCI devices.
+ * MSP7120 does nothing funky, so just set to zero.
+ *
+ * io_resource - address range pciauto() uses to assign to PCI device
+ * I/O BARs.
+ *
+ * io_offset - offset between how MSP7120 outbound PCI I/O
+ * transaction addresses appear on the PCI bus and how
+ * Linux defaults to configure I/O BARs of the PCI devices.
+ * MSP7120 maps outbound I/O accesses into the bottom
+ * bottom 4K of PCI address space (and ignores OATRAN).
+ * Since the Linux default is to configure I/O BARs to the
+ * bottom 4K, no special offset is needed. Just set to zero.
+ *
+ ****************************************************************************/
+static struct pci_controller msp_pci_controller = {
+ .pci_ops = &msp_pci_ops,
+ .mem_resource = &pci_mem_resource,
+ .mem_offset = 0,
+ .io_resource = &pci_io_resource,
+ .io_offset = 0
+};
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pci_init
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Initialize the PCI Host Controller and register it with
+ * Linux so Linux can seize control of the PCI bus.
+ *
+ ****************************************************************************/
+void __init msp_pci_init(void)
+{
+ struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+ u32 id;
+
+ /* Extract Device ID */
+ id = read_reg32(PCI_JTAG_DEVID_REG, 0xFFFF) >> 12;
+
+ /* Check if JTAG ID identifies MSP7120 */
+ if (!MSP_HAS_PCI(id)) {
+ printk(KERN_WARNING "PCI: No PCI; id reads as %x\n", id);
+ goto no_pci;
+ }
+
+ /*
+ * Enable flushing of the PCI-SDRAM queue upon a read
+ * of the SDRAM's Memory Configuration Register.
+ */
+ *(unsigned long *)QFLUSH_REG_1 = 3;
+
+ /* Configure PCI Host Controller. */
+ preg->if_status = ~0; /* Clear cause register bits */
+ preg->config_addr = 0; /* Clear config access */
+ preg->oatran = MSP_PCI_OATRAN; /* PCI outbound addr translation */
+ preg->if_mask = 0xF8BF87C0; /* Enable all PCI status interrupts */
+
+ /* configure so inb(), outb(), and family are functional */
+ set_io_port_base(MSP_PCI_IOSPACE_BASE);
+
+ /* Tell Linux the details of the MSP7120 PCI Host Controller */
+ register_pci_controller(&msp_pci_controller);
+
+ return;
+
+no_pci:
+ /* Disable PCI channel */
+ printk(KERN_WARNING "PCI: no host PCI bus detected\n");
+}
diff --git a/arch/mips/pci/ops-tx4938.c b/arch/mips/pci/ops-tx4938.c
index 445007084515..a450c4062031 100644
--- a/arch/mips/pci/ops-tx4938.c
+++ b/arch/mips/pci/ops-tx4938.c
@@ -46,50 +46,63 @@ struct resource tx4938_pcic1_pci_mem_resource = {
.flags = IORESOURCE_MEM
};
-static int mkaddr(int bus, int dev_fn, int where, int *flagsp)
+static int mkaddr(int bus, int dev_fn, int where,
+ struct tx4938_pcic_reg *pcicptr)
{
if (bus > 0) {
/* Type 1 configuration */
- tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+ pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
} else {
if (dev_fn >= PCI_DEVFN(TX4938_PCIC_MAX_DEVNU, 0))
return -1;
/* Type 0 configuration */
- tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+ pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
((dev_fn & 0xff) << 0x08) | (where & 0xfc);
}
/* clear M_ABORT and Disable M_ABORT Int. */
- tx4938_pcicptr->pcistatus =
- (tx4938_pcicptr->pcistatus & 0x0000ffff) |
+ pcicptr->pcistatus =
+ (pcicptr->pcistatus & 0x0000ffff) |
(PCI_STATUS_REC_MASTER_ABORT << 16);
- tx4938_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
+ pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
return 0;
}
-static int check_abort(int flags)
+static int check_abort(struct tx4938_pcic_reg *pcicptr)
{
int code = PCIBIOS_SUCCESSFUL;
/* wait write cycle completion before checking error status */
- while (tx4938_pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
+ while (pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
;
- if (tx4938_pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
- tx4938_pcicptr->pcistatus =
- (tx4938_pcicptr->
+ if (pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+ pcicptr->pcistatus =
+ (pcicptr->
pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
<< 16);
- tx4938_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
+ pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
code = PCIBIOS_DEVICE_NOT_FOUND;
}
return code;
}
+extern struct pci_controller tx4938_pci_controller[];
+extern struct tx4938_pcic_reg *get_tx4938_pcicptr(int ch);
+
+static struct tx4938_pcic_reg *pci_bus_to_pcicptr(struct pci_bus *bus)
+{
+ struct pci_controller *channel = bus->sysdata;
+ return get_tx4938_pcicptr(channel - &tx4938_pci_controller[0]);
+}
+
static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 * val)
{
- int flags, retval, dev, busno, func;
+ int retval, dev, busno, func;
+ struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
+ void __iomem *cfgdata =
+ (void __iomem *)(unsigned long)&pcicptr->g2pcfgdata;
dev = PCI_SLOT(devfn);
func = PCI_FUNC(devfn);
@@ -101,32 +114,32 @@ static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
busno = 0;
}
- if (mkaddr(busno, devfn, where, &flags))
+ if (mkaddr(busno, devfn, where, pcicptr))
return -1;
switch (size) {
case 1:
- *val = *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
#ifdef __BIG_ENDIAN
- ((where & 3) ^ 3));
+ cfgdata += (where & 3) ^ 3;
#else
- (where & 3));
+ cfgdata += where & 3;
#endif
+ *val = __raw_readb(cfgdata);
break;
case 2:
- *val = *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
#ifdef __BIG_ENDIAN
- ((where & 3) ^ 2));
+ cfgdata += (where & 2) ^ 2;
#else
- (where & 3));
+ cfgdata += where & 2;
#endif
+ *val = __raw_readw(cfgdata);
break;
case 4:
- *val = tx4938_pcicptr->g2pcfgdata;
+ *val = __raw_readl(cfgdata);
break;
}
- retval = check_abort(flags);
+ retval = check_abort(pcicptr);
if (retval == PCIBIOS_DEVICE_NOT_FOUND)
*val = 0xffffffff;
@@ -136,7 +149,10 @@ static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
- int flags, dev, busno, func;
+ int dev, busno, func;
+ struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
+ void __iomem *cfgdata =
+ (void __iomem *)(unsigned long)&pcicptr->g2pcfgdata;
busno = bus->number;
dev = PCI_SLOT(devfn);
@@ -149,32 +165,32 @@ static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn,
busno = 0;
}
- if (mkaddr(busno, devfn, where, &flags))
+ if (mkaddr(busno, devfn, where, pcicptr))
return -1;
switch (size) {
case 1:
- *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
#ifdef __BIG_ENDIAN
- ((where & 3) ^ 3)) = val;
+ cfgdata += (where & 3) ^ 3;
#else
- (where & 3)) = val;
+ cfgdata += where & 3;
#endif
+ __raw_writeb(val, cfgdata);
break;
case 2:
- *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
#ifdef __BIG_ENDIAN
- ((where & 0x3) ^ 0x2)) = val;
+ cfgdata += (where & 2) ^ 2;
#else
- (where & 3)) = val;
+ cfgdata += where & 2;
#endif
+ __raw_writew(val, cfgdata);
break;
case 4:
- tx4938_pcicptr->g2pcfgdata = val;
+ __raw_writel(val, cfgdata);
break;
}
- return check_abort(flags);
+ return check_abort(pcicptr);
}
struct pci_ops tx4938_pci_ops = {
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c
index d7b9e1349f6d..2b4e30c7d105 100644
--- a/arch/mips/pci/pci-bcm1480.c
+++ b/arch/mips/pci/pci-bcm1480.c
@@ -74,8 +74,9 @@ static inline void WRITECFG32(u32 addr, u32 data)
*(u32 *)(cfg_space + (addr & ~3)) = data;
}
-int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
+ This is b0rked.
return dev->irq;
}
diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c
index d071bc375b11..7363e1877842 100644
--- a/arch/mips/pci/pci-ddb5477.c
+++ b/arch/mips/pci/pci-ddb5477.c
@@ -131,7 +131,7 @@ static unsigned char rockhopperII_irq_map[MAX_SLOT_NUM] = {
/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int slot_num;
unsigned char *slot_irq_map;
diff --git a/arch/mips/pci/pci-ev64120.c b/arch/mips/pci/pci-ev64120.c
deleted file mode 100644
index a84f594b5a18..000000000000
--- a/arch/mips/pci/pci-ev64120.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <linux/pci.h>
-#include <asm/irq.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int irq;
-
- if (!pin)
- return 0;
-
- irq = allocate_irqno();
- if (irq < 0)
- return 0;
-
- return irq;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 405ce0152739..a322543ac34e 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -134,7 +134,7 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid)
* A given PCI device, in general, should be able to intr any of the cpus
* on any one of the hubs connected to its xbow.
*/
-int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
int irq = bc->pci_int[slot];
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c
deleted file mode 100644
index 985784a3e6f8..000000000000
--- a/arch/mips/pci/pci-lasat.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000, 2001, 04 Keith M Wesolowski
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-
-extern struct pci_ops nile4_pci_ops;
-extern struct pci_ops gt64xxx_pci0_ops;
-static struct resource lasat_pci_mem_resource = {
- .name = "LASAT PCI MEM",
- .start = 0x18000000,
- .end = 0x19ffffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct resource lasat_pci_io_resource = {
- .name = "LASAT PCI IO",
- .start = 0x1a000000,
- .end = 0x1bffffff,
- .flags = IORESOURCE_IO,
-};
-
-static struct pci_controller lasat_pci_controller = {
- .mem_resource = &lasat_pci_mem_resource,
- .io_resource = &lasat_pci_io_resource,
-};
-
-static int __init lasat_pci_setup(void)
-{
- printk("PCI: starting\n");
-
- switch (mips_machtype) {
- case MACH_LASAT_100:
- lasat_pci_controller.pci_ops = &gt64xxx_pci0_ops;
- break;
- case MACH_LASAT_200:
- lasat_pci_controller.pci_ops = &nile4_pci_ops;
- break;
- default:
- panic("pcibios_init: mips_machtype incorrect");
- }
-
- register_pci_controller(&lasat_pci_controller);
-
- return 0;
-}
-
-arch_initcall(lasat_pci_setup);
-
-#define LASATINT_ETH1 0
-#define LASATINT_ETH0 1
-#define LASATINT_HDC 2
-#define LASATINT_COMP 3
-#define LASATINT_HDLC 4
-#define LASATINT_PCIA 5
-#define LASATINT_PCIB 6
-#define LASATINT_PCIC 7
-#define LASATINT_PCID 8
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- switch (slot) {
- case 1:
- case 2:
- case 3:
- return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4);
- case 4:
- return LASATINT_ETH1; /* Ethernet 1 (LAN 2) */
- case 5:
- return LASATINT_ETH0; /* Ethernet 0 (LAN 1) */
- case 6:
- return LASATINT_HDC; /* IDE controller */
- default:
- return 0xff; /* Illegal */
- }
-
- return -1;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c
deleted file mode 100644
index 027759f7c904..000000000000
--- a/arch/mips/pci/pci-ocelot-c.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004, 06 by Ralf Baechle (ralf@linux-mips.org)
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/mv643xx.h>
-
-#include <linux/init.h>
-
-#include <asm/marvell.h>
-
-/*
- * We assume the address ranges have already been setup appropriately by
- * the firmware. PMON in case of the Ocelot C does that.
- */
-static struct resource mv_pci_io_mem0_resource = {
- .name = "MV64340 PCI0 IO MEM",
- .flags = IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem0_resource = {
- .name = "MV64340 PCI0 MEM",
- .flags = IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem0_resource,
- .io_resource = &mv_pci_io_mem0_resource,
- },
- .config_addr = MV64340_PCI_0_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static uint32_t mv_io_base, mv_io_size;
-
-static void mv64340_pci0_init(void)
-{
- uint32_t mem0_base, mem0_size;
- uint32_t io_base, io_size;
-
- io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
- io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
- mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
- mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
-
- mv_pci_io_mem0_resource.start = 0;
- mv_pci_io_mem0_resource.end = io_size - 1;
- mv_pci_mem0_resource.start = mem0_base;
- mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
- mv_bus0_controller.pcic.mem_offset = mem0_base;
- mv_bus0_controller.pcic.io_offset = 0;
-
- ioport_resource.end = io_size - 1;
-
- register_pci_controller(&mv_bus0_controller.pcic);
-
- mv_io_base = io_base;
- mv_io_size = io_size;
-}
-
-static struct resource mv_pci_io_mem1_resource = {
- .name = "MV64340 PCI1 IO MEM",
- .flags = IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem1_resource = {
- .name = "MV64340 PCI1 MEM",
- .flags = IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem1_resource,
- .io_resource = &mv_pci_io_mem1_resource,
- },
- .config_addr = MV64340_PCI_1_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init void mv64340_pci1_init(void)
-{
- uint32_t mem0_base, mem0_size;
- uint32_t io_base, io_size;
-
- io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
- io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
- mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
- mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
-
- /*
- * Here we assume the I/O window of second bus to be contiguous with
- * the first. A gap is no problem but would waste address space for
- * remapping the port space.
- */
- mv_pci_io_mem1_resource.start = mv_io_size;
- mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
- mv_pci_mem1_resource.start = mem0_base;
- mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
- mv_bus1_controller.pcic.mem_offset = mem0_base;
- mv_bus1_controller.pcic.io_offset = 0;
-
- ioport_resource.end = io_base + io_size -mv_io_base - 1;
-
- register_pci_controller(&mv_bus1_controller.pcic);
-
- mv_io_size = io_base + io_size - mv_io_base;
-}
-
-static __init int __init ocelot_c_pci_init(void)
-{
- unsigned long io_v_base;
- uint32_t enable;
-
- enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
-
- /*
- * We require at least one enabled I/O or PCI memory window or we
- * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
- */
- if (enable & (0x01 << 9) || enable & (0x01 << 10))
- mv64340_pci0_init();
-
- if (enable & (0x01 << 14) || enable & (0x01 << 15))
- mv64340_pci1_init();
-
- if (mv_io_size) {
- io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
- if (!io_v_base)
- panic("Could not ioremap I/O port range");
-
- set_io_port_base(io_v_base);
- }
-
- return 0;
-}
-
-arch_initcall(ocelot_c_pci_init);
diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c
index 75c1246ced5f..c1ac6493155e 100644
--- a/arch/mips/pci/pci-sb1250.c
+++ b/arch/mips/pci/pci-sb1250.c
@@ -84,7 +84,7 @@ static inline void WRITECFG32(u32 addr, u32 data)
*(u32 *) (cfg_space + (addr & ~3)) = data;
}
-int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return dev->irq;
}
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
index d43f56e2cd78..c839436bd012 100644
--- a/arch/mips/philips/pnx8550/common/platform.c
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -123,7 +123,7 @@ static struct platform_device *pnx8550_platform_devices[] __initdata = {
&pnx8550_uart_device,
};
-int pnx8550_platform_init(void)
+static int __init pnx8550_platform_init(void)
{
return platform_add_devices(pnx8550_platform_devices,
ARRAY_SIZE(pnx8550_platform_devices));
diff --git a/arch/mips/philips/pnx8550/common/proc.c b/arch/mips/philips/pnx8550/common/proc.c
index 3f097558ef13..92311e95b700 100644
--- a/arch/mips/philips/pnx8550/common/proc.c
+++ b/arch/mips/philips/pnx8550/common/proc.c
@@ -78,29 +78,33 @@ static int pnx8550_proc_init( void )
{
// Create /proc/pnx8550
- pnx8550_dir = create_proc_entry("pnx8550", S_IFDIR|S_IRUGO, NULL);
+ pnx8550_dir = proc_mkdir("pnx8550", NULL);
if (!pnx8550_dir) {
printk(KERN_ERR "Can't create pnx8550 proc dir\n");
return -1;
}
// Create /proc/pnx8550/timers
- pnx8550_timers = create_proc_entry("timers", S_IFREG|S_IRUGO, pnx8550_dir );
- if (pnx8550_timers){
- pnx8550_timers->read_proc = pnx8550_timers_read;
- }
- else {
+ pnx8550_timers = create_proc_read_entry(
+ "timers",
+ 0,
+ pnx8550_dir,
+ pnx8550_timers_read,
+ NULL);
+
+ if (!pnx8550_timers)
printk(KERN_ERR "Can't create pnx8550 timers proc file\n");
- }
// Create /proc/pnx8550/registers
- pnx8550_registers = create_proc_entry("registers", S_IFREG|S_IRUGO, pnx8550_dir );
- if (pnx8550_registers){
- pnx8550_registers->read_proc = pnx8550_registers_read;
- }
- else {
+ pnx8550_registers = create_proc_read_entry(
+ "registers",
+ 0,
+ pnx8550_dir,
+ pnx8550_registers_read,
+ NULL);
+
+ if (!pnx8550_registers)
printk(KERN_ERR "Can't create pnx8550 registers proc file\n");
- }
return 0;
}
diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig
index 24d514c9dff9..abbd0bbfabd7 100644
--- a/arch/mips/pmc-sierra/Kconfig
+++ b/arch/mips/pmc-sierra/Kconfig
@@ -1,3 +1,49 @@
+choice
+ prompt "PMC-Sierra MSP SOC type"
+ depends on PMC_MSP
+
+config PMC_MSP4200_EVAL
+ bool "PMC-Sierra MSP4200 Eval Board"
+ select IRQ_MSP_SLP
+ select HW_HAS_PCI
+
+config PMC_MSP4200_GW
+ bool "PMC-Sierra MSP4200 VoIP Gateway"
+ select IRQ_MSP_SLP
+ select HW_HAS_PCI
+
+config PMC_MSP7120_EVAL
+ bool "PMC-Sierra MSP7120 Eval Board"
+ select SYS_SUPPORTS_MULTITHREADING
+ select IRQ_MSP_CIC
+ select HW_HAS_PCI
+
+config PMC_MSP7120_GW
+ bool "PMC-Sierra MSP7120 Residential Gateway"
+ select SYS_SUPPORTS_MULTITHREADING
+ select IRQ_MSP_CIC
+ select HW_HAS_PCI
+
+config PMC_MSP7120_FPGA
+ bool "PMC-Sierra MSP7120 FPGA"
+ select SYS_SUPPORTS_MULTITHREADING
+ select IRQ_MSP_CIC
+ select HW_HAS_PCI
+
+endchoice
+
+menu "Options for PMC-Sierra MSP chipsets"
+ depends on PMC_MSP
+
+config PMC_MSP_EMBEDDED_ROOTFS
+ bool "Root filesystem embedded in kernel image"
+ select MTD
+ select MTD_BLOCK
+ select MTD_PMC_MSP_RAMROOT
+ select MTD_RAM
+
+endmenu
+
config HYPERTRANSPORT
bool "Hypertransport Support for PMC-Sierra Yosemite"
depends on PMC_YOSEMITE
diff --git a/arch/mips/pmc-sierra/msp71xx/Makefile b/arch/mips/pmc-sierra/msp71xx/Makefile
new file mode 100644
index 000000000000..4bba79c1cc79
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the PMC-Sierra MSP SOCs
+#
+obj-y += msp_prom.o msp_setup.o msp_irq.o \
+ msp_time.o msp_serial.o msp_elb.o
+obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o
+obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o
+obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o
+obj-$(CONFIG_PCI) += msp_pci.o
+obj-$(CONFIG_MSPETH) += msp_eth.o
+obj-$(CONFIG_USB_MSP71XX) += msp_usb.o
diff --git a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/pmc-sierra/msp71xx/msp_elb.c
index f0f5581dcb50..3e9641007216 100644
--- a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
+++ b/arch/mips/pmc-sierra/msp71xx/msp_elb.c
@@ -1,7 +1,9 @@
/*
- * Ocelot-C Board Register Definitions
+ * Sets up the proper Chip Select configuration registers. It is assumed that
+ * PMON sets up the ADDR and MASK registers properly.
*
- * (C) 2002 Momentum Computer Inc.
+ * Copyright 2005-2006 PMC-Sierra, Inc.
+ * Author: Marc St-Jean, Marc_St-Jean@pmc-sierra.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -22,40 +24,23 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
*/
-#ifndef __OCELOT_C_FPGA_H__
-#define __OCELOT_C_FPGA_H__
-
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <msp_regs.h>
-#ifdef CONFIG_64BIT
-#define OCELOT_C_CS0_ADDR (0xfffffffffc000000)
-#else
-#define OCELOT_C_CS0_ADDR (0xfc000000)
+static int __init msp_elb_setup(void)
+{
+#if defined(CONFIG_PMC_MSP7120_GW) \
+ || defined(CONFIG_PMC_MSP7120_EVAL)
+ /*
+ * Force all CNFG to be identical and equal to CS0,
+ * according to OPS doc
+ */
+ *CS1_CNFG_REG = *CS2_CNFG_REG = *CS3_CNFG_REG = *CS0_CNFG_REG;
#endif
+ return 0;
+}
-#define OCELOT_C_REG_BOARDREV 0x0
-#define OCELOT_C_REG_FPGA_REV 0x1
-#define OCELOT_C_REG_FPGA_TYPE 0x2
-#define OCELOT_C_REG_RESET_STATUS 0x3
-#define OCELOT_C_REG_BOARD_STATUS 0x4
-#define OCELOT_C_REG_CPCI_ID 0x5
-#define OCELOT_C_REG_SET 0x6
-#define OCELOT_C_REG_CLR 0x7
-#define OCELOT_C_REG_EEPROM_MODE 0x9
-#define OCELOT_C_REG_INTMASK 0xa
-#define OCELOT_C_REG_INTSTAT 0xb
-#define OCELOT_C_REG_UART_INTMASK 0xc
-#define OCELOT_C_REG_UART_INTSTAT 0xd
-#define OCELOT_C_REG_INTSET 0xe
-#define OCELOT_C_REG_INTCLR 0xf
-
-#define __FPGA_REG_TO_ADDR(reg) \
- ((void *) OCELOT_C_CS0_ADDR + OCELOT_C_REG_##reg)
-#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
-
-#endif
+subsys_initcall(msp_elb_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c
new file mode 100644
index 000000000000..6fa85728158b
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c
@@ -0,0 +1,179 @@
+/*
+ * Sets up interrupt handlers for various hardware switches which are
+ * connected to interrupt lines.
+ *
+ * Copyright 2005-2207 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <msp_int.h>
+#include <msp_regs.h>
+#include <msp_regops.h>
+#ifdef CONFIG_PMCTWILED
+#include <msp_led_macros.h>
+#endif
+
+/* For hwbutton_interrupt->initial_state */
+#define HWBUTTON_HI 0x1
+#define HWBUTTON_LO 0x2
+
+/*
+ * This struct describes a hardware button
+ */
+struct hwbutton_interrupt {
+ char *name; /* Name of button */
+ int irq; /* Actual LINUX IRQ */
+ int eirq; /* Extended IRQ number (0-7) */
+ int initial_state; /* The "normal" state of the switch */
+ void (*handle_hi)(void *); /* Handler: switch input has gone HI */
+ void (*handle_lo)(void *); /* Handler: switch input has gone LO */
+ void *data; /* Optional data to pass to handler */
+};
+
+#ifdef CONFIG_PMC_MSP7120_GW
+extern void msp_restart(char *);
+
+static void softreset_push(void *data)
+{
+ printk(KERN_WARNING "SOFTRESET switch was pushed\n");
+
+ /*
+ * In the future you could move this to the release handler,
+ * timing the difference between the 'push' and 'release', and only
+ * doing this ungraceful restart if the button has been down for
+ * a certain amount of time; otherwise doing a graceful restart.
+ */
+
+ msp_restart(NULL);
+}
+
+static void softreset_release(void *data)
+{
+ printk(KERN_WARNING "SOFTRESET switch was released\n");
+
+ /* Do nothing */
+}
+
+static void standby_on(void *data)
+{
+ printk(KERN_WARNING "STANDBY switch was set to ON (not implemented)\n");
+
+ /* TODO: Put board in standby mode */
+#ifdef CONFIG_PMCTWILED
+ msp_led_turn_off(MSP_LED_PWRSTANDBY_GREEN);
+ msp_led_turn_on(MSP_LED_PWRSTANDBY_RED);
+#endif
+}
+
+static void standby_off(void *data)
+{
+ printk(KERN_WARNING
+ "STANDBY switch was set to OFF (not implemented)\n");
+
+ /* TODO: Take out of standby mode */
+#ifdef CONFIG_PMCTWILED
+ msp_led_turn_on(MSP_LED_PWRSTANDBY_GREEN);
+ msp_led_turn_off(MSP_LED_PWRSTANDBY_RED);
+#endif
+}
+
+static struct hwbutton_interrupt softreset_sw = {
+ .name = "Softreset button",
+ .irq = MSP_INT_EXT0,
+ .eirq = 0,
+ .initial_state = HWBUTTON_HI,
+ .handle_hi = softreset_release,
+ .handle_lo = softreset_push,
+ .data = NULL,
+};
+
+static struct hwbutton_interrupt standby_sw = {
+ .name = "Standby switch",
+ .irq = MSP_INT_EXT1,
+ .eirq = 1,
+ .initial_state = HWBUTTON_HI,
+ .handle_hi = standby_off,
+ .handle_lo = standby_on,
+ .data = NULL,
+};
+#endif /* CONFIG_PMC_MSP7120_GW */
+
+static irqreturn_t hwbutton_handler(int irq, void *data)
+{
+ struct hwbutton_interrupt *hirq = data;
+ unsigned long cic_ext = *CIC_EXT_CFG_REG;
+
+ if (irq != hirq->irq)
+ return IRQ_NONE;
+
+ if (CIC_EXT_IS_ACTIVE_HI(cic_ext, hirq->eirq)) {
+ /* Interrupt: pin is now HI */
+ CIC_EXT_SET_ACTIVE_LO(cic_ext, hirq->eirq);
+ hirq->handle_hi(hirq->data);
+ } else {
+ /* Interrupt: pin is now LO */
+ CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq);
+ hirq->handle_lo(hirq->data);
+ }
+
+ /*
+ * Invert the POLARITY of this level interrupt to ack the interrupt
+ * Thus next state change will invoke the opposite message
+ */
+ *CIC_EXT_CFG_REG = cic_ext;
+
+ return IRQ_HANDLED;
+}
+
+static int msp_hwbutton_register(struct hwbutton_interrupt *hirq)
+{
+ unsigned long cic_ext;
+
+ if (hirq->handle_hi == NULL || hirq->handle_lo == NULL)
+ return -EINVAL;
+
+ cic_ext = *CIC_EXT_CFG_REG;
+ CIC_EXT_SET_TRIGGER_LEVEL(cic_ext, hirq->eirq);
+ if (hirq->initial_state == HWBUTTON_HI)
+ CIC_EXT_SET_ACTIVE_LO(cic_ext, hirq->eirq);
+ else
+ CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq);
+ *CIC_EXT_CFG_REG = cic_ext;
+
+ return request_irq(hirq->irq, hwbutton_handler, SA_INTERRUPT,
+ hirq->name, (void *)hirq);
+}
+
+static int __init msp_hwbutton_setup(void)
+{
+#ifdef CONFIG_PMC_MSP7120_GW
+ msp_hwbutton_register(&softreset_sw);
+ msp_hwbutton_register(&standby_sw);
+#endif
+ return 0;
+}
+
+subsys_initcall(msp_hwbutton_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq.c b/arch/mips/pmc-sierra/msp71xx/msp_irq.c
new file mode 100644
index 000000000000..734d598a2e3a
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq.c
@@ -0,0 +1,124 @@
+/*
+ * IRQ vector handles
+ *
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/time.h>
+
+#include <asm/irq_cpu.h>
+
+#include <msp_int.h>
+
+extern void msp_int_handle(void);
+
+/* SLP bases systems */
+extern void msp_slp_irq_init(void);
+extern void msp_slp_irq_dispatch(void);
+
+/* CIC based systems */
+extern void msp_cic_irq_init(void);
+extern void msp_cic_irq_dispatch(void);
+
+/*
+ * The PMC-Sierra MSP interrupts are arranged in a 3 level cascaded
+ * hierarchical system. The first level are the direct MIPS interrupts
+ * and are assigned the interrupt range 0-7. The second level is the SLM
+ * interrupt controller and is assigned the range 8-39. The third level
+ * comprises the Peripherial block, the PCI block, the PCI MSI block and
+ * the SLP. The PCI interrupts and the SLP errors are handled by the
+ * relevant subsystems so the core interrupt code needs only concern
+ * itself with the Peripheral block. These are assigned interrupts in
+ * the range 40-71.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ u32 pending;
+
+ pending = read_c0_status() & read_c0_cause();
+
+ /*
+ * jump to the correct interrupt routine
+ * These are arranged in priority order and the timer
+ * comes first!
+ */
+
+#ifdef CONFIG_IRQ_MSP_CIC /* break out the CIC stuff for now */
+ if (pending & C_IRQ4) /* do the peripherals first, that's the timer */
+ msp_cic_irq_dispatch();
+
+ else if (pending & C_IRQ0)
+ do_IRQ(MSP_INT_MAC0);
+
+ else if (pending & C_IRQ1)
+ do_IRQ(MSP_INT_MAC1);
+
+ else if (pending & C_IRQ2)
+ do_IRQ(MSP_INT_USB);
+
+ else if (pending & C_IRQ3)
+ do_IRQ(MSP_INT_SAR);
+
+ else if (pending & C_IRQ5)
+ do_IRQ(MSP_INT_SEC);
+
+#else
+ if (pending & C_IRQ5)
+ do_IRQ(MSP_INT_TIMER);
+
+ else if (pending & C_IRQ0)
+ do_IRQ(MSP_INT_MAC0);
+
+ else if (pending & C_IRQ1)
+ do_IRQ(MSP_INT_MAC1);
+
+ else if (pending & C_IRQ3)
+ do_IRQ(MSP_INT_VE);
+
+ else if (pending & C_IRQ4)
+ msp_slp_irq_dispatch();
+#endif
+
+ else if (pending & C_SW0) /* do software after hardware */
+ do_IRQ(MSP_INT_SW0);
+
+ else if (pending & C_SW1)
+ do_IRQ(MSP_INT_SW1);
+}
+
+static struct irqaction cascade_msp = {
+ .handler = no_action,
+ .name = "MSP cascade"
+};
+
+
+void __init arch_init_irq(void)
+{
+ /* initialize the 1st-level CPU based interrupt controller */
+ mips_cpu_irq_init();
+
+#ifdef CONFIG_IRQ_MSP_CIC
+ msp_cic_irq_init();
+
+ /* setup the cascaded interrupts */
+ setup_irq(MSP_INT_CIC, &cascade_msp);
+ setup_irq(MSP_INT_PER, &cascade_msp);
+#else
+ /* setup the 2nd-level SLP register based interrupt controller */
+ msp_slp_irq_init();
+
+ /* setup the cascaded SLP/PER interrupts */
+ setup_irq(MSP_INT_SLP, &cascade_msp);
+ setup_irq(MSP_INT_PER, &cascade_msp);
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
new file mode 100644
index 000000000000..5175357d0a25
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
@@ -0,0 +1,134 @@
+/*
+ * This file define the irq handler for MSP SLM subsystem interrupts.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc, derived from irq_cpu.c
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+
+#include <msp_cic_int.h>
+#include <msp_regs.h>
+
+/*
+ * NOTE: We are only enabling support for VPE0 right now.
+ */
+
+static inline void unmask_msp_cic_irq(unsigned int irq)
+{
+
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *CIC_VPE0_MSK_REG |= (1 << (irq - MSP_CIC_INTBASE));
+ else
+ *PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+}
+
+static inline void mask_msp_cic_irq(unsigned int irq)
+{
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *CIC_VPE0_MSK_REG &= ~(1 << (irq - MSP_CIC_INTBASE));
+ else
+ *PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues. Same for msp_cic_irq_end.
+ */
+static inline void ack_msp_cic_irq(unsigned int irq)
+{
+ mask_msp_cic_irq(irq);
+
+ /*
+ * only really necessary for 18, 16-14 and sometimes 3:0 (since
+ * these can be edge sensitive) but it doesn't hurt for the others.
+ */
+
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *CIC_STS_REG = (1 << (irq - MSP_CIC_INTBASE));
+ else
+ *PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
+}
+
+static struct irq_chip msp_cic_irq_controller = {
+ .name = "MSP_CIC",
+ .ack = ack_msp_cic_irq,
+ .mask = ack_msp_cic_irq,
+ .mask_ack = ack_msp_cic_irq,
+ .unmask = unmask_msp_cic_irq,
+};
+
+
+void __init msp_cic_irq_init(void)
+{
+ int i;
+
+ /* Mask/clear interrupts. */
+ *CIC_VPE0_MSK_REG = 0x00000000;
+ *PER_INT_MSK_REG = 0x00000000;
+ *CIC_STS_REG = 0xFFFFFFFF;
+ *PER_INT_STS_REG = 0xFFFFFFFF;
+
+#if defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_EVAL)
+ /*
+ * The MSP7120 RG and EVBD boards use IRQ[6:4] for PCI.
+ * These inputs map to EXT_INT_POL[6:4] inside the CIC.
+ * They are to be active low, level sensitive.
+ */
+ *CIC_EXT_CFG_REG &= 0xFFFF8F8F;
+#endif
+
+ /* initialize all the IRQ descriptors */
+ for (i = MSP_CIC_INTBASE; i < MSP_PER_INTBASE + 32; i++)
+ set_irq_chip_and_handler(i, &msp_cic_irq_controller,
+ handle_level_irq);
+}
+
+void msp_cic_irq_dispatch(void)
+{
+ u32 pending;
+ int intbase;
+
+ intbase = MSP_CIC_INTBASE;
+ pending = *CIC_STS_REG & *CIC_VPE0_MSK_REG;
+
+ /* check for PER interrupt */
+ if (pending == (1 << (MSP_INT_PER - MSP_CIC_INTBASE))) {
+ intbase = MSP_PER_INTBASE;
+ pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
+ }
+
+ /* check for spurious interrupt */
+ if (pending == 0x00000000) {
+ printk(KERN_ERR
+ "Spurious %s interrupt? status %08x, mask %08x\n",
+ (intbase == MSP_CIC_INTBASE) ? "CIC" : "PER",
+ (intbase == MSP_CIC_INTBASE) ?
+ *CIC_STS_REG : *PER_INT_STS_REG,
+ (intbase == MSP_CIC_INTBASE) ?
+ *CIC_VPE0_MSK_REG : *PER_INT_MSK_REG);
+ return;
+ }
+
+ /* check for the timer and dispatch it first */
+ if ((intbase == MSP_CIC_INTBASE) &&
+ (pending & (1 << (MSP_INT_VPE0_TIMER - MSP_CIC_INTBASE))))
+ do_IRQ(MSP_INT_VPE0_TIMER);
+ else
+ do_IRQ(ffs(pending) + intbase - 1);
+}
+
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
new file mode 100644
index 000000000000..f5f1b8d2bb9a
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
@@ -0,0 +1,109 @@
+/*
+ * This file define the irq handler for MSP SLM subsystem interrupts.
+ *
+ * Copyright 2005-2006 PMC-Sierra, Inc, derived from irq_cpu.c
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <msp_slp_int.h>
+#include <msp_regs.h>
+
+static inline void unmask_msp_slp_irq(unsigned int irq)
+{
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *SLP_INT_MSK_REG |= (1 << (irq - MSP_SLP_INTBASE));
+ else
+ *PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+}
+
+static inline void mask_msp_slp_irq(unsigned int irq)
+{
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *SLP_INT_MSK_REG &= ~(1 << (irq - MSP_SLP_INTBASE));
+ else
+ *PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues. Same for msp_slp_irq_end.
+ */
+static inline void ack_msp_slp_irq(unsigned int irq)
+{
+ mask_slp_irq(irq);
+
+ /*
+ * only really necessary for 18, 16-14 and sometimes 3:0 (since
+ * these can be edge sensitive) but it doesn't hurt for the others.
+ */
+
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *SLP_INT_STS_REG = (1 << (irq - MSP_SLP_INTBASE));
+ else
+ *PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
+}
+
+static struct irq_chip msp_slp_irq_controller = {
+ .name = "MSP_SLP",
+ .ack = ack_msp_slp_irq,
+ .mask = ack_msp_slp_irq,
+ .mask_ack = ack_msp_slp_irq,
+ .unmask = unmask_msp_slp_irq,
+};
+
+void __init msp_slp_irq_init(void)
+{
+ int i;
+
+ /* Mask/clear interrupts. */
+ *SLP_INT_MSK_REG = 0x00000000;
+ *PER_INT_MSK_REG = 0x00000000;
+ *SLP_INT_STS_REG = 0xFFFFFFFF;
+ *PER_INT_STS_REG = 0xFFFFFFFF;
+
+ /* initialize all the IRQ descriptors */
+ for (i = MSP_SLP_INTBASE; i < MSP_PER_INTBASE + 32; i++)
+ set_irq_chip_and_handler(i, &msp_slp_irq_controller
+ handle_level_irq);
+}
+
+void msp_slp_irq_dispatch(void)
+{
+ u32 pending;
+ int intbase;
+
+ intbase = MSP_SLP_INTBASE;
+ pending = *SLP_INT_STS_REG & *SLP_INT_MSK_REG;
+
+ /* check for PER interrupt */
+ if (pending == (1 << (MSP_INT_PER - MSP_SLP_INTBASE))) {
+ intbase = MSP_PER_INTBASE;
+ pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
+ }
+
+ /* check for spurious interrupt */
+ if (pending == 0x00000000) {
+ printk(KERN_ERR "Spurious %s interrupt?\n",
+ (intbase == MSP_SLP_INTBASE) ? "SLP" : "PER");
+ return;
+ }
+
+ /* dispatch the irq */
+ do_IRQ(ffs(pending) + intbase - 1);
+}
diff --git a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h b/arch/mips/pmc-sierra/msp71xx/msp_pci.c
index 5710a9029f1c..f764fe7748d6 100644
--- a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h
+++ b/arch/mips/pmc-sierra/msp71xx/msp_pci.c
@@ -1,7 +1,7 @@
/*
- * Ocelot-3 Board Register Definitions
+ * The setup file for PCI related hardware on PMC-Sierra MSP processors.
*
- * (C) 2002 Momentum Computer Inc.
+ * Copyright 2005-2006 PMC-Sierra, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -22,38 +22,29 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
*/
-#ifndef __OCELOT_3_FPGA_H__
-#define __OCELOT_3_FPGA_H__
-
-#define OCELOT_3_REG_BOARDREV 0x0
-#define OCELOT_3_REG_FPGA_REV 0x1
-#define OCELOT_3_REG_FPGA_TYPE 0x2
-#define OCELOT_3_REG_RESET_STATUS 0x3
-#define OCELOT_3_REG_BOARD_STATUS 0x4
-#define OCELOT_3_REG_CPCI_ID 0x5
-#define OCELOT_3_REG_SET 0x6
-#define OCELOT_3_REG_CLR 0x7
-#define OCELOT_3_REG_EEPROM_MODE 0x9
-#define OCELOT_3_REG_INTMASK 0xa
-#define OCELOT_3_REG_INTSTAT 0xb
-#define OCELOT_3_REG_UART_INTMASK 0xc
-#define OCELOT_3_REG_UART_INTSTAT 0xd
-#define OCELOT_3_REG_INTSET 0xe
-#define OCELOT_3_REG_INTCLR 0xf
-
-extern unsigned long ocelot_fpga_base;
-
-#define __FPGA_REG_TO_ADDR(reg) \
- ((void *) ocelot_fpga_base + OCELOT_3_REG_##reg)
-#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
+#include <linux/init.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+extern void msp_pci_init(void);
+static int __init msp_pci_setup(void)
+{
+#if 0 /* Linux 2.6 initialization code to be completed */
+ if (getdeviceid() & DEV_ID_SINGLE_PC) {
+ /* If single card mode */
+ slmRegs *sreg = (slmRegs *) SREG_BASE;
+
+ sreg->single_pc_enable = SINGLE_PCCARD;
+ }
#endif
+
+ msp_pci_init();
+
+ return 0;
+}
+
+subsys_initcall(msp_pci_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_prom.c b/arch/mips/pmc-sierra/msp71xx/msp_prom.c
new file mode 100644
index 000000000000..e5bd5481d8db
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_prom.c
@@ -0,0 +1,566 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * PROM library initialisation code, assuming a version of
+ * pmon is the boot code.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#ifdef CONFIG_CRAMFS
+#include <linux/cramfs_fs.h>
+#endif
+#ifdef CONFIG_SQUASHFS
+#include <linux/squashfs_fs.h>
+#endif
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm-generic/sections.h>
+#include <asm/page.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+/* global PROM environment variables and pointers */
+int prom_argc;
+char **prom_argv, **prom_envp;
+int *prom_vec;
+
+/* debug flag */
+int init_debug = 1;
+
+/* memory blocks */
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+/* default feature sets */
+static char msp_default_features[] =
+#if defined(CONFIG_PMC_MSP4200_EVAL) \
+ || defined(CONFIG_PMC_MSP4200_GW)
+ "ERER";
+#elif defined(CONFIG_PMC_MSP7120_EVAL) \
+ || defined(CONFIG_PMC_MSP7120_GW)
+ "EMEMSP";
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+ "EMEM";
+#endif
+
+/* conversion functions */
+static inline unsigned char str2hexnum(unsigned char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0; /* foo */
+}
+
+static inline int str2eaddr(unsigned char *ea, unsigned char *str)
+{
+ int index = 0;
+ unsigned char num = 0;
+
+ while (*str != '\0') {
+ if ((*str == '.') || (*str == ':')) {
+ ea[index++] = num;
+ num = 0;
+ str++;
+ } else {
+ num = num << 4;
+ num |= str2hexnum(*str++);
+ }
+ }
+
+ if (index == 5) {
+ ea[index++] = num;
+ return 0;
+ } else
+ return -1;
+}
+EXPORT_SYMBOL(str2eaddr);
+
+static inline unsigned long str2hex(unsigned char *str)
+{
+ int value = 0;
+
+ while (*str) {
+ value = value << 4;
+ value |= str2hexnum(*str++);
+ }
+
+ return value;
+}
+
+/* function to query the system information */
+const char *get_system_type(void)
+{
+#if defined(CONFIG_PMC_MSP4200_EVAL)
+ return "PMC-Sierra MSP4200 Eval Board";
+#elif defined(CONFIG_PMC_MSP4200_GW)
+ return "PMC-Sierra MSP4200 VoIP Gateway";
+#elif defined(CONFIG_PMC_MSP7120_EVAL)
+ return "PMC-Sierra MSP7120 Eval Board";
+#elif defined(CONFIG_PMC_MSP7120_GW)
+ return "PMC-Sierra MSP7120 Residential Gateway";
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+ return "PMC-Sierra MSP7120 FPGA";
+#else
+ #error "What is the type of *your* MSP?"
+#endif
+}
+
+int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr)
+{
+ char *ethaddr_str;
+
+ ethaddr_str = prom_getenv(ethaddr_name);
+ if (!ethaddr_str) {
+ printk(KERN_WARNING "%s not set in boot prom\n", ethaddr_name);
+ return -1;
+ }
+
+ if (str2eaddr(ethernet_addr, ethaddr_str) == -1) {
+ printk(KERN_WARNING "%s badly formatted-<%s>\n",
+ ethaddr_name, ethaddr_str);
+ return -1;
+ }
+
+ if (init_debug > 1) {
+ int i;
+ printk(KERN_DEBUG "get_ethernet_addr: for %s ", ethaddr_name);
+ for (i = 0; i < 5; i++)
+ printk(KERN_DEBUG "%02x:",
+ (unsigned char)*(ethernet_addr+i));
+ printk(KERN_DEBUG "%02x\n", *(ethernet_addr+i));
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(get_ethernet_addr);
+
+static char *get_features(void)
+{
+ char *feature = prom_getenv(FEATURES);
+
+ if (feature == NULL) {
+ /* default features based on MACHINE_TYPE */
+ feature = msp_default_features;
+ }
+
+ return feature;
+}
+
+static char test_feature(char c)
+{
+ char *feature = get_features();
+
+ while (*feature) {
+ if (*feature++ == c)
+ return *feature;
+ feature++;
+ }
+
+ return FEATURE_NOEXIST;
+}
+
+unsigned long get_deviceid(void)
+{
+ char *deviceid = prom_getenv(DEVICEID);
+
+ if (deviceid == NULL)
+ return *DEV_ID_REG;
+ else
+ return str2hex(deviceid);
+}
+
+char identify_pci(void)
+{
+ return test_feature(PCI_KEY);
+}
+EXPORT_SYMBOL(identify_pci);
+
+char identify_pcimux(void)
+{
+ return test_feature(PCIMUX_KEY);
+}
+
+char identify_sec(void)
+{
+ return test_feature(SEC_KEY);
+}
+EXPORT_SYMBOL(identify_sec);
+
+char identify_spad(void)
+{
+ return test_feature(SPAD_KEY);
+}
+EXPORT_SYMBOL(identify_spad);
+
+char identify_tdm(void)
+{
+ return test_feature(TDM_KEY);
+}
+EXPORT_SYMBOL(identify_tdm);
+
+char identify_zsp(void)
+{
+ return test_feature(ZSP_KEY);
+}
+EXPORT_SYMBOL(identify_zsp);
+
+static char identify_enetfeature(char key, unsigned long interface_num)
+{
+ char *feature = get_features();
+
+ while (*feature) {
+ if (*feature++ == key && interface_num-- == 0)
+ return *feature;
+ feature++;
+ }
+
+ return FEATURE_NOEXIST;
+}
+
+char identify_enet(unsigned long interface_num)
+{
+ return identify_enetfeature(ENET_KEY, interface_num);
+}
+EXPORT_SYMBOL(identify_enet);
+
+char identify_enetTxD(unsigned long interface_num)
+{
+ return identify_enetfeature(ENETTXD_KEY, interface_num);
+}
+EXPORT_SYMBOL(identify_enetTxD);
+
+unsigned long identify_family(void)
+{
+ unsigned long deviceid;
+
+ deviceid = get_deviceid();
+
+ return deviceid & CPU_DEVID_FAMILY;
+}
+EXPORT_SYMBOL(identify_family);
+
+unsigned long identify_revision(void)
+{
+ unsigned long deviceid;
+
+ deviceid = get_deviceid();
+
+ return deviceid & CPU_DEVID_REVISION;
+}
+EXPORT_SYMBOL(identify_revision);
+
+/* PROM environment functions */
+char *prom_getenv(char *env_name)
+{
+ /*
+ * Return a pointer to the given environment variable. prom_envp
+ * points to a null terminated array of pointers to variables.
+ * Environment variables are stored in the form of "memsize=64"
+ */
+
+ char **var = prom_envp;
+ int i = strlen(env_name);
+
+ while (*var) {
+ if (strncmp(env_name, *var, i) == 0) {
+ return (*var + strlen(env_name) + 1);
+ }
+ var++;
+ }
+
+ return NULL;
+}
+
+/* PROM commandline functions */
+char *prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+EXPORT_SYMBOL(prom_getcmdline);
+
+void __init prom_init_cmdline(void)
+{
+ char *cp;
+ int actr;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = &(arcs_cmdline[0]);
+ while (actr < prom_argc) {
+ strcpy(cp, prom_argv[actr]);
+ cp += strlen(prom_argv[actr]);
+ *cp++ = ' ';
+ actr++;
+ }
+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+}
+
+/* memory allocation functions */
+static int __init prom_memtype_classify(unsigned int type)
+{
+ switch (type) {
+ case yamon_free:
+ return BOOT_MEM_RAM;
+ case yamon_prom:
+ return BOOT_MEM_ROM_DATA;
+ default:
+ return BOOT_MEM_RESERVED;
+ }
+}
+
+void __init prom_meminit(void)
+{
+ struct prom_pmemblock *p;
+
+ p = prom_getmdesc();
+
+ while (p->size) {
+ long type;
+ unsigned long base, size;
+
+ type = prom_memtype_classify(p->type);
+ base = p->base;
+ size = p->size;
+
+ add_memory_region(base, size, type);
+ p++;
+ }
+}
+
+void __init prom_free_prom_memory(void)
+{
+ int argc;
+ char **argv;
+ char **envp;
+ char *ptr;
+ int len = 0;
+ int i;
+ unsigned long addr;
+
+ /*
+ * preserve environment variables and command line from pmon/bbload
+ * first preserve the command line
+ */
+ for (argc = 0; argc < prom_argc; argc++) {
+ len += sizeof(char *); /* length of pointer */
+ len += strlen(prom_argv[argc]) + 1; /* length of string */
+ }
+ len += sizeof(char *); /* plus length of null pointer */
+
+ argv = kmalloc(len, GFP_KERNEL);
+ ptr = (char *) &argv[prom_argc + 1]; /* strings follow array */
+
+ for (argc = 0; argc < prom_argc; argc++) {
+ argv[argc] = ptr;
+ strcpy(ptr, prom_argv[argc]);
+ ptr += strlen(prom_argv[argc]) + 1;
+ }
+ argv[prom_argc] = NULL; /* end array with null pointer */
+ prom_argv = argv;
+
+ /* next preserve the environment variables */
+ len = 0;
+ i = 0;
+ for (envp = prom_envp; *envp != NULL; envp++) {
+ i++; /* count number of environment variables */
+ len += sizeof(char *); /* length of pointer */
+ len += strlen(*envp) + 1; /* length of string */
+ }
+ len += sizeof(char *); /* plus length of null pointer */
+
+ envp = kmalloc(len, GFP_KERNEL);
+ ptr = (char *) &envp[i+1];
+
+ for (argc = 0; argc < i; argc++) {
+ envp[argc] = ptr;
+ strcpy(ptr, prom_envp[argc]);
+ ptr += strlen(prom_envp[argc]) + 1;
+ }
+ envp[i] = NULL; /* end array with null pointer */
+ prom_envp = envp;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+ continue;
+
+ addr = boot_mem_map.map[i].addr;
+ free_init_pages("prom memory",
+ addr, addr + boot_mem_map.map[i].size);
+ }
+}
+
+struct prom_pmemblock *__init prom_getmdesc(void)
+{
+ static char memsz_env[] __initdata = "memsize";
+ static char heaptop_env[] __initdata = "heaptop";
+ char *str;
+ unsigned int memsize;
+ unsigned int heaptop;
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+ void *ramroot_start;
+ unsigned long ramroot_size;
+#endif
+ int i;
+
+ str = prom_getenv(memsz_env);
+ if (!str) {
+ ppfinit("memsize not set in boot prom, "
+ "set to default (32Mb)\n");
+ memsize = 0x02000000;
+ } else {
+ memsize = simple_strtol(str, NULL, 0);
+
+ if (memsize == 0) {
+ /* if memsize is a bad size, use reasonable default */
+ memsize = 0x02000000;
+ }
+
+ /* convert to physical address (removing caching bits, etc) */
+ memsize = CPHYSADDR(memsize);
+ }
+
+ str = prom_getenv(heaptop_env);
+ if (!str) {
+ heaptop = CPHYSADDR((u32)&_text);
+ ppfinit("heaptop not set in boot prom, "
+ "set to default 0x%08x\n", heaptop);
+ } else {
+ heaptop = simple_strtol(str, NULL, 16);
+ if (heaptop == 0) {
+ /* heaptop conversion bad, might have 0xValue */
+ heaptop = simple_strtol(str, NULL, 0);
+
+ if (heaptop == 0) {
+ /* heaptop still bad, use reasonable default */
+ heaptop = CPHYSADDR((u32)&_text);
+ }
+ }
+
+ /* convert to physical address (removing caching bits, etc) */
+ heaptop = CPHYSADDR((u32)heaptop);
+ }
+
+ /* the base region */
+ i = 0;
+ mdesc[i].type = BOOT_MEM_RESERVED;
+ mdesc[i].base = 0x00000000;
+ mdesc[i].size = PAGE_ALIGN(0x300 + 0x80);
+ /* jtag interrupt vector + sizeof vector */
+
+ /* PMON data */
+ if (heaptop > mdesc[i].base + mdesc[i].size) {
+ i++; /* 1 */
+ mdesc[i].type = BOOT_MEM_ROM_DATA;
+ mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
+ mdesc[i].size = heaptop - mdesc[i].base;
+ }
+
+ /* end of PMON data to start of kernel -- probably zero .. */
+ if (heaptop != CPHYSADDR((u32)_text)) {
+ i++; /* 2 */
+ mdesc[i].type = BOOT_MEM_RAM;
+ mdesc[i].base = heaptop;
+ mdesc[i].size = CPHYSADDR((u32)_text) - mdesc[i].base;
+ }
+
+ /* kernel proper */
+ i++; /* 3 */
+ mdesc[i].type = BOOT_MEM_RESERVED;
+ mdesc[i].base = CPHYSADDR((u32)_text);
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+ if (get_ramroot(&ramroot_start, &ramroot_size)) {
+ /*
+ * Rootfs in RAM -- follows kernel
+ * Combine rootfs image with kernel block so a
+ * page (4k) isn't wasted between memory blocks
+ */
+ mdesc[i].size = CPHYSADDR(PAGE_ALIGN(
+ (u32)ramroot_start + ramroot_size)) - mdesc[i].base;
+ } else
+#endif
+ mdesc[i].size = CPHYSADDR(PAGE_ALIGN(
+ (u32)_end)) - mdesc[i].base;
+
+ /* Remainder of RAM -- under memsize */
+ i++; /* 5 */
+ mdesc[i].type = yamon_free;
+ mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
+ mdesc[i].size = memsize - mdesc[i].base;
+
+ return &mdesc[0];
+}
+
+/* rootfs functions */
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+bool get_ramroot(void **start, unsigned long *size)
+{
+ extern char _end[];
+
+ /* Check for start following the end of the kernel */
+ void *check_start = (void *)_end;
+
+ /* Check for supported rootfs types */
+#ifdef CONFIG_CRAMFS
+ if (*(__u32 *)check_start == CRAMFS_MAGIC) {
+ /* Get CRAMFS size */
+ *start = check_start;
+ *size = PAGE_ALIGN(((struct cramfs_super *)
+ check_start)->size);
+
+ return true;
+ }
+#endif
+#ifdef CONFIG_SQUASHFS
+ if (*((unsigned int *)check_start) == SQUASHFS_MAGIC) {
+ /* Get SQUASHFS size */
+ *start = check_start;
+ *size = PAGE_ALIGN(((struct squashfs_super_block *)
+ check_start)->bytes_used);
+
+ return true;
+ }
+#endif
+
+ return false;
+}
+EXPORT_SYMBOL(get_ramroot);
+#endif
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
new file mode 100644
index 000000000000..8f69b789be90
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
@@ -0,0 +1,256 @@
+/*
+ * The generic setup file for PMC-Sierra MSP processors
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc,
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bootinfo.h>
+#include <asm/cacheflush.h>
+#include <asm/r4kcache.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+#include <msp_regops.h>
+#include <msp_gpio.h>
+#define MSP_BOARD_RESET_GPIO 9
+#endif
+
+extern void msp_timer_init(void);
+extern void msp_serial_setup(void);
+extern void pmctwiled_setup(void);
+
+#if defined(CONFIG_PMC_MSP7120_EVAL) || \
+ defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_FPGA)
+/*
+ * Performs the reset for MSP7120-based boards
+ */
+void msp7120_reset(void)
+{
+ void *start, *end, *iptr;
+ register int i;
+
+ /* Diasble all interrupts */
+ local_irq_disable();
+#ifdef CONFIG_SYS_SUPPORTS_MULTITHREADING
+ dvpe();
+#endif
+
+ /* Cache the reset code of this function */
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set mips3 \n"
+ " la %0,startpoint \n"
+ " la %1,endpoint \n"
+ " .set pop \n"
+ : "=r" (start), "=r" (end)
+ :
+ );
+
+ for (iptr = (void *)((unsigned int)start & ~(L1_CACHE_BYTES - 1));
+ iptr < end; iptr += L1_CACHE_BYTES)
+ cache_op(Fill, iptr);
+
+ __asm__ __volatile__ (
+ "startpoint: \n"
+ );
+
+ /* Put the DDRC into self-refresh mode */
+ DDRC_INDIRECT_WRITE(DDRC_CTL(10), 0xb, 1 << 16);
+
+ /*
+ * IMPORTANT!
+ * DO NOT do anything from here on out that might even
+ * think about fetching from RAM - i.e., don't call any
+ * non-inlined functions, and be VERY sure that any inline
+ * functions you do call do NOT access any sort of RAM
+ * anywhere!
+ */
+
+ /* Wait a bit for the DDRC to settle */
+ for (i = 0; i < 100000000; i++);
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+ /*
+ * Set GPIO 9 HI, (tied to board reset logic)
+ * GPIO 9 is the 4th GPIO of register 3
+ *
+ * NOTE: We cannot use the higher-level msp_gpio_mode()/out()
+ * as GPIO char driver may not be enabled and it would look up
+ * data inRAM!
+ */
+ set_value_reg32(GPIO_CFG3_REG,
+ basic_mode_mask(MSP_BOARD_RESET_GPIO),
+ basic_mode(MSP_GPIO_OUTPUT, MSP_BOARD_RESET_GPIO));
+ set_reg32(GPIO_DATA3_REG,
+ basic_data_mask(MSP_BOARD_RESET_GPIO));
+
+ /*
+ * In case GPIO9 doesn't reset the board (jumper configurable!)
+ * fallback to device reset below.
+ */
+#endif
+ /* Set bit 1 of the MSP7120 reset register */
+ *RST_SET_REG = 0x00000001;
+
+ __asm__ __volatile__ (
+ "endpoint: \n"
+ );
+}
+#endif
+
+void msp_restart(char *command)
+{
+ printk(KERN_WARNING "Now rebooting .......\n");
+
+#if defined(CONFIG_PMC_MSP7120_EVAL) || \
+ defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_FPGA)
+ msp7120_reset();
+#else
+ /* No chip-specific reset code, just jump to the ROM reset vector */
+ set_c0_status(ST0_BEV | ST0_ERL);
+ change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+ flush_cache_all();
+ write_c0_wired(0);
+
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+#endif
+}
+
+void msp_halt(void)
+{
+ printk(KERN_WARNING "\n** You can safely turn off the power\n");
+ while (1)
+ /* If possible call official function to get CPU WARs */
+ if (cpu_wait)
+ (*cpu_wait)();
+ else
+ __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
+}
+
+void msp_power_off(void)
+{
+ msp_halt();
+}
+
+void __init plat_mem_setup(void)
+{
+ _machine_restart = msp_restart;
+ _machine_halt = msp_halt;
+ pm_power_off = msp_power_off;
+
+ board_time_init = msp_timer_init;
+}
+
+void __init prom_init(void)
+{
+ unsigned long family;
+ unsigned long revision;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **)fw_arg1;
+ prom_envp = (char **)fw_arg2;
+
+ /*
+ * Someday we can use this with PMON2000 to get a
+ * platform call prom routines for output etc. without
+ * having to use grody hacks. For now it's unused.
+ *
+ * struct callvectors *cv = (struct callvectors *) fw_arg3;
+ */
+ family = identify_family();
+ revision = identify_revision();
+
+ switch (family) {
+ case FAMILY_FPGA:
+ if (FPGA_IS_MSP4200(revision)) {
+ /* Old-style revision ID */
+ mips_machgroup = MACH_GROUP_MSP;
+ mips_machtype = MACH_MSP4200_FPGA;
+ } else {
+ mips_machgroup = MACH_GROUP_MSP;
+ mips_machtype = MACH_MSP_OTHER;
+ }
+ break;
+
+ case FAMILY_MSP4200:
+ mips_machgroup = MACH_GROUP_MSP;
+#if defined(CONFIG_PMC_MSP4200_EVAL)
+ mips_machtype = MACH_MSP4200_EVAL;
+#elif defined(CONFIG_PMC_MSP4200_GW)
+ mips_machtype = MACH_MSP4200_GW;
+#else
+ mips_machtype = MACH_MSP_OTHER;
+#endif
+ break;
+
+ case FAMILY_MSP4200_FPGA:
+ mips_machgroup = MACH_GROUP_MSP;
+ mips_machtype = MACH_MSP4200_FPGA;
+ break;
+
+ case FAMILY_MSP7100:
+ mips_machgroup = MACH_GROUP_MSP;
+#if defined(CONFIG_PMC_MSP7120_EVAL)
+ mips_machtype = MACH_MSP7120_EVAL;
+#elif defined(CONFIG_PMC_MSP7120_GW)
+ mips_machtype = MACH_MSP7120_GW;
+#else
+ mips_machtype = MACH_MSP_OTHER;
+#endif
+ break;
+
+ case FAMILY_MSP7100_FPGA:
+ mips_machgroup = MACH_GROUP_MSP;
+ mips_machtype = MACH_MSP7120_FPGA;
+ break;
+
+ default:
+ /* we don't recognize the machine */
+ mips_machgroup = MACH_GROUP_UNKNOWN;
+ mips_machtype = MACH_UNKNOWN;
+ break;
+ }
+
+ /* make sure we have the right initialization routine - sanity */
+ if (mips_machgroup != MACH_GROUP_MSP) {
+ ppfinit("Unknown machine group in a "
+ "MSP initialization routine\n");
+ panic("***Bogosity factor five***, exiting\n");
+ }
+
+ prom_init_cmdline();
+
+ prom_meminit();
+
+ /*
+ * Sub-system setup follows.
+ * Setup functions can either be called here or using the
+ * subsys_initcall mechanism (i.e. see msp_pci_setup). The
+ * order in which they are called can be changed by using the
+ * link order in arch/mips/pmc-sierra/msp71xx/Makefile.
+ *
+ * NOTE: Please keep sub-system specific initialization code
+ * in separate specific files.
+ */
+ msp_serial_setup();
+
+#ifdef CONFIG_PMCTWILED
+ /*
+ * Setup LED states before the subsys_initcall loads other
+ * dependant drivers/modules.
+ */
+ pmctwiled_setup();
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c
new file mode 100644
index 000000000000..2a2beac5a4f8
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c
@@ -0,0 +1,94 @@
+/*
+ * Setting up the clock on MSP SOCs. No RTC typically.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+
+#include <asm/mipsregs.h>
+#include <asm/time.h>
+
+#include <msp_prom.h>
+#include <msp_int.h>
+#include <msp_regs.h>
+
+void __init msp_timer_init(void)
+{
+ char *endp, *s;
+ unsigned long cpu_rate = 0;
+
+ if (cpu_rate == 0) {
+ s = prom_getenv("clkfreqhz");
+ cpu_rate = simple_strtoul(s, &endp, 10);
+ if (endp != NULL && *endp != 0) {
+ printk(KERN_ERR
+ "Clock rate in Hz parse error: %s\n", s);
+ cpu_rate = 0;
+ }
+ }
+
+ if (cpu_rate == 0) {
+ s = prom_getenv("clkfreq");
+ cpu_rate = 1000 * simple_strtoul(s, &endp, 10);
+ if (endp != NULL && *endp != 0) {
+ printk(KERN_ERR
+ "Clock rate in MHz parse error: %s\n", s);
+ cpu_rate = 0;
+ }
+ }
+
+ if (cpu_rate == 0) {
+#if defined(CONFIG_PMC_MSP7120_EVAL) \
+ || defined(CONFIG_PMC_MSP7120_GW)
+ cpu_rate = 400000000;
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+ cpu_rate = 25000000;
+#else
+ cpu_rate = 150000000;
+#endif
+ printk(KERN_ERR
+ "Failed to determine CPU clock rate, "
+ "assuming %ld hz ...\n", cpu_rate);
+ }
+
+ printk(KERN_WARNING "Clock rate set to %ld\n", cpu_rate);
+
+ /* timer frequency is 1/2 clock rate */
+ mips_hpt_frequency = cpu_rate/2;
+}
+
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+#ifdef CONFIG_IRQ_MSP_CIC
+ /* we are using the vpe0 counter for timer interrupts */
+ setup_irq(MSP_INT_VPE0_TIMER, irq);
+#else
+ /* we are using the mips counter for timer interrupts */
+ setup_irq(MSP_INT_TIMER, irq);
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_usb.c b/arch/mips/pmc-sierra/msp71xx/msp_usb.c
new file mode 100644
index 000000000000..21f9c70b6923
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_usb.c
@@ -0,0 +1,150 @@
+/*
+ * The setup file for USB related hardware on PMC-Sierra MSP processors.
+ *
+ * Copyright 2006-2007 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/mipsregs.h>
+
+#include <msp_regs.h>
+#include <msp_int.h>
+#include <msp_prom.h>
+
+#if defined(CONFIG_USB_EHCI_HCD)
+static struct resource msp_usbhost_resources [] = {
+ [0] = {
+ .start = MSP_USB_BASE_START,
+ .end = MSP_USB_BASE_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MSP_INT_USB,
+ .end = MSP_INT_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 msp_usbhost_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device msp_usbhost_device = {
+ .name = "pmcmsp-ehci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &msp_usbhost_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ },
+ .num_resources = ARRAY_SIZE (msp_usbhost_resources),
+ .resource = msp_usbhost_resources,
+};
+#endif /* CONFIG_USB_EHCI_HCD */
+
+#if defined(CONFIG_USB_GADGET)
+static struct resource msp_usbdev_resources [] = {
+ [0] = {
+ .start = MSP_USB_BASE,
+ .end = MSP_USB_BASE_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MSP_INT_USB,
+ .end = MSP_INT_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 msp_usbdev_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device msp_usbdev_device = {
+ .name = "msp71xx_udc",
+ .id = 0,
+ .dev = {
+ .dma_mask = &msp_usbdev_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ },
+ .num_resources = ARRAY_SIZE (msp_usbdev_resources),
+ .resource = msp_usbdev_resources,
+};
+#endif /* CONFIG_USB_GADGET */
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
+static struct platform_device *msp_devs[1];
+#endif
+
+
+static int __init msp_usb_setup(void)
+{
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
+ char *strp;
+ char envstr[32];
+ unsigned int val = 0;
+ int result = 0;
+
+ /*
+ * construct environment name usbmode
+ * set usbmode <host/device> as pmon environment var
+ */
+ snprintf((char *)&envstr[0], sizeof(envstr), "usbmode");
+
+#if defined(CONFIG_USB_EHCI_HCD)
+ /* default to host mode */
+ val = 1;
+#endif
+
+ /* get environment string */
+ strp = prom_getenv((char *)&envstr[0]);
+ if (strp) {
+ if (!strcmp(strp, "device"))
+ val = 0;
+ }
+
+ if (val) {
+#if defined(CONFIG_USB_EHCI_HCD)
+ /* get host mode device */
+ msp_devs[0] = &msp_usbhost_device;
+ ppfinit("platform add USB HOST done %s.\n",
+ msp_devs[0]->name);
+
+ result = platform_add_devices(msp_devs, ARRAY_SIZE (msp_devs));
+#endif /* CONFIG_USB_EHCI_HCD */
+ }
+#if defined(CONFIG_USB_GADGET)
+ else {
+ /* get device mode structure */
+ msp_devs[0] = &msp_usbdev_device;
+ ppfinit("platform add USB DEVICE done %s.\n",
+ msp_devs[0]->name);
+
+ result = platform_add_devices(msp_devs, ARRAY_SIZE (msp_devs));
+ }
+#endif /* CONFIG_USB_GADGET */
+#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */
+
+ return result;
+}
+
+subsys_initcall(msp_usb_setup);
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 305491e74dbe..d83c4ada14f3 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -77,7 +77,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
* stack so the first thing we do is throw away that stuff and load useful
* values into the registers ...
*/
-void prom_boot_secondary(int cpu, struct task_struct *idle)
+void __init prom_boot_secondary(int cpu, struct task_struct *idle)
{
unsigned long gp = (unsigned long) task_thread_info(idle);
unsigned long sp = __KSTK_TOS(idle);
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 66df5ac8f089..63afd7e44428 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -46,7 +46,7 @@ static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer;
static int machine_state;
-static void ATTRIB_NORET sgi_machine_power_off(void)
+static void __noreturn sgi_machine_power_off(void)
{
unsigned int tmp;
@@ -68,7 +68,7 @@ static void ATTRIB_NORET sgi_machine_power_off(void)
}
}
-static void ATTRIB_NORET sgi_machine_restart(char *command)
+static void __noreturn sgi_machine_restart(char *command)
{
if (machine_state & MACHINE_SHUTTING_DOWN)
sgi_machine_power_off();
@@ -76,7 +76,7 @@ static void ATTRIB_NORET sgi_machine_restart(char *command)
while (1);
}
-static void ATTRIB_NORET sgi_machine_halt(void)
+static void __noreturn sgi_machine_halt(void)
{
if (machine_state & MACHINE_SHUTTING_DOWN)
sgi_machine_power_off();
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c
index ce907eda221b..123141ab21a2 100644
--- a/arch/mips/sgi-ip27/ip27-berr.c
+++ b/arch/mips/sgi-ip27/ip27-berr.c
@@ -21,7 +21,6 @@
#include <asm/traps.h>
#include <asm/uaccess.h>
-extern void dump_tlb_addr(unsigned long addr);
extern void dump_tlb_all(void);
static void dump_hub_information(unsigned long errst0, unsigned long errst1)
diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c
index 120b15932caf..ba3697ee7ff6 100644
--- a/arch/mips/sgi-ip32/ip32-platform.c
+++ b/arch/mips/sgi-ip32/ip32-platform.c
@@ -1,5 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+/*
+ * .iobase isn't a constant (in the sense of C) so we fill it in at runtime.
+ */
+#define MACE_PORT(int) \
+{ \
+ .irq = int, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_MEM, \
+ .flags = UPF_SKIP_TEST, \
+ .regshift = 8, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ MACE_PORT(MACEISA_SERIAL1_IRQ),
+ MACE_PORT(MACEISA_SERIAL2_IRQ),
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ uart8250_data[0].iobase = (unsigned long) &mace->isa.serial1;
+ uart8250_data[1].iobase = (unsigned long) &mace->isa.serial1;
+
+ return platform_device_register(&uart8250_device);
+}
+
+device_initcall(uart8250_init);
static __init int meth_devinit(void)
{
@@ -18,3 +66,7 @@ static __init int meth_devinit(void)
}
device_initcall(meth_devinit);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for SGI IP32 aka O2");
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index 57708fe28bd7..bbba066cb405 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -62,12 +62,6 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str)
}
#endif
-#ifdef CONFIG_SERIAL_8250
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#endif /* CONFIG_SERIAL_8250 */
-
/* An arbitrary time; this can be decreased if reliability looks good */
#define WAIT_MS 10
@@ -96,36 +90,6 @@ void __init plat_mem_setup(void)
board_time_init = ip32_time_init;
-#ifdef CONFIG_SERIAL_8250
- {
- static struct uart_port o2_serial[2];
-
- memset(o2_serial, 0, sizeof(o2_serial));
- o2_serial[0].type = PORT_16550A;
- o2_serial[0].line = 0;
- o2_serial[0].irq = MACEISA_SERIAL1_IRQ;
- o2_serial[0].flags = UPF_SKIP_TEST;
- o2_serial[0].uartclk = 1843200;
- o2_serial[0].iotype = UPIO_MEM;
- o2_serial[0].membase = (char *)&mace->isa.serial1;
- o2_serial[0].fifosize = 14;
- /* How much to shift register offset by. Each UART register
- * is replicated over 256 byte space */
- o2_serial[0].regshift = 8;
- o2_serial[1].type = PORT_16550A;
- o2_serial[1].line = 1;
- o2_serial[1].irq = MACEISA_SERIAL2_IRQ;
- o2_serial[1].flags = UPF_SKIP_TEST;
- o2_serial[1].uartclk = 1843200;
- o2_serial[1].iotype = UPIO_MEM;
- o2_serial[1].membase = (char *)&mace->isa.serial2;
- o2_serial[1].fifosize = 14;
- o2_serial[1].regshift = 8;
-
- early_serial_setup(&o2_serial[0]);
- early_serial_setup(&o2_serial[1]);
- }
-#endif
#ifdef CONFIG_SGI_O2MACE_ETH
{
char *mac = ArcGetEnvironmentVariable("eaddr");
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
index ae4a92c3e529..51898dd1304a 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -62,7 +62,7 @@ extern unsigned long initrd_start, initrd_end;
extern int kgdb_port;
#endif
-static void ATTRIB_NORET cfe_linux_exit(void *arg)
+static void __noreturn cfe_linux_exit(void *arg)
{
int warm = *(int *)arg;
@@ -83,14 +83,14 @@ static void ATTRIB_NORET cfe_linux_exit(void *arg)
while (1);
}
-static void ATTRIB_NORET cfe_linux_restart(char *command)
+static void __noreturn cfe_linux_restart(char *command)
{
static const int zero;
cfe_linux_exit((void *)&zero);
}
-static void ATTRIB_NORET cfe_linux_halt(void)
+static void __noreturn cfe_linux_halt(void)
{
static const int one = 1;
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index e5777b7e2bc9..471418e4f446 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,5 +2,5 @@
# Makefile for the SNI specific part of the kernel
#
-obj-y += irq.o reset.o setup.o ds1216.o a20r.o rm200.o pcimt.o pcit.o time.o
+obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o
obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index 31ab80f1befa..6850a29defcd 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -15,7 +15,6 @@
#include <asm/sni.h>
#include <asm/time.h>
-#include <asm/ds1216.h>
#define PORT(_base,_irq) \
{ \
@@ -40,20 +39,34 @@ static struct platform_device a20r_serial8250_device = {
},
};
+static struct resource a20r_ds1216_rsrc[] = {
+ {
+ .start = 0x1c081ffc,
+ .end = 0x1c081fff,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct platform_device a20r_ds1216_device = {
+ .name = "rtc-ds1216",
+ .num_resources = ARRAY_SIZE(a20r_ds1216_rsrc),
+ .resource = a20r_ds1216_rsrc
+};
+
static struct resource snirm_82596_rsrc[] = {
{
- .start = 0xb8000000,
- .end = 0xb8000004,
+ .start = 0x18000000,
+ .end = 0x18000004,
.flags = IORESOURCE_MEM
},
{
- .start = 0xb8010000,
- .end = 0xb8010004,
+ .start = 0x18010000,
+ .end = 0x18010004,
.flags = IORESOURCE_MEM
},
{
- .start = 0xbff00000,
- .end = 0xbff00020,
+ .start = 0x1ff00000,
+ .end = 0x1ff00020,
.flags = IORESOURCE_MEM
},
{
@@ -205,8 +218,7 @@ void __init sni_a20r_irq_init(void)
void sni_a20r_init(void)
{
- ds1216_base = (volatile unsigned char *) SNI_DS1216_A20R_BASE;
- rtc_mips_get_time = ds1216_get_cmos_time;
+ /* FIXME, remove if not needed */
}
static int __init snirm_a20r_setup_devinit(void)
@@ -218,6 +230,7 @@ static int __init snirm_a20r_setup_devinit(void)
platform_device_register(&snirm_53c710_pdev);
platform_device_register(&sc26xx_pdev);
platform_device_register(&a20r_serial8250_device);
+ platform_device_register(&a20r_ds1216_device);
break;
}
diff --git a/arch/mips/sni/ds1216.c b/arch/mips/sni/ds1216.c
deleted file mode 100644
index 1d92732c14f1..000000000000
--- a/arch/mips/sni/ds1216.c
+++ /dev/null
@@ -1,81 +0,0 @@
-
-#include <linux/bcd.h>
-#include <linux/time.h>
-
-#include <asm/ds1216.h>
-
-volatile unsigned char *ds1216_base;
-
-/*
- * Read the 64 bit we'd like to have - It a series
- * of 64 bits showing up in the LSB of the base register.
- *
- */
-static unsigned char *ds1216_read(void)
-{
- static unsigned char rdbuf[8];
- unsigned char c;
- int i, j;
-
- for (i = 0; i < 8; i++) {
- c = 0x0;
- for (j = 0; j < 8; j++) {
- c |= (*ds1216_base & 0x1) << j;
- }
- rdbuf[i] = c;
- }
-
- return rdbuf;
-}
-
-static void ds1216_switch_ds_to_clock(void)
-{
- unsigned char magic[] = {
- 0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
- };
- int i,j,c;
-
- /* Reset magic pointer */
- c = *ds1216_base;
-
- /* Write 64 bit magic to DS1216 */
- for (i = 0; i < 8; i++) {
- c = magic[i];
- for (j = 0; j < 8; j++) {
- *ds1216_base = c;
- c = c >> 1;
- }
- }
-}
-
-unsigned long ds1216_get_cmos_time(void)
-{
- unsigned char *rdbuf;
- unsigned int year, month, date, hour, min, sec;
-
- ds1216_switch_ds_to_clock();
- rdbuf = ds1216_read();
-
- sec = BCD2BIN(DS1216_SEC(rdbuf));
- min = BCD2BIN(DS1216_MIN(rdbuf));
- hour = BCD2BIN(DS1216_HOUR(rdbuf));
- date = BCD2BIN(DS1216_DATE(rdbuf));
- month = BCD2BIN(DS1216_MONTH(rdbuf));
- year = BCD2BIN(DS1216_YEAR(rdbuf));
-
- if (DS1216_1224(rdbuf) && DS1216_AMPM(rdbuf))
- hour+=12;
-
- if (year < 70)
- year += 2000;
- else
- year += 1900;
-
- return mktime(year, month, date, hour, min, sec);
-}
-
-int ds1216_set_rtc_mmss(unsigned long nowtime)
-{
- printk("ds1216_set_rtc_mmss called but not implemented\n");
- return -1;
-}
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 97b234361b4d..44b1ae62aa4a 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -14,7 +14,6 @@
#include <linux/pci.h>
#include <linux/serial_8250.h>
-#include <asm/mc146818-time.h>
#include <asm/sni.h>
#include <asm/time.h>
#include <asm/i8259.h>
@@ -90,6 +89,26 @@ static struct platform_device pcimt_serial8250_device = {
},
};
+static struct resource pcimt_cmos_rsrc[] = {
+ {
+ .start = 0x70,
+ .end = 0x71,
+ .flags = IORESOURCE_IO
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device pcimt_cmos_device = {
+ .name = "rtc_cmos",
+ .num_resources = ARRAY_SIZE(pcimt_cmos_rsrc),
+ .resource = pcimt_cmos_rsrc
+};
+
+
static struct resource sni_io_resource = {
.start = 0x00000000UL,
.end = 0x03bfffffUL,
@@ -290,12 +309,10 @@ void __init sni_pcimt_irq_init(void)
change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
}
-void sni_pcimt_init(void)
+void __init sni_pcimt_init(void)
{
sni_pcimt_detect();
sni_pcimt_sc_init();
- rtc_mips_get_time = mc146818_get_cmos_time;
- rtc_mips_set_time = mc146818_set_rtc_mmss;
board_time_init = sni_cpu_time_init;
ioport_resource.end = sni_io_resource.end;
#ifdef CONFIG_PCI
@@ -312,6 +329,7 @@ static int __init snirm_pcimt_setup_devinit(void)
case SNI_BRD_PCI_DESKTOP:
case SNI_BRD_PCI_MTOWER_CPLUS:
platform_device_register(&pcimt_serial8250_device);
+ platform_device_register(&pcimt_cmos_device);
break;
}
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index 00d151f4d121..2480c478dcbd 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -13,7 +13,6 @@
#include <linux/pci.h>
#include <linux/serial_8250.h>
-#include <asm/mc146818-time.h>
#include <asm/sni.h>
#include <asm/time.h>
#include <asm/irq_cpu.h>
@@ -58,6 +57,25 @@ static struct platform_device pcit_cplus_serial8250_device = {
},
};
+static struct resource pcit_cmos_rsrc[] = {
+ {
+ .start = 0x70,
+ .end = 0x71,
+ .flags = IORESOURCE_IO
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device pcit_cmos_device = {
+ .name = "rtc_cmos",
+ .num_resources = ARRAY_SIZE(pcit_cmos_rsrc),
+ .resource = pcit_cmos_rsrc
+};
+
static struct resource sni_io_resource = {
.start = 0x00000000UL,
.end = 0x03bfffffUL,
@@ -243,10 +261,8 @@ void __init sni_pcit_cplus_irq_init(void)
setup_irq (MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq);
}
-void sni_pcit_init(void)
+void __init sni_pcit_init(void)
{
- rtc_mips_get_time = mc146818_get_cmos_time;
- rtc_mips_set_time = mc146818_set_rtc_mmss;
board_time_init = sni_cpu_time_init;
ioport_resource.end = sni_io_resource.end;
#ifdef CONFIG_PCI
@@ -261,10 +277,12 @@ static int __init snirm_pcit_setup_devinit(void)
switch (sni_brd_type) {
case SNI_BRD_PCI_TOWER:
platform_device_register(&pcit_serial8250_device);
+ platform_device_register(&pcit_cmos_device);
break;
case SNI_BRD_PCI_TOWER_CPLUS:
platform_device_register(&pcit_cplus_serial8250_device);
+ platform_device_register(&pcit_cmos_device);
break;
}
return 0;
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index b82ff129f5ea..4bfda020fdc7 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -15,7 +15,6 @@
#include <asm/sni.h>
#include <asm/time.h>
-#include <asm/ds1216.h>
#include <asm/irq_cpu.h>
#define PORT(_base,_irq) \
@@ -41,20 +40,34 @@ static struct platform_device rm200_serial8250_device = {
},
};
+static struct resource rm200_ds1216_rsrc[] = {
+ {
+ .start = 0x1cd41ffc,
+ .end = 0x1cd41fff,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct platform_device rm200_ds1216_device = {
+ .name = "rtc-ds1216",
+ .num_resources = ARRAY_SIZE(rm200_ds1216_rsrc),
+ .resource = rm200_ds1216_rsrc
+};
+
static struct resource snirm_82596_rm200_rsrc[] = {
{
- .start = 0xb8000000,
- .end = 0xb80fffff,
+ .start = 0x18000000,
+ .end = 0x180fffff,
.flags = IORESOURCE_MEM
},
{
- .start = 0xbb000000,
- .end = 0xbb000004,
+ .start = 0x1b000000,
+ .end = 0x1b000004,
.flags = IORESOURCE_MEM
},
{
- .start = 0xbff00000,
- .end = 0xbff00020,
+ .start = 0x1ff00000,
+ .end = 0x1ff00020,
.flags = IORESOURCE_MEM
},
{
@@ -96,6 +109,7 @@ static int __init snirm_setup_devinit(void)
{
if (sni_brd_type == SNI_BRD_RM200) {
platform_device_register(&rm200_serial8250_device);
+ platform_device_register(&rm200_ds1216_device);
platform_device_register(&snirm_82596_rm200_pdev);
platform_device_register(&snirm_53c710_rm200_pdev);
}
@@ -176,11 +190,9 @@ void __init sni_rm200_irq_init(void)
setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq);
}
-void sni_rm200_init(void)
+void __init sni_rm200_init(void)
{
set_io_port_base(SNI_PORT_BASE + 0x02000000);
ioport_resource.end += 0x02000000;
- ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE;
- rtc_mips_get_time = ds1216_get_cmos_time;
board_time_init = sni_cpu_time_init;
}
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
index 643366eb854a..00a03a6e8f58 100644
--- a/arch/mips/sni/sniprom.c
+++ b/arch/mips/sni/sniprom.c
@@ -146,7 +146,10 @@ static void __init sni_console_setup(void)
}
if (baud)
strcpy(options, baud);
- add_preferred_console("ttyS", port, baud ? options : NULL);
+ if (strncmp (cdev, "tty552", 6) == 0)
+ add_preferred_console("ttyS", port, baud ? options : NULL);
+ else
+ add_preferred_console("ttySC", port, baud ? options : NULL);
}
}
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
index 2033ae77f632..83cda518f204 100644
--- a/arch/mips/tx4938/common/Makefile
+++ b/arch/mips/tx4938/common/Makefile
@@ -6,6 +6,6 @@
# unless it's something special (ie not a .c file).
#
-obj-y += prom.o setup.o irq.o rtc_rx5c348.o
+obj-y += prom.o setup.o irq.o
obj-$(CONFIG_KGDB) += dbgio.o
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c
deleted file mode 100644
index 07f782fc0725..000000000000
--- a/arch/mips/tx4938/common/rtc_rx5c348.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * RTC routines for RICOH Rx5C348 SPI chip.
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/rtc.h>
-#include <linux/time.h>
-#include <linux/bcd.h>
-#include <asm/time.h>
-#include <asm/tx4938/spi.h>
-
-#define EPOCH 2000
-
-/* registers */
-#define Rx5C348_REG_SECOND 0
-#define Rx5C348_REG_MINUTE 1
-#define Rx5C348_REG_HOUR 2
-#define Rx5C348_REG_WEEK 3
-#define Rx5C348_REG_DAY 4
-#define Rx5C348_REG_MONTH 5
-#define Rx5C348_REG_YEAR 6
-#define Rx5C348_REG_ADJUST 7
-#define Rx5C348_REG_ALARM_W_MIN 8
-#define Rx5C348_REG_ALARM_W_HOUR 9
-#define Rx5C348_REG_ALARM_W_WEEK 10
-#define Rx5C348_REG_ALARM_D_MIN 11
-#define Rx5C348_REG_ALARM_D_HOUR 12
-#define Rx5C348_REG_CTL1 14
-#define Rx5C348_REG_CTL2 15
-
-/* register bits */
-#define Rx5C348_BIT_PM 0x20 /* REG_HOUR */
-#define Rx5C348_BIT_Y2K 0x80 /* REG_MONTH */
-#define Rx5C348_BIT_24H 0x20 /* REG_CTL1 */
-#define Rx5C348_BIT_XSTP 0x10 /* REG_CTL2 */
-
-/* commands */
-#define Rx5C348_CMD_W(addr) (((addr) << 4) | 0x08) /* single write */
-#define Rx5C348_CMD_R(addr) (((addr) << 4) | 0x0c) /* single read */
-#define Rx5C348_CMD_MW(addr) (((addr) << 4) | 0x00) /* burst write */
-#define Rx5C348_CMD_MR(addr) (((addr) << 4) | 0x04) /* burst read */
-
-static struct spi_dev_desc srtc_dev_desc = {
- .baud = 1000000, /* 1.0Mbps @ Vdd 2.0V */
- .tcss = 31,
- .tcsh = 1,
- .tcsr = 62,
- /* 31us for Tcss (62us for Tcsr) is required for carry operation) */
- .byteorder = 1, /* MSB-First */
- .polarity = 0, /* High-Active */
- .phase = 1, /* Shift-Then-Sample */
-
-};
-static int srtc_chipid;
-static int srtc_24h;
-
-static inline int
-spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
-{
- unsigned char *inbufs[1], *outbufs[1];
- unsigned int incounts[2], outcounts[2];
- inbufs[0] = inbuf;
- incounts[0] = count;
- incounts[1] = 0;
- outbufs[0] = outbuf;
- outcounts[0] = count;
- outcounts[1] = 0;
- return txx9_spi_io(srtc_chipid, &srtc_dev_desc,
- inbufs, incounts, outbufs, outcounts, 0);
-}
-
-/* RTC-dependent code for time.c */
-
-static int
-rtc_rx5c348_set_time(unsigned long t)
-{
- unsigned char inbuf[8];
- struct rtc_time tm;
- u8 year, month, day, hour, minute, second, century;
-
- /* convert */
- to_tm(t, &tm);
-
- year = tm.tm_year % 100;
- month = tm.tm_mon+1; /* tm_mon starts from 0 to 11 */
- day = tm.tm_mday;
- hour = tm.tm_hour;
- minute = tm.tm_min;
- second = tm.tm_sec;
- century = tm.tm_year / 100;
-
- inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND);
- BIN_TO_BCD(second);
- inbuf[1] = second;
- BIN_TO_BCD(minute);
- inbuf[2] = minute;
-
- if (srtc_24h) {
- BIN_TO_BCD(hour);
- inbuf[3] = hour;
- } else {
- /* hour 0 is AM12, noon is PM12 */
- inbuf[3] = 0;
- if (hour >= 12)
- inbuf[3] = Rx5C348_BIT_PM;
- hour = (hour + 11) % 12 + 1;
- BIN_TO_BCD(hour);
- inbuf[3] |= hour;
- }
- inbuf[4] = 0; /* ignore week */
- BIN_TO_BCD(day);
- inbuf[5] = day;
- BIN_TO_BCD(month);
- inbuf[6] = month;
- if (century >= 20)
- inbuf[6] |= Rx5C348_BIT_Y2K;
- BIN_TO_BCD(year);
- inbuf[7] = year;
- /* write in one transfer to avoid data inconsistency */
- return spi_rtc_io(inbuf, NULL, 8);
-}
-
-static unsigned long
-rtc_rx5c348_get_time(void)
-{
- unsigned char inbuf[8], outbuf[8];
- unsigned int year, month, day, hour, minute, second;
-
- inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND);
- memset(inbuf + 1, 0, 7);
- /* read in one transfer to avoid data inconsistency */
- if (spi_rtc_io(inbuf, outbuf, 8))
- return 0;
- second = outbuf[1];
- BCD_TO_BIN(second);
- minute = outbuf[2];
- BCD_TO_BIN(minute);
- if (srtc_24h) {
- hour = outbuf[3];
- BCD_TO_BIN(hour);
- } else {
- hour = outbuf[3] & ~Rx5C348_BIT_PM;
- BCD_TO_BIN(hour);
- hour %= 12;
- if (outbuf[3] & Rx5C348_BIT_PM)
- hour += 12;
- }
- day = outbuf[5];
- BCD_TO_BIN(day);
- month = outbuf[6] & ~Rx5C348_BIT_Y2K;
- BCD_TO_BIN(month);
- year = outbuf[7];
- BCD_TO_BIN(year);
- year += EPOCH;
-
- return mktime(year, month, day, hour, minute, second);
-}
-
-void __init
-rtc_rx5c348_init(int chipid)
-{
- unsigned char inbuf[2], outbuf[2];
- srtc_chipid = chipid;
- /* turn on RTC if it is not on */
- inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2);
- inbuf[1] = 0;
- spi_rtc_io(inbuf, outbuf, 2);
- if (outbuf[1] & Rx5C348_BIT_XSTP) {
- inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2);
- inbuf[1] = 0;
- spi_rtc_io(inbuf, NULL, 2);
- }
-
- inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1);
- inbuf[1] = 0;
- spi_rtc_io(inbuf, outbuf, 2);
- if (outbuf[1] & Rx5C348_BIT_24H)
- srtc_24h = 1;
-
- /* set the function pointers */
- rtc_mips_get_time = rtc_rx5c348_get_time;
- rtc_mips_set_time = rtc_rx5c348_set_time;
-}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/Makefile b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
index 226941279d75..10c94e62bf5b 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/Makefile
+++ b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
@@ -6,4 +6,4 @@
# unless it's something special (ie not a .c file).
#
-obj-y += prom.o setup.o irq.o spi_eeprom.o spi_txx9.o
+obj-y += prom.o setup.o irq.o spi_eeprom.o
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
index 2e96dbb248b1..91aea7aff515 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
@@ -165,8 +165,6 @@ toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
}
-extern void __init txx9_spi_irqinit(int irc_irq);
-
void __init arch_init_irq(void)
{
extern void tx4938_irq_init(void);
@@ -185,9 +183,5 @@ void __init arch_init_irq(void)
/* Onboard 10M Ether: High Active */
TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000040);
- if (tx4938_ccfgptr->pcfg & TX4938_PCFG_SPI_SEL) {
- txx9_spi_irqinit(RBTX4938_IRQ_IRC_SPI);
- }
-
wbflush();
}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index f5d1ce739fcc..6ed39a5aea72 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -14,13 +14,13 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/ioport.h>
-#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/console.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/wbflush.h>
#include <asm/reboot.h>
@@ -35,6 +35,9 @@
#include <linux/serial.h>
#include <linux/serial_core.h>
#endif
+#include <linux/spi/spi.h>
+#include <asm/tx4938/spi.h>
+#include <asm/gpio.h>
extern void rbtx4938_time_init(void) __init;
extern char * __init prom_getcmdline(void);
@@ -349,7 +352,7 @@ static struct pci_dev *fake_pci_dev(struct pci_controller *hose,
static struct pci_dev dev;
static struct pci_bus bus;
- dev.sysdata = (void *)hose;
+ dev.sysdata = bus.sysdata = hose;
dev.devfn = devfn;
bus.number = busnr;
bus.ops = hose->pci_ops;
@@ -382,8 +385,10 @@ int txboard_pci66_check(struct pci_controller *hose, int top_bus, int current_bu
printk("PCI: Checking 66MHz capabilities...\n");
for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
- early_read_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_VENDOR_ID, &vid);
+ if (early_read_config_word(hose, top_bus, current_bus,
+ pci_devfn, PCI_VENDOR_ID,
+ &vid) != PCIBIOS_SUCCESSFUL)
+ continue;
if (vid == 0xffff) continue;
@@ -460,7 +465,6 @@ static int __init tx4938_pcibios_init(void)
int extarb = !(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB);
PCIBIOS_MIN_IO = 0x00001000UL;
- PCIBIOS_MIN_MEM = 0x01000000UL;
mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]);
io_base[0] = txboard_request_phys_region_shrink(&io_size[0]);
@@ -574,82 +578,43 @@ arch_initcall(tx4938_pcibios_init);
#define SEEPROM3_CS 1 /* IOC */
#define SRTC_CS 2 /* IOC */
-static int rbtx4938_spi_cs_func(int chipid, int on)
-{
- unsigned char bit;
- switch (chipid) {
- case RBTX4938_SEEPROM1_CHIPID:
- if (on)
- tx4938_pioptr->dout &= ~(1 << SEEPROM1_CS);
- else
- tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
- return 0;
- break;
- case RBTX4938_SEEPROM2_CHIPID:
- bit = (1 << SEEPROM2_CS);
- break;
- case RBTX4938_SEEPROM3_CHIPID:
- bit = (1 << SEEPROM3_CS);
- break;
- case RBTX4938_SRTC_CHIPID:
- bit = (1 << SRTC_CS);
- break;
- default:
- return -ENODEV;
- }
- /* bit1,2,4 are low active, bit3 is high active */
- *rbtx4938_spics_ptr =
- (*rbtx4938_spics_ptr & ~bit) |
- ((on ? (bit ^ 0x0b) : ~(bit ^ 0x0b)) & bit);
- return 0;
-}
-
#ifdef CONFIG_PCI
-extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
-
-int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr)
+static int __init rbtx4938_ethaddr_init(void)
{
- struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata;
- static unsigned char dat[17];
- static int read_dat = 0;
- int ch = 0;
+ unsigned char dat[17];
+ unsigned char sum;
+ int i;
- if (channel != &tx4938_pci_controller[1])
- return -ENODEV;
- /* TX4938 PCIC1 */
- switch (PCI_SLOT(dev->devfn)) {
- case TX4938_PCIC_IDSEL_AD_TO_SLOT(31):
- ch = 0;
- break;
- case TX4938_PCIC_IDSEL_AD_TO_SLOT(30):
- ch = 1;
- break;
- default:
+ /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
+ if (spi_eeprom_read(SEEPROM1_CS, 0, dat, sizeof(dat))) {
+ printk(KERN_ERR "seeprom: read error.\n");
return -ENODEV;
+ } else {
+ if (strcmp(dat, "MAC") != 0)
+ printk(KERN_WARNING "seeprom: bad signature.\n");
+ for (i = 0, sum = 0; i < sizeof(dat); i++)
+ sum += dat[i];
+ if (sum)
+ printk(KERN_WARNING "seeprom: bad checksum.\n");
}
- if (!read_dat) {
- unsigned char sum;
- int i;
- read_dat = 1;
- /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
- if (spi_eeprom_read(RBTX4938_SEEPROM1_CHIPID,
- 0, dat, sizeof(dat))) {
- printk(KERN_ERR "seeprom: read error.\n");
- } else {
- if (strcmp(dat, "MAC") != 0)
- printk(KERN_WARNING "seeprom: bad signature.\n");
- for (i = 0, sum = 0; i < sizeof(dat); i++)
- sum += dat[i];
- if (sum)
- printk(KERN_WARNING "seeprom: bad checksum.\n");
- }
+ for (i = 0; i < 2; i++) {
+ unsigned int slot = TX4938_PCIC_IDSEL_AD_TO_SLOT(31 - i);
+ unsigned int id = (1 << 8) | PCI_DEVFN(slot, 0); /* bus 1 */
+ struct platform_device *pdev;
+ if (!(tx4938_ccfgptr->pcfg &
+ (i ? TX4938_PCFG_ETH1_SEL : TX4938_PCFG_ETH0_SEL)))
+ continue;
+ pdev = platform_device_alloc("tc35815-mac", id);
+ if (!pdev ||
+ platform_device_add_data(pdev, &dat[4 + 6 * i], 6) ||
+ platform_device_add(pdev))
+ platform_device_put(pdev);
}
- memcpy(addr, &dat[4 + 6 * ch], 6);
return 0;
}
+device_initcall(rbtx4938_ethaddr_init);
#endif /* CONFIG_PCI */
-extern void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on));
static void __init rbtx4938_spi_setup(void)
{
/* set SPI_SEL */
@@ -657,7 +622,6 @@ static void __init rbtx4938_spi_setup(void)
/* chip selects for SPI devices */
tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
tx4938_pioptr->dir |= (1 << SEEPROM1_CS);
- txx9_spi_init(TX4938_SPI_REG, rbtx4938_spi_cs_func);
}
static struct resource rbtx4938_fpga_resource;
@@ -896,10 +860,8 @@ void tx4938_report_pcic_status(void)
/* We use onchip r4k counter or TMR timer as our system wide timer
* interrupt running at 100HZ. */
-extern void __init rtc_rx5c348_init(int chipid);
void __init rbtx4938_time_init(void)
{
- rtc_rx5c348_init(RBTX4938_SRTC_CHIPID);
mips_hpt_frequency = txx9_cpu_clock / 2;
}
@@ -1016,29 +978,6 @@ void __init toshiba_rbtx4938_setup(void)
*rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr);
}
-#ifdef CONFIG_PROC_FS
-extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid);
-static int __init tx4938_spi_proc_setup(void)
-{
- struct proc_dir_entry *tx4938_spi_eeprom_dir;
-
- tx4938_spi_eeprom_dir = proc_mkdir("spi_eeprom", 0);
-
- if (!tx4938_spi_eeprom_dir)
- return -ENOMEM;
-
- /* don't allow user access to RBTX4938_SEEPROM1_CHIPID
- * as it contains eth0 and eth1 MAC addresses
- */
- spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM2_CHIPID);
- spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM3_CHIPID);
-
- return 0;
-}
-
-__initcall(tx4938_spi_proc_setup);
-#endif
-
static int __init rbtx4938_ne_init(void)
{
struct resource res[] = {
@@ -1057,3 +996,176 @@ static int __init rbtx4938_ne_init(void)
return IS_ERR(dev) ? PTR_ERR(dev) : 0;
}
device_initcall(rbtx4938_ne_init);
+
+/* GPIO support */
+
+static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock);
+
+static void rbtx4938_spi_gpio_set(unsigned gpio, int value)
+{
+ u8 val;
+ unsigned long flags;
+ gpio -= 16;
+ spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags);
+ val = *rbtx4938_spics_ptr;
+ if (value)
+ val |= 1 << gpio;
+ else
+ val &= ~(1 << gpio);
+ *rbtx4938_spics_ptr = val;
+ mmiowb();
+ spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags);
+}
+
+static int rbtx4938_spi_gpio_dir_out(unsigned gpio, int value)
+{
+ rbtx4938_spi_gpio_set(gpio, value);
+ return 0;
+}
+
+static DEFINE_SPINLOCK(tx4938_gpio_lock);
+
+static int tx4938_gpio_get(unsigned gpio)
+{
+ return tx4938_pioptr->din & (1 << gpio);
+}
+
+static void tx4938_gpio_set_raw(unsigned gpio, int value)
+{
+ u32 val;
+ val = tx4938_pioptr->dout;
+ if (value)
+ val |= 1 << gpio;
+ else
+ val &= ~(1 << gpio);
+ tx4938_pioptr->dout = val;
+}
+
+static void tx4938_gpio_set(unsigned gpio, int value)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tx4938_gpio_lock, flags);
+ tx4938_gpio_set_raw(gpio, value);
+ mmiowb();
+ spin_unlock_irqrestore(&tx4938_gpio_lock, flags);
+}
+
+static int tx4938_gpio_dir_in(unsigned gpio)
+{
+ spin_lock_irq(&tx4938_gpio_lock);
+ tx4938_pioptr->dir &= ~(1 << gpio);
+ mmiowb();
+ spin_unlock_irq(&tx4938_gpio_lock);
+ return 0;
+}
+
+static int tx4938_gpio_dir_out(unsigned int gpio, int value)
+{
+ spin_lock_irq(&tx4938_gpio_lock);
+ tx4938_gpio_set_raw(gpio, value);
+ tx4938_pioptr->dir |= 1 << gpio;
+ mmiowb();
+ spin_unlock_irq(&tx4938_gpio_lock);
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ if (gpio < 16)
+ return tx4938_gpio_dir_in(gpio);
+ return -EINVAL;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ if (gpio < 16)
+ return tx4938_gpio_dir_out(gpio, value);
+ if (gpio < 16 + 3)
+ return rbtx4938_spi_gpio_dir_out(gpio, value);
+ return -EINVAL;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ if (gpio < 16)
+ return tx4938_gpio_get(gpio);
+ return 0;
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ if (gpio < 16)
+ tx4938_gpio_set(gpio, value);
+ else
+ rbtx4938_spi_gpio_set(gpio, value);
+}
+
+/* SPI support */
+
+static void __init txx9_spi_init(unsigned long base, int irq)
+{
+ struct resource res[] = {
+ {
+ .start = base,
+ .end = base + 0x20 - 1,
+ .flags = IORESOURCE_MEM,
+ .parent = &tx4938_reg_resource,
+ }, {
+ .start = irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+ platform_device_register_simple("txx9spi", 0,
+ res, ARRAY_SIZE(res));
+}
+
+static int __init rbtx4938_spi_init(void)
+{
+ struct spi_board_info srtc_info = {
+ .modalias = "rs5c348",
+ .max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */
+ .bus_num = 0,
+ .chip_select = 16 + SRTC_CS,
+ /* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS */
+ .mode = SPI_MODE_1 | SPI_CS_HIGH,
+ };
+ spi_register_board_info(&srtc_info, 1);
+ spi_eeprom_register(SEEPROM1_CS);
+ spi_eeprom_register(16 + SEEPROM2_CS);
+ spi_eeprom_register(16 + SEEPROM3_CS);
+ txx9_spi_init(TX4938_SPI_REG & 0xfffffffffULL, RBTX4938_IRQ_IRC_SPI);
+ return 0;
+}
+arch_initcall(rbtx4938_spi_init);
+
+/* Minimum CLK support */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ if (!strcmp(id, "spi-baseclk"))
+ return (struct clk *)(txx9_gbus_clock / 2 / 4);
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return (unsigned long)clk;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
index 89596e62f909..4d6b4ade5e8c 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
@@ -10,209 +10,90 @@
* Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
*/
#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
#include <asm/tx4938/spi.h>
-#include <asm/tx4938/tx4938.h>
-/* ATMEL 250x0 instructions */
-#define ATMEL_WREN 0x06
-#define ATMEL_WRDI 0x04
-#define ATMEL_RDSR 0x05
-#define ATMEL_WRSR 0x01
-#define ATMEL_READ 0x03
-#define ATMEL_WRITE 0x02
+#define AT250X0_PAGE_SIZE 8
-#define ATMEL_SR_BSY 0x01
-#define ATMEL_SR_WEN 0x02
-#define ATMEL_SR_BP0 0x04
-#define ATMEL_SR_BP1 0x08
-
-DEFINE_SPINLOCK(spi_eeprom_lock);
-
-static struct spi_dev_desc seeprom_dev_desc = {
- .baud = 1500000, /* 1.5Mbps */
- .tcss = 1,
- .tcsh = 1,
- .tcsr = 1,
- .byteorder = 1, /* MSB-First */
- .polarity = 0, /* High-Active */
- .phase = 0, /* Sample-Then-Shift */
-
-};
-static inline int
-spi_eeprom_io(int chipid,
- unsigned char **inbufs, unsigned int *incounts,
- unsigned char **outbufs, unsigned int *outcounts)
-{
- return txx9_spi_io(chipid, &seeprom_dev_desc,
- inbufs, incounts, outbufs, outcounts, 0);
-}
-
-int spi_eeprom_write_enable(int chipid, int enable)
+/* register board information for at25 driver */
+int __init spi_eeprom_register(int chipid)
{
- unsigned char inbuf[1];
- unsigned char *inbufs[1];
- unsigned int incounts[2];
- unsigned long flags;
- int stat;
- inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;
- inbufs[0] = inbuf;
- incounts[0] = sizeof(inbuf);
- incounts[1] = 0;
- spin_lock_irqsave(&spi_eeprom_lock, flags);
- stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
- return stat;
-}
-
-static int spi_eeprom_read_status_nolock(int chipid)
-{
- unsigned char inbuf[2], outbuf[2];
- unsigned char *inbufs[1], *outbufs[1];
- unsigned int incounts[2], outcounts[2];
- int stat;
- inbuf[0] = ATMEL_RDSR;
- inbuf[1] = 0;
- inbufs[0] = inbuf;
- incounts[0] = sizeof(inbuf);
- incounts[1] = 0;
- outbufs[0] = outbuf;
- outcounts[0] = sizeof(outbuf);
- outcounts[1] = 0;
- stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
- if (stat < 0)
- return stat;
- return outbuf[1];
+ static struct spi_eeprom eeprom = {
+ .name = "at250x0",
+ .byte_len = 128,
+ .page_size = AT250X0_PAGE_SIZE,
+ .flags = EE_ADDR1,
+ };
+ struct spi_board_info info = {
+ .modalias = "at25",
+ .max_speed_hz = 1500000, /* 1.5Mbps */
+ .bus_num = 0,
+ .chip_select = chipid,
+ .platform_data = &eeprom,
+ /* Mode 0: High-Active, Sample-Then-Shift */
+ };
+
+ return spi_register_board_info(&info, 1);
}
-int spi_eeprom_read_status(int chipid)
-{
- unsigned long flags;
- int stat;
- spin_lock_irqsave(&spi_eeprom_lock, flags);
- stat = spi_eeprom_read_status_nolock(chipid);
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
- return stat;
-}
+/* simple temporary spi driver to provide early access to seeprom. */
-int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
-{
- unsigned char inbuf[2];
- unsigned char *inbufs[2], *outbufs[2];
- unsigned int incounts[2], outcounts[3];
- unsigned long flags;
- int stat;
- inbuf[0] = ATMEL_READ;
- inbuf[1] = address;
- inbufs[0] = inbuf;
- inbufs[1] = NULL;
- incounts[0] = sizeof(inbuf);
- incounts[1] = 0;
- outbufs[0] = NULL;
- outbufs[1] = buf;
- outcounts[0] = 2;
- outcounts[1] = len;
- outcounts[2] = 0;
- spin_lock_irqsave(&spi_eeprom_lock, flags);
- stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
- return stat;
-}
+static struct read_param {
+ int chipid;
+ int address;
+ unsigned char *buf;
+ int len;
+} *read_param;
-int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
+static int __init early_seeprom_probe(struct spi_device *spi)
{
- unsigned char inbuf[2];
- unsigned char *inbufs[2];
- unsigned int incounts[3];
- unsigned long flags;
- int i, stat;
-
- if (address / 8 != (address + len - 1) / 8)
- return -EINVAL;
- stat = spi_eeprom_write_enable(chipid, 1);
- if (stat < 0)
- return stat;
- stat = spi_eeprom_read_status(chipid);
- if (stat < 0)
- return stat;
- if (!(stat & ATMEL_SR_WEN))
- return -EPERM;
-
- inbuf[0] = ATMEL_WRITE;
- inbuf[1] = address;
- inbufs[0] = inbuf;
- inbufs[1] = buf;
- incounts[0] = sizeof(inbuf);
- incounts[1] = len;
- incounts[2] = 0;
- spin_lock_irqsave(&spi_eeprom_lock, flags);
- stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
- if (stat < 0)
- goto unlock_return;
-
- /* write start. max 10ms */
- for (i = 10; i > 0; i--) {
- int stat = spi_eeprom_read_status_nolock(chipid);
- if (stat < 0)
- goto unlock_return;
- if (!(stat & ATMEL_SR_BSY))
- break;
- mdelay(1);
+ int stat = 0;
+ u8 cmd[2];
+ int len = read_param->len;
+ char *buf = read_param->buf;
+ int address = read_param->address;
+
+ dev_info(&spi->dev, "spiclk %u KHz.\n",
+ (spi->max_speed_hz + 500) / 1000);
+ if (read_param->chipid != spi->chip_select)
+ return -ENODEV;
+ while (len > 0) {
+ /* spi_write_then_read can only work with small chunk */
+ int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE;
+ cmd[0] = 0x03; /* AT25_READ */
+ cmd[1] = address;
+ stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c);
+ buf += c;
+ len -= c;
+ address += c;
}
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
- if (i == 0)
- return -EIO;
- return len;
- unlock_return:
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
return stat;
}
-#ifdef CONFIG_PROC_FS
-#define MAX_SIZE 0x80 /* for ATMEL 25010 */
-static int spi_eeprom_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- unsigned int size = MAX_SIZE;
- if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)
- size = 0;
- return size;
-}
-
-static int spi_eeprom_write_proc(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- unsigned int size = MAX_SIZE;
- int i;
- if (file->f_pos >= size)
- return -EIO;
- if (file->f_pos + count > size)
- count = size - file->f_pos;
- for (i = 0; i < count; i += 8) {
- int len = count - i < 8 ? count - i : 8;
- if (spi_eeprom_write((int)data, file->f_pos,
- (unsigned char *)buffer, len) < 0) {
- count = -EIO;
- break;
- }
- buffer += len;
- file->f_pos += len;
- }
- return count;
-}
+static struct spi_driver early_seeprom_driver __initdata = {
+ .driver = {
+ .name = "at25",
+ .owner = THIS_MODULE,
+ },
+ .probe = early_seeprom_probe,
+};
-__init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
+int __init spi_eeprom_read(int chipid, int address,
+ unsigned char *buf, int len)
{
- struct proc_dir_entry *entry;
- char name[128];
- sprintf(name, "seeprom-%d", chipid);
- entry = create_proc_entry(name, 0600, dir);
- if (entry) {
- entry->read_proc = spi_eeprom_read_proc;
- entry->write_proc = spi_eeprom_write_proc;
- entry->data = (void *)chipid;
- }
+ int ret;
+ struct read_param param = {
+ .chipid = chipid,
+ .address = address,
+ .buf = buf,
+ .len = len
+ };
+
+ read_param = &param;
+ ret = spi_register_driver(&early_seeprom_driver);
+ if (!ret)
+ spi_unregister_driver(&early_seeprom_driver);
+ return ret;
}
-#endif /* CONFIG_PROC_FS */
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
deleted file mode 100644
index 08b20cdfd7b3..000000000000
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <asm/tx4938/spi.h>
-#include <asm/tx4938/tx4938.h>
-
-static int (*txx9_spi_cs_func)(int chipid, int on);
-static DEFINE_SPINLOCK(txx9_spi_lock);
-
-extern unsigned int txx9_gbus_clock;
-
-#define SPI_FIFO_SIZE 4
-
-void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on))
-{
- txx9_spi_cs_func = cs_func;
- /* enter config mode */
- tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
-}
-
-static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait);
-
-static irqreturn_t txx9_spi_interrupt(int irq, void *dev_id)
-{
- /* disable rx intr */
- tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE;
- wake_up(&txx9_spi_wait);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction txx9_spi_action = {
- .handler = txx9_spi_interrupt,
- .name = "spi",
-};
-
-void __init txx9_spi_irqinit(int irc_irq)
-{
- setup_irq(irc_irq, &txx9_spi_action);
-}
-
-int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
- unsigned char **inbufs, unsigned int *incounts,
- unsigned char **outbufs, unsigned int *outcounts,
- int cansleep)
-{
- unsigned int incount, outcount;
- unsigned char *inp, *outp;
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&txx9_spi_lock, flags);
- if ((tx4938_spiptr->mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE) {
- spin_unlock_irqrestore(&txx9_spi_lock, flags);
- return -EBUSY;
- }
- /* enter config mode */
- tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
- tx4938_spiptr->cr0 =
- (desc->byteorder ? TXx9_SPCR0_SBOS : 0) |
- (desc->polarity ? TXx9_SPCR0_SPOL : 0) |
- (desc->phase ? TXx9_SPCR0_SPHA : 0) |
- 0x08;
- tx4938_spiptr->cr1 =
- (((TXX9_IMCLK + desc->baud) / (2 * desc->baud) - 1) << 8) |
- 0x08 /* 8 bit only */;
- /* enter active mode */
- tx4938_spiptr->mcr = TXx9_SPMCR_ACTIVE;
- spin_unlock_irqrestore(&txx9_spi_lock, flags);
-
- /* CS ON */
- if ((ret = txx9_spi_cs_func(chipid, 1)) < 0) {
- spin_unlock_irqrestore(&txx9_spi_lock, flags);
- return ret;
- }
- udelay(desc->tcss);
-
- /* do scatter IO */
- inp = inbufs ? *inbufs : NULL;
- outp = outbufs ? *outbufs : NULL;
- incount = 0;
- outcount = 0;
- while (1) {
- unsigned char data;
- unsigned int count;
- int i;
- if (!incount) {
- incount = incounts ? *incounts++ : 0;
- inp = (incount && inbufs) ? *inbufs++ : NULL;
- }
- if (!outcount) {
- outcount = outcounts ? *outcounts++ : 0;
- outp = (outcount && outbufs) ? *outbufs++ : NULL;
- }
- if (!inp && !outp)
- break;
- count = SPI_FIFO_SIZE;
- if (incount)
- count = min(count, incount);
- if (outcount)
- count = min(count, outcount);
-
- /* now tx must be idle... */
- while (!(tx4938_spiptr->sr & TXx9_SPSR_SIDLE))
- ;
-
- tx4938_spiptr->cr0 =
- (tx4938_spiptr->cr0 & ~TXx9_SPCR0_RXIFL_MASK) |
- ((count - 1) << 12);
- if (cansleep) {
- /* enable rx intr */
- tx4938_spiptr->cr0 |= TXx9_SPCR0_RBSIE;
- }
- /* send */
- for (i = 0; i < count; i++)
- tx4938_spiptr->dr = inp ? *inp++ : 0;
- /* wait all rx data */
- if (cansleep) {
- wait_event(txx9_spi_wait,
- tx4938_spiptr->sr & TXx9_SPSR_SRRDY);
- } else {
- while (!(tx4938_spiptr->sr & TXx9_SPSR_RBSI))
- ;
- }
- /* receive */
- for (i = 0; i < count; i++) {
- data = tx4938_spiptr->dr;
- if (outp)
- *outp++ = data;
- }
- if (incount)
- incount -= count;
- if (outcount)
- outcount -= count;
- }
-
- /* CS OFF */
- udelay(desc->tcsh);
- txx9_spi_cs_func(chipid, 0);
- udelay(desc->tcsr);
-
- spin_lock_irqsave(&txx9_spi_lock, flags);
- /* enter config mode */
- tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
- spin_unlock_irqrestore(&txx9_spi_lock, flags);
-
- return 0;
-}
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index 2775d2618332..95f5160df27f 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -24,7 +24,7 @@
#define CRYPT_S390_PRIORITY 300
#define CRYPT_S390_COMPOSITE_PRIORITY 400
-/* s930 cryptographic operations */
+/* s390 cryptographic operations */
enum crypt_s390_operations {
CRYPT_S390_KM = 0x0100,
CRYPT_S390_KMC = 0x0200,
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 50538e545618..e6289ee74ecd 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -171,37 +171,6 @@ static inline int memory_fast_detect(void)
}
#endif
-#define ADDR2G (1UL << 31)
-
-static noinline __init unsigned long sclp_memory_detect(void)
-{
- struct sclp_readinfo_sccb *sccb;
- unsigned long long memsize;
-
- sccb = &s390_readinfo_sccb;
-
- if (sccb->header.response_code != 0x10)
- return 0;
-
- if (sccb->rnsize)
- memsize = sccb->rnsize << 20;
- else
- memsize = sccb->rnsize2 << 20;
- if (sccb->rnmax)
- memsize *= sccb->rnmax;
- else
- memsize *= sccb->rnmax2;
-#ifndef CONFIG_64BIT
- /*
- * Can't deal with more than 2G in 31 bit addressing mode, so
- * limit the value in order to avoid strange side effects.
- */
- if (memsize > ADDR2G)
- memsize = ADDR2G;
-#endif
- return (unsigned long) memsize;
-}
-
static inline __init unsigned long __tprot(unsigned long addr)
{
int cc = -1;
@@ -218,6 +187,7 @@ static inline __init unsigned long __tprot(unsigned long addr)
/* Checking memory in 128KB increments. */
#define CHUNK_INCR (1UL << 17)
+#define ADDR2G (1UL << 31)
static noinline __init void find_memory_chunks(unsigned long memsize)
{
@@ -293,7 +263,7 @@ static noinline __init void setup_lowcore_early(void)
*/
void __init startup_init(void)
{
- unsigned long memsize;
+ unsigned long long memsize;
ipl_save_parameters();
clear_bss_section();
@@ -305,8 +275,17 @@ void __init startup_init(void)
sort_main_extable();
setup_lowcore_early();
sclp_readinfo_early();
+ sclp_facilities_detect();
memsize = sclp_memory_detect();
+#ifndef CONFIG_64BIT
+ /*
+ * Can't deal with more than 2G in 31 bit addressing mode, so
+ * limit the value in order to avoid strange side effects.
+ */
+ if (memsize > ADDR2G)
+ memsize = ADDR2G;
+#endif
if (memory_fast_detect() < 0)
- find_memory_chunks(memsize);
+ find_memory_chunks((unsigned long) memsize);
lockdep_on();
}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 6234c6978a1f..bc7ff3658c3d 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -107,6 +107,11 @@ STACK_SIZE = 1 << STACK_SHIFT
l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13
.endm
+ .macro SAVE_ALL_SVC psworg,savearea
+ la %r12,\psworg
+ l %r15,__LC_KERNEL_STACK # problem state -> load ksp
+ .endm
+
.macro SAVE_ALL_SYNC psworg,savearea
la %r12,\psworg
tm \psworg+1,0x01 # test problem state bit
@@ -218,7 +223,7 @@ system_call:
STORE_TIMER __LC_SYNC_ENTER_TIMER
sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
- SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+ SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
lh %r7,0x8a # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 685f11faa4bc..2a7b1304418b 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -99,6 +99,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
larl %r13,system_call
.endm
+ .macro SAVE_ALL_SVC psworg,savearea
+ la %r12,\psworg
+ lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
+ .endm
+
.macro SAVE_ALL_SYNC psworg,savearea
la %r12,\psworg
tm \psworg+1,0x01 # test problem state bit
@@ -207,7 +212,7 @@ system_call:
STORE_TIMER __LC_SYNC_ENTER_TIMER
sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
- SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+ SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 367caf92ea78..82b131ddd7ff 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -25,10 +25,6 @@
#define IPL_PARM_BLOCK_VERSION 0
-#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
-#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
-#define SCCB_FLAG (s390_readinfo_sccb.flags)
-
#define IPL_UNKNOWN_STR "unknown"
#define IPL_CCW_STR "ccw"
#define IPL_FCP_STR "fcp"
@@ -146,6 +142,8 @@ static struct ipl_parameter_block *dump_block_ccw;
static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
+static struct sclp_ipl_info sclp_ipl_info;
+
int diag308(unsigned long subcode, void *addr)
{
register unsigned long _addr asm("0") = (unsigned long) addr;
@@ -375,9 +373,9 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
{
char loadparm[LOADPARM_LEN + 1] = {};
- if (!SCCB_VALID)
+ if (!sclp_ipl_info.is_valid)
return sprintf(page, "#unknown#\n");
- memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
+ memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
EBCASC(loadparm, LOADPARM_LEN);
strstrip(loadparm);
return sprintf(page, "%s\n", loadparm);
@@ -910,9 +908,9 @@ static int __init reipl_ccw_init(void)
reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
/* check if read scp info worked and set loadparm */
- if (SCCB_VALID)
+ if (sclp_ipl_info.is_valid)
memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
- SCCB_LOADPARM, LOADPARM_LEN);
+ &sclp_ipl_info.loadparm, LOADPARM_LEN);
else
/* read scp info failed: set empty loadparm (EBCDIC blanks) */
memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
@@ -1007,7 +1005,7 @@ static int __init dump_fcp_init(void)
{
int rc;
- if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
+ if (!sclp_ipl_info.has_dump)
return 0; /* LDIPL DUMP is not installed */
if (!diag308_set_works)
return 0;
@@ -1088,6 +1086,7 @@ static int __init s390_ipl_init(void)
{
int rc;
+ sclp_get_ipl_info(&sclp_ipl_info);
reipl_probe();
rc = ipl_init();
if (rc)
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index eb43c3b31269..441975b796fb 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -93,8 +93,8 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
/* disable monitor call class 0 */
__ctl_clear_bit(8, 15);
- atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
- (void *)(long) smp_processor_id());
+ atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+ (void *)(long) smp_processor_id());
}
extern void s390_handle_mcck(void);
@@ -115,7 +115,7 @@ static void default_idle(void)
}
rc = atomic_notifier_call_chain(&idle_chain,
- CPU_IDLE, (void *)(long) cpu);
+ S390_CPU_IDLE, (void *)(long) cpu);
if (rc != NOTIFY_OK && rc != NOTIFY_DONE)
BUG();
if (rc != NOTIFY_OK) {
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 8ff2feaf9b00..182c085ae4dd 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -410,58 +410,40 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \
__attribute__((__section__(".data")));
-static void __init smp_get_save_areas(void)
+static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
{
- unsigned int cpu, cpu_num, rc;
- __u16 boot_cpu_addr;
-
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
return;
- boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
- cpu_num = 1;
- for (cpu = 0; cpu <= 65535; cpu++) {
- if ((u16) cpu == boot_cpu_addr)
- continue;
- __cpu_logical_map[1] = (__u16) cpu;
- if (signal_processor(1, sigp_sense) == sigp_not_operational)
- continue;
- if (cpu_num >= NR_CPUS) {
- printk("WARNING: Registers for cpu %i are not "
- "saved, since dump kernel was compiled with"
- "NR_CPUS=%i!\n", cpu_num, NR_CPUS);
- continue;
- }
- zfcpdump_save_areas[cpu_num] =
- alloc_bootmem(sizeof(union save_area));
- while (1) {
- rc = signal_processor(1, sigp_stop_and_store_status);
- if (rc != sigp_busy)
- break;
- cpu_relax();
- }
- memcpy(zfcpdump_save_areas[cpu_num],
- (void *)(unsigned long) store_prefix() +
- SAVE_AREA_BASE, SAVE_AREA_SIZE);
-#ifdef __s390x__
- /* copy original prefix register */
- zfcpdump_save_areas[cpu_num]->s390x.pref_reg =
- zfcpdump_prefix_array[cpu_num];
-#endif
- cpu_num++;
+ if (cpu >= NR_CPUS) {
+ printk(KERN_WARNING "Registers for cpu %i not saved since dump "
+ "kernel was compiled with NR_CPUS=%i\n", cpu, NR_CPUS);
+ return;
}
+ zfcpdump_save_areas[cpu] = alloc_bootmem(sizeof(union save_area));
+ __cpu_logical_map[1] = (__u16) phy_cpu;
+ while (signal_processor(1, sigp_stop_and_store_status) == sigp_busy)
+ cpu_relax();
+ memcpy(zfcpdump_save_areas[cpu],
+ (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
+ SAVE_AREA_SIZE);
+#ifdef CONFIG_64BIT
+ /* copy original prefix register */
+ zfcpdump_save_areas[cpu]->s390x.pref_reg = zfcpdump_prefix_array[cpu];
+#endif
}
union save_area *zfcpdump_save_areas[NR_CPUS + 1];
EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
#else
-#define smp_get_save_areas() do { } while (0)
-#endif
+
+static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
+
+#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */
/*
* Lets check how many CPUs we have.
*/
-
static unsigned int __init smp_count_cpus(void)
{
unsigned int cpu, num_cpus;
@@ -470,7 +452,6 @@ static unsigned int __init smp_count_cpus(void)
/*
* cpu 0 is the boot cpu. See smp_prepare_boot_cpu.
*/
-
boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
current_thread_info()->cpu = 0;
num_cpus = 1;
@@ -480,12 +461,11 @@ static unsigned int __init smp_count_cpus(void)
__cpu_logical_map[1] = (__u16) cpu;
if (signal_processor(1, sigp_sense) == sigp_not_operational)
continue;
+ smp_get_save_area(num_cpus, cpu);
num_cpus++;
}
-
printk("Detected %d CPU's\n", (int) num_cpus);
printk("Boot cpu address %2X\n", boot_cpu_addr);
-
return num_cpus;
}
@@ -606,7 +586,6 @@ void __init smp_setup_cpu_possible_map(void)
{
unsigned int phy_cpus, pos_cpus, cpu;
- smp_get_save_areas();
phy_cpus = smp_count_cpus();
pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS);
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9c2872a7cca7..48dae49bc1ec 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -226,10 +226,10 @@ static int nohz_idle_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
switch (action) {
- case CPU_IDLE:
+ case S390_CPU_IDLE:
stop_hz_timer();
break;
- case CPU_NOT_IDLE:
+ case S390_CPU_NOT_IDLE:
start_hz_timer();
break;
}
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 1e1a6ee2cac1..b6ed143e8597 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -545,10 +545,10 @@ static int vtimer_idle_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
switch (action) {
- case CPU_IDLE:
+ case S390_CPU_IDLE:
stop_cpu_timer();
break;
- case CPU_NOT_IDLE:
+ case S390_CPU_NOT_IDLE:
start_cpu_timer();
break;
}
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 59aea65ce99f..52084436ab69 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,7 +4,7 @@
EXTRA_AFLAGS := -traditional
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o
-obj-$(CONFIG_32BIT) += div64.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+obj-$(CONFIG_32BIT) += div64.o qrnnd.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 4d9ad59031bb..4fea3ac7bff0 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -68,16 +68,6 @@ void __cpuinit smp_store_cpu_info(int id)
cpu_data(id).prom_node = cpu_node;
cpu_data(id).mid = cpu_get_hwmid(cpu_node);
- /* this is required to tune the scheduler correctly */
- /* is it possible to have CPUs with different cache sizes? */
- if (id == boot_cpu_id) {
- int cache_line,cache_nlines;
- cache_line = 0x20;
- cache_line = prom_getintdefault(cpu_node, "ecache-line-size", cache_line);
- cache_nlines = 0x8000;
- cache_nlines = prom_getintdefault(cpu_node, "ecache-nlines", cache_nlines);
- max_cache_size = cache_line * cache_nlines;
- }
if (cpu_data(id).mid < 0)
panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
}
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 4dcd7d0b60f2..40e40f968d61 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1163,32 +1163,6 @@ int setup_profiling_timer(unsigned int multiplier)
return -EINVAL;
}
-static void __init smp_tune_scheduling(void)
-{
- unsigned int smallest = ~0U;
- int i;
-
- for (i = 0; i < NR_CPUS; i++) {
- unsigned int val = cpu_data(i).ecache_size;
-
- if (val && val < smallest)
- smallest = val;
- }
-
- /* Any value less than 256K is nonsense. */
- if (smallest < (256U * 1024U))
- smallest = 256 * 1024;
-
- max_cache_size = smallest;
-
- if (smallest < 1U * 1024U * 1024U)
- printk(KERN_INFO "Using max_cache_size of %uKB\n",
- smallest / 1024U);
- else
- printk(KERN_INFO "Using max_cache_size of %uMB\n",
- smallest / 1024U / 1024U);
-}
-
/* Constrain the number of cpus to max_cpus. */
void __init smp_prepare_cpus(unsigned int max_cpus)
{
@@ -1206,7 +1180,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
cpu_data(boot_cpu_id).udelay_val = loops_per_jiffy;
- smp_tune_scheduling();
}
void __devinit smp_prepare_boot_cpu(void)
diff --git a/block/Kconfig b/block/Kconfig
index a50f48111647..285935134bcd 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -1,7 +1,7 @@
#
# Block layer core configuration
#
-config BLOCK
+menuconfig BLOCK
bool "Enable the block layer" if EMBEDDED
default y
help
@@ -49,6 +49,6 @@ config LSF
If unsure, say Y.
-endif
+endif # BLOCK
source block/Kconfig.iosched
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index baef5fc7cff8..e0aa4dad6742 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -92,6 +92,8 @@ struct cfq_data {
struct cfq_queue *active_queue;
struct cfq_io_context *active_cic;
+ struct cfq_queue *async_cfqq[IOPRIO_BE_NR];
+
struct timer_list idle_class_timer;
sector_t last_position;
@@ -1351,8 +1353,8 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc)
}
static struct cfq_queue *
-cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
- gfp_t gfp_mask)
+cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
+ struct task_struct *tsk, gfp_t gfp_mask)
{
struct cfq_queue *cfqq, *new_cfqq = NULL;
struct cfq_io_context *cic;
@@ -1405,12 +1407,35 @@ retry:
if (new_cfqq)
kmem_cache_free(cfq_pool, new_cfqq);
- atomic_inc(&cfqq->ref);
out:
WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
return cfqq;
}
+static struct cfq_queue *
+cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
+ gfp_t gfp_mask)
+{
+ const int ioprio = task_ioprio(tsk);
+ struct cfq_queue *cfqq = NULL;
+
+ if (!is_sync)
+ cfqq = cfqd->async_cfqq[ioprio];
+ if (!cfqq)
+ cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask);
+
+ /*
+ * pin the queue now that it's allocated, scheduler exit will prune it
+ */
+ if (!is_sync && !cfqd->async_cfqq[ioprio]) {
+ atomic_inc(&cfqq->ref);
+ cfqd->async_cfqq[ioprio] = cfqq;
+ }
+
+ atomic_inc(&cfqq->ref);
+ return cfqq;
+}
+
/*
* We drop cfq io contexts lazily, so we may find a dead one.
*/
@@ -2019,6 +2044,7 @@ static void cfq_exit_queue(elevator_t *e)
{
struct cfq_data *cfqd = e->elevator_data;
request_queue_t *q = cfqd->queue;
+ int i;
cfq_shutdown_timer_wq(cfqd);
@@ -2035,6 +2061,13 @@ static void cfq_exit_queue(elevator_t *e)
__cfq_exit_single_io_context(cfqd, cic);
}
+ /*
+ * Put the async queues
+ */
+ for (i = 0; i < IOPRIO_BE_NR; i++)
+ if (cfqd->async_cfqq[i])
+ cfq_put_queue(cfqd->async_cfqq[i]);
+
spin_unlock_irq(q->queue_lock);
cfq_shutdown_timer_wq(cfqd);
diff --git a/block/elevator.c b/block/elevator.c
index ce866eb75f6a..4769a25d7037 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -112,12 +112,8 @@ static inline int elv_try_merge(struct request *__rq, struct bio *bio)
static struct elevator_type *elevator_find(const char *name)
{
struct elevator_type *e;
- struct list_head *entry;
-
- list_for_each(entry, &elv_list) {
-
- e = list_entry(entry, struct elevator_type, list);
+ list_for_each_entry(e, &elv_list, list) {
if (!strcmp(e->elevator_name, name))
return e;
}
@@ -1116,14 +1112,11 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
{
elevator_t *e = q->elevator;
struct elevator_type *elv = e->elevator_type;
- struct list_head *entry;
+ struct elevator_type *__e;
int len = 0;
spin_lock(&elv_list_lock);
- list_for_each(entry, &elv_list) {
- struct elevator_type *__e;
-
- __e = list_entry(entry, struct elevator_type, list);
+ list_for_each_entry(__e, &elv_list, list) {
if (!strcmp(elv->elevator_name, __e->elevator_name))
len += sprintf(name+len, "[%s] ", elv->elevator_name);
else
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index c99b46354859..ef42bb2b12b6 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -527,8 +527,6 @@ int blk_do_ordered(request_queue_t *q, struct request **rqp)
static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
{
request_queue_t *q = bio->bi_private;
- struct bio_vec *bvec;
- int i;
/*
* This is dry run, restore bio_sector and size. We'll finish
@@ -540,13 +538,6 @@ static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
if (bio->bi_size)
return 1;
- /* Rewind bvec's */
- bio->bi_idx = 0;
- bio_for_each_segment(bvec, bio, i) {
- bvec->bv_len += bvec->bv_offset;
- bvec->bv_offset = 0;
- }
-
/* Reset bio */
set_bit(BIO_UPTODATE, &bio->bi_flags);
bio->bi_size = q->bi_size;
@@ -1304,9 +1295,9 @@ static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID)))
blk_recount_segments(q, nxt);
if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) ||
- BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size))
+ BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size))
return 0;
- if (bio->bi_size + nxt->bi_size > q->max_segment_size)
+ if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size)
return 0;
return 1;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 050323fd79e9..7916f4b86d23 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -24,8 +24,6 @@ source "drivers/scsi/Kconfig"
source "drivers/ata/Kconfig"
-source "drivers/cdrom/Kconfig"
-
source "drivers/md/Kconfig"
source "drivers/message/fusion/Kconfig"
@@ -54,6 +52,8 @@ source "drivers/spi/Kconfig"
source "drivers/w1/Kconfig"
+source "drivers/power/Kconfig"
+
source "drivers/hwmon/Kconfig"
source "drivers/mfd/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index adad2f3d438a..503d82569449 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_RTC_LIB) += rtc/
obj-y += i2c/
obj-$(CONFIG_W1) += w1/
+obj-$(CONFIG_POWER_SUPPLY) += power/
obj-$(CONFIG_HWMON) += hwmon/
obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 674bf81c6e66..423ed08fb6f7 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1246,7 +1246,7 @@ repeat:
del_timer(&motor_off_timer);
ReqCnt = 0;
- ReqCmd = CURRENT->cmd;
+ ReqCmd = rq_data_dir(CURRENT);
ReqBlock = CURRENT->sector;
ReqBuffer = CURRENT->buffer;
setup_req_params(drive);
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 689a4c3542ba..d85520f78e68 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -439,7 +439,7 @@ static void mfm_rw_intr(void)
a choice of command end or some data which is ready to be collected */
/* I think we have to transfer data while the interrupt line is on and its
not any other type of interrupt */
- if (CURRENT->cmd == WRITE) {
+ if (rq_data_dir(CURRENT) == WRITE) {
extern void hdc63463_writedma(void);
if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
@@ -799,7 +799,7 @@ static void issue_request(unsigned int block, unsigned int nsect,
raw_cmd.head = start_head;
raw_cmd.cylinder = track / p->heads;
raw_cmd.cmdtype = CURRENT->cmd;
- raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
+ raw_cmd.cmdcode = rq_data_dir(CURRENT) == WRITE ? CMD_WD : CMD_RD;
raw_cmd.cmddata[0] = dev + 1; /* DAG: +1 to get US */
raw_cmd.cmddata[1] = raw_cmd.head;
raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
@@ -830,7 +830,7 @@ static void issue_request(unsigned int block, unsigned int nsect,
hdc63463_dataleft = nsect * 256; /* Better way? */
DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
- raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",
+ raw_cmd.dev + 'a', rq_data_dir(CURRENT) == READ ? "read" : "writ",
raw_cmd.cylinder,
raw_cmd.head,
raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
@@ -917,13 +917,6 @@ static void mfm_request(void)
DBG("mfm_request: block after offset=%d\n", block);
- if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {
- printk("unknown mfm-command %d\n", CURRENT->cmd);
- end_request(CURRENT, 0);
- Busy = 0;
- printk("mfm: continue 4\n");
- continue;
- }
issue_request(block, nsect, CURRENT);
break;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b4c8319138b2..6e23af1ecbdb 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -2,9 +2,12 @@
# Block device driver configuration
#
-if BLOCK
+menuconfig BLK_DEV
+ bool "Block devices"
+ depends on BLOCK
+ default y
-menu "Block devices"
+if BLK_DEV
config BLK_DEV_FD
tristate "Normal floppy disk support"
@@ -56,40 +59,9 @@ config AMIGA_Z2RAM
To compile this driver as a module, choose M here: the
module will be called z2ram.
-config ATARI_ACSI
- tristate "Atari ACSI support"
- depends on ATARI && BROKEN
- ---help---
- This enables support for the Atari ACSI interface. The driver
- supports hard disks and CD-ROMs, which have 512-byte sectors, or can
- be switched to that mode. Due to the ACSI command format, only disks
- up to 1 GB are supported. Special support for certain ACSI to SCSI
- adapters, which could relax that, isn't included yet. The ACSI
- driver is also the basis for certain other drivers for devices
- attached to the ACSI bus: Atari SLM laser printer, BioNet-100
- Ethernet, and PAMsNet Ethernet. If you want to use one of these
- devices, you need ACSI support, too.
-
- To compile this driver as a module, choose M here: the
- module will be called acsi.
-
-comment "Some devices (e.g. CD jukebox) support multiple LUNs"
- depends on ATARI && ATARI_ACSI
-
-config ACSI_MULTI_LUN
- bool "Probe all LUNs on each ACSI device"
- depends on ATARI_ACSI
- help
- If you have a ACSI device that supports more than one LUN (Logical
- Unit Number), e.g. a CD jukebox, you should say Y here so that all
- will be found by the ACSI driver. An ACSI device with multiple LUNs
- acts logically like multiple ACSI devices. The vast majority of ACSI
- devices have only one LUN, and so most people can say N here and
- should in fact do so, because it is safer.
-
config ATARI_SLM
tristate "Atari SLM laser printer support"
- depends on ATARI && ATARI_ACSI!=n
+ depends on ATARI
help
If you have an Atari SLM laser printer, say Y to include support for
it in the kernel. Otherwise, say N. This driver is also available as
@@ -453,6 +425,4 @@ config ATA_OVER_ETH
source "drivers/s390/block/Kconfig"
-endmenu
-
-endif
+endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index dd88e33c1eb1..e5f98acc5d52 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
-obj-$(CONFIG_ATARI_ACSI) += acsi.o
obj-$(CONFIG_ATARI_SLM) += acsi_slm.o
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
obj-$(CONFIG_BLK_DEV_RAM) += rd.o
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
deleted file mode 100644
index e3d9152e231a..000000000000
--- a/drivers/block/acsi.c
+++ /dev/null
@@ -1,1825 +0,0 @@
-/*
- * acsi.c -- Device driver for Atari ACSI hard disks
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * Some parts are based on hd.c by Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- */
-
-/*
- * Still to in this file:
- * - If a command ends with an error status (!= 0), the following
- * REQUEST SENSE commands (4 to fill the ST-DMA FIFO) are done by
- * polling the _IRQ signal (not interrupt-driven). This should be
- * avoided in future because it takes up a non-neglectible time in
- * the interrupt service routine while interrupts are disabled.
- * Maybe a timer interrupt will get lost :-(
- */
-
-/*
- * General notes:
- *
- * - All ACSI devices (disks, CD-ROMs, ...) use major number 28.
- * Minors are organized like it is with SCSI: The upper 4 bits
- * identify the device, the lower 4 bits the partition.
- * The device numbers (the upper 4 bits) are given in the same
- * order as the devices are found on the bus.
- * - Up to 8 LUNs are supported for each target (if CONFIG_ACSI_MULTI_LUN
- * is defined), but only a total of 16 devices (due to minor
- * numbers...). Note that Atari allows only a maximum of 4 targets
- * (i.e. controllers, not devices) on the ACSI bus!
- * - A optimizing scheme similar to SCSI scatter-gather is implemented.
- * - Removable media are supported. After a medium change to device
- * is reinitialized (partition check etc.). Also, if the device
- * knows the PREVENT/ALLOW MEDIUM REMOVAL command, the door should
- * be locked and unlocked when mounting the first or unmounting the
- * last filesystem on the device. The code is untested, because I
- * don't have a removable hard disk.
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/genhd.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */
-#include <scsi/scsi_ioctl.h>
-#include <linux/hdreg.h> /* for HDIO_GETGEO */
-#include <linux/blkpg.h>
-#include <linux/buffer_head.h>
-#include <linux/blkdev.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-static void (*do_acsi)(void) = NULL;
-static struct request_queue *acsi_queue;
-#define QUEUE (acsi_queue)
-#define CURRENT elv_next_request(acsi_queue)
-
-#define DEBUG
-#undef DEBUG_DETECT
-#undef NO_WRITE
-
-#define MAX_ERRORS 8 /* Max read/write errors/sector */
-#define MAX_LUN 8 /* Max LUNs per target */
-#define MAX_DEV 16
-
-#define ACSI_BUFFER_SIZE (16*1024) /* "normal" ACSI buffer size */
-#define ACSI_BUFFER_MINSIZE (2048) /* min. buf size if ext. DMA */
-#define ACSI_BUFFER_SIZE_ORDER 2 /* order size for above */
-#define ACSI_BUFFER_MINSIZE_ORDER 0 /* order size for above */
-#define ACSI_BUFFER_SECTORS (ACSI_BUFFER_SIZE/512)
-
-#define ACSI_BUFFER_ORDER \
- (ATARIHW_PRESENT(EXTD_DMA) ? \
- ACSI_BUFFER_MINSIZE_ORDER : \
- ACSI_BUFFER_SIZE_ORDER)
-
-#define ACSI_TIMEOUT (4*HZ)
-
-/* minimum delay between two commands */
-
-#define COMMAND_DELAY 500
-
-typedef enum {
- NONE, HARDDISK, CDROM
-} ACSI_TYPE;
-
-struct acsi_info_struct {
- ACSI_TYPE type; /* type of device */
- unsigned target; /* target number */
- unsigned lun; /* LUN in target controller */
- unsigned removable : 1; /* Flag for removable media */
- unsigned read_only : 1; /* Flag for read only devices */
- unsigned old_atari_disk : 1; /* Is an old Atari disk */
- unsigned changed : 1; /* Medium has been changed */
- unsigned long size; /* #blocks */
- int access_count;
-} acsi_info[MAX_DEV];
-
-/*
- * SENSE KEYS
- */
-
-#define NO_SENSE 0x00
-#define RECOVERED_ERROR 0x01
-#define NOT_READY 0x02
-#define MEDIUM_ERROR 0x03
-#define HARDWARE_ERROR 0x04
-#define ILLEGAL_REQUEST 0x05
-#define UNIT_ATTENTION 0x06
-#define DATA_PROTECT 0x07
-#define BLANK_CHECK 0x08
-#define COPY_ABORTED 0x0a
-#define ABORTED_COMMAND 0x0b
-#define VOLUME_OVERFLOW 0x0d
-#define MISCOMPARE 0x0e
-
-
-/*
- * DEVICE TYPES
- */
-
-#define TYPE_DISK 0x00
-#define TYPE_TAPE 0x01
-#define TYPE_WORM 0x04
-#define TYPE_ROM 0x05
-#define TYPE_MOD 0x07
-#define TYPE_NO_LUN 0x7f
-
-/* The data returned by MODE SENSE differ between the old Atari
- * hard disks and SCSI disks connected to ACSI. In the following, both
- * formats are defined and some macros to operate on them potably.
- */
-
-typedef struct {
- unsigned long dummy[2];
- unsigned long sector_size;
- unsigned char format_code;
-#define ATARI_SENSE_FORMAT_FIX 1
-#define ATARI_SENSE_FORMAT_CHNG 2
- unsigned char cylinders_h;
- unsigned char cylinders_l;
- unsigned char heads;
- unsigned char reduced_h;
- unsigned char reduced_l;
- unsigned char precomp_h;
- unsigned char precomp_l;
- unsigned char landing_zone;
- unsigned char steprate;
- unsigned char type;
-#define ATARI_SENSE_TYPE_FIXCHNG_MASK 4
-#define ATARI_SENSE_TYPE_SOFTHARD_MASK 8
-#define ATARI_SENSE_TYPE_FIX 4
-#define ATARI_SENSE_TYPE_CHNG 0
-#define ATARI_SENSE_TYPE_SOFT 0
-#define ATARI_SENSE_TYPE_HARD 8
- unsigned char sectors;
-} ATARI_SENSE_DATA;
-
-#define ATARI_CAPACITY(sd) \
- (((int)((sd).cylinders_h<<8)|(sd).cylinders_l) * \
- (sd).heads * (sd).sectors)
-
-
-typedef struct {
- unsigned char dummy1;
- unsigned char medium_type;
- unsigned char dummy2;
- unsigned char descriptor_size;
- unsigned long block_count;
- unsigned long sector_size;
- /* Page 0 data */
- unsigned char page_code;
- unsigned char page_size;
- unsigned char page_flags;
- unsigned char qualifier;
-} SCSI_SENSE_DATA;
-
-#define SCSI_CAPACITY(sd) ((sd).block_count & 0xffffff)
-
-
-typedef union {
- ATARI_SENSE_DATA atari;
- SCSI_SENSE_DATA scsi;
-} SENSE_DATA;
-
-#define SENSE_TYPE_UNKNOWN 0
-#define SENSE_TYPE_ATARI 1
-#define SENSE_TYPE_SCSI 2
-
-#define SENSE_TYPE(sd) \
- (((sd).atari.dummy[0] == 8 && \
- ((sd).atari.format_code == 1 || \
- (sd).atari.format_code == 2)) ? SENSE_TYPE_ATARI : \
- ((sd).scsi.dummy1 >= 11) ? SENSE_TYPE_SCSI : \
- SENSE_TYPE_UNKNOWN)
-
-#define CAPACITY(sd) \
- (SENSE_TYPE(sd) == SENSE_TYPE_ATARI ? \
- ATARI_CAPACITY((sd).atari) : \
- SCSI_CAPACITY((sd).scsi))
-
-#define SECTOR_SIZE(sd) \
- (SENSE_TYPE(sd) == SENSE_TYPE_ATARI ? \
- (sd).atari.sector_size : \
- (sd).scsi.sector_size & 0xffffff)
-
-/* Default size if capacity cannot be determined (1 GByte) */
-#define DEFAULT_SIZE 0x1fffff
-
-#define CARTRCH_STAT(aip,buf) \
- (aip->old_atari_disk ? \
- (((buf)[0] & 0x7f) == 0x28) : \
- ((((buf)[0] & 0x70) == 0x70) ? \
- (((buf)[2] & 0x0f) == 0x06) : \
- (((buf)[0] & 0x0f) == 0x06))) \
-
-/* These two are also exported to other drivers that work on the ACSI bus and
- * need an ST-RAM buffer. */
-char *acsi_buffer;
-unsigned long phys_acsi_buffer;
-
-static int NDevices;
-
-static int CurrentNReq;
-static int CurrentNSect;
-static char *CurrentBuffer;
-
-static DEFINE_SPINLOCK(acsi_lock);
-
-
-#define SET_TIMER() mod_timer(&acsi_timer, jiffies + ACSI_TIMEOUT)
-#define CLEAR_TIMER() del_timer(&acsi_timer)
-
-static unsigned long STramMask;
-#define STRAM_ADDR(a) (((a) & STramMask) == 0)
-
-
-
-/* ACSI commands */
-
-static char tur_cmd[6] = { 0x00, 0, 0, 0, 0, 0 };
-static char modesense_cmd[6] = { 0x1a, 0, 0, 0, 24, 0 };
-static char modeselect_cmd[6] = { 0x15, 0, 0, 0, 12, 0 };
-static char inquiry_cmd[6] = { 0x12, 0, 0, 0,255, 0 };
-static char reqsense_cmd[6] = { 0x03, 0, 0, 0, 4, 0 };
-static char read_cmd[6] = { 0x08, 0, 0, 0, 0, 0 };
-static char write_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 };
-static char pa_med_rem_cmd[6] = { 0x1e, 0, 0, 0, 0, 0 };
-
-#define CMDSET_TARG_LUN(cmd,targ,lun) \
- do { \
- cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5; \
- cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \
- } while(0)
-
-#define CMDSET_BLOCK(cmd,blk) \
- do { \
- unsigned long __blk = (blk); \
- cmd[3] = __blk; __blk >>= 8; \
- cmd[2] = __blk; __blk >>= 8; \
- cmd[1] = (cmd[1] & 0xe0) | (__blk & 0x1f); \
- } while(0)
-
-#define CMDSET_LEN(cmd,len) \
- do { \
- cmd[4] = (len); \
- } while(0)
-
-/* ACSI errors (from REQUEST SENSE); There are two tables, one for the
- * old Atari disks and one for SCSI on ACSI disks.
- */
-
-struct acsi_error {
- unsigned char code;
- const char *text;
-} atari_acsi_errors[] = {
- { 0x00, "No error (??)" },
- { 0x01, "No index pulses" },
- { 0x02, "Seek not complete" },
- { 0x03, "Write fault" },
- { 0x04, "Drive not ready" },
- { 0x06, "No Track 00 signal" },
- { 0x10, "ECC error in ID field" },
- { 0x11, "Uncorrectable data error" },
- { 0x12, "ID field address mark not found" },
- { 0x13, "Data field address mark not found" },
- { 0x14, "Record not found" },
- { 0x15, "Seek error" },
- { 0x18, "Data check in no retry mode" },
- { 0x19, "ECC error during verify" },
- { 0x1a, "Access to bad block" },
- { 0x1c, "Unformatted or bad format" },
- { 0x20, "Invalid command" },
- { 0x21, "Invalid block address" },
- { 0x23, "Volume overflow" },
- { 0x24, "Invalid argument" },
- { 0x25, "Invalid drive number" },
- { 0x26, "Byte zero parity check" },
- { 0x28, "Cartride changed" },
- { 0x2c, "Error count overflow" },
- { 0x30, "Controller selftest failed" }
-},
-
- scsi_acsi_errors[] = {
- { 0x00, "No error (??)" },
- { 0x01, "Recovered error" },
- { 0x02, "Drive not ready" },
- { 0x03, "Uncorrectable medium error" },
- { 0x04, "Hardware error" },
- { 0x05, "Illegal request" },
- { 0x06, "Unit attention (Reset or cartridge changed)" },
- { 0x07, "Data protection" },
- { 0x08, "Blank check" },
- { 0x0b, "Aborted Command" },
- { 0x0d, "Volume overflow" }
-};
-
-
-
-/***************************** Prototypes *****************************/
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
- rwflag, int enable);
-static int acsi_reqsense( char *buffer, int targ, int lun);
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip);
-static irqreturn_t acsi_interrupt (int irq, void *data);
-static void unexpected_acsi_interrupt( void );
-static void bad_rw_intr( void );
-static void read_intr( void );
-static void write_intr( void);
-static void acsi_times_out( unsigned long dummy );
-static void copy_to_acsibuffer( void );
-static void copy_from_acsibuffer( void );
-static void do_end_requests( void );
-static void do_acsi_request( request_queue_t * );
-static void redo_acsi_request( void );
-static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int
- cmd, unsigned long arg );
-static int acsi_open( struct inode * inode, struct file * filp );
-static int acsi_release( struct inode * inode, struct file * file );
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag );
-static int acsi_change_blk_size( int target, int lun);
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
-static int acsi_revalidate (struct gendisk *disk);
-
-/************************* End of Prototypes **************************/
-
-
-DEFINE_TIMER(acsi_timer, acsi_times_out, 0, 0);
-
-
-#ifdef CONFIG_ATARI_SLM
-
-extern int attach_slm( int target, int lun );
-extern int slm_init( void );
-
-#endif
-
-
-
-/***********************************************************************
- *
- * ACSI primitives
- *
- **********************************************************************/
-
-
-/*
- * The following two functions wait for _IRQ to become Low or High,
- * resp., with a timeout. The 'timeout' parameter is in jiffies
- * (10ms).
- * If the functions are called with timer interrupts on (int level <
- * 6), the timeout is based on the 'jiffies' variable to provide exact
- * timeouts for device probing etc.
- * If interrupts are disabled, the number of tries is based on the
- * 'loops_per_jiffy' variable. A rough estimation is sufficient here...
- */
-
-#define INT_LEVEL \
- ({ unsigned __sr; \
- __asm__ __volatile__ ( "movew %/sr,%0" : "=dm" (__sr) ); \
- (__sr >> 8) & 7; \
- })
-
-int acsi_wait_for_IRQ( unsigned timeout )
-
-{
- if (INT_LEVEL < 6) {
- unsigned long maxjif = jiffies + timeout;
- while (time_before(jiffies, maxjif))
- if (!(mfp.par_dt_reg & 0x20)) return( 1 );
- }
- else {
- long tries = loops_per_jiffy / 8 * timeout;
- while( --tries >= 0 )
- if (!(mfp.par_dt_reg & 0x20)) return( 1 );
- }
- return( 0 ); /* timeout! */
-}
-
-
-int acsi_wait_for_noIRQ( unsigned timeout )
-
-{
- if (INT_LEVEL < 6) {
- unsigned long maxjif = jiffies + timeout;
- while (time_before(jiffies, maxjif))
- if (mfp.par_dt_reg & 0x20) return( 1 );
- }
- else {
- long tries = loops_per_jiffy * timeout / 8;
- while( tries-- >= 0 )
- if (mfp.par_dt_reg & 0x20) return( 1 );
- }
- return( 0 ); /* timeout! */
-}
-
-static struct timeval start_time;
-
-void
-acsi_delay_start(void)
-{
- do_gettimeofday(&start_time);
-}
-
-/* wait from acsi_delay_start to now usec (<1E6) usec */
-
-void
-acsi_delay_end(long usec)
-{
- struct timeval end_time;
- long deltau,deltas;
- do_gettimeofday(&end_time);
- deltau=end_time.tv_usec - start_time.tv_usec;
- deltas=end_time.tv_sec - start_time.tv_sec;
- if (deltas > 1 || deltas < 0)
- return;
- if (deltas > 0)
- deltau += 1000*1000;
- if (deltau >= usec)
- return;
- udelay(usec-deltau);
-}
-
-/* acsicmd_dma() sends an ACSI command and sets up the DMA to transfer
- * 'blocks' blocks of 512 bytes from/to 'buffer'.
- * Because the _IRQ signal is used for handshaking the command bytes,
- * the ACSI interrupt has to be disabled in this function. If the end
- * of the operation should be signalled by a real interrupt, it has to be
- * reenabled afterwards.
- */
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, int enable)
-
-{ unsigned long flags, paddr;
- int i;
-
-#ifdef NO_WRITE
- if (rwflag || *cmd == 0x0a) {
- printk( "ACSI: Write commands disabled!\n" );
- return( 0 );
- }
-#endif
-
- rwflag = rwflag ? 0x100 : 0;
- paddr = virt_to_phys( buffer );
-
- acsi_delay_end(COMMAND_DELAY);
- DISABLE_IRQ();
-
- local_irq_save(flags);
- /* Low on A1 */
- dma_wd.dma_mode_status = 0x88 | rwflag;
- MFPDELAY();
-
- /* set DMA address */
- dma_wd.dma_lo = (unsigned char)paddr;
- paddr >>= 8;
- MFPDELAY();
- dma_wd.dma_md = (unsigned char)paddr;
- paddr >>= 8;
- MFPDELAY();
- if (ATARIHW_PRESENT(EXTD_DMA))
- st_dma_ext_dmahi = (unsigned short)paddr;
- else
- dma_wd.dma_hi = (unsigned char)paddr;
- MFPDELAY();
- local_irq_restore(flags);
-
- /* send the command bytes except the last */
- for( i = 0; i < 5; ++i ) {
- DMA_LONG_WRITE( *cmd++, 0x8a | rwflag );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
-
- /* Clear FIFO and switch DMA to correct direction */
- dma_wd.dma_mode_status = 0x92 | (rwflag ^ 0x100);
- MFPDELAY();
- dma_wd.dma_mode_status = 0x92 | rwflag;
- MFPDELAY();
-
- /* How many sectors for DMA */
- dma_wd.fdc_acces_seccount = blocks;
- MFPDELAY();
-
- /* send last command byte */
- dma_wd.dma_mode_status = 0x8a | rwflag;
- MFPDELAY();
- DMA_LONG_WRITE( *cmd++, 0x0a | rwflag );
- if (enable)
- ENABLE_IRQ();
- udelay(80);
-
- return( 1 );
-}
-
-
-/*
- * acsicmd_nodma() sends an ACSI command that requires no DMA.
- */
-
-int acsicmd_nodma( const char *cmd, int enable)
-
-{ int i;
-
- acsi_delay_end(COMMAND_DELAY);
- DISABLE_IRQ();
-
- /* send first command byte */
- dma_wd.dma_mode_status = 0x88;
- MFPDELAY();
- DMA_LONG_WRITE( *cmd++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-
- /* send the intermediate command bytes */
- for( i = 0; i < 4; ++i ) {
- DMA_LONG_WRITE( *cmd++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
-
- /* send last command byte */
- DMA_LONG_WRITE( *cmd++, 0x0a );
- if (enable)
- ENABLE_IRQ();
- udelay(80);
-
- return( 1 );
- /* Note that the ACSI interrupt is still disabled after this
- * function. If you want to get the IRQ delivered, enable it manually!
- */
-}
-
-
-static int acsi_reqsense( char *buffer, int targ, int lun)
-
-{
- CMDSET_TARG_LUN( reqsense_cmd, targ, lun);
- if (!acsicmd_dma( reqsense_cmd, buffer, 1, 0, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- dma_cache_maintenance( virt_to_phys(buffer), 16, 0 );
-
- return( 1 );
-}
-
-
-/*
- * ACSI status phase: get the status byte from the bus
- *
- * I've seen several times that a 0xff status is read, propably due to
- * a timing error. In this case, the procedure is repeated after the
- * next _IRQ edge.
- */
-
-int acsi_getstatus( void )
-
-{ int status;
-
- DISABLE_IRQ();
- for(;;) {
- if (!acsi_wait_for_IRQ( 100 )) {
- acsi_delay_start();
- return( -1 );
- }
- dma_wd.dma_mode_status = 0x8a;
- MFPDELAY();
- status = dma_wd.fdc_acces_seccount;
- if (status != 0xff) break;
-#ifdef DEBUG
- printk("ACSI: skipping 0xff status byte\n" );
-#endif
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
- }
- dma_wd.dma_mode_status = 0x80;
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
-
- acsi_delay_start();
- return( status & 0x1f ); /* mask of the device# */
-}
-
-
-#if (defined(CONFIG_ATARI_SLM) || defined(CONFIG_ATARI_SLM_MODULE))
-
-/* Receive data in an extended status phase. Needed by SLM printer. */
-
-int acsi_extstatus( char *buffer, int cnt )
-
-{ int status;
-
- DISABLE_IRQ();
- udelay(80);
- while( cnt-- > 0 ) {
- if (!acsi_wait_for_IRQ( 40 )) return( 0 );
- dma_wd.dma_mode_status = 0x8a;
- MFPDELAY();
- status = dma_wd.fdc_acces_seccount;
- MFPDELAY();
- *buffer++ = status & 0xff;
- udelay(40);
- }
- return( 1 );
-}
-
-
-/* Finish an extended status phase */
-
-void acsi_end_extstatus( void )
-
-{
- dma_wd.dma_mode_status = 0x80;
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
- acsi_delay_start();
-}
-
-
-/* Send data in an extended command phase */
-
-int acsi_extcmd( unsigned char *buffer, int cnt )
-
-{
- while( cnt-- > 0 ) {
- DMA_LONG_WRITE( *buffer++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
- return( 1 );
-}
-
-#endif
-
-
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip)
-
-{ int atari_err, i, errcode;
- struct acsi_error *arr;
-
- atari_err = aip->old_atari_disk;
- if (atari_err)
- errcode = errblk[0] & 0x7f;
- else
- if ((errblk[0] & 0x70) == 0x70)
- errcode = errblk[2] & 0x0f;
- else
- errcode = errblk[0] & 0x0f;
-
- printk( KERN_ERR "ACSI error 0x%02x", errcode );
-
- if (errblk[0] & 0x80)
- printk( " for sector %d",
- ((errblk[1] & 0x1f) << 16) |
- (errblk[2] << 8) | errblk[0] );
-
- arr = atari_err ? atari_acsi_errors : scsi_acsi_errors;
- i = atari_err ? sizeof(atari_acsi_errors)/sizeof(*atari_acsi_errors) :
- sizeof(scsi_acsi_errors)/sizeof(*scsi_acsi_errors);
-
- for( --i; i >= 0; --i )
- if (arr[i].code == errcode) break;
- if (i >= 0)
- printk( ": %s\n", arr[i].text );
-}
-
-/*******************************************************************
- *
- * ACSI interrupt routine
- * Test, if this is a ACSI interrupt and call the irq handler
- * Otherwise ignore this interrupt.
- *
- *******************************************************************/
-
-static irqreturn_t acsi_interrupt(int irq, void *data )
-
-{ void (*acsi_irq_handler)(void) = do_acsi;
-
- do_acsi = NULL;
- CLEAR_TIMER();
-
- if (!acsi_irq_handler)
- acsi_irq_handler = unexpected_acsi_interrupt;
- acsi_irq_handler();
- return IRQ_HANDLED;
-}
-
-
-/******************************************************************
- *
- * The Interrupt handlers
- *
- *******************************************************************/
-
-
-static void unexpected_acsi_interrupt( void )
-
-{
- printk( KERN_WARNING "Unexpected ACSI interrupt\n" );
-}
-
-
-/* This function is called in case of errors. Because we cannot reset
- * the ACSI bus or a single device, there is no other choice than
- * retrying several times :-(
- */
-
-static void bad_rw_intr( void )
-
-{
- if (!CURRENT)
- return;
-
- if (++CURRENT->errors >= MAX_ERRORS)
- end_request(CURRENT, 0);
- /* Otherwise just retry */
-}
-
-
-static void read_intr( void )
-
-{ int status;
-
- status = acsi_getstatus();
- if (status != 0) {
- struct gendisk *disk = CURRENT->rq_disk;
- struct acsi_info_struct *aip = disk->private_data;
- printk(KERN_ERR "%s: ", disk->disk_name);
- if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun))
- printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
- else {
- acsi_print_error(acsi_buffer, aip);
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- ENABLE_IRQ();
- bad_rw_intr();
- redo_acsi_request();
- return;
- }
-
- dma_cache_maintenance( virt_to_phys(CurrentBuffer), CurrentNSect*512, 0 );
- if (CurrentBuffer == acsi_buffer)
- copy_from_acsibuffer();
-
- do_end_requests();
- redo_acsi_request();
-}
-
-
-static void write_intr(void)
-
-{ int status;
-
- status = acsi_getstatus();
- if (status != 0) {
- struct gendisk *disk = CURRENT->rq_disk;
- struct acsi_info_struct *aip = disk->private_data;
- printk( KERN_ERR "%s: ", disk->disk_name);
- if (!acsi_reqsense( acsi_buffer, aip->target, aip->lun))
- printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
- else {
- acsi_print_error(acsi_buffer, aip);
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- bad_rw_intr();
- redo_acsi_request();
- return;
- }
-
- do_end_requests();
- redo_acsi_request();
-}
-
-
-static void acsi_times_out( unsigned long dummy )
-
-{
- DISABLE_IRQ();
- if (!do_acsi) return;
-
- do_acsi = NULL;
- printk( KERN_ERR "ACSI timeout\n" );
- if (!CURRENT)
- return;
- if (++CURRENT->errors >= MAX_ERRORS) {
-#ifdef DEBUG
- printk( KERN_ERR "ACSI: too many errors.\n" );
-#endif
- end_request(CURRENT, 0);
- }
-
- redo_acsi_request();
-}
-
-
-
-/***********************************************************************
- *
- * Scatter-gather utility functions
- *
- ***********************************************************************/
-
-
-static void copy_to_acsibuffer( void )
-
-{ int i;
- char *src, *dst;
- struct buffer_head *bh;
-
- src = CURRENT->buffer;
- dst = acsi_buffer;
- bh = CURRENT->bh;
-
- if (!bh)
- memcpy( dst, src, CurrentNSect*512 );
- else
- for( i = 0; i < CurrentNReq; ++i ) {
- memcpy( dst, src, bh->b_size );
- dst += bh->b_size;
- if ((bh = bh->b_reqnext))
- src = bh->b_data;
- }
-}
-
-
-static void copy_from_acsibuffer( void )
-
-{ int i;
- char *src, *dst;
- struct buffer_head *bh;
-
- dst = CURRENT->buffer;
- src = acsi_buffer;
- bh = CURRENT->bh;
-
- if (!bh)
- memcpy( dst, src, CurrentNSect*512 );
- else
- for( i = 0; i < CurrentNReq; ++i ) {
- memcpy( dst, src, bh->b_size );
- src += bh->b_size;
- if ((bh = bh->b_reqnext))
- dst = bh->b_data;
- }
-}
-
-
-static void do_end_requests( void )
-
-{ int i, n;
-
- if (!CURRENT->bh) {
- CURRENT->nr_sectors -= CurrentNSect;
- CURRENT->current_nr_sectors -= CurrentNSect;
- CURRENT->sector += CurrentNSect;
- if (CURRENT->nr_sectors == 0)
- end_request(CURRENT, 1);
- }
- else {
- for( i = 0; i < CurrentNReq; ++i ) {
- n = CURRENT->bh->b_size >> 9;
- CURRENT->nr_sectors -= n;
- CURRENT->current_nr_sectors -= n;
- CURRENT->sector += n;
- end_request(CURRENT, 1);
- }
- }
-}
-
-
-
-
-/***********************************************************************
- *
- * do_acsi_request and friends
- *
- ***********************************************************************/
-
-static void do_acsi_request( request_queue_t * q )
-
-{
- stdma_lock( acsi_interrupt, NULL );
- redo_acsi_request();
-}
-
-
-static void redo_acsi_request( void )
-{
- unsigned block, target, lun, nsect;
- char *buffer;
- unsigned long pbuffer;
- struct buffer_head *bh;
- struct gendisk *disk;
- struct acsi_info_struct *aip;
-
- repeat:
- CLEAR_TIMER();
-
- if (do_acsi)
- return;
-
- if (!CURRENT) {
- do_acsi = NULL;
- ENABLE_IRQ();
- stdma_release();
- return;
- }
-
- disk = CURRENT->rq_disk;
- aip = disk->private_data;
- if (CURRENT->bh) {
- if (!CURRENT->bh && !buffer_locked(CURRENT->bh))
- panic("ACSI: block not locked");
- }
-
- block = CURRENT->sector;
- if (block+CURRENT->nr_sectors >= get_capacity(disk)) {
-#ifdef DEBUG
- printk( "%s: attempted access for blocks %d...%ld past end of device at block %ld.\n",
- disk->disk_name,
- block, block + CURRENT->nr_sectors - 1,
- get_capacity(disk));
-#endif
- end_request(CURRENT, 0);
- goto repeat;
- }
- if (aip->changed) {
- printk( KERN_NOTICE "%s: request denied because cartridge has "
- "been changed.\n", disk->disk_name);
- end_request(CURRENT, 0);
- goto repeat;
- }
-
- target = aip->target;
- lun = aip->lun;
-
- /* Find out how many sectors should be transferred from/to
- * consecutive buffers and thus can be done with a single command.
- */
- buffer = CURRENT->buffer;
- pbuffer = virt_to_phys(buffer);
- nsect = CURRENT->current_nr_sectors;
- CurrentNReq = 1;
-
- if ((bh = CURRENT->bh) && bh != CURRENT->bhtail) {
- if (!STRAM_ADDR(pbuffer)) {
- /* If transfer is done via the ACSI buffer anyway, we can
- * assemble as much bh's as fit in the buffer.
- */
- while( (bh = bh->b_reqnext) ) {
- if (nsect + (bh->b_size>>9) > ACSI_BUFFER_SECTORS) break;
- nsect += bh->b_size >> 9;
- ++CurrentNReq;
- if (bh == CURRENT->bhtail) break;
- }
- buffer = acsi_buffer;
- pbuffer = phys_acsi_buffer;
- }
- else {
- unsigned long pendadr, pnewadr;
- pendadr = pbuffer + nsect*512;
- while( (bh = bh->b_reqnext) ) {
- pnewadr = virt_to_phys(bh->b_data);
- if (!STRAM_ADDR(pnewadr) || pendadr != pnewadr) break;
- nsect += bh->b_size >> 9;
- pendadr = pnewadr + bh->b_size;
- ++CurrentNReq;
- if (bh == CURRENT->bhtail) break;
- }
- }
- }
- else {
- if (!STRAM_ADDR(pbuffer)) {
- buffer = acsi_buffer;
- pbuffer = phys_acsi_buffer;
- if (nsect > ACSI_BUFFER_SECTORS)
- nsect = ACSI_BUFFER_SECTORS;
- }
- }
- CurrentBuffer = buffer;
- CurrentNSect = nsect;
-
- if (rq_data_dir(CURRENT) == WRITE) {
- CMDSET_TARG_LUN( write_cmd, target, lun );
- CMDSET_BLOCK( write_cmd, block );
- CMDSET_LEN( write_cmd, nsect );
- if (buffer == acsi_buffer)
- copy_to_acsibuffer();
- dma_cache_maintenance( pbuffer, nsect*512, 1 );
- do_acsi = write_intr;
- if (!acsicmd_dma( write_cmd, buffer, nsect, 1, 1)) {
- do_acsi = NULL;
- printk( KERN_ERR "ACSI (write): Timeout in command block\n" );
- bad_rw_intr();
- goto repeat;
- }
- SET_TIMER();
- return;
- }
- if (rq_data_dir(CURRENT) == READ) {
- CMDSET_TARG_LUN( read_cmd, target, lun );
- CMDSET_BLOCK( read_cmd, block );
- CMDSET_LEN( read_cmd, nsect );
- do_acsi = read_intr;
- if (!acsicmd_dma( read_cmd, buffer, nsect, 0, 1)) {
- do_acsi = NULL;
- printk( KERN_ERR "ACSI (read): Timeout in command block\n" );
- bad_rw_intr();
- goto repeat;
- }
- SET_TIMER();
- return;
- }
- panic("unknown ACSI command");
-}
-
-
-
-/***********************************************************************
- *
- * Misc functions: ioctl, open, release, check_change, ...
- *
- ***********************************************************************/
-
-static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- struct acsi_info_struct *aip = bdev->bd_disk->private_data;
-
- /*
- * Just fake some geometry here, it's nonsense anyway
- * To make it easy, use Adaptec's usual 64/32 mapping
- */
- geo->heads = 64;
- geo->sectors = 32;
- geo->cylinders = aip->size >> 11;
- return 0;
-}
-
-static int acsi_ioctl( struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
- switch (cmd) {
- case SCSI_IOCTL_GET_IDLUN:
- /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
- put_user( aip->target | (aip->lun << 8),
- &((Scsi_Idlun *) arg)->dev_id );
- put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-
-/*
- * Open a device, check for read-only and lock the medium if it is
- * removable.
- *
- * Changes by Martin Rogge, 9th Aug 1995:
- * Check whether check_disk_change (and therefore revalidate_acsidisk)
- * was successful. They fail when there is no medium in the drive.
- *
- * The problem of media being changed during an operation can be
- * ignored because of the prevent_removal code.
- *
- * Added check for the validity of the device number.
- *
- */
-
-static int acsi_open( struct inode * inode, struct file * filp )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
-
- if (aip->access_count == 0 && aip->removable) {
-#if 0
- aip->changed = 1; /* safety first */
-#endif
- check_disk_change( inode->i_bdev );
- if (aip->changed) /* revalidate was not successful (no medium) */
- return -ENXIO;
- acsi_prevent_removal(aip, 1);
- }
- aip->access_count++;
-
- if (filp && filp->f_mode) {
- check_disk_change( inode->i_bdev );
- if (filp->f_mode & 2) {
- if (aip->read_only) {
- acsi_release( inode, filp );
- return -EROFS;
- }
- }
- }
-
- return 0;
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-
-static int acsi_release( struct inode * inode, struct file * file )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
- if (--aip->access_count == 0 && aip->removable)
- acsi_prevent_removal(aip, 0);
- return( 0 );
-}
-
-/*
- * Prevent or allow a media change for removable devices.
- */
-
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag)
-{
- stdma_lock( NULL, NULL );
-
- CMDSET_TARG_LUN(pa_med_rem_cmd, aip->target, aip->lun);
- CMDSET_LEN( pa_med_rem_cmd, flag );
-
- if (acsicmd_nodma(pa_med_rem_cmd, 0) && acsi_wait_for_IRQ(3*HZ))
- acsi_getstatus();
- /* Do not report errors -- some devices may not know this command. */
-
- ENABLE_IRQ();
- stdma_release();
-}
-
-static int acsi_media_change(struct gendisk *disk)
-{
- struct acsi_info_struct *aip = disk->private_data;
-
- if (!aip->removable)
- return 0;
-
- if (aip->changed)
- /* We can be sure that the medium has been changed -- REQUEST
- * SENSE has reported this earlier.
- */
- return 1;
-
- /* If the flag isn't set, make a test by reading block 0.
- * If errors happen, it seems to be better to say "changed"...
- */
- stdma_lock( NULL, NULL );
- CMDSET_TARG_LUN(read_cmd, aip->target, aip->lun);
- CMDSET_BLOCK( read_cmd, 0 );
- CMDSET_LEN( read_cmd, 1 );
- if (acsicmd_dma(read_cmd, acsi_buffer, 1, 0, 0) &&
- acsi_wait_for_IRQ(3*HZ)) {
- if (acsi_getstatus()) {
- if (acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- else {
- printk( KERN_ERR "%s: REQUEST SENSE failed in test for "
- "medium change; assuming a change\n", disk->disk_name );
- aip->changed = 1;
- }
- }
- }
- else {
- printk( KERN_ERR "%s: Test for medium changed timed out; "
- "assuming a change\n", disk->disk_name);
- aip->changed = 1;
- }
- ENABLE_IRQ();
- stdma_release();
-
- /* Now, after reading a block, the changed status is surely valid. */
- return aip->changed;
-}
-
-
-static int acsi_change_blk_size( int target, int lun)
-
-{ int i;
-
- for (i=0; i<12; i++)
- acsi_buffer[i] = 0;
-
- acsi_buffer[3] = 8;
- acsi_buffer[10] = 2;
- CMDSET_TARG_LUN( modeselect_cmd, target, lun);
-
- if (!acsicmd_dma( modeselect_cmd, acsi_buffer, 1,1,0) ||
- !acsi_wait_for_IRQ( 3*HZ ) ||
- acsi_getstatus() != 0 ) {
- return(0);
- }
- return(1);
-}
-
-
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd )
-
-{
- int page;
-
- CMDSET_TARG_LUN( modesense_cmd, target, lun );
- for (page=0; page<4; page++) {
- modesense_cmd[2] = page;
- if (!acsicmd_dma( modesense_cmd, acsi_buffer, 1, 0, 0 ) ||
- !acsi_wait_for_IRQ( 3*HZ ) ||
- acsi_getstatus())
- continue;
-
- /* read twice to jump over the second 16-byte border! */
- udelay(300);
- if (acsi_wait_for_noIRQ( 20 ) &&
- acsicmd_nodma( modesense_cmd, 0 ) &&
- acsi_wait_for_IRQ( 3*HZ ) &&
- acsi_getstatus() == 0)
- break;
- }
- if (page == 4) {
- return(0);
- }
-
- dma_cache_maintenance( phys_acsi_buffer, sizeof(SENSE_DATA), 0 );
- *sd = *(SENSE_DATA *)acsi_buffer;
-
- /* Validity check, depending on type of data */
-
- switch( SENSE_TYPE(*sd) ) {
-
- case SENSE_TYPE_ATARI:
- if (CAPACITY(*sd) == 0)
- goto invalid_sense;
- break;
-
- case SENSE_TYPE_SCSI:
- if (sd->scsi.descriptor_size != 8)
- goto invalid_sense;
- break;
-
- case SENSE_TYPE_UNKNOWN:
-
- printk( KERN_ERR "ACSI target %d, lun %d: Cannot interpret "
- "sense data\n", target, lun );
-
- invalid_sense:
-
-#ifdef DEBUG
- { int i;
- printk( "Mode sense data for ACSI target %d, lun %d seem not valid:",
- target, lun );
- for( i = 0; i < sizeof(SENSE_DATA); ++i )
- printk( "%02x ", (unsigned char)acsi_buffer[i] );
- printk( "\n" );
- }
-#endif
- return( 0 );
- }
-
- return( 1 );
-}
-
-
-
-/*******************************************************************
- *
- * Initialization
- *
- ********************************************************************/
-
-
-extern struct block_device_operations acsi_fops;
-
-static struct gendisk *acsi_gendisk[MAX_DEV];
-
-#define MAX_SCSI_DEVICE_CODE 10
-
-static const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
-{
- "Direct-Access ",
- "Sequential-Access",
- "Printer ",
- "Processor ",
- "WORM ",
- "CD-ROM ",
- "Scanner ",
- "Optical Device ",
- "Medium Changer ",
- "Communications "
-};
-
-static void print_inquiry(unsigned char *data)
-{
- int i;
-
- printk(KERN_INFO " Vendor: ");
- for (i = 8; i < 16; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk(" Model: ");
- for (i = 16; i < 32; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk(" Rev: ");
- for (i = 32; i < 36; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk("\n");
-
- i = data[0] & 0x1f;
-
- printk(KERN_INFO " Type: %s ", (i < MAX_SCSI_DEVICE_CODE
- ? scsi_device_types[i]
- : "Unknown "));
- printk(" ANSI SCSI revision: %02x", data[2] & 0x07);
- if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
- printk(" CCS\n");
- else
- printk("\n");
-}
-
-
-/*
- * Changes by Martin Rogge, 9th Aug 1995:
- * acsi_devinit has been taken out of acsi_geninit, because it needs
- * to be called from revalidate_acsidisk. The result of request sense
- * is now checked for DRIVE NOT READY.
- *
- * The structure *aip is only valid when acsi_devinit returns
- * DEV_SUPPORTED.
- *
- */
-
-#define DEV_NONE 0
-#define DEV_UNKNOWN 1
-#define DEV_SUPPORTED 2
-#define DEV_SLM 3
-
-static int acsi_devinit(struct acsi_info_struct *aip)
-{
- int status, got_inquiry;
- SENSE_DATA sense;
- unsigned char reqsense, extsense;
-
- /*****************************************************************/
- /* Do a TEST UNIT READY command to test the presence of a device */
- /*****************************************************************/
-
- CMDSET_TARG_LUN(tur_cmd, aip->target, aip->lun);
- if (!acsicmd_nodma(tur_cmd, 0)) {
- /* timed out -> no device here */
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: timeout\n", aip->target, aip->lun);
-#endif
- return DEV_NONE;
- }
-
- /*************************/
- /* Read the ACSI status. */
- /*************************/
-
- status = acsi_getstatus();
- if (status) {
- if (status == 0x12) {
- /* The SLM printer should be the only device that
- * responds with the error code in the status byte. In
- * correct status bytes, bit 4 is never set.
- */
- printk( KERN_INFO "Detected SLM printer at id %d lun %d\n",
- aip->target, aip->lun);
- return DEV_SLM;
- }
- /* ignore CHECK CONDITION, since some devices send a
- UNIT ATTENTION */
- if ((status & 0x1e) != 0x2) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: status %d\n",
- aip->target, aip->lun, status);
-#endif
- return DEV_UNKNOWN;
- }
- }
-
- /*******************************/
- /* Do a REQUEST SENSE command. */
- /*******************************/
-
- if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
- printk( KERN_WARNING "acsi_reqsense failed\n");
- acsi_buffer[0] = 0;
- acsi_buffer[2] = UNIT_ATTENTION;
- }
- reqsense = acsi_buffer[0];
- extsense = acsi_buffer[2] & 0xf;
- if (status) {
- if ((reqsense & 0x70) == 0x70) { /* extended sense */
- if (extsense != UNIT_ATTENTION &&
- extsense != NOT_READY) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: extended sense %d\n",
- aip->target, aip->lun, extsense);
-#endif
- return DEV_UNKNOWN;
- }
- }
- else {
- if (reqsense & 0x7f) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: sense %d\n",
- aip->target, aip->lun, reqsense);
-#endif
- return DEV_UNKNOWN;
- }
- }
- }
- else
- if (reqsense == 0x4) { /* SH204 Bug workaround */
-#ifdef DEBUG_DETECT
- printk("target %d lun %d status=0 sense=4\n",
- aip->target, aip->lun);
-#endif
- return DEV_UNKNOWN;
- }
-
- /***********************************************************/
- /* Do an INQUIRY command to get more infos on this device. */
- /***********************************************************/
-
- /* Assume default values */
- aip->removable = 1;
- aip->read_only = 0;
- aip->old_atari_disk = 0;
- aip->changed = (extsense == NOT_READY); /* medium inserted? */
- aip->size = DEFAULT_SIZE;
- got_inquiry = 0;
- /* Fake inquiry result for old atari disks */
- memcpy(acsi_buffer, "\000\000\001\000 Adaptec 40xx"
- " ", 40);
- CMDSET_TARG_LUN(inquiry_cmd, aip->target, aip->lun);
- if (acsicmd_dma(inquiry_cmd, acsi_buffer, 1, 0, 0) &&
- acsi_getstatus() == 0) {
- acsicmd_nodma(inquiry_cmd, 0);
- acsi_getstatus();
- dma_cache_maintenance( phys_acsi_buffer, 256, 0 );
- got_inquiry = 1;
- aip->removable = !!(acsi_buffer[1] & 0x80);
- }
- if (aip->type == NONE) /* only at boot time */
- print_inquiry(acsi_buffer);
- switch(acsi_buffer[0]) {
- case TYPE_DISK:
- aip->type = HARDDISK;
- break;
- case TYPE_ROM:
- aip->type = CDROM;
- aip->read_only = 1;
- break;
- default:
- return DEV_UNKNOWN;
- }
- /****************************/
- /* Do a MODE SENSE command. */
- /****************************/
-
- if (!acsi_mode_sense(aip->target, aip->lun, &sense)) {
- printk( KERN_WARNING "No mode sense data.\n" );
- return DEV_UNKNOWN;
- }
- if ((SECTOR_SIZE(sense) != 512) &&
- ((aip->type != CDROM) ||
- !acsi_change_blk_size(aip->target, aip->lun) ||
- !acsi_mode_sense(aip->target, aip->lun, &sense) ||
- (SECTOR_SIZE(sense) != 512))) {
- printk( KERN_WARNING "Sector size != 512 not supported.\n" );
- return DEV_UNKNOWN;
- }
- /* There are disks out there that claim to have 0 sectors... */
- if (CAPACITY(sense))
- aip->size = CAPACITY(sense); /* else keep DEFAULT_SIZE */
- if (!got_inquiry && SENSE_TYPE(sense) == SENSE_TYPE_ATARI) {
- /* If INQUIRY failed and the sense data suggest an old
- * Atari disk (SH20x, Megafile), the disk is not removable
- */
- aip->removable = 0;
- aip->old_atari_disk = 1;
- }
-
- /******************/
- /* We've done it. */
- /******************/
-
- return DEV_SUPPORTED;
-}
-
-EXPORT_SYMBOL(acsi_delay_start);
-EXPORT_SYMBOL(acsi_delay_end);
-EXPORT_SYMBOL(acsi_wait_for_IRQ);
-EXPORT_SYMBOL(acsi_wait_for_noIRQ);
-EXPORT_SYMBOL(acsicmd_nodma);
-EXPORT_SYMBOL(acsi_getstatus);
-EXPORT_SYMBOL(acsi_buffer);
-EXPORT_SYMBOL(phys_acsi_buffer);
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-
-EXPORT_SYMBOL(acsi_extstatus);
-EXPORT_SYMBOL(acsi_end_extstatus);
-EXPORT_SYMBOL(acsi_extcmd);
-EXPORT_SYMBOL(acsi_attach_SLMs);
-
-/* to remember IDs of SLM devices, SLM module is loaded later
- * (index is target#, contents is lun#, -1 means "no SLM") */
-int SLM_devices[8];
-#endif
-
-static struct block_device_operations acsi_fops = {
- .owner = THIS_MODULE,
- .open = acsi_open,
- .release = acsi_release,
- .ioctl = acsi_ioctl,
- .getgeo = acsi_getgeo,
- .media_changed = acsi_media_change,
- .revalidate_disk= acsi_revalidate,
-};
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-/* call attach_slm() for each device that is a printer; needed for init of SLM
- * driver as a module, since it's not yet present if acsi.c is inited and thus
- * the bus gets scanned. */
-void acsi_attach_SLMs( int (*attach_func)( int, int ) )
-{
- int i, n = 0;
-
- for( i = 0; i < 8; ++i )
- if (SLM_devices[i] >= 0)
- n += (*attach_func)( i, SLM_devices[i] );
- printk( KERN_INFO "Found %d SLM printer(s) total.\n", n );
-}
-#endif /* CONFIG_ATARI_SLM_MODULE */
-
-
-int acsi_init( void )
-{
- int err = 0;
- int i, target, lun;
- struct acsi_info_struct *aip;
-#ifdef CONFIG_ATARI_SLM
- int n_slm = 0;
-#endif
- if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
- return 0;
- if (register_blkdev(ACSI_MAJOR, "ad")) {
- err = -EBUSY;
- goto out1;
- }
- if (!(acsi_buffer =
- (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) {
- err = -ENOMEM;
- printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );
- goto out2;
- }
- phys_acsi_buffer = virt_to_phys( acsi_buffer );
- STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
-
- acsi_queue = blk_init_queue(do_acsi_request, &acsi_lock);
- if (!acsi_queue) {
- err = -ENOMEM;
- goto out2a;
- }
-#ifdef CONFIG_ATARI_SLM
- err = slm_init();
-#endif
- if (err)
- goto out3;
-
- printk( KERN_INFO "Probing ACSI devices:\n" );
- NDevices = 0;
-#ifdef CONFIG_ATARI_SLM_MODULE
- for( i = 0; i < 8; ++i )
- SLM_devices[i] = -1;
-#endif
- stdma_lock(NULL, NULL);
-
- for (target = 0; target < 8 && NDevices < MAX_DEV; ++target) {
- lun = 0;
- do {
- aip = &acsi_info[NDevices];
- aip->type = NONE;
- aip->target = target;
- aip->lun = lun;
- i = acsi_devinit(aip);
- switch (i) {
- case DEV_SUPPORTED:
- printk( KERN_INFO "Detected ");
- switch (aip->type) {
- case HARDDISK:
- printk("disk");
- break;
- case CDROM:
- printk("cdrom");
- break;
- default:
- }
- printk(" ad%c at id %d lun %d ",
- 'a' + NDevices, target, lun);
- if (aip->removable)
- printk("(removable) ");
- if (aip->read_only)
- printk("(read-only) ");
- if (aip->size == DEFAULT_SIZE)
- printk(" unkown size, using default ");
- printk("%ld MByte\n",
- (aip->size*512+1024*1024/2)/(1024*1024));
- NDevices++;
- break;
- case DEV_SLM:
-#ifdef CONFIG_ATARI_SLM
- n_slm += attach_slm( target, lun );
- break;
-#endif
-#ifdef CONFIG_ATARI_SLM_MODULE
- SLM_devices[target] = lun;
- break;
-#endif
- /* neither of the above: fall through to unknown device */
- case DEV_UNKNOWN:
- printk( KERN_INFO "Detected unsupported device at "
- "id %d lun %d\n", target, lun);
- break;
- }
- }
-#ifdef CONFIG_ACSI_MULTI_LUN
- while (i != DEV_NONE && ++lun < MAX_LUN);
-#else
- while (0);
-#endif
- }
-
- /* reenable interrupt */
- ENABLE_IRQ();
- stdma_release();
-
-#ifndef CONFIG_ATARI_SLM
- printk( KERN_INFO "Found %d ACSI device(s) total.\n", NDevices );
-#else
- printk( KERN_INFO "Found %d ACSI device(s) and %d SLM printer(s) total.\n",
- NDevices, n_slm );
-#endif
- err = -ENOMEM;
- for( i = 0; i < NDevices; ++i ) {
- acsi_gendisk[i] = alloc_disk(16);
- if (!acsi_gendisk[i])
- goto out4;
- }
-
- for( i = 0; i < NDevices; ++i ) {
- struct gendisk *disk = acsi_gendisk[i];
- sprintf(disk->disk_name, "ad%c", 'a'+i);
- aip = &acsi_info[NDevices];
- disk->major = ACSI_MAJOR;
- disk->first_minor = i << 4;
- if (acsi_info[i].type != HARDDISK)
- disk->minors = 1;
- disk->fops = &acsi_fops;
- disk->private_data = &acsi_info[i];
- set_capacity(disk, acsi_info[i].size);
- disk->queue = acsi_queue;
- add_disk(disk);
- }
- return 0;
-out4:
- while (i--)
- put_disk(acsi_gendisk[i]);
-out3:
- blk_cleanup_queue(acsi_queue);
-out2a:
- atari_stram_free( acsi_buffer );
-out2:
- unregister_blkdev( ACSI_MAJOR, "ad" );
-out1:
- return err;
-}
-
-
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
- int err;
-
- if ((err = acsi_init()))
- return( err );
- printk( KERN_INFO "ACSI driver loaded as module.\n");
- return( 0 );
-}
-
-void cleanup_module(void)
-{
- int i;
- del_timer( &acsi_timer );
- blk_cleanup_queue(acsi_queue);
- atari_stram_free( acsi_buffer );
-
- if (unregister_blkdev( ACSI_MAJOR, "ad" ) != 0)
- printk( KERN_ERR "acsi: cleanup_module failed\n");
-
- for (i = 0; i < NDevices; i++) {
- del_gendisk(acsi_gendisk[i]);
- put_disk(acsi_gendisk[i]);
- }
-}
-#endif
-
-/*
- * This routine is called to flush all partitions and partition tables
- * for a changed scsi disk, and then re-read the new partition table.
- * If we are revalidating a disk because of a media change, then we
- * enter with usage == 0. If we are using an ioctl, we automatically have
- * usage == 1 (we need an open channel to use an ioctl :-), so this
- * is our limit.
- *
- * Changes by Martin Rogge, 9th Aug 1995:
- * got cd-roms to work by calling acsi_devinit. There are only two problems:
- * First, if there is no medium inserted, the status will remain "changed".
- * That is no problem at all, but our design of three-valued logic (medium
- * changed, medium not changed, no medium inserted).
- * Secondly the check could fail completely and the drive could deliver
- * nonsensical data, which could mess up the acsi_info[] structure. In
- * that case we try to make the entry safe.
- *
- */
-
-static int acsi_revalidate(struct gendisk *disk)
-{
- struct acsi_info_struct *aip = disk->private_data;
- stdma_lock( NULL, NULL );
- if (acsi_devinit(aip) != DEV_SUPPORTED) {
- printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",
- aip->target, aip->lun);
- aip->size = 0;
- aip->read_only = 1;
- aip->removable = 1;
- aip->changed = 1; /* next acsi_open will try again... */
- }
-
- ENABLE_IRQ();
- stdma_release();
- set_capacity(disk, aip->size);
- return 0;
-}
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 27a139025ced..6ce8b897e262 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1363,7 +1363,7 @@ static void redo_fd_request(void)
#ifdef DEBUG
printk("fd: sector %ld + %d requested for %s\n",
CURRENT->sector,cnt,
- (CURRENT->cmd==READ)?"read":"write");
+ (rq_data_dir(CURRENT) == READ) ? "read" : "write");
#endif
block = CURRENT->sector + cnt;
if ((int)block > floppy->blocks) {
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5acc6c44aead..0fcad430474e 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -87,6 +87,7 @@ static const struct pci_device_id cciss_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D},
{PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
{0,}
@@ -119,6 +120,7 @@ static struct board_type products[] = {
{0x3214103C, "Smart Array E200i", &SA5_access, 120},
{0x3215103C, "Smart Array E200i", &SA5_access, 120},
{0x3237103C, "Smart Array E500", &SA5_access, 512},
+ {0x323D103C, "Smart Array P700m", &SA5_access, 512},
{0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
};
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0ed5470d2533..4503290da407 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -74,6 +74,7 @@
#include <linux/highmem.h>
#include <linux/gfp.h>
#include <linux/kthread.h>
+#include <linux/splice.h>
#include <asm/uaccess.h>
@@ -401,50 +402,73 @@ struct lo_read_data {
};
static int
-lo_read_actor(read_descriptor_t *desc, struct page *page,
- unsigned long offset, unsigned long size)
+lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
{
- unsigned long count = desc->count;
- struct lo_read_data *p = desc->arg.data;
+ struct lo_read_data *p = sd->u.data;
struct loop_device *lo = p->lo;
+ struct page *page = buf->page;
sector_t IV;
+ size_t size;
+ int ret;
- IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
+ ret = buf->ops->confirm(pipe, buf);
+ if (unlikely(ret))
+ return ret;
- if (size > count)
- size = count;
+ IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
+ (buf->offset >> 9);
+ size = sd->len;
+ if (size > p->bsize)
+ size = p->bsize;
- if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) {
- size = 0;
+ if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) {
printk(KERN_ERR "loop: transfer error block %ld\n",
page->index);
- desc->error = -EINVAL;
+ size = -EINVAL;
}
flush_dcache_page(p->page);
- desc->count = count - size;
- desc->written += size;
- p->offset += size;
+ if (size > 0)
+ p->offset += size;
+
return size;
}
static int
+lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+ return __splice_from_pipe(pipe, sd, lo_splice_actor);
+}
+
+static int
do_lo_receive(struct loop_device *lo,
struct bio_vec *bvec, int bsize, loff_t pos)
{
struct lo_read_data cookie;
+ struct splice_desc sd;
struct file *file;
- int retval;
+ long retval;
cookie.lo = lo;
cookie.page = bvec->bv_page;
cookie.offset = bvec->bv_offset;
cookie.bsize = bsize;
+
+ sd.len = 0;
+ sd.total_len = bvec->bv_len;
+ sd.flags = 0;
+ sd.pos = pos;
+ sd.u.data = &cookie;
+
file = lo->lo_backing_file;
- retval = file->f_op->sendfile(file, &pos, bvec->bv_len,
- lo_read_actor, &cookie);
- return (retval < 0)? retval: 0;
+ retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
+
+ if (retval < 0)
+ return retval;
+
+ return 0;
}
static int
@@ -679,8 +703,8 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file,
if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
goto out_putf;
- /* new backing store needs to support loop (eg sendfile) */
- if (!inode->i_fop->sendfile)
+ /* new backing store needs to support loop (eg splice_read) */
+ if (!inode->i_fop->splice_read)
goto out_putf;
/* size of the new backing store needs to be the same */
@@ -760,7 +784,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
* If we can't read - sorry. If we only can't write - well,
* it's going to be read-only.
*/
- if (!file->f_op->sendfile)
+ if (!file->f_op->splice_read)
goto out_putf;
if (aops->prepare_write && aops->commit_write)
lo_flags |= LO_FLAGS_USE_AOPS;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 069ae39a9cd9..c575fb1d585f 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -416,7 +416,7 @@ static void nbd_clear_que(struct nbd_device *lo)
/*
* We always wait for result of write, for now. It would be nice to make it optional
* in future
- * if ((req->cmd == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
+ * if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
* { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
*/
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig
deleted file mode 100644
index 4b12e9031fb3..000000000000
--- a/drivers/cdrom/Kconfig
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# CDROM driver configuration
-#
-
-menu "Old CD-ROM drivers (not SCSI, not IDE)"
- depends on ISA && BLOCK
-
-config CD_NO_IDESCSI
- bool "Support non-SCSI/IDE/ATAPI CDROM drives"
- ---help---
- If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
- here, otherwise N. Read the CD-ROM-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about these CD-ROM drives. If you are unsure what you
- have, say Y and find out whether you have one of the following
- drives.
-
- For each of these drivers, a <file:Documentation/cdrom/{driver_name}>
- exists. Especially in cases where you do not know exactly which kind
- of drive you have you should read there. Most of these drivers use a
- file drivers/cdrom/{driver_name}.h where you can define your
- interface parameters and switch some internal goodies.
-
- To compile these CD-ROM drivers as a module, choose M instead of Y.
-
- If you want to use any of these CD-ROM drivers, you also have to
- answer Y or M to "ISO 9660 CD-ROM file system support" below (this
- answer will get "defaulted" for you if you enable any of the Linux
- CD-ROM drivers).
-
-config AZTCD
- tristate "Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is your driver if you have an Aztech CDA268-01A, Orchid
- CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or
- CR540 CD-ROM drive. This driver -- just like all these CD-ROM
- drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such
- as Aztech CDA269-031SE. Please read the file
- <file:Documentation/cdrom/aztcd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called aztcd.
-
-config GSCD
- tristate "Goldstar R420 CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- If this is your CD-ROM drive, say Y here. As described in the file
- <file:Documentation/cdrom/gscd>, you might have to change a setting
- in the file <file:drivers/cdrom/gscd.h> before compiling the
- kernel. Please read the file <file:Documentation/cdrom/gscd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called gscd.
-
-config SBPCD
- tristate "Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- This driver supports most of the drives which use the Panasonic or
- Sound Blaster interface. Please read the file
- <file:Documentation/cdrom/sbpcd>.
-
- The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives
- (sometimes labeled "Creative"), the Creative Labs CD200, the
- Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x
- model), the TEAC CD-55A fall under this category. Some other
- "electrically compatible" drives (Vertos, Genoa, some Funai models)
- are currently not supported; for the Sanyo H94A drive currently a
- separate driver (asked later) is responsible. Most drives have a
- uniquely shaped faceplate, with a caddyless motorized drawer, but
- without external brand markings. The older CR-52x drives have a
- caddy and manual loading/eject, but still no external markings. The
- driver is able to do an extended auto-probing for interface
- addresses and drive types; this can help to find facts in cases you
- are not sure, but can consume some time during the boot process if
- none of the supported drives gets found. Once your drive got found,
- you should enter the reported parameters into
- <file:drivers/cdrom/sbpcd.h> and set "DISTRIBUTION 0" there.
-
- This driver can support up to four CD-ROM controller cards, and each
- card can support up to four CD-ROM drives; if you say Y here, you
- will be asked how many controller cards you have. If compiled as a
- module, only one controller card (but with up to four drives) is
- usable.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sbpcd.
-
-config MCDX
- tristate "Mitsumi CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- Use this driver if you want to be able to use your Mitsumi LU-005,
- FX-001 or FX-001D CD-ROM drive.
-
- Please read the file <file:Documentation/cdrom/mcdx>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called mcdx.
-
-config OPTCD
- tristate "Optics Storage DOLPHIN 8000AT CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is the driver for the 'DOLPHIN' drive with a 34-pin Sony
- compatible interface. It also works with the Lasermate CR328A. If
- you have one of those, say Y. This driver does not work for the
- Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that
- one. Please read the file <file:Documentation/cdrom/optcd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called optcd.
-
-config CM206
- tristate "Philips/LMS CM206 CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- If you have a Philips/LMS CD-ROM drive cm206 in combination with a
- cm260 host adapter card, say Y here. Please also read the file
- <file:Documentation/cdrom/cm206>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called cm206.
-
-config SJCD
- tristate "Sanyo CDR-H94A CDROM support"
- depends on CD_NO_IDESCSI
- help
- If this is your CD-ROM drive, say Y here and read the file
- <file:Documentation/cdrom/sjcd>. You should then also say Y or M to
- "ISO 9660 CD-ROM file system support" below, because that's the
- file system used on CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sjcd.
-
-config ISP16_CDI
- tristate "ISP16/MAD16/Mozart soft configurable cdrom interface support"
- depends on CD_NO_IDESCSI
- ---help---
- These are sound cards with built-in cdrom interfaces using the OPTi
- 82C928 or 82C929 chips. Say Y here to have them detected and
- possibly configured at boot time. In addition, You'll have to say Y
- to a driver for the particular cdrom drive you have attached to the
- card. Read <file:Documentation/cdrom/isp16> for details.
-
- To compile this driver as a module, choose M here: the
- module will be called isp16.
-
-config CDU31A
- tristate "Sony CDU31A/CDU33A CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- These CD-ROM drives have a spring-pop-out caddyless drawer, and a
- rectangular green LED centered beneath it. NOTE: these CD-ROM
- drives will not be auto detected by the kernel at boot time; you
- have to provide the interface address as an option to the kernel at
- boot time as described in <file:Documentation/cdrom/cdu31a> or fill
- in your parameters into <file:drivers/cdrom/cdu31a.c>. Try "man
- bootparam" or see the documentation of your boot loader (lilo or
- loadlin) about how to pass options to the kernel.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called cdu31a.
-
-config CDU535
- tristate "Sony CDU535 CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM
- drives. Please read the file <file:Documentation/cdrom/sonycd535>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sonycd535.
-
-endmenu
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
index d1d1e5a4be73..774c180a4e11 100644
--- a/drivers/cdrom/Makefile
+++ b/drivers/cdrom/Makefile
@@ -10,14 +10,4 @@ obj-$(CONFIG_BLK_DEV_SR) += cdrom.o
obj-$(CONFIG_PARIDE_PCD) += cdrom.o
obj-$(CONFIG_CDROM_PKTCDVD) += cdrom.o
-obj-$(CONFIG_AZTCD) += aztcd.o
-obj-$(CONFIG_CDU31A) += cdu31a.o cdrom.o
-obj-$(CONFIG_CM206) += cm206.o cdrom.o
-obj-$(CONFIG_GSCD) += gscd.o
-obj-$(CONFIG_ISP16_CDI) += isp16.o
-obj-$(CONFIG_MCDX) += mcdx.o cdrom.o
-obj-$(CONFIG_OPTCD) += optcd.o
-obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o
-obj-$(CONFIG_SJCD) += sjcd.o
-obj-$(CONFIG_CDU535) += sonycd535.o
obj-$(CONFIG_VIOCD) += viocd.o cdrom.o
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
deleted file mode 100644
index 1f9fb7a96703..000000000000
--- a/drivers/cdrom/aztcd.c
+++ /dev/null
@@ -1,2492 +0,0 @@
-#define AZT_VERSION "2.60"
-
-/* $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $
- linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver
-
- Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
-
- based on Mitsumi CDROM driver by Martin Hariss and preworks by
- Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby
- Schirmer.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- HISTORY
- V0.0 Adaption to Aztech CD268-01A Version 1.3
- Version is PRE_ALPHA, unresolved points:
- 1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW
- thus driver causes CPU overhead and is very slow
- 2. could not find a way to stop the drive, when it is
- in data read mode, therefore I had to set
- msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one
- frame can be read in sequence, this is also the reason for
- 3. getting 'timeout in state 4' messages, but nevertheless
- it works
- W.Zimmermann, Oct. 31, 1994
- V0.1 Version is ALPHA, problems #2 and #3 resolved.
- W.Zimmermann, Nov. 3, 1994
- V0.2 Modification to some comments, debugging aids for partial test
- with Borland C under DOS eliminated. Timer interrupt wait
- STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented;
- use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_
- SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy
- waiting seems better to me than interrupt rescheduling.
- Besides that, when used in the wrong place, STEN_LOW_WAIT causes
- kernel panic.
- In function aztPlay command ACMD_PLAY_AUDIO added, should make
- audio functions work. The Aztech drive needs different commands
- to read data tracks and play audio tracks.
- W.Zimmermann, Nov. 8, 1994
- V0.3 Recognition of missing drive during boot up improved (speeded up).
- W.Zimmermann, Nov. 13, 1994
- V0.35 Rewrote the control mechanism in azt_poll (formerly mcd_poll)
- including removal of all 'goto' commands. :-);
- J. Nardone, Nov. 14, 1994
- V0.4 Renamed variables and constants to 'azt' instead of 'mcd'; had
- to make some "compatibility" defines in azt.h; please note,
- that the source file was renamed to azt.c, the include file to
- azt.h
- Speeded up drive recognition during init (will be a little bit
- slower than before if no drive is installed!); suggested by
- Robby Schirmer.
- read_count declared volatile and set to AZT_BUF_SIZ to make
- drive faster (now 300kB/sec, was 60kB/sec before, measured
- by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096';
- different AZT_BUF_SIZes were test, above 16 no further im-
- provement seems to be possible; suggested by E.Moenkeberg.
- W.Zimmermann, Nov. 18, 1994
- V0.42 Included getAztStatus command in GetQChannelInfo() to allow
- reading Q-channel info on audio disks, if drive is stopped,
- and some other bug fixes in the audio stuff, suggested by
- Robby Schirmer.
- Added more ioctls (reading data in mode 1 and mode 2).
- Completely removed the old azt_poll() routine.
- Detection of ORCHID CDS-3110 in aztcd_init implemented.
- Additional debugging aids (see the readme file).
- W.Zimmermann, Dec. 9, 1994
- V0.50 Autodetection of drives implemented.
- W.Zimmermann, Dec. 12, 1994
- V0.52 Prepared for including in the standard kernel, renamed most
- variables to contain 'azt', included autoconf.h
- W.Zimmermann, Dec. 16, 1994
- V0.6 Version for being included in the standard Linux kernel.
- Renamed source and header file to aztcd.c and aztcd.h
- W.Zimmermann, Dec. 24, 1994
- V0.7 Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case
- CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl,
- which causes kernel crashes when playing audio, changed
- include-files (config.h instead of autoconf.h, removed
- delay.h)
- W.Zimmermann, Jan. 8, 1995
- V0.72 Some more modifications for adaption to the standard kernel.
- W.Zimmermann, Jan. 16, 1995
- V0.80 aztcd is now part of the standard kernel since version 1.1.83.
- Modified the SET_TIMER and CLEAR_TIMER macros to comply with
- the new timer scheme.
- W.Zimmermann, Jan. 21, 1995
- V0.90 Included CDROMVOLCTRL, but with my Aztech drive I can only turn
- the channels on and off. If it works better with your drive,
- please mail me. Also implemented ACMD_CLOSE for CDROMSTART.
- W.Zimmermann, Jan. 24, 1995
- V1.00 Implemented close and lock tray commands. Patches supplied by
- Frank Racis
- Added support for loadable MODULEs, so aztcd can now also be
- loaded by insmod and removed by rmmod during run time
- Werner Zimmermann, Mar. 24, 95
- V1.10 Implemented soundcard configuration for Orchid CDS-3110 drives
- connected to Soundwave32 cards. Release for LST 2.1.
- (still experimental)
- Werner Zimmermann, May 8, 95
- V1.20 Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but
- sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver-
- sion needs an update of Dosemu0.60's cdrom.c, which will come with the
- next revision of Dosemu.
- Also Soundwave32 support now works.
- Werner Zimmermann, May 22, 95
- V1.30 Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
- Werner Zimmermann, July 4, 95
- V1.40 Started multisession support. Implementation copied from mcdx.c
- by Heiko Schlittermann. Not tested yet.
- Werner Zimmermann, July 15, 95
- V1.50 Implementation of ioctl CDROMRESET, continued multisession, began
- XA, but still untested. Heavy modifications to drive status de-
- tection.
- Werner Zimmermann, July 25, 95
- V1.60 XA support now should work. Speeded up drive recognition in cases,
- where no drive is installed.
- Werner Zimmermann, August 8, 1995
- V1.70 Multisession support now is completed, but there is still not
- enough testing done. If you can test it, please contact me. For
- details please read Documentation/cdrom/aztcd
- Werner Zimmermann, August 19, 1995
- V1.80 Modification to suit the new kernel boot procedure introduced
- with kernel 1.3.33. Will definitely not work with older kernels.
- Programming done by Linus himself.
- Werner Zimmermann, October 11, 1995
- V1.90 Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza.
- Werner Zimmermann, October 21, 1995
- V2.00 Changed #include "blk.h" to <linux/blk.h> as the directory
- structure was changed. README.aztcd is now /usr/src/docu-
- mentation/cdrom/aztcd
- Werner Zimmermann, November 10, 95
- V2.10 Started to modify azt_poll to prevent reading beyond end of
- tracks.
- Werner Zimmermann, December 3, 95
- V2.20 Changed some comments
- Werner Zimmermann, April 1, 96
- V2.30 Implemented support for CyCDROM CR520, CR940, Code for CR520
- delivered by H.Berger with preworks by E.Moenkeberg.
- Werner Zimmermann, April 29, 96
- V2.40 Reorganized the placement of functions in the source code file
- to reflect the layered approach; did not actually change code
- Werner Zimmermann, May 1, 96
- V2.50 Heiko Eissfeldt suggested to remove some VERIFY_READs in
- aztcd_ioctl; check_aztcd_media_change modified
- Werner Zimmermann, May 16, 96
- V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
- Adaption to linux kernel > 2.1.0
- Werner Zimmermann, Nov 29, 97
-
- November 1999 -- Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-*/
-
-#include <linux/blkdev.h>
-#include "aztcd.h"
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/uaccess.h>
-
-/*###########################################################################
- Defines
- ###########################################################################
-*/
-
-#define MAJOR_NR AZTECH_CDROM_MAJOR
-#define QUEUE (azt_queue)
-#define CURRENT elv_next_request(azt_queue)
-#define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \
- delay_timer.function = (void *) (func); \
- add_timer(&delay_timer);
-
-#define CLEAR_TIMER del_timer(&delay_timer);
-
-#define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
- return value;}
-#define RETURN(message) {printk("aztcd: Warning: %s failed\n",message);\
- return;}
-
-/* Macros to switch the IDE-interface to the slave device and back to the master*/
-#define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \
- outb_p(0x10,azt_port+6); \
- outb_p(0x00,azt_port+7); \
- outb_p(0x10,azt_port+6);
-#define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
-
-
-#if 0
-#define AZT_TEST
-#define AZT_TEST1 /* <int-..> */
-#define AZT_TEST2 /* do_aztcd_request */
-#define AZT_TEST3 /* AZT_S_state */
-#define AZT_TEST4 /* QUICK_LOOP-counter */
-#define AZT_TEST5 /* port(1) state */
-#define AZT_DEBUG
-#define AZT_DEBUG_MULTISESSION
-#endif
-
-static struct request_queue *azt_queue;
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
-#define AZT_BUF_SIZ 16
-
-#define READ_TIMEOUT 3000
-
-#define azt_port aztcd /*needed for the modutils */
-
-/*##########################################################################
- Type Definitions
- ##########################################################################
-*/
-enum azt_state_e { AZT_S_IDLE, /* 0 */
- AZT_S_START, /* 1 */
- AZT_S_MODE, /* 2 */
- AZT_S_READ, /* 3 */
- AZT_S_DATA, /* 4 */
- AZT_S_STOP, /* 5 */
- AZT_S_STOPPING /* 6 */
-};
-enum azt_read_modes { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware */
- AZT_MODE_1, /*read mode for normal CD-ROMs */
- AZT_MODE_2 /*read mode for XA CD-ROMs */
-};
-
-/*##########################################################################
- Global Variables
- ##########################################################################
-*/
-static int aztPresent = 0;
-
-static volatile int azt_transfer_is_active = 0;
-
-static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ]; /*buffer for block size conversion */
-#if AZT_PRIVATE_IOCTLS
-static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls */
-#endif
-
-static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
-static volatile int azt_buf_in, azt_buf_out = -1;
-static volatile int azt_error = 0;
-static int azt_open_count = 0;
-static volatile enum azt_state_e azt_state = AZT_S_IDLE;
-#ifdef AZT_TEST3
-static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
-static volatile int azt_st_old = 0;
-#endif
-static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
-
-static int azt_mode = -1;
-static volatile int azt_read_count = 1;
-
-static int azt_port = AZT_BASE_ADDR;
-
-module_param(azt_port, int, 0);
-
-static int azt_port_auto[16] = AZT_BASE_AUTO;
-
-static char azt_cont = 0;
-static char azt_init_end = 0;
-static char azt_auto_eject = AZT_AUTO_EJECT;
-
-static int AztTimeout, AztTries;
-static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static DEFINE_TIMER(delay_timer, NULL, 0, 0);
-
-static struct azt_DiskInfo DiskInfo;
-static struct azt_Toc Toc[MAX_TRACKS];
-static struct azt_Play_msf azt_Play;
-
-static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-static char aztDiskChanged = 1;
-static char aztTocUpToDate = 0;
-
-static unsigned char aztIndatum;
-static unsigned long aztTimeOutCount;
-static int aztCmd = 0;
-
-static DEFINE_SPINLOCK(aztSpin);
-
-/*###########################################################################
- Function Prototypes
- ###########################################################################
-*/
-/* CDROM Drive Low Level I/O Functions */
-static void aztStatTimer(void);
-
-/* CDROM Drive Command Functions */
-static int aztGetDiskInfo(void);
-#if AZT_MULTISESSION
-static int aztGetMultiDiskInfo(void);
-#endif
-static int aztGetToc(int multi);
-
-/* Kernel Interface Functions */
-static int check_aztcd_media_change(struct gendisk *disk);
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg);
-static int aztcd_open(struct inode *ip, struct file *fp);
-static int aztcd_release(struct inode *inode, struct file *file);
-
-static struct block_device_operations azt_fops = {
- .owner = THIS_MODULE,
- .open = aztcd_open,
- .release = aztcd_release,
- .ioctl = aztcd_ioctl,
- .media_changed = check_aztcd_media_change,
-};
-
-/* Aztcd State Machine: Controls Drive Operating State */
-static void azt_poll(void);
-
-/* Miscellaneous support functions */
-static void azt_hsg2msf(long hsg, struct msf *msf);
-static long azt_msf2hsg(struct msf *mp);
-static void azt_bin2bcd(unsigned char *p);
-static int azt_bcd2bin(unsigned char bcd);
-
-/*##########################################################################
- CDROM Drive Low Level I/O Functions
- ##########################################################################
-*/
-/* Macros for the drive hardware interface handshake, these macros use
- busy waiting */
-/* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
-# define OP_OK op_ok()
-static void op_ok(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(DATA_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait OP_OK\n");
- break;
- }
- } while (aztIndatum != AFL_OP_OK);
-}
-
-/* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
-#if 0
-# define PA_OK pa_ok()
-static void pa_ok(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(DATA_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait PA_OK\n");
- break;
- }
- } while (aztIndatum != AFL_PA_OK);
-}
-#endif
-
-/* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
-# define STEN_LOW sten_low()
-static void sten_low(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- if (azt_init_end)
- printk
- ("aztcd: Error Wait STEN_LOW commands:%x\n",
- aztCmd);
- break;
- }
- } while (aztIndatum & AFL_STATUS);
-}
-
-/* Wait for DTEN=Low = handshake signal 'Data available'*/
-# define DTEN_LOW dten_low()
-static void dten_low(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait DTEN_OK\n");
- break;
- }
- } while (aztIndatum & AFL_DATA);
-}
-
-/*
- * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
- * may cause kernel panic when used in the wrong place
-*/
-#define STEN_LOW_WAIT statusAzt()
-static void statusAzt(void)
-{
- AztTimeout = AZT_STATUS_DELAY;
- SET_TIMER(aztStatTimer, HZ / 100);
- sleep_on(&azt_waitq);
- if (AztTimeout <= 0)
- printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",
- aztCmd);
- return;
-}
-
-static void aztStatTimer(void)
-{
- if (!(inb(STATUS_PORT) & AFL_STATUS)) {
- wake_up(&azt_waitq);
- return;
- }
- AztTimeout--;
- if (AztTimeout <= 0) {
- wake_up(&azt_waitq);
- printk("aztcd: Error aztStatTimer: Timeout\n");
- return;
- }
- SET_TIMER(aztStatTimer, HZ / 100);
-}
-
-/*##########################################################################
- CDROM Drive Command Functions
- ##########################################################################
-*/
-/*
- * Send a single command, return -1 on error, else 0
-*/
-static int aztSendCmd(int cmd)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: Executing command %x\n", cmd);
-#endif
-
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */
-
- aztCmd = cmd;
- outb(POLLED, MODE_PORT);
- do {
- if (inb(STATUS_PORT) & AFL_STATUS)
- break;
- inb(DATA_PORT); /* if status left from last command, read and */
- } while (1); /* discard it */
- do {
- if (inb(STATUS_PORT) & AFL_DATA)
- break;
- inb(DATA_PORT); /* if data left from last command, read and */
- } while (1); /* discard it */
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- outb((unsigned char) cmd, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_OP_OK) {
- return 0;
- } /*OP_OK? */
- if (data == AFL_OP_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: aztSendCmd %x Error Code %x\n",
- cmd, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSendCmd %x \n", cmd);
- azt_error = 0xA5;
- }
- RETURNM("aztSendCmd", -1);
-}
-
-/*
- * Send a play or read command to the drive, return -1 on error, else 0
-*/
-static int sendAztCmd(int cmd, struct azt_Play_msf *params)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n",
- params->start.min, params->start.sec, params->start.frame,
- params->end.min, params->end.sec, params->end.frame);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(cmd);
- outb(params->start.min, CMD_PORT);
- outb(params->start.sec, CMD_PORT);
- outb(params->start.frame, CMD_PORT);
- outb(params->end.min, CMD_PORT);
- outb(params->end.sec, CMD_PORT);
- outb(params->end.frame, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) {
- return 0;
- } /*PA_OK ? */
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: sendAztCmd %x Error Code %x\n",
- cmd, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd);
- azt_error = 0xA5;
- }
- RETURNM("sendAztCmd", -1);
-}
-
-/*
- * Send a seek command to the drive, return -1 on error, else 0
-*/
-static int aztSeek(struct azt_Play_msf *params)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: aztSeek %02x:%02x:%02x\n",
- params->start.min, params->start.sec, params->start.frame);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(ACMD_SEEK);
- outb(params->start.min, CMD_PORT);
- outb(params->start.sec, CMD_PORT);
- outb(params->start.frame, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) {
- return 0;
- } /*PA_OK ? */
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk("### Error 1 aztcd: aztSeek\n");
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSeek\n ");
- azt_error = 0xA5;
- }
- RETURNM("aztSeek", -1);
-}
-
-/* Send a Set Disk Type command
- does not seem to work with Aztech drives, behavior is completely indepen-
- dent on which mode is set ???
-*/
-static int aztSetDiskType(int type)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: set disk type command: type= %i\n", type);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(ACMD_SET_DISK_TYPE);
- outb(type, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) { /*PA_OK ? */
- azt_read_mode = type;
- return 0;
- }
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",
- type, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSetDiskType %x\n ", type);
- azt_error = 0xA5;
- }
- RETURNM("aztSetDiskType", -1);
-}
-
-
-/* used in azt_poll to poll the status, expects another program to issue a
- * ACMD_GET_STATUS directly before
- */
-static int aztStatus(void)
-{
- int st;
-/* int i;
-
- i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ???
- if (!i)
-*/ STEN_LOW;
- if (aztTimeOutCount < AZT_TIMEOUT) {
- st = inb(DATA_PORT) & 0xFF;
- return st;
- } else
- RETURNM("aztStatus", -1);
-}
-
-/*
- * Get the drive status
- */
-static int getAztStatus(void)
-{
- int st;
-
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURNM("getAztStatus 1", -1);
- STEN_LOW;
- st = inb(DATA_PORT) & 0xFF;
-#ifdef AZT_DEBUG
- printk("aztcd: Status = %x\n", st);
-#endif
- if ((st == 0xFF) || (st & AST_CMD_CHECK)) {
- printk
- ("aztcd: AST_CMD_CHECK error or no status available\n");
- return -1;
- }
-
- if (((st & AST_MODE_BITS) != AST_BUSY)
- && (aztAudioStatus == CDROM_AUDIO_PLAY))
- /* XXX might be an error? look at q-channel? */
- aztAudioStatus = CDROM_AUDIO_COMPLETED;
-
- if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- }
- return st;
-}
-
-
-/*
- * Send a 'Play' command and get the status. Use only from the top half.
- */
-static int aztPlay(struct azt_Play_msf *arg)
-{
- if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0)
- RETURNM("aztPlay", -1);
- return 0;
-}
-
-/*
- * Subroutines to automatically close the door (tray) and
- * lock it closed when the cd is mounted. Leave the tray
- * locking as an option
- */
-static void aztCloseDoor(void)
-{
- aztSendCmd(ACMD_CLOSE);
- STEN_LOW;
- return;
-}
-
-static void aztLockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
- aztSendCmd(ACMD_LOCK);
- STEN_LOW;
-#endif
- return;
-}
-
-static void aztUnlockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
- aztSendCmd(ACMD_UNLOCK);
- STEN_LOW;
-#endif
- return;
-}
-
-/*
- * Read a value from the drive. Should return quickly, so a busy wait
- * is used to avoid excessive rescheduling. The read command itself must
- * be issued with aztSendCmd() directly before
- */
-static int aztGetValue(unsigned char *result)
-{
- int s;
-
- STEN_LOW;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: aztGetValue timeout\n");
- return -1;
- }
- s = inb(DATA_PORT) & 0xFF;
- *result = (unsigned char) s;
- return 0;
-}
-
-/*
- * Read the current Q-channel info. Also used for reading the
- * table of contents.
- */
-static int aztGetQChannelInfo(struct azt_Toc *qp)
-{
- unsigned char notUsed;
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetQChannelInfo Time:%li\n", jiffies);
-#endif
- if ((st = getAztStatus()) == -1)
- RETURNM("aztGetQChannelInfo 1", -1);
- if (aztSendCmd(ACMD_GET_Q_CHANNEL))
- RETURNM("aztGetQChannelInfo 2", -1);
- /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */
- if (aztGetValue(&notUsed))
- RETURNM("aztGetQChannelInfo 3", -1); /*??? Nullbyte einlesen */
- if ((st & AST_MODE_BITS) == AST_INITIAL) {
- qp->ctrl_addr = 0; /* when audio stop ACMD_GET_Q_CHANNEL returns */
- qp->track = 0; /* only one byte with Aztech drives */
- qp->pointIndex = 0;
- qp->trackTime.min = 0;
- qp->trackTime.sec = 0;
- qp->trackTime.frame = 0;
- qp->diskTime.min = 0;
- qp->diskTime.sec = 0;
- qp->diskTime.frame = 0;
- return 0;
- } else {
- if (aztGetValue(&qp->ctrl_addr) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->track) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->pointIndex) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.min) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.sec) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.frame) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&notUsed) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.min) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.sec) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.frame) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetQChannelInfo Time:%li\n", jiffies);
-#endif
- return 0;
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary
- */
-static int aztUpdateToc(void)
-{
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztUpdateToc Time:%li\n", jiffies);
-#endif
- if (aztTocUpToDate)
- return 0;
-
- if (aztGetDiskInfo() < 0)
- return -EIO;
-
- if (aztGetToc(0) < 0)
- return -EIO;
-
- /*audio disk detection
- with my Aztech drive there is no audio status bit, so I use the copy
- protection bit of the first track. If this track is copy protected
- (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */
- if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
- DiskInfo.audio = 1;
- else
- DiskInfo.audio = 0;
-
- /* XA detection */
- if (!DiskInfo.audio) {
- azt_Play.start.min = 0; /*XA detection only seems to work */
- azt_Play.start.sec = 2; /*when we play a track */
- azt_Play.start.frame = 0;
- azt_Play.end.min = 0;
- azt_Play.end.sec = 0;
- azt_Play.end.frame = 1;
- if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
- return -1;
- DTEN_LOW;
- for (st = 0; st < CD_FRAMESIZE; st++)
- inb(DATA_PORT);
- }
- DiskInfo.xa = getAztStatus() & AST_MODE;
- if (DiskInfo.xa) {
- printk
- ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
- }
-
- /*multisession detection
- support for multisession CDs is done automatically with Aztech drives,
- we don't have to take care about TOC redirection; if we want the isofs
- to take care about redirection, we have to set AZT_MULTISESSION to 1 */
- DiskInfo.multi = 0;
-#if AZT_MULTISESSION
- if (DiskInfo.xa) {
- aztGetMultiDiskInfo(); /*here Disk.Info.multi is set */
- }
-#endif
- if (DiskInfo.multi) {
- DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
- DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
- DiskInfo.lastSession.frame =
- Toc[DiskInfo.next].diskTime.frame;
- printk("aztcd: Multisession support experimental\n");
- } else {
- DiskInfo.lastSession.min =
- Toc[DiskInfo.first].diskTime.min;
- DiskInfo.lastSession.sec =
- Toc[DiskInfo.first].diskTime.sec;
- DiskInfo.lastSession.frame =
- Toc[DiskInfo.first].diskTime.frame;
- }
-
- aztTocUpToDate = 1;
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztUpdateToc Time:%li\n", jiffies);
-#endif
- return 0;
-}
-
-
-/* Read the table of contents header, i.e. no. of tracks and start of first
- * track
- */
-static int aztGetDiskInfo(void)
-{
- int limit;
- unsigned char test;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetDiskInfo Time:%li\n", jiffies);
-#endif
- if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
- RETURNM("aztGetDiskInfo 1", -1);
- STEN_LOW_WAIT;
- test = 0;
- for (limit = 300; limit > 0; limit--) {
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetDiskInfo 2", -1);
- if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */
- DiskInfo.first = qInfo.diskTime.min;
- DiskInfo.first = azt_bcd2bin(DiskInfo.first);
- test = test | 0x01;
- }
- if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
- DiskInfo.last = qInfo.diskTime.min;
- DiskInfo.last = azt_bcd2bin(DiskInfo.last);
- test = test | 0x02;
- }
- if (qInfo.pointIndex == 0xA2) { /*DiskLength */
- DiskInfo.diskLength.min = qInfo.diskTime.min;
- DiskInfo.diskLength.sec = qInfo.diskTime.sec;
- DiskInfo.diskLength.frame = qInfo.diskTime.frame;
- test = test | 0x04;
- }
- if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) { /*StartTime of First Track */
- DiskInfo.firstTrack.min = qInfo.diskTime.min;
- DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
- DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
- test = test | 0x08;
- }
- if (test == 0x0F)
- break;
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetDiskInfo Time:%li\n", jiffies);
- printk
- ("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n",
- DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
- DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
- DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
- DiskInfo.firstTrack.frame);
-#endif
- if (test != 0x0F)
- return -1;
- return 0;
-}
-
-#if AZT_MULTISESSION
-/*
- * Get Multisession Disk Info
- */
-static int aztGetMultiDiskInfo(void)
-{
- int limit, k = 5;
- unsigned char test;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetMultiDiskInfo\n");
-#endif
-
- do {
- azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min;
- azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec;
- azt_Play.start.frame =
- Toc[DiskInfo.last + 1].diskTime.frame;
- test = 0;
-
- for (limit = 30; limit > 0; limit--) { /*Seek for LeadIn of next session */
- if (aztSeek(&azt_Play))
- RETURNM("aztGetMultiDiskInfo 1", -1);
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetMultiDiskInfo 2", -1);
- if ((qInfo.track == 0) && (qInfo.pointIndex))
- break; /*LeadIn found */
- if ((azt_Play.start.sec += 10) > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- }
- if (!limit)
- break; /*Check, if a leadin track was found, if not we're
- at the end of the disk */
-#ifdef AZT_DEBUG_MULTISESSION
- printk("leadin found track %d pointIndex %x limit %d\n",
- qInfo.track, qInfo.pointIndex, limit);
-#endif
- for (limit = 300; limit > 0; limit--) {
- if (++azt_Play.start.frame > 74) {
- azt_Play.start.frame = 0;
- if (azt_Play.start.sec > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- }
- if (aztSeek(&azt_Play))
- RETURNM("aztGetMultiDiskInfo 3", -1);
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetMultiDiskInfo 4", -1);
- if (qInfo.pointIndex == 0xA0) { /*Number of NextTrack */
- DiskInfo.next = qInfo.diskTime.min;
- DiskInfo.next = azt_bcd2bin(DiskInfo.next);
- test = test | 0x01;
- }
- if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
- DiskInfo.last = qInfo.diskTime.min;
- DiskInfo.last = azt_bcd2bin(DiskInfo.last);
- test = test | 0x02;
- }
- if (qInfo.pointIndex == 0xA2) { /*DiskLength */
- DiskInfo.diskLength.min =
- qInfo.diskTime.min;
- DiskInfo.diskLength.sec =
- qInfo.diskTime.sec;
- DiskInfo.diskLength.frame =
- qInfo.diskTime.frame;
- test = test | 0x04;
- }
- if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) { /*StartTime of Next Track */
- DiskInfo.nextSession.min =
- qInfo.diskTime.min;
- DiskInfo.nextSession.sec =
- qInfo.diskTime.sec;
- DiskInfo.nextSession.frame =
- qInfo.diskTime.frame;
- test = test | 0x08;
- }
- if (test == 0x0F)
- break;
- }
-#ifdef AZT_DEBUG_MULTISESSION
- printk
- ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n",
- DiskInfo.first, DiskInfo.next, DiskInfo.last,
- DiskInfo.diskLength.min, DiskInfo.diskLength.sec,
- DiskInfo.diskLength.frame, DiskInfo.firstTrack.min,
- DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame,
- DiskInfo.nextSession.min, DiskInfo.nextSession.sec,
- DiskInfo.nextSession.frame);
-#endif
- if (test != 0x0F)
- break;
- else
- DiskInfo.multi = 1; /*found TOC of more than one session */
- aztGetToc(1);
- } while (--k);
-
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetMultiDiskInfo Time:%li\n", jiffies);
-#endif
- return 0;
-}
-#endif
-
-/*
- * Read the table of contents (TOC)
- */
-static int aztGetToc(int multi)
-{
- int i, px;
- int limit;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetToc Time:%li\n", jiffies);
-#endif
- if (!multi) {
- for (i = 0; i < MAX_TRACKS; i++)
- Toc[i].pointIndex = 0;
- i = DiskInfo.last + 3;
- } else {
- for (i = DiskInfo.next; i < MAX_TRACKS; i++)
- Toc[i].pointIndex = 0;
- i = DiskInfo.last + 4 - DiskInfo.next;
- }
-
-/*Is there a good reason to stop motor before TOC read?
- if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
- STEN_LOW_WAIT;
-*/
-
- if (!multi) {
- azt_mode = 0x05;
- if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
- RETURNM("aztGetToc 2", -1);
- STEN_LOW_WAIT;
- }
- for (limit = 300; limit > 0; limit--) {
- if (multi) {
- if (++azt_Play.start.sec > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- if (aztSeek(&azt_Play))
- RETURNM("aztGetToc 3", -1);
- }
- if (aztGetQChannelInfo(&qInfo) < 0)
- break;
-
- px = azt_bcd2bin(qInfo.pointIndex);
-
- if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
- if (Toc[px].pointIndex == 0) {
- Toc[px] = qInfo;
- i--;
- }
-
- if (i <= 0)
- break;
- }
-
- Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
- Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
-
-#ifdef AZT_DEBUG_MULTISESSION
- printk("aztcd: exiting aztGetToc\n");
- for (i = 1; i <= DiskInfo.last + 1; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
- for (i = 100; i < 103; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-#endif
-
- return limit > 0 ? 0 : -1;
-}
-
-
-/*##########################################################################
- Kernel Interface Functions
- ##########################################################################
-*/
-
-#ifndef MODULE
-static int __init aztcd_setup(char *str)
-{
- int ints[4];
-
- (void) get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0)
- azt_port = ints[1];
- if (ints[1] > 1)
- azt_cont = ints[2];
- return 1;
-}
-
-__setup("aztcd=", aztcd_setup);
-
-#endif /* !MODULE */
-
-/*
- * Checking if the media has been changed
-*/
-static int check_aztcd_media_change(struct gendisk *disk)
-{
- if (aztDiskChanged) { /* disk changed */
- aztDiskChanged = 0;
- return 1;
- } else
- return 0; /* no change */
-}
-
-/*
- * Kernel IO-controls
-*/
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- int i;
- struct azt_Toc qInfo;
- struct cdrom_ti ti;
- struct cdrom_tochdr tocHdr;
- struct cdrom_msf msf;
- struct cdrom_tocentry entry;
- struct azt_Toc *tocPtr;
- struct cdrom_subchnl subchnl;
- struct cdrom_volctrl volctrl;
- void __user *argp = (void __user *)arg;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n",
- cmd, jiffies);
- printk("aztcd Status %x\n", getAztStatus());
-#endif
- if (!ip)
- RETURNM("aztcd_ioctl 1", -EINVAL);
- if (getAztStatus() < 0)
- RETURNM("aztcd_ioctl 2", -EIO);
- if ((!aztTocUpToDate) || (aztDiskChanged)) {
- if ((i = aztUpdateToc()) < 0)
- RETURNM("aztcd_ioctl 3", i); /* error reading TOC */
- }
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive. Don't know, what to do,
- at least close the tray */
-#if AZT_PRIVATE_IOCTLS
- if (aztSendCmd(ACMD_CLOSE))
- RETURNM("aztcd_ioctl 4", -1);
- STEN_LOW_WAIT;
-#endif
- break;
- case CDROMSTOP: /* Spin down the drive */
- if (aztSendCmd(ACMD_STOP))
- RETURNM("aztcd_ioctl 5", -1);
- STEN_LOW_WAIT;
- /* should we do anything if it fails? */
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMPAUSE: /* Pause the drive */
- if (aztAudioStatus != CDROM_AUDIO_PLAY)
- return -EINVAL;
-
- if (aztGetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- RETURNM("aztcd_ioctl 7", 0);
- }
- azt_Play.start = qInfo.diskTime; /* remember restart point */
-
- if (aztSendCmd(ACMD_PAUSE))
- RETURNM("aztcd_ioctl 8", -1);
- STEN_LOW_WAIT;
- aztAudioStatus = CDROM_AUDIO_PAUSED;
- break;
- case CDROMRESUME: /* Play it again, Sam */
- if (aztAudioStatus != CDROM_AUDIO_PAUSED)
- return -EINVAL;
- /* restart the drive at the saved position. */
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
- case CDROMMULTISESSION: /*multisession support -- experimental */
- {
- struct cdrom_multisession ms;
-#ifdef AZT_DEBUG
- printk("aztcd ioctl MULTISESSION\n");
-#endif
- if (copy_from_user(&ms, argp,
- sizeof(struct cdrom_multisession)))
- return -EFAULT;
- if (ms.addr_format == CDROM_MSF) {
- ms.addr.msf.minute =
- azt_bcd2bin(DiskInfo.lastSession.min);
- ms.addr.msf.second =
- azt_bcd2bin(DiskInfo.lastSession.sec);
- ms.addr.msf.frame =
- azt_bcd2bin(DiskInfo.lastSession.
- frame);
- } else if (ms.addr_format == CDROM_LBA)
- ms.addr.lba =
- azt_msf2hsg(&DiskInfo.lastSession);
- else
- return -EINVAL;
- ms.xa_flag = DiskInfo.xa;
- if (copy_to_user(argp, &ms,
- sizeof(struct cdrom_multisession)))
- return -EFAULT;
-#ifdef AZT_DEBUG
- if (ms.addr_format == CDROM_MSF)
- printk
- ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
- ms.xa_flag, ms.addr.msf.minute,
- ms.addr.msf.second, ms.addr.msf.frame,
- DiskInfo.lastSession.min,
- DiskInfo.lastSession.sec,
- DiskInfo.lastSession.frame);
- else
- printk
- ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
- ms.xa_flag, ms.addr.lba,
- DiskInfo.lastSession.min,
- DiskInfo.lastSession.sec,
- DiskInfo.lastSession.frame);
-#endif
- return 0;
- }
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- if (copy_from_user(&ti, argp, sizeof ti))
- return -EFAULT;
- if (ti.cdti_trk0 < DiskInfo.first
- || ti.cdti_trk0 > DiskInfo.last
- || ti.cdti_trk1 < ti.cdti_trk0) {
- return -EINVAL;
- }
- if (ti.cdti_trk1 > DiskInfo.last)
- ti.cdti_trk1 = DiskInfo.last;
- azt_Play.start = Toc[ti.cdti_trk0].diskTime;
- azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
-#ifdef AZT_DEBUG
- printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- azt_Play.start.min, azt_Play.start.sec,
- azt_Play.start.frame, azt_Play.end.min,
- azt_Play.end.sec, azt_Play.end.frame);
-#endif
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
-/* if (aztAudioStatus == CDROM_AUDIO_PLAY)
- { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
- STEN_LOW;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- }
-*/
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- azt_bin2bcd(&msf.cdmsf_min1);
- azt_bin2bcd(&msf.cdmsf_sec1);
- azt_bin2bcd(&msf.cdmsf_frame1);
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- azt_Play.end.min = msf.cdmsf_min1;
- azt_Play.end.sec = msf.cdmsf_sec1;
- azt_Play.end.frame = msf.cdmsf_frame1;
-#ifdef AZT_DEBUG
- printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- azt_Play.start.min, azt_Play.start.sec,
- azt_Play.start.frame, azt_Play.end.min,
- azt_Play.end.sec, azt_Play.end.frame);
-#endif
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- tocHdr.cdth_trk0 = DiskInfo.first;
- tocHdr.cdth_trk1 = DiskInfo.last;
- if (copy_to_user(argp, &tocHdr, sizeof tocHdr))
- return -EFAULT;
- break;
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- if (copy_from_user(&entry, argp, sizeof entry))
- return -EFAULT;
- if ((!aztTocUpToDate) || aztDiskChanged)
- aztUpdateToc();
- if (entry.cdte_track == CDROM_LEADOUT)
- tocPtr = &Toc[DiskInfo.last + 1];
- else if (entry.cdte_track > DiskInfo.last
- || entry.cdte_track < DiskInfo.first) {
- return -EINVAL;
- } else
- tocPtr = &Toc[entry.cdte_track];
- entry.cdte_adr = tocPtr->ctrl_addr;
- entry.cdte_ctrl = tocPtr->ctrl_addr >> 4;
- if (entry.cdte_format == CDROM_LBA)
- entry.cdte_addr.lba =
- azt_msf2hsg(&tocPtr->diskTime);
- else if (entry.cdte_format == CDROM_MSF) {
- entry.cdte_addr.msf.minute =
- azt_bcd2bin(tocPtr->diskTime.min);
- entry.cdte_addr.msf.second =
- azt_bcd2bin(tocPtr->diskTime.sec);
- entry.cdte_addr.msf.frame =
- azt_bcd2bin(tocPtr->diskTime.frame);
- } else {
- return -EINVAL;
- }
- if (copy_to_user(argp, &entry, sizeof entry))
- return -EFAULT;
- break;
- case CDROMSUBCHNL: /* Get subchannel info */
- if (copy_from_user
- (&subchnl, argp, sizeof(struct cdrom_subchnl)))
- return -EFAULT;
- if (aztGetQChannelInfo(&qInfo) < 0) {
-#ifdef AZT_DEBUG
- printk
- ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",
- cmd);
-#endif
- return -EIO;
- }
- subchnl.cdsc_audiostatus = aztAudioStatus;
- subchnl.cdsc_adr = qInfo.ctrl_addr;
- subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
- subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
- subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
- if (subchnl.cdsc_format == CDROM_LBA) {
- subchnl.cdsc_absaddr.lba =
- azt_msf2hsg(&qInfo.diskTime);
- subchnl.cdsc_reladdr.lba =
- azt_msf2hsg(&qInfo.trackTime);
- } else { /*default */
- subchnl.cdsc_format = CDROM_MSF;
- subchnl.cdsc_absaddr.msf.minute =
- azt_bcd2bin(qInfo.diskTime.min);
- subchnl.cdsc_absaddr.msf.second =
- azt_bcd2bin(qInfo.diskTime.sec);
- subchnl.cdsc_absaddr.msf.frame =
- azt_bcd2bin(qInfo.diskTime.frame);
- subchnl.cdsc_reladdr.msf.minute =
- azt_bcd2bin(qInfo.trackTime.min);
- subchnl.cdsc_reladdr.msf.second =
- azt_bcd2bin(qInfo.trackTime.sec);
- subchnl.cdsc_reladdr.msf.frame =
- azt_bcd2bin(qInfo.trackTime.frame);
- }
- if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl)))
- return -EFAULT;
- break;
- case CDROMVOLCTRL: /* Volume control
- * With my Aztech CD268-01A volume control does not work, I can only
- turn the channels on (any value !=0) or off (value==0). Maybe it
- works better with your drive */
- if (copy_from_user(&volctrl, argp, sizeof(volctrl)))
- return -EFAULT;
- azt_Play.start.min = 0x21;
- azt_Play.start.sec = 0x84;
- azt_Play.start.frame = volctrl.channel0;
- azt_Play.end.min = volctrl.channel1;
- azt_Play.end.sec = volctrl.channel2;
- azt_Play.end.frame = volctrl.channel3;
- sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
- STEN_LOW_WAIT;
- break;
- case CDROMEJECT:
- aztUnlockDoor(); /* Assume user knows what they're doing */
- /* all drives can at least stop! */
- if (aztAudioStatus == CDROM_AUDIO_PLAY) {
- if (aztSendCmd(ACMD_STOP))
- RETURNM("azt_ioctl 10", -1);
- STEN_LOW_WAIT;
- }
- if (aztSendCmd(ACMD_EJECT))
- RETURNM("azt_ioctl 11", -1);
- STEN_LOW_WAIT;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMEJECT_SW:
- azt_auto_eject = (char) arg;
- break;
- case CDROMRESET:
- outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
- STEN_LOW;
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
- printk
- ("aztcd: AZTECH CD-ROM drive does not respond\n");
- }
- break;
-/*Take care, the following code is not compatible with other CD-ROM drivers,
- use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
- if you do not want to use it!
-*/
-#if AZT_PRIVATE_IOCTLS
- case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes) */
- case CDROMREADRAW: /*read data in mode 2 (2336 Bytes) */
- {
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- msf.cdmsf_min1 = 0;
- msf.cdmsf_sec1 = 0;
- msf.cdmsf_frame1 = 1; /*read only one frame */
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- azt_Play.end.min = msf.cdmsf_min1;
- azt_Play.end.sec = msf.cdmsf_sec1;
- azt_Play.end.frame = msf.cdmsf_frame1;
- if (cmd == CDROMREADRAW) {
- if (DiskInfo.xa) {
- return -1; /*XA Disks can't be read raw */
- } else {
- if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play))
- return -1;
- DTEN_LOW;
- insb(DATA_PORT, buf, CD_FRAMESIZE_RAW);
- if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW))
- return -EFAULT;
- }
- } else
- /*CDROMREADCOOKED*/ {
- if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
- return -1;
- DTEN_LOW;
- insb(DATA_PORT, buf, CD_FRAMESIZE);
- if (copy_to_user(argp, &buf, CD_FRAMESIZE))
- return -EFAULT;
- }
- }
- break;
- case CDROMSEEK: /*seek msf address */
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- if (aztSeek(&azt_Play))
- return -1;
- break;
-#endif /*end of incompatible code */
- case CDROMREADMODE1: /*set read data in mode 1 */
- return aztSetDiskType(AZT_MODE_1);
- case CDROMREADMODE2: /*set read data in mode 2 */
- return aztSetDiskType(AZT_MODE_2);
- default:
- return -EINVAL;
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n", cmd,
- jiffies);
-#endif
- return 0;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-static void azt_transfer(void)
-{
-#ifdef AZT_TEST
- printk("aztcd: executing azt_transfer Time:%li\n", jiffies);
-#endif
- if (!current_valid())
- return;
-
- while (CURRENT->nr_sectors) {
- int bn = CURRENT->sector / 4;
- int i;
- for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i);
- if (i < AZT_BUF_SIZ) {
- int offs = (i * 4 + (CURRENT->sector & 3)) * 512;
- int nr_sectors = 4 - (CURRENT->sector & 3);
- if (azt_buf_out != i) {
- azt_buf_out = i;
- if (azt_buf_bn[i] != bn) {
- azt_buf_out = -1;
- continue;
- }
- }
- if (nr_sectors > CURRENT->nr_sectors)
- nr_sectors = CURRENT->nr_sectors;
- memcpy(CURRENT->buffer, azt_buf + offs,
- nr_sectors * 512);
- CURRENT->nr_sectors -= nr_sectors;
- CURRENT->sector += nr_sectors;
- CURRENT->buffer += nr_sectors * 512;
- } else {
- azt_buf_out = -1;
- break;
- }
- }
-}
-
-static void do_aztcd_request(request_queue_t * q)
-{
-#ifdef AZT_TEST
- printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector,
- CURRENT->nr_sectors, jiffies);
-#endif
- if (DiskInfo.audio) {
- printk("aztcd: Error, tried to mount an Audio CD\n");
- end_request(CURRENT, 0);
- return;
- }
- azt_transfer_is_active = 1;
- while (current_valid()) {
- azt_transfer();
- if (CURRENT->nr_sectors == 0) {
- end_request(CURRENT, 1);
- } else {
- azt_buf_out = -1; /* Want to read a block not in buffer */
- if (azt_state == AZT_S_IDLE) {
- if ((!aztTocUpToDate) || aztDiskChanged) {
- if (aztUpdateToc() < 0) {
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- }
- azt_state = AZT_S_START;
- AztTries = 5;
- SET_TIMER(azt_poll, HZ / 100);
- }
- break;
- }
- }
- azt_transfer_is_active = 0;
-#ifdef AZT_TEST2
- printk
- ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
- azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
- printk(" do_aztcd_request ends Time:%li\n", jiffies);
-#endif
-}
-
-
-static void azt_invalidate_buffers(void)
-{
- int i;
-
-#ifdef AZT_DEBUG
- printk("aztcd: executing azt_invalidate_buffers\n");
-#endif
- for (i = 0; i < AZT_BUF_SIZ; ++i)
- azt_buf_bn[i] = -1;
- azt_buf_out = -1;
-}
-
-/*
- * Open the device special file. Check that a disk is in.
- */
-static int aztcd_open(struct inode *ip, struct file *fp)
-{
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztcd_open\n");
-#endif
-
- if (aztPresent == 0)
- return -ENXIO; /* no hardware */
-
- if (!azt_open_count && azt_state == AZT_S_IDLE) {
- azt_invalidate_buffers();
-
- st = getAztStatus(); /* check drive status */
- if (st == -1)
- goto err_out; /* drive doesn't respond */
-
- if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */
- printk("aztcd: Door Open?\n");
- aztCloseDoor();
- st = getAztStatus();
- }
-
- if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) { /*no disk in drive or changed */
- printk
- ("aztcd: Disk Changed or No Disk in Drive?\n");
- aztTocUpToDate = 0;
- }
- if (aztUpdateToc())
- goto err_out;
-
- }
- ++azt_open_count;
- aztLockDoor();
-
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztcd_open\n");
-#endif
- return 0;
-
- err_out:
- return -EIO;
-}
-
-
-/*
- * On close, we flush all azt blocks from the buffer cache.
- */
-static int aztcd_release(struct inode *inode, struct file *file)
-{
-#ifdef AZT_DEBUG
- printk("aztcd: executing aztcd_release\n");
- printk("inode: %p, device: %s file: %p\n", inode,
- inode->i_bdev->bd_disk->disk_name, file);
-#endif
- if (!--azt_open_count) {
- azt_invalidate_buffers();
- aztUnlockDoor();
- if (azt_auto_eject)
- aztSendCmd(ACMD_EJECT);
- CLEAR_TIMER;
- }
- return 0;
-}
-
-static struct gendisk *azt_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- */
-
-static int __init aztcd_init(void)
-{
- long int count, max_count;
- unsigned char result[50];
- int st;
- void* status = NULL;
- int i = 0;
- int ret = 0;
-
- if (azt_port == 0) {
- printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization");
- return -EIO;
- }
-
- printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM "
- "CD-ROM Driver\n");
- printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n");
- if (azt_port == -1) {
- printk
- ("aztcd: DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",
- AZT_VERSION);
- } else
- printk
- ("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",
- AZT_VERSION, azt_port);
- printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/"
- "Documentation/cdrom/aztcd\n");
-
-
-#ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */
- if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) {
- printk
- ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
- AZT_SW32_BASE_ADDR, AZT_SW32_INIT,
- AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG);
- return -EIO;
- } else {
- printk(KERN_INFO
- "aztcd: Soundwave32 card detected at %x Version %x\n",
- AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
- outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG);
- for (count = 0; count < 10000; count++); /*delay a bit */
- }
-#endif
-
- /* check for presence of drive */
-
- if (azt_port == -1) { /* autoprobing for proprietary interface */
- for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) {
- azt_port = azt_port_auto[i];
- printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x"
- "\n", azt_port);
- /*proprietary interfaces need 4 bytes */
- if (!request_region(azt_port, 4, "aztcd")) {
- continue;
- }
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */
-
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
- if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */
- break;
- }
- else { /* Drive not found on this port - try next one */
- release_region(azt_port, 4);
- }
- }
- if ((i == 16) || (azt_port_auto[i] == 0)) {
- printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
- return -EIO;
- }
- } else { /* no autoprobing */
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- status = request_region(azt_port, 8, "aztcd"); /*IDE-interfaces need 8 bytes */
- else
- status = request_region(azt_port, 4, "aztcd"); /*proprietary interfaces need 4 bytes */
- if (!status) {
- printk(KERN_WARNING "aztcd: conflict, I/O port (%X) "
- "already used\n", azt_port);
- return -EIO;
- }
-
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */
-
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */
-
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
-
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */
-#ifndef MODULE
- if (azt_cont != 0x79) {
- printk(KERN_WARNING "aztcd: no AZTECH CD-ROM "
- "drive found-Try boot parameter aztcd="
- "<BaseAddress>,0x79\n");
- ret = -EIO;
- goto err_out;
- }
-#else
- if (0) {
- }
-#endif
- else {
- printk(KERN_INFO "aztcd: drive reset - "
- "please wait\n");
- for (count = 0; count < 50; count++) {
- inb(STATUS_PORT); /*removing all data from earlier tries */
- inb(DATA_PORT);
- }
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- getAztStatus(); /*trap errors */
- outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
- STEN_LOW;
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
- printk(KERN_WARNING "aztcd: no AZTECH "
- "CD-ROM drive found\n");
- ret = -EIO;
- goto err_out;
- }
-
- for (count = 0; count < AZT_TIMEOUT;
- count++)
- barrier(); /* Stop gcc 2.96 being smart */
- /* use udelay(), damnit -- AV */
-
- if ((st = getAztStatus()) == -1) {
- printk(KERN_WARNING "aztcd: Drive Status"
- " Error Status=%x\n", st);
- ret = -EIO;
- goto err_out;
- }
-#ifdef AZT_DEBUG
- printk(KERN_DEBUG "aztcd: Status = %x\n", st);
-#endif
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*GetVersion */
- STEN_LOW;
- OP_OK;
- }
- }
- }
-
- azt_init_end = 1;
- STEN_LOW;
- result[0] = inb(DATA_PORT); /*reading in a null byte??? */
- for (count = 1; count < 50; count++) { /*Reading version string */
- aztTimeOutCount = 0; /*here we must implement STEN_LOW differently */
- do {
- aztIndatum = inb(STATUS_PORT); /*because we want to exit by timeout */
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break; /*all chars read? */
- result[count] = inb(DATA_PORT);
- }
- if (count > 30)
- max_count = 30; /*print max.30 chars of the version string */
- else
- max_count = count;
- printk(KERN_INFO "aztcd: FirmwareVersion=");
- for (count = 1; count < max_count; count++)
- printk("%c", result[count]);
- printk("<<>> ");
-
- if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) {
- printk("AZTECH drive detected\n");
- /*AZTECH*/}
- else if ((result[2] == 'C') && (result[3] == 'D')
- && (result[4] == 'D')) {
- printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES */
- } else if ((result[1] == 0x03) && (result[2] == '5')) {
- printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM */
- } else { /*OTHERS or none */
- printk("\nunknown drive or firmware version detected\n");
- printk
- ("aztcd may not run stable, if you want to try anyhow,\n");
- printk("boot with: aztcd=<BaseAddress>,0x79\n");
- if ((azt_cont != 0x79)) {
- printk("aztcd: FirmwareVersion=");
- for (count = 1; count < 5; count++)
- printk("%c", result[count]);
- printk("<<>> ");
- printk("Aborted\n");
- ret = -EIO;
- goto err_out;
- }
- }
- azt_disk = alloc_disk(1);
- if (!azt_disk)
- goto err_out;
-
- if (register_blkdev(MAJOR_NR, "aztcd")) {
- ret = -EIO;
- goto err_out2;
- }
-
- azt_queue = blk_init_queue(do_aztcd_request, &aztSpin);
- if (!azt_queue) {
- ret = -ENOMEM;
- goto err_out3;
- }
-
- blk_queue_hardsect_size(azt_queue, 2048);
- azt_disk->major = MAJOR_NR;
- azt_disk->first_minor = 0;
- azt_disk->fops = &azt_fops;
- sprintf(azt_disk->disk_name, "aztcd");
- azt_disk->queue = azt_queue;
- add_disk(azt_disk);
- azt_invalidate_buffers();
- aztPresent = 1;
- aztCloseDoor();
- return 0;
-err_out3:
- unregister_blkdev(MAJOR_NR, "aztcd");
-err_out2:
- put_disk(azt_disk);
-err_out:
- if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
- SWITCH_IDE_MASTER;
- release_region(azt_port, 8); /*IDE-interface */
- } else
- release_region(azt_port, 4); /*proprietary interface */
- return ret;
-
-}
-
-static void __exit aztcd_exit(void)
-{
- del_gendisk(azt_disk);
- put_disk(azt_disk);
- if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
- printk("What's that: can't unregister aztcd\n");
- return;
- }
- blk_cleanup_queue(azt_queue);
- if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
- SWITCH_IDE_MASTER;
- release_region(azt_port, 8); /*IDE-interface */
- } else
- release_region(azt_port, 4); /*proprietary interface */
- printk(KERN_INFO "aztcd module released.\n");
-}
-
-module_init(aztcd_init);
-module_exit(aztcd_exit);
-
-/*##########################################################################
- Aztcd State Machine: Controls Drive Operating State
- ##########################################################################
-*/
-static void azt_poll(void)
-{
- int st = 0;
- int loop_ctl = 1;
- int skip = 0;
-
- if (azt_error) {
- if (aztSendCmd(ACMD_GET_ERROR))
- RETURN("azt_poll 1");
- STEN_LOW;
- azt_error = inb(DATA_PORT) & 0xFF;
- printk("aztcd: I/O error 0x%02x\n", azt_error);
- azt_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
- if (AztTries == 5)
- printk
- ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n",
- azt_next_bn);
-#endif
- if (!AztTries--) {
- printk
- ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n",
- azt_next_bn);
- if (azt_transfer_is_active) {
- AztTries = 0;
- loop_ctl = 0;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- AztTries = 5;
- }
- azt_error = 0;
- azt_state = AZT_S_STOP;
- }
-
- while (loop_ctl) {
- loop_ctl = 0; /* each case must flip this back to 1 if we want
- to come back up here */
- switch (azt_state) {
-
- case AZT_S_IDLE:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_IDLE\n");
- }
-#endif
- return;
-
- case AZT_S_START:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_START\n");
- }
-#endif
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 2"); /*result will be checked by aztStatus() */
- azt_state =
- azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
- AztTimeout = 3000;
- break;
-
- case AZT_S_MODE:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_MODE\n");
- }
-#endif
- if (!skip) {
- if ((st = aztStatus()) != -1) {
- if ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- end_request(CURRENT, 0);
- printk
- ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
- }
- } else
- break;
- }
- skip = 0;
-
- if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- printk
- ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- printk((st & AST_DOOR_OPEN) ?
- "aztcd: door open\n" :
- "aztcd: disk removed\n");
- if (azt_transfer_is_active) {
- azt_state = AZT_S_START;
- loop_ctl = 1; /* goto immediately */
- break;
- }
- azt_state = AZT_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
-
-/* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
- outb(0x01, DATA_PORT);
- PA_OK;
- STEN_LOW;
-*/
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 4");
- STEN_LOW;
- azt_mode = 1;
- azt_state = AZT_S_READ;
- AztTimeout = 3000;
-
- break;
-
-
- case AZT_S_READ:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_READ\n");
- }
-#endif
- if (!skip) {
- if ((st = aztStatus()) != -1) {
- if ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- printk
- ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- }
- } else
- break;
- }
-
- skip = 0;
- if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- printk((st & AST_DOOR_OPEN) ?
- "aztcd: door open\n" :
- "aztcd: disk removed\n");
- if (azt_transfer_is_active) {
- azt_state = AZT_S_START;
- loop_ctl = 1;
- break;
- }
- azt_state = AZT_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
-
- if (current_valid()) {
- struct azt_Play_msf msf;
- int i;
- azt_next_bn = CURRENT->sector / 4;
- azt_hsg2msf(azt_next_bn, &msf.start);
- i = 0;
- /* find out in which track we are */
- while (azt_msf2hsg(&msf.start) >
- azt_msf2hsg(&Toc[++i].trackTime)) {
- };
- if (azt_msf2hsg(&msf.start) <
- azt_msf2hsg(&Toc[i].trackTime) -
- AZT_BUF_SIZ) {
- azt_read_count = AZT_BUF_SIZ; /*fast, because we read ahead */
- /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead */
- } else /* don't read beyond end of track */
-#if AZT_MULTISESSION
- {
- azt_read_count =
- (azt_msf2hsg(&Toc[i].trackTime)
- / 4) * 4 -
- azt_msf2hsg(&msf.start);
- if (azt_read_count < 0)
- azt_read_count = 0;
- if (azt_read_count > AZT_BUF_SIZ)
- azt_read_count =
- AZT_BUF_SIZ;
- printk
- ("aztcd: warning - trying to read beyond end of track\n");
-/* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
-*/ }
-#else
- {
- azt_read_count = AZT_BUF_SIZ;
- }
-#endif
- msf.end.min = 0;
- msf.end.sec = 0;
- msf.end.frame = azt_read_count; /*Mitsumi here reads 0xffffff sectors */
-#ifdef AZT_TEST3
- printk
- ("---reading msf-address %x:%x:%x %x:%x:%x\n",
- msf.start.min, msf.start.sec,
- msf.start.frame, msf.end.min,
- msf.end.sec, msf.end.frame);
- printk
- ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
- azt_next_bn, azt_buf_in, azt_buf_out,
- azt_buf_bn[azt_buf_in]);
-#endif
- if (azt_read_mode == AZT_MODE_2) {
- sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode */
- } else {
- sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode */
- }
- azt_state = AZT_S_DATA;
- AztTimeout = READ_TIMEOUT;
- } else {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
-
- break;
-
-
- case AZT_S_DATA:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_DATA\n");
- }
-#endif
-
- st = inb(STATUS_PORT) & AFL_STATUSorDATA;
-
- switch (st) {
-
- case AFL_DATA:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk("---AFL_DATA st:%x\n", st);
- }
-#endif
- if (!AztTries--) {
- printk
- ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n",
- azt_next_bn);
- if (azt_transfer_is_active) {
- AztTries = 0;
- break;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- AztTries = 5;
- }
- azt_state = AZT_S_START;
- AztTimeout = READ_TIMEOUT;
- loop_ctl = 1;
- break;
-
- case AFL_STATUSorDATA:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk
- ("---AFL_STATUSorDATA st:%x\n",
- st);
- }
-#endif
- break;
-
- default:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk("---default: st:%x\n", st);
- }
-#endif
- AztTries = 5;
- if (!current_valid() && azt_buf_in == azt_buf_out) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- if (azt_read_count <= 0)
- printk
- ("aztcd: warning - try to read 0 frames\n");
- while (azt_read_count) { /*??? fast read ahead loop */
- azt_buf_bn[azt_buf_in] = -1;
- DTEN_LOW; /*??? unsolved problem, very
- seldom we get timeouts
- here, don't now the real
- reason. With my drive this
- sometimes also happens with
- Aztech's original driver under
- DOS. Is it a hardware bug?
- I tried to recover from such
- situations here. Zimmermann */
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk
- ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n",
- azt_read_count,
- CURRENT->nr_sectors,
- azt_buf_in);
- printk
- ("azt_transfer_is_active:%x\n",
- azt_transfer_is_active);
- azt_read_count = 0;
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- end_request(CURRENT, 1); /*should we have here (1) or (0)? */
- } else {
- if (azt_read_mode ==
- AZT_MODE_2) {
- insb(DATA_PORT,
- azt_buf +
- CD_FRAMESIZE_RAW
- * azt_buf_in,
- CD_FRAMESIZE_RAW);
- } else {
- insb(DATA_PORT,
- azt_buf +
- CD_FRAMESIZE *
- azt_buf_in,
- CD_FRAMESIZE);
- }
- azt_read_count--;
-#ifdef AZT_TEST3
- printk
- ("AZT_S_DATA; ---I've read data- read_count: %d\n",
- azt_read_count);
- printk
- ("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n",
- azt_next_bn,
- azt_buf_in,
- azt_buf_out,
- azt_buf_bn
- [azt_buf_in]);
-#endif
- azt_buf_bn[azt_buf_in] =
- azt_next_bn++;
- if (azt_buf_out == -1)
- azt_buf_out =
- azt_buf_in;
- azt_buf_in =
- azt_buf_in + 1 ==
- AZT_BUF_SIZ ? 0 :
- azt_buf_in + 1;
- }
- }
- if (!azt_transfer_is_active) {
- while (current_valid()) {
- azt_transfer();
- if (CURRENT->nr_sectors ==
- 0)
- end_request(CURRENT, 1);
- else
- break;
- }
- }
-
- if (current_valid()
- && (CURRENT->sector / 4 < azt_next_bn
- || CURRENT->sector / 4 >
- azt_next_bn + AZT_BUF_SIZ)) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- AztTimeout = READ_TIMEOUT;
- if (azt_read_count == 0) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- break;
- }
- break;
-
-
- case AZT_S_STOP:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_STOP\n");
- }
-#endif
- if (azt_read_count != 0)
- printk("aztcd: discard data=%x frames\n",
- azt_read_count);
- while (azt_read_count != 0) {
- int i;
- if (!(inb(STATUS_PORT) & AFL_DATA)) {
- if (azt_read_mode == AZT_MODE_2)
- for (i = 0;
- i < CD_FRAMESIZE_RAW;
- i++)
- inb(DATA_PORT);
- else
- for (i = 0;
- i < CD_FRAMESIZE; i++)
- inb(DATA_PORT);
- }
- azt_read_count--;
- }
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 5");
- azt_state = AZT_S_STOPPING;
- AztTimeout = 1000;
- break;
-
- case AZT_S_STOPPING:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_STOPPING\n");
- }
-#endif
-
- if ((st = aztStatus()) == -1 && AztTimeout)
- break;
-
- if ((st != -1)
- && ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY))) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- printk
- ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- }
-
-#ifdef AZT_TEST3
- printk("CURRENT_VALID %d azt_mode %d\n",
- current_valid(), azt_mode);
-#endif
-
- if (current_valid()) {
- if (st != -1) {
- if (azt_mode == 1) {
- azt_state = AZT_S_READ;
- loop_ctl = 1;
- skip = 1;
- break;
- } else {
- azt_state = AZT_S_MODE;
- loop_ctl = 1;
- skip = 1;
- break;
- }
- } else {
- azt_state = AZT_S_START;
- AztTimeout = 1;
- }
- } else {
- azt_state = AZT_S_IDLE;
- return;
- }
- break;
-
- default:
- printk("aztcd: invalid state %d\n", azt_state);
- return;
- } /* case */
- } /* while */
-
-
- if (!AztTimeout--) {
- printk("aztcd: timeout in state %d\n", azt_state);
- azt_state = AZT_S_STOP;
- if (aztSendCmd(ACMD_STOP))
- RETURN("azt_poll 6");
- STEN_LOW_WAIT;
- };
-
- SET_TIMER(azt_poll, HZ / 100);
-}
-
-
-/*###########################################################################
- * Miscellaneous support functions
- ###########################################################################
-*/
-static void azt_hsg2msf(long hsg, struct msf *msf)
-{
- hsg += 150;
- msf->min = hsg / 4500;
- hsg %= 4500;
- msf->sec = hsg / 75;
- msf->frame = hsg % 75;
-#ifdef AZT_DEBUG
- if (msf->min >= 70)
- printk("aztcd: Error hsg2msf address Minutes\n");
- if (msf->sec >= 60)
- printk("aztcd: Error hsg2msf address Seconds\n");
- if (msf->frame >= 75)
- printk("aztcd: Error hsg2msf address Frames\n");
-#endif
- azt_bin2bcd(&msf->min); /* convert to BCD */
- azt_bin2bcd(&msf->sec);
- azt_bin2bcd(&msf->frame);
-}
-
-static long azt_msf2hsg(struct msf *mp)
-{
- return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75
- + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET;
-}
-
-static void azt_bin2bcd(unsigned char *p)
-{
- int u, t;
-
- u = *p % 10;
- t = *p / 10;
- *p = u | (t << 4);
-}
-
-static int azt_bcd2bin(unsigned char bcd)
-{
- return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR);
diff --git a/drivers/cdrom/aztcd.h b/drivers/cdrom/aztcd.h
deleted file mode 100644
index 057501e31628..000000000000
--- a/drivers/cdrom/aztcd.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id: aztcd.h,v 2.60 1997/11/29 09:51:22 root Exp root $
- *
- * Definitions for a AztechCD268 CD-ROM interface
- * Copyright (C) 1994-98 Werner Zimmermann
- *
- * based on Mitsumi CDROM driver by Martin Harriss
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * History: W.Zimmermann adaption to Aztech CD268-01A Version 1.3
- * October 1994 Email: Werner.Zimmermann@fht-esslingen.de
- */
-
-/* *** change this to set the I/O port address of your CD-ROM drive,
- set to '-1', if you want autoprobing */
-#define AZT_BASE_ADDR -1
-
-/* list of autoprobing addresses (not more than 15), last value must be 0x000
- Note: Autoprobing is only enabled, if AZT_BASE_ADDR is set to '-1' ! */
-#define AZT_BASE_AUTO { 0x320, 0x300, 0x310, 0x330, 0x000 }
-
-/* Uncomment this, if your CDROM is connected to a Soundwave32-soundcard
- and configure AZT_BASE_ADDR and AZT_SW32_BASE_ADDR */
-/*#define AZT_SW32 1
-*/
-
-#ifdef AZT_SW32
-#define AZT_SW32_BASE_ADDR 0x220 /*I/O port base address of your soundcard*/
-#endif
-
-/* Set this to 1, if you want your tray to be locked, set to 0 to prevent tray
- from locking */
-#define AZT_ALLOW_TRAY_LOCK 1
-
-/*Set this to 1 to allow auto-eject when unmounting a disk, set to 0, if you
- don't want the auto-eject feature*/
-#define AZT_AUTO_EJECT 0
-
-/*Set this to 1, if you want to use incompatible ioctls for reading in raw and
- cooked mode */
-#define AZT_PRIVATE_IOCTLS 1
-
-/*Set this to 1, if you want multisession support by the ISO fs. Even if you set
- this value to '0' you can use multisession CDs. In that case the drive's firm-
- ware will do the appropriate redirection automatically. The CD will then look
- like a single session CD (but nevertheless all data may be read). Please read
- chapter '5.1 Multisession support' in README.aztcd for details. Normally it's
- uncritical to leave this setting untouched */
-#define AZT_MULTISESSION 1
-
-/*Uncomment this, if you are using a linux kernel version prior to 2.1.0 */
-/*#define AZT_KERNEL_PRIOR_2_1 */
-
-/*---------------------------------------------------------------------------*/
-/*-----nothing to be configured for normal applications below this line------*/
-
-
-/* Increase this if you get lots of timeouts; if you get kernel panic, replace
- STEN_LOW_WAIT by STEN_LOW in the source code */
-#define AZT_STATUS_DELAY 400 /*for timer wait, STEN_LOW_WAIT*/
-#define AZT_TIMEOUT 8000000 /*for busy wait STEN_LOW, DTEN_LOW*/
-#define AZT_FAST_TIMEOUT 10000 /*for reading the version string*/
-
-/* number of times to retry a command before giving up */
-#define AZT_RETRY_ATTEMPTS 3
-
-/* port access macros */
-#define CMD_PORT azt_port
-#define DATA_PORT azt_port
-#define STATUS_PORT azt_port+1
-#define MODE_PORT azt_port+2
-#ifdef AZT_SW32
- #define AZT_SW32_INIT (unsigned int) (0xFF00 & (AZT_BASE_ADDR*16))
- #define AZT_SW32_CONFIG_REG AZT_SW32_BASE_ADDR+0x16 /*Soundwave32 Config. Register*/
- #define AZT_SW32_ID_REG AZT_SW32_BASE_ADDR+0x04 /*Soundwave32 ID Version Register*/
-#endif
-
-/* status bits */
-#define AST_CMD_CHECK 0x80 /* 1 = command error */
-#define AST_DOOR_OPEN 0x40 /* 1 = door is open */
-#define AST_NOT_READY 0x20 /* 1 = no disk in the drive */
-#define AST_DSK_CHG 0x02 /* 1 = disk removed or changed */
-#define AST_MODE 0x01 /* 0=MODE1, 1=MODE2 */
-#define AST_MODE_BITS 0x1C /* Mode Bits */
-#define AST_INITIAL 0x0C /* initial, only valid ... */
-#define AST_BUSY 0x04 /* now playing, only valid
- in combination with mode
- bits */
-/* flag bits */
-#define AFL_DATA 0x02 /* data available if low */
-#define AFL_STATUS 0x04 /* status available if low */
-#define AFL_OP_OK 0x01 /* OP_OK command correct*/
-#define AFL_PA_OK 0x02 /* PA_OK parameter correct*/
-#define AFL_OP_ERR 0x05 /* error in command*/
-#define AFL_PA_ERR 0x06 /* error in parameters*/
-#define POLLED 0x04 /* polled mode */
-
-/* commands */
-#define ACMD_SOFT_RESET 0x10 /* reset drive */
-#define ACMD_PLAY_READ 0x20 /* read data track in cooked mode */
-#define ACMD_PLAY_READ_RAW 0x21 /* reading in raw mode*/
-#define ACMD_SEEK 0x30 /* seek msf address*/
-#define ACMD_SEEK_TO_LEADIN 0x31 /* seek to leadin track*/
-#define ACMD_GET_ERROR 0x40 /* get error code */
-#define ACMD_GET_STATUS 0x41 /* get status */
-#define ACMD_GET_Q_CHANNEL 0x50 /* read info from q channel */
-#define ACMD_EJECT 0x60 /* eject/open tray */
-#define ACMD_CLOSE 0x61 /* close tray */
-#define ACMD_LOCK 0x71 /* lock tray closed */
-#define ACMD_UNLOCK 0x72 /* unlock tray */
-#define ACMD_PAUSE 0x80 /* pause */
-#define ACMD_STOP 0x81 /* stop play */
-#define ACMD_PLAY_AUDIO 0x90 /* play audio track */
-#define ACMD_SET_VOLUME 0x93 /* set audio level */
-#define ACMD_GET_VERSION 0xA0 /* get firmware version */
-#define ACMD_SET_DISK_TYPE 0xA1 /* set disk data mode */
-
-#define MAX_TRACKS 104
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct azt_Play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct azt_DiskInfo {
- unsigned char first;
- unsigned char next;
- unsigned char last;
- struct msf diskLength;
- struct msf firstTrack;
- unsigned char multi;
- struct msf nextSession;
- struct msf lastSession;
- unsigned char xa;
- unsigned char audio;
-};
-
-struct azt_Toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char pointIndex;
- struct msf trackTime;
- struct msf diskTime;
-};
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 3625a05bc3d3..aa5468f487ba 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -302,7 +302,7 @@ module_param(lockdoor, bool, 0);
module_param(check_media_type, bool, 0);
module_param(mrw_format_restart, bool, 0);
-static DEFINE_SPINLOCK(cdrom_lock);
+static DEFINE_MUTEX(cdrom_mutex);
static const char *mrw_format_status[] = {
"not mrw",
@@ -438,10 +438,10 @@ int register_cdrom(struct cdrom_device_info *cdi)
cdo->generic_packet = cdrom_dummy_generic_packet;
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
- spin_lock(&cdrom_lock);
+ mutex_lock(&cdrom_mutex);
cdi->next = topCdromPtr;
topCdromPtr = cdi;
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
return 0;
}
#undef ENSURE
@@ -452,7 +452,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
cdinfo(CD_OPEN, "entering unregister_cdrom\n");
prev = NULL;
- spin_lock(&cdrom_lock);
+ mutex_lock(&cdrom_mutex);
cdi = topCdromPtr;
while (cdi && cdi != unreg) {
prev = cdi;
@@ -460,7 +460,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
}
if (cdi == NULL) {
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
return -2;
}
if (prev)
@@ -468,7 +468,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
else
topCdromPtr = cdi->next;
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
if (cdi->exit)
cdi->exit(cdi);
@@ -3289,103 +3289,137 @@ static struct cdrom_sysctl_settings {
int check; /* check media type */
} cdrom_sysctl_settings;
+enum cdrom_print_option {
+ CTL_NAME,
+ CTL_SPEED,
+ CTL_SLOTS,
+ CTL_CAPABILITY
+};
+
+static int cdrom_print_info(const char *header, int val, char *info,
+ int *pos, enum cdrom_print_option option)
+{
+ const int max_size = sizeof(cdrom_sysctl_settings.info);
+ struct cdrom_device_info *cdi;
+ int ret;
+
+ ret = scnprintf(info + *pos, max_size - *pos, header);
+ if (!ret)
+ return 1;
+
+ *pos += ret;
+
+ for (cdi = topCdromPtr; cdi; cdi = cdi->next) {
+ switch (option) {
+ case CTL_NAME:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%s", cdi->name);
+ break;
+ case CTL_SPEED:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", cdi->speed);
+ break;
+ case CTL_SLOTS:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", cdi->capacity);
+ break;
+ case CTL_CAPABILITY:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", CDROM_CAN(val) != 0);
+ break;
+ default:
+ printk(KERN_INFO "cdrom: invalid option%d\n", option);
+ return 1;
+ }
+ if (!ret)
+ return 1;
+ *pos += ret;
+ }
+
+ return 0;
+}
+
static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- int pos;
- struct cdrom_device_info *cdi;
+ int pos;
char *info = cdrom_sysctl_settings.info;
+ const int max_size = sizeof(cdrom_sysctl_settings.info);
if (!*lenp || (*ppos && !write)) {
*lenp = 0;
return 0;
}
+ mutex_lock(&cdrom_mutex);
+
pos = sprintf(info, "CD-ROM information, " VERSION "\n");
- pos += sprintf(info+pos, "\ndrive name:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%s", cdi->name);
-
- pos += sprintf(info+pos, "\ndrive speed:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", cdi->speed);
-
- pos += sprintf(info+pos, "\ndrive # of slots:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", cdi->capacity);
-
- pos += sprintf(info+pos, "\nCan close tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0);
-
- pos += sprintf(info+pos, "\nCan open tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0);
-
- pos += sprintf(info+pos, "\nCan lock tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0);
-
- pos += sprintf(info+pos, "\nCan change speed:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0);
-
- pos += sprintf(info+pos, "\nCan select disk:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0);
-
- pos += sprintf(info+pos, "\nCan read multisession:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0);
-
- pos += sprintf(info+pos, "\nCan read MCN:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0);
-
- pos += sprintf(info+pos, "\nReports media changed:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0);
-
- pos += sprintf(info+pos, "\nCan play audio:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0);
-
- pos += sprintf(info+pos, "\nCan write CD-R:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0);
-
- pos += sprintf(info+pos, "\nCan write CD-RW:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0);
-
- pos += sprintf(info+pos, "\nCan read DVD:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0);
-
- pos += sprintf(info+pos, "\nCan write DVD-R:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0);
-
- pos += sprintf(info+pos, "\nCan write DVD-RAM:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
-
- pos += sprintf(info+pos, "\nCan read MRW:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0);
-
- pos += sprintf(info+pos, "\nCan write MRW:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
-
- pos += sprintf(info+pos, "\nCan write RAM:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
-
- strcpy(info+pos,"\n\n");
-
- return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+ if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
+ goto done;
+ if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
+ goto done;
+ if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
+ goto done;
+ if (cdrom_print_info("\nCan close tray:\t",
+ CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan open tray:\t",
+ CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan lock tray:\t",
+ CDC_LOCK, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan change speed:",
+ CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan select disk:",
+ CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read multisession:",
+ CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read MCN:\t",
+ CDC_MCN, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nReports media changed:",
+ CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan play audio:\t",
+ CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write CD-R:\t",
+ CDC_CD_R, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write CD-RW:",
+ CDC_CD_RW, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read DVD:\t",
+ CDC_DVD, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write DVD-R:",
+ CDC_DVD_R, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write DVD-RAM:",
+ CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read MRW:\t",
+ CDC_MRW, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write MRW:\t",
+ CDC_MRW_W, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write RAM:\t",
+ CDC_RAM, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (!scnprintf(info + pos, max_size - pos, "\n\n"))
+ goto done;
+doit:
+ mutex_unlock(&cdrom_mutex);
+ return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+done:
+ printk(KERN_INFO "cdrom: info buffer too small\n");
+ goto doit;
}
/* Unfortunately, per device settings are not implemented through
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
deleted file mode 100644
index 2157c58755e0..000000000000
--- a/drivers/cdrom/cdu31a.c
+++ /dev/null
@@ -1,3251 +0,0 @@
-/*
-* Sony CDU-31A CDROM interface device driver.
-*
-* Corey Minyard (minyard@wf-rch.cirr.com)
-*
-* Colossians 3:17
-*
-* See Documentation/cdrom/cdu31a for additional details about this driver.
-*
-* The Sony interface device driver handles Sony interface CDROM
-* drives and provides a complete block-level interface as well as an
-* ioctl() interface compatible with the Sun (as specified in
-* include/linux/cdrom.h). With this interface, CDROMs can be
-* accessed and standard audio CDs can be played back normally.
-*
-* WARNING - All autoprobes have been removed from the driver.
-* You MUST configure the CDU31A via a LILO config
-* at boot time or in lilo.conf. I have the
-* following in my lilo.conf:
-*
-* append="cdu31a=0x1f88,0,PAS"
-*
-* The first number is the I/O base address of the
-* card. The second is the interrupt (0 means none).
- * The third should be "PAS" if on a Pro-Audio
- * spectrum, or nothing if on something else.
- *
- * This interface is (unfortunately) a polled interface. This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables. Some (like mine) do not even have the capability to
- * handle interrupts or DMA. For this reason you will see a lot of
- * the following:
- *
- * retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
- * while (time_before(jiffies, retry_count) && (! <some condition to wait for))
- * {
- * while (handle_sony_cd_attention())
- * ;
- *
- * sony_sleep();
- * }
- * if (the condition not met)
- * {
- * return an error;
- * }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try. it also handles attentions, which are
- * asynchronous events from the drive informing the driver that a disk
- * has been inserted, removed, etc.
- *
- * NEWS FLASH - The driver now supports interrupts but they are
- * turned off by default. Use of interrupts is highly encouraged, it
- * cuts CPU usage down to a reasonable level. I had DMA in for a while
- * but PC DMA is just too slow. Better to just insb() it.
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk. The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal. A lot of conversion goes on.
- *
- * DRIVER SPECIAL FEATURES
- * -----------------------
- *
- * This section describes features beyond the normal audio and CD-ROM
- * functions of the drive.
- *
- * XA compatibility
- *
- * The driver should support XA disks for both the CDU31A and CDU33A.
- * It does this transparently, the using program doesn't need to set it.
- *
- * Multi-Session
- *
- * A multi-session disk looks just like a normal disk to the user.
- * Just mount one normally, and all the data should be there.
- * A special thanks to Koen for help with this!
- *
- * Raw sector I/O
- *
- * Using the CDROMREADAUDIO it is possible to read raw audio and data
- * tracks. Both operations return 2352 bytes per sector. On the data
- * tracks, the first 12 bytes is not returned by the drive and the value
- * of that data is indeterminate.
- *
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * TODO:
- * CDs with form1 and form2 sectors cause problems
- * with current read-ahead strategy.
- *
- * Credits:
- * Heiko Eissfeldt <heiko@colossus.escape.de>
- * For finding abug in the return of the track numbers.
- * TOC processing redone for proper multisession support.
- *
- *
- * It probably a little late to be adding a history, but I guess I
- * will start.
- *
- * 10/24/95 - Added support for disabling the eject button when the
- * drive is open. Note that there is a small problem
- * still here, if the eject button is pushed while the
- * drive light is flashing, the drive will return a bad
- * status and be reset. It recovers, though.
- *
- * 03/07/97 - Fixed a problem with timers.
- *
- *
- * 18 Spetember 1997 -- Ported to Uniform CD-ROM driver by
- * Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- * changes by Erik Andersen <andersee@debian.org>
- *
- * 24 January 1998 -- Removed the scd_disc_status() function, which was now
- * just dead code left over from the port.
- * Erik Andersen <andersee@debian.org>
- *
- * 16 July 1998 -- Drive donated to Erik Andersen by John Kodis
- * <kodis@jagunet.com>. Work begun on fixing driver to
- * work under 2.1.X. Added temporary extra printks
- * which seem to slow it down enough to work.
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 22 October 2004 -- Make the driver work in 2.6.X
- * Added workaround to fix hard lockups on eject
- * Fixed door locking problem after mounting empty drive
- * Set double-speed drives to double speed by default
- * Removed all readahead things - not needed anymore
- * Ondrej Zary <rainbow@rainbow-software.org>
-*/
-
-#define DEBUG 1
-
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/cdrom.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/dma.h>
-
-#include "cdu31a.h"
-
-#define MAJOR_NR CDU31A_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
-
-#define PFX "CDU31A: "
-
-/*
-** Edit the following data to change interrupts, DMA channels, etc.
-** Default is polled and no DMA. DMA is not recommended for double-speed
-** drives.
-*/
-static struct {
- unsigned short base; /* I/O Base Address */
- short int_num; /* Interrupt Number (-1 means scan for it,
- 0 means don't use) */
-} cdu31a_addresses[] __initdata = {
- {0}
-};
-
-static int handle_sony_cd_attention(void);
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int scd_spinup(void);
-/*static int scd_open(struct inode *inode, struct file *filp);*/
-static int scd_open(struct cdrom_device_info *, int);
-static void do_sony_cd_cmd(unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer,
- unsigned int *result_size);
-static void size_to_buf(unsigned int size, unsigned char *buf);
-
-/* Parameters for the read-ahead. */
-static unsigned int sony_next_block; /* Next 512 byte block offset */
-static unsigned int sony_blocks_left = 0; /* Number of 512 byte blocks left
- in the current read command. */
-
-
-/* The base I/O address of the Sony Interface. This is a variable (not a
- #define) so it can be easily changed via some future ioctl() */
-static unsigned int cdu31a_port = 0;
-module_param(cdu31a_port, uint, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive. The
- * comment for the base address also applies here.
- */
-static volatile unsigned short sony_cd_cmd_reg;
-static volatile unsigned short sony_cd_param_reg;
-static volatile unsigned short sony_cd_write_reg;
-static volatile unsigned short sony_cd_control_reg;
-static volatile unsigned short sony_cd_status_reg;
-static volatile unsigned short sony_cd_result_reg;
-static volatile unsigned short sony_cd_read_reg;
-static volatile unsigned short sony_cd_fifost_reg;
-
-static struct request_queue *cdu31a_queue;
-static DEFINE_SPINLOCK(cdu31a_lock); /* queue lock */
-
-static int sony_spun_up = 0; /* Has the drive been spun up? */
-
-static int sony_speed = 0; /* Last wanted speed */
-
-static int sony_xa_mode = 0; /* Is an XA disk in the drive
- and the drive a CDU31A? */
-
-static int sony_raw_data_mode = 1; /* 1 if data tracks, 0 if audio.
- For raw data reads. */
-
-static unsigned int sony_usage = 0; /* How many processes have the
- drive open. */
-
-static int sony_pas_init = 0; /* Initialize the Pro-Audio
- Spectrum card? */
-
-static struct s_sony_session_toc single_toc; /* Holds the
- table of
- contents. */
-
-static struct s_all_sessions_toc sony_toc; /* entries gathered from all
- sessions */
-
-static int sony_toc_read = 0; /* Has the TOC been read for
- the drive? */
-
-static struct s_sony_subcode last_sony_subcode; /* Points to the last
- subcode address read */
-
-static DECLARE_MUTEX(sony_sem); /* Semaphore for drive hardware access */
-
-static int is_double_speed = 0; /* does the drive support double speed ? */
-
-static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play. The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over. This holds the
- * position during a pause so a resume can restart it. It uses the
- * audio status variable above to tell if it is paused.
- */
-static unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 };
-static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
-
-/* What IRQ is the drive using? 0 if none. */
-static int cdu31a_irq = 0;
-module_param(cdu31a_irq, int, 0);
-
-/* The interrupt handler will wake this queue up when it gets an
- interrupts. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
-static int irq_flag = 0;
-
-static int curr_control_reg = 0; /* Current value of the control register */
-
-/* A disk changed variable. When a disk change is detected, it will
- all be set to TRUE. As the upper layers ask for disk_changed status
- it will be cleared. */
-static char disk_changed;
-
-/* This was readahead_buffer once... Now it's used only for audio reads */
-static char audio_buffer[CD_FRAMESIZE_RAW];
-
-/* Used to time a short period to abort an operation after the
- drive has been idle for a while. This keeps the light on
- the drive from flashing for very long. */
-static struct timer_list cdu31a_abort_timer;
-
-/* Marks if the timeout has started an abort read. This is used
- on entry to the drive to tell the code to read out the status
- from the abort read. */
-static int abort_read_started = 0;
-
-/*
- * Uniform cdrom interface function
- * report back, if disc has changed from time of last request.
- */
-static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- int retval;
-
- retval = disk_changed;
- disk_changed = 0;
-
- return retval;
-}
-
-/*
- * Uniform cdrom interface function
- * report back, if drive is ready
- */
-static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- if (CDSL_CURRENT != slot_nr)
- /* we have no changer support */
- return -EINVAL;
- if (sony_spun_up)
- return CDS_DISC_OK;
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (scd_spinup() == 0)
- sony_spun_up = 1;
- up(&sony_sem);
- return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
-}
-
-static inline void enable_interrupts(void)
-{
- curr_control_reg |= (SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-}
-
-static inline void disable_interrupts(void)
-{
- curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-}
-
-/*
- * Wait a little while (used for polling the drive). If in initialization,
- * setting a timeout doesn't work, so just loop for a while.
- */
-static inline void sony_sleep(void)
-{
- if (cdu31a_irq <= 0) {
- yield();
- } else { /* Interrupt driven */
- DEFINE_WAIT(w);
- int first = 1;
-
- while (1) {
- prepare_to_wait(&cdu31a_irq_wait, &w,
- TASK_INTERRUPTIBLE);
- if (first) {
- enable_interrupts();
- first = 0;
- }
-
- if (irq_flag != 0)
- break;
- if (!signal_pending(current)) {
- schedule();
- continue;
- } else
- disable_interrupts();
- break;
- }
- finish_wait(&cdu31a_irq_wait, &w);
- irq_flag = 0;
- }
-}
-
-
-/*
- * The following are convenience routine to read various status and set
- * various conditions in the drive.
- */
-static inline int is_attention(void)
-{
- return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0;
-}
-
-static inline int is_busy(void)
-{
- return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0;
-}
-
-static inline int is_data_ready(void)
-{
- return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0;
-}
-
-static inline int is_data_requested(void)
-{
- return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0;
-}
-
-static inline int is_result_ready(void)
-{
- return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0;
-}
-
-static inline int is_param_write_rdy(void)
-{
- return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0;
-}
-
-static inline int is_result_reg_not_empty(void)
-{
- return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0;
-}
-
-static inline void reset_drive(void)
-{
- curr_control_reg = 0;
- sony_toc_read = 0;
- outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
-}
-
-/*
- * Uniform cdrom interface function
- * reset drive and return when it is ready
- */
-static int scd_reset(struct cdrom_device_info *cdi)
-{
- unsigned long retry_count;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- reset_drive();
-
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count) && (!is_attention())) {
- sony_sleep();
- }
-
- up(&sony_sem);
- return 0;
-}
-
-static inline void clear_attention(void)
-{
- outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_result_ready(void)
-{
- outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_data_ready(void)
-{
- outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT,
- sony_cd_control_reg);
-}
-
-static inline void clear_param_reg(void)
-{
- outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline unsigned char read_status_register(void)
-{
- return inb(sony_cd_status_reg);
-}
-
-static inline unsigned char read_result_register(void)
-{
- return inb(sony_cd_result_reg);
-}
-
-static inline unsigned char read_data_register(void)
-{
- return inb(sony_cd_read_reg);
-}
-
-static inline void write_param(unsigned char param)
-{
- outb(param, sony_cd_param_reg);
-}
-
-static inline void write_cmd(unsigned char cmd)
-{
- outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT,
- sony_cd_control_reg);
- outb(cmd, sony_cd_cmd_reg);
-}
-
-static irqreturn_t cdu31a_interrupt(int irq, void *dev_id)
-{
- unsigned char val;
-
- if (abort_read_started) {
- /* We might be waiting for an abort to finish. Don't
- disable interrupts yet, though, because we handle
- this one here. */
- /* Clear out the result registers. */
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
-
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
- abort_read_started = 0;
-
- /* If something was waiting, wake it up now. */
- if (waitqueue_active(&cdu31a_irq_wait)) {
- disable_interrupts();
- irq_flag = 1;
- wake_up_interruptible(&cdu31a_irq_wait);
- }
- } else if (waitqueue_active(&cdu31a_irq_wait)) {
- disable_interrupts();
- irq_flag = 1;
- wake_up_interruptible(&cdu31a_irq_wait);
- } else {
- disable_interrupts();
- printk(KERN_NOTICE PFX
- "Got an interrupt but nothing was waiting\n");
- }
- return IRQ_HANDLED;
-}
-
-/*
- * give more verbose error messages
- */
-static unsigned char *translate_error(unsigned char err_code)
-{
- static unsigned char errbuf[80];
-
- switch (err_code) {
- case 0x10: return "illegal command ";
- case 0x11: return "illegal parameter ";
-
- case 0x20: return "not loaded ";
- case 0x21: return "no disc ";
- case 0x22: return "not spinning ";
- case 0x23: return "spinning ";
- case 0x25: return "spindle servo ";
- case 0x26: return "focus servo ";
- case 0x29: return "eject mechanism ";
- case 0x2a: return "audio playing ";
- case 0x2c: return "emergency eject ";
-
- case 0x30: return "focus ";
- case 0x31: return "frame sync ";
- case 0x32: return "subcode address ";
- case 0x33: return "block sync ";
- case 0x34: return "header address ";
-
- case 0x40: return "illegal track read ";
- case 0x41: return "mode 0 read ";
- case 0x42: return "illegal mode read ";
- case 0x43: return "illegal block size read ";
- case 0x44: return "mode read ";
- case 0x45: return "form read ";
- case 0x46: return "leadout read ";
- case 0x47: return "buffer overrun ";
-
- case 0x53: return "unrecoverable CIRC ";
- case 0x57: return "unrecoverable LECC ";
-
- case 0x60: return "no TOC ";
- case 0x61: return "invalid subcode data ";
- case 0x63: return "focus on TOC read ";
- case 0x64: return "frame sync on TOC read ";
- case 0x65: return "TOC data ";
-
- case 0x70: return "hardware failure ";
- case 0x91: return "leadin ";
- case 0x92: return "leadout ";
- case 0x93: return "data track ";
- }
- sprintf(errbuf, "unknown 0x%02x ", err_code);
- return errbuf;
-}
-
-/*
- * Set the drive parameters so the drive will auto-spin-up when a
- * disk is inserted.
- */
-static void set_drive_params(int want_doublespeed)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[3];
-
-
- params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME;
- params[1] = 0x00; /* Never spin down the drive. */
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX
- "Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
- }
-
- params[0] = SONY_SD_MECH_CONTROL;
- params[1] = SONY_AUTO_SPIN_UP_BIT; /* Set auto spin up */
-
- if (is_auto_eject)
- params[1] |= SONY_AUTO_EJECT_BIT;
-
- if (is_double_speed && want_doublespeed) {
- params[1] |= SONY_DOUBLE_SPEED_BIT; /* Set the drive to double speed if
- possible */
- }
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX "Unable to set mechanical "
- "parameters: 0x%2.2x\n", res_reg[1]);
- }
-}
-
-/*
- * Uniform cdrom interface function
- * select reading speed for data access
- */
-static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- if (speed == 0)
- sony_speed = 1;
- else
- sony_speed = speed - 1;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- set_drive_params(sony_speed);
- up(&sony_sem);
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * lock or unlock eject button
- */
-static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- if (lock == 0) {
- is_auto_eject = 1;
- } else {
- is_auto_eject = 0;
- }
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- set_drive_params(sony_speed);
- up(&sony_sem);
- return 0;
-}
-
-/*
- * This code will reset the drive and attempt to restore sane parameters.
- */
-static void restart_on_error(void)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned long retry_count;
-
-
- printk(KERN_NOTICE PFX "Resetting drive on error\n");
- reset_drive();
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count) && (!is_attention())) {
- sony_sleep();
- }
- set_drive_params(sony_speed);
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n",
- res_reg[1]);
- }
-
- msleep(2000);
-
- sony_get_toc();
-}
-
-/*
- * This routine writes data to the parameter register. Since this should
- * happen fairly fast, it is polled with no OS waits between.
- */
-static int write_params(unsigned char *params, int num_params)
-{
- unsigned int retry_count;
-
-
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0) && (!is_param_write_rdy())) {
- retry_count--;
- }
- if (!is_param_write_rdy()) {
- return -EIO;
- }
-
- while (num_params > 0) {
- write_param(*params);
- params++;
- num_params--;
- }
-
- return 0;
-}
-
-
-/*
- * The following reads data from the command result register. It is a
- * fairly complex routine, all status info flows back through this
- * interface. The algorithm is stolen directly from the flowcharts in
- * the drive manual.
- */
-static void
-get_result(unsigned char *result_buffer, unsigned int *result_size)
-{
- unsigned char a, b;
- int i;
- unsigned long retry_count;
-
-
- while (handle_sony_cd_attention());
- /* Wait for the result data to be ready */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && (is_busy() || (!(is_result_ready())))) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
- if (is_busy() || (!(is_result_ready()))) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] = SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
-
- /*
- * Get the first two bytes. This determines what else needs
- * to be done.
- */
- clear_result_ready();
- a = read_result_register();
- *result_buffer = a;
- result_buffer++;
-
- /* Check for block error status result. */
- if ((a & 0xf0) == 0x50) {
- *result_size = 1;
- return;
- }
-
- b = read_result_register();
- *result_buffer = b;
- result_buffer++;
- *result_size = 2;
-
- /*
- * 0x20 means an error occurred. Byte 2 will have the error code.
- * Otherwise, the command succeeded, byte 2 will have the count of
- * how many more status bytes are coming.
- *
- * The result register can be read 10 bytes at a time, a wait for
- * result ready to be asserted must be done between every 10 bytes.
- */
- if ((a & 0xf0) != 0x20) {
- if (b > 8) {
- for (i = 0; i < 8; i++) {
- *result_buffer = read_result_register();
- result_buffer++;
- (*result_size)++;
- }
- b = b - 8;
-
- while (b > 10) {
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0)
- && (!is_result_ready())) {
- retry_count--;
- }
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n",
- __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] =
- SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
-
- clear_result_ready();
-
- for (i = 0; i < 10; i++) {
- *result_buffer =
- read_result_register();
- result_buffer++;
- (*result_size)++;
- }
- b = b - 10;
- }
-
- if (b > 0) {
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0)
- && (!is_result_ready())) {
- retry_count--;
- }
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n",
- __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] =
- SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
- }
- }
-
- while (b > 0) {
- *result_buffer = read_result_register();
- result_buffer++;
- (*result_size)++;
- b--;
- }
- }
-}
-
-/*
- * Do a command that does not involve data transfer. This routine must
- * be re-entrant from the same task to support being called from the
- * data operation code when an error occurs.
- */
-static void
-do_sony_cd_cmd(unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer, unsigned int *result_size)
-{
- unsigned long retry_count;
- int num_retries = 0;
-
-retry_cd_operation:
-
- while (handle_sony_cd_attention());
-
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && (is_busy())) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
- if (is_busy()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] = SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- } else {
- clear_result_ready();
- clear_param_reg();
-
- write_params(params, num_params);
- write_cmd(cmd);
-
- get_result(result_buffer, result_size);
- }
-
- if (((result_buffer[0] & 0xf0) == 0x20)
- && (num_retries < MAX_CDU31A_RETRIES)) {
- num_retries++;
- msleep(100);
- goto retry_cd_operation;
- }
-}
-
-
-/*
- * Handle an attention from the drive. This will return 1 if it found one
- * or 0 if not (if one is found, the caller might want to call again).
- *
- * This routine counts the number of consecutive times it is called
- * (since this is always called from a while loop until it returns
- * a 0), and returns a 0 if it happens too many times. This will help
- * prevent a lockup.
- */
-static int handle_sony_cd_attention(void)
-{
- unsigned char atten_code;
- static int num_consecutive_attentions = 0;
- volatile int val;
-
-
-#if 0
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#endif
- if (is_attention()) {
- if (num_consecutive_attentions >
- CDU31A_MAX_CONSECUTIVE_ATTENTIONS) {
- printk(KERN_NOTICE PFX "Too many consecutive "
- "attentions: %d\n", num_consecutive_attentions);
- num_consecutive_attentions = 0;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__,
- __LINE__);
- return 0;
- }
-
- clear_attention();
- atten_code = read_result_register();
-
- switch (atten_code) {
- /* Someone changed the CD. Mark it as changed */
- case SONY_MECH_LOADED_ATTN:
- disk_changed = 1;
- sony_toc_read = 0;
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- sony_blocks_left = 0;
- break;
-
- case SONY_SPIN_DOWN_COMPLETE_ATTN:
- /* Mark the disk as spun down. */
- sony_spun_up = 0;
- break;
-
- case SONY_AUDIO_PLAY_DONE_ATTN:
- sony_audio_status = CDROM_AUDIO_COMPLETED;
- read_subcode();
- break;
-
- case SONY_EJECT_PUSHED_ATTN:
- if (is_auto_eject) {
- sony_audio_status = CDROM_AUDIO_INVALID;
- }
- break;
-
- case SONY_LEAD_IN_ERR_ATTN:
- case SONY_LEAD_OUT_ERR_ATTN:
- case SONY_DATA_TRACK_ERR_ATTN:
- case SONY_AUDIO_PLAYBACK_ERR_ATTN:
- sony_audio_status = CDROM_AUDIO_ERROR;
- break;
- }
-
- num_consecutive_attentions++;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- } else if (abort_read_started) {
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
- abort_read_started = 0;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- }
-
- num_consecutive_attentions = 0;
-#if 0
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-#endif
- return 0;
-}
-
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int int_to_bcd(unsigned int val)
-{
- int retval;
-
-
- retval = (val / 10) << 4;
- retval = retval | val % 10;
- return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int bcd_to_int(unsigned int bcd)
-{
- return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void log_to_msf(unsigned int log, unsigned char *msf)
-{
- log = log + LOG_START_OFFSET;
- msf[0] = int_to_bcd(log / 4500);
- log = log % 4500;
- msf[1] = int_to_bcd(log / 75);
- msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int msf_to_log(unsigned char *msf)
-{
- unsigned int log;
-
-
- log = msf[2];
- log += msf[1] * 75;
- log += msf[0] * 4500;
- log = log - LOG_START_OFFSET;
-
- return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void size_to_buf(unsigned int size, unsigned char *buf)
-{
- buf[0] = size / 65536;
- size = size % 65536;
- buf[1] = size / 256;
- buf[2] = size % 256;
-}
-
-/* Starts a read operation. Returns 0 on success and 1 on failure.
- The read operation used here allows multiple sequential sectors
- to be read and status returned for each sector. The driver will
- read the output one at a time as the requests come and abort the
- operation if the requested sector is not the next one from the
- drive. */
-static int
-start_request(unsigned int sector, unsigned int nsect)
-{
- unsigned char params[6];
- unsigned long retry_count;
-
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
- log_to_msf(sector, params);
- size_to_buf(nsect, &params[3]);
-
- /*
- * Clear any outstanding attentions and wait for the drive to
- * complete any pending operations.
- */
- while (handle_sony_cd_attention());
-
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && (is_busy())) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
-
- if (is_busy()) {
- printk(KERN_NOTICE PFX "Timeout while waiting "
- "to issue command\n");
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- } else {
- /* Issue the command */
- clear_result_ready();
- clear_param_reg();
-
- write_params(params, 6);
- write_cmd(SONY_READ_BLKERR_STAT_CMD);
-
- sony_blocks_left = nsect * 4;
- sony_next_block = sector * 4;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 0;
- }
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-/* Abort a pending read operation. Clear all the drive status variables. */
-static void abort_read(void)
-{
- unsigned char result_reg[2];
- int result_size;
- volatile int val;
-
-
- do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
- if ((result_reg[0] & 0xf0) == 0x20) {
- printk(KERN_ERR PFX "Aborting read, %s error\n",
- translate_error(result_reg[1]));
- }
-
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
-
- sony_blocks_left = 0;
-}
-
-/* Called when the timer times out. This will abort the
- pending read operation. */
-static void handle_abort_timeout(unsigned long data)
-{
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
- /* If it is in use, ignore it. */
- if (down_trylock(&sony_sem) == 0) {
- /* We can't use abort_read(), because it will sleep
- or schedule in the timer interrupt. Just start
- the operation, finish it on the next access to
- the drive. */
- clear_result_ready();
- clear_param_reg();
- write_cmd(SONY_ABORT_CMD);
-
- sony_blocks_left = 0;
- abort_read_started = 1;
- up(&sony_sem);
- }
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* Actually get one sector of data from the drive. */
-static void
-input_data_sector(char *buffer)
-{
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- /* If an XA disk on a CDU31A, skip the first 12 bytes of data from
- the disk. The real data is after that. We can use audio_buffer. */
- if (sony_xa_mode)
- insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD);
-
- clear_data_ready();
-
- insb(sony_cd_read_reg, buffer, 2048);
-
- /* If an XA disk, we have to clear out the rest of the unused
- error correction data. We can use audio_buffer for that. */
- if (sony_xa_mode)
- insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL);
-
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* read data from the drive. Note the nsect must be <= 4. */
-static void
-read_data_block(char *buffer,
- unsigned int block,
- unsigned int nblocks,
- unsigned char res_reg[], int *res_size)
-{
- unsigned long retry_count;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- res_reg[0] = 0;
- res_reg[1] = 0;
- *res_size = 0;
-
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && !(is_data_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
- if (!(is_data_ready())) {
- if (is_result_ready()) {
- get_result(res_reg, res_size);
- if ((res_reg[0] & 0xf0) != 0x20) {
- printk(KERN_NOTICE PFX "Got result that should"
- " have been error: %d\n", res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- abort_read();
- } else {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- }
- } else {
- input_data_sector(buffer);
- sony_blocks_left -= nblocks;
- sony_next_block += nblocks;
-
- /* Wait for the status from the drive. */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && !(is_result_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
-
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- } else {
- get_result(res_reg, res_size);
-
- /* If we got a buffer status, handle that. */
- if ((res_reg[0] & 0xf0) == 0x50) {
-
- if ((res_reg[0] ==
- SONY_NO_CIRC_ERR_BLK_STAT)
- || (res_reg[0] ==
- SONY_NO_LECC_ERR_BLK_STAT)
- || (res_reg[0] ==
- SONY_RECOV_LECC_ERR_BLK_STAT)) {
- /* nothing here */
- } else {
- printk(KERN_ERR PFX "Data block "
- "error: 0x%x\n", res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
-
- /* Final transfer is done for read command, get final result. */
- if (sony_blocks_left == 0) {
- get_result(res_reg, res_size);
- }
- } else if ((res_reg[0] & 0xf0) != 0x20) {
- /* The drive gave me bad status, I don't know what to do.
- Reset the driver and return an error. */
- printk(KERN_ERR PFX "Invalid block "
- "status: 0x%x\n", res_reg[0]);
- restart_on_error();
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- }
- }
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail. Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations. This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void do_cdu31a_request(request_queue_t * q)
-{
- struct request *req;
- int block, nblock, num_retries;
- unsigned char res_reg[12];
- unsigned int res_size;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- spin_unlock_irq(q->queue_lock);
- if (down_interruptible(&sony_sem)) {
- spin_lock_irq(q->queue_lock);
- return;
- }
-
- /* Get drive status before doing anything. */
- while (handle_sony_cd_attention());
-
- /* Make sure we have a valid TOC. */
- sony_get_toc();
-
-
- /* Make sure the timer is cancelled. */
- del_timer(&cdu31a_abort_timer);
-
- while (1) {
- /*
- * The beginning here is stolen from the hard disk driver. I hope
- * it's right.
- */
- req = elv_next_request(q);
- if (!req)
- goto end_do_cdu31a_request;
-
- if (!sony_spun_up)
- scd_spinup();
-
- block = req->sector;
- nblock = req->nr_sectors;
- pr_debug(PFX "request at block %d, length %d blocks\n",
- block, nblock);
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
-
- /* WTF??? */
- if (!blk_fs_request(req)) {
- end_request(req, 0);
- continue;
- }
- if (rq_data_dir(req) == WRITE) {
- end_request(req, 0);
- continue;
- }
-
- /*
- * If the block address is invalid or the request goes beyond the end of
- * the media, return an error.
- */
- if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
- printk(KERN_NOTICE PFX "Request past end of media\n");
- end_request(req, 0);
- continue;
- }
-
- if (nblock > 4)
- nblock = 4;
- num_retries = 0;
-
- try_read_again:
- while (handle_sony_cd_attention());
-
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
-
- /* If no data is left to be read from the drive, start the
- next request. */
- if (sony_blocks_left == 0) {
- if (start_request(block / 4, nblock / 4)) {
- end_request(req, 0);
- continue;
- }
- }
- /* If the requested block is not the next one waiting in
- the driver, abort the current operation and start a
- new one. */
- else if (block != sony_next_block) {
- pr_debug(PFX "Read for block %d, expected %d\n",
- block, sony_next_block);
- abort_read();
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
- if (start_request(block / 4, nblock / 4)) {
- printk(KERN_NOTICE PFX "start request failed\n");
- end_request(req, 0);
- continue;
- }
- }
-
- read_data_block(req->buffer, block, nblock, res_reg, &res_size);
-
- if (res_reg[0] != 0x20) {
- if (!end_that_request_first(req, 1, nblock)) {
- spin_lock_irq(q->queue_lock);
- blkdev_dequeue_request(req);
- end_that_request_last(req, 1);
- spin_unlock_irq(q->queue_lock);
- }
- continue;
- }
-
- if (num_retries > MAX_CDU31A_RETRIES) {
- end_request(req, 0);
- continue;
- }
-
- num_retries++;
- if (res_reg[1] == SONY_NOT_SPIN_ERR) {
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
- } else {
- printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n",
- translate_error(res_reg[1]), block, nblock);
- }
- goto try_read_again;
- }
- end_do_cdu31a_request:
-#if 0
- /* After finished, cancel any pending operations. */
- abort_read();
-#else
- /* Start a timer to time out after a while to disable
- the read. */
- cdu31a_abort_timer.expires = jiffies + 2 * HZ; /* Wait 2 seconds */
- add_timer(&cdu31a_abort_timer);
-#endif
-
- up(&sony_sem);
- spin_lock_irq(q->queue_lock);
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * Read the table of contents from the drive and set up TOC if
- * successful.
- */
-static void sony_get_toc(void)
-{
- unsigned char res_reg[2];
- unsigned int res_size;
- unsigned char parms[1];
- int session;
- int num_spin_ups;
- int totaltracks = 0;
- int mint = 99;
- int maxt = 0;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- num_spin_ups = 0;
- if (!sony_toc_read) {
- respinup_on_gettoc:
- /* Ignore the result, since it might error if spinning already. */
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2)
- || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- /* If the drive is already playing, it's ok. */
- if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
- || (res_reg[1] == 0)) {
- goto gettoc_drive_spinning;
- }
-
- /* If the drive says it is not spun up (even though we just did it!)
- then retry the operation at least a few times. */
- if ((res_reg[1] == SONY_NOT_SPIN_ERR)
- && (num_spin_ups < MAX_CDU31A_RETRIES)) {
- num_spin_ups++;
- goto respinup_on_gettoc;
- }
-
- printk("cdu31a: Error reading TOC: %x %s\n",
- res_reg[0], translate_error(res_reg[1]));
- return;
- }
-
- gettoc_drive_spinning:
-
- /* The idea here is we keep asking for sessions until the command
- fails. Then we know what the last valid session on the disk is.
- No need to check session 0, since session 0 is the same as session
- 1; the command returns different information if you give it 0.
- */
-#if DEBUG
- memset(&sony_toc, 0x0e, sizeof(sony_toc));
- memset(&single_toc, 0x0f, sizeof(single_toc));
-#endif
- session = 1;
- while (1) {
-/* This seems to slow things down enough to make it work. This
- * appears to be a problem in do_sony_cd_cmd. This printk seems
- * to address the symptoms... -Erik */
- pr_debug(PFX "Trying session %d\n", session);
- parms[0] = session;
- do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,
- parms, 1, res_reg, &res_size);
-
- pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]);
-
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- /* An error reading the TOC, this must be past the last session. */
- if (session == 1)
- printk
- ("Yikes! Couldn't read any sessions!");
- break;
- }
- pr_debug(PFX "Reading session %d\n", session);
-
- parms[0] = session;
- do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
- parms,
- 1,
- (unsigned char *) &single_toc,
- &res_size);
- if ((res_size < 2)
- || ((single_toc.exec_status[0] & 0xf0) ==
- 0x20)) {
- printk(KERN_ERR PFX "Error reading "
- "session %d: %x %s\n",
- session, single_toc.exec_status[0],
- translate_error(single_toc.
- exec_status[1]));
- /* An error reading the TOC. Return without sony_toc_read
- set. */
- return;
- }
- pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, "
- "1st trk %d, dsktyp %x, dum0 %x\n",
- single_toc.address0, single_toc.control0,
- single_toc.point0,
- bcd_to_int(single_toc.first_track_num),
- single_toc.disk_type, single_toc.dummy0);
- pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, "
- "lst trk %d, dummy1 %x, dum2 %x\n",
- single_toc.address1, single_toc.control1,
- single_toc.point1,
- bcd_to_int(single_toc.last_track_num),
- single_toc.dummy1, single_toc.dummy2);
- pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x "
- "leadout start min %d, sec %d, frame %d\n",
- single_toc.address2, single_toc.control2,
- single_toc.point2,
- bcd_to_int(single_toc.lead_out_start_msf[0]),
- bcd_to_int(single_toc.lead_out_start_msf[1]),
- bcd_to_int(single_toc.lead_out_start_msf[2]));
- if (res_size > 18 && single_toc.pointb0 > 0xaf)
- pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
- "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
- single_toc.addressb0,
- single_toc.controlb0,
- single_toc.pointb0,
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [0]),
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [1]),
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [2]),
- single_toc.num_mode_5_pointers,
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [0]),
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [1]),
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [2]));
- if (res_size > 27 && single_toc.pointb1 > 0xaf)
- pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
- single_toc.addressb1,
- single_toc.controlb1,
- single_toc.pointb1,
- single_toc.dummyb0_1[0],
- single_toc.dummyb0_1[1],
- single_toc.dummyb0_1[2],
- single_toc.dummyb0_1[3],
- single_toc.num_skip_interval_pointers,
- single_toc.num_skip_track_assignments,
- single_toc.dummyb0_2);
- if (res_size > 36 && single_toc.pointb2 > 0xaf)
- pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb2,
- single_toc.controlb2,
- single_toc.pointb2,
- single_toc.tracksb2[0],
- single_toc.tracksb2[1],
- single_toc.tracksb2[2],
- single_toc.tracksb2[3],
- single_toc.tracksb2[4],
- single_toc.tracksb2[5],
- single_toc.tracksb2[6]);
- if (res_size > 45 && single_toc.pointb3 > 0xaf)
- pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb3,
- single_toc.controlb3,
- single_toc.pointb3,
- single_toc.tracksb3[0],
- single_toc.tracksb3[1],
- single_toc.tracksb3[2],
- single_toc.tracksb3[3],
- single_toc.tracksb3[4],
- single_toc.tracksb3[5],
- single_toc.tracksb3[6]);
- if (res_size > 54 && single_toc.pointb4 > 0xaf)
- pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb4,
- single_toc.controlb4,
- single_toc.pointb4,
- single_toc.tracksb4[0],
- single_toc.tracksb4[1],
- single_toc.tracksb4[2],
- single_toc.tracksb4[3],
- single_toc.tracksb4[4],
- single_toc.tracksb4[5],
- single_toc.tracksb4[6]);
- if (res_size > 63 && single_toc.pointc0 > 0xaf)
- pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressc0,
- single_toc.controlc0,
- single_toc.pointc0,
- single_toc.dummyc0[0],
- single_toc.dummyc0[1],
- single_toc.dummyc0[2],
- single_toc.dummyc0[3],
- single_toc.dummyc0[4],
- single_toc.dummyc0[5],
- single_toc.dummyc0[6]);
-#undef DEBUG
-#define DEBUG 0
-
- sony_toc.lead_out_start_msf[0] =
- bcd_to_int(single_toc.lead_out_start_msf[0]);
- sony_toc.lead_out_start_msf[1] =
- bcd_to_int(single_toc.lead_out_start_msf[1]);
- sony_toc.lead_out_start_msf[2] =
- bcd_to_int(single_toc.lead_out_start_msf[2]);
- sony_toc.lead_out_start_lba =
- single_toc.lead_out_start_lba =
- msf_to_log(sony_toc.lead_out_start_msf);
-
- /* For points that do not exist, move the data over them
- to the right location. */
- if (single_toc.pointb0 != 0xb0) {
- memmove(((char *) &single_toc) + 27,
- ((char *) &single_toc) + 18,
- res_size - 18);
- res_size += 9;
- } else if (res_size > 18) {
- sony_toc.lead_out_start_msf[0] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [0]);
- sony_toc.lead_out_start_msf[1] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [1]);
- sony_toc.lead_out_start_msf[2] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [2]);
- sony_toc.lead_out_start_lba =
- msf_to_log(sony_toc.
- lead_out_start_msf);
- }
- if (single_toc.pointb1 != 0xb1) {
- memmove(((char *) &single_toc) + 36,
- ((char *) &single_toc) + 27,
- res_size - 27);
- res_size += 9;
- }
- if (single_toc.pointb2 != 0xb2) {
- memmove(((char *) &single_toc) + 45,
- ((char *) &single_toc) + 36,
- res_size - 36);
- res_size += 9;
- }
- if (single_toc.pointb3 != 0xb3) {
- memmove(((char *) &single_toc) + 54,
- ((char *) &single_toc) + 45,
- res_size - 45);
- res_size += 9;
- }
- if (single_toc.pointb4 != 0xb4) {
- memmove(((char *) &single_toc) + 63,
- ((char *) &single_toc) + 54,
- res_size - 54);
- res_size += 9;
- }
- if (single_toc.pointc0 != 0xc0) {
- memmove(((char *) &single_toc) + 72,
- ((char *) &single_toc) + 63,
- res_size - 63);
- res_size += 9;
- }
-#if DEBUG
- printk(PRINT_INFO PFX "start track lba %u, "
- "leadout start lba %u\n",
- single_toc.start_track_lba,
- single_toc.lead_out_start_lba);
- {
- int i;
- for (i = 0;
- i <
- 1 +
- bcd_to_int(single_toc.last_track_num)
- -
- bcd_to_int(single_toc.
- first_track_num); i++) {
- printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
- i,
- single_toc.tracks[i].address,
- single_toc.tracks[i].control,
- bcd_to_int(single_toc.
- tracks[i].track),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [0]),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [1]),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [2]));
- if (mint >
- bcd_to_int(single_toc.
- tracks[i].track))
- mint =
- bcd_to_int(single_toc.
- tracks[i].
- track);
- if (maxt <
- bcd_to_int(single_toc.
- tracks[i].track))
- maxt =
- bcd_to_int(single_toc.
- tracks[i].
- track);
- }
- printk(KERN_INFO PFX "min track number %d, "
- "max track number %d\n",
- mint, maxt);
- }
-#endif
-
- /* prepare a special table of contents for a CD-I disc. They don't have one. */
- if (single_toc.disk_type == 0x10 &&
- single_toc.first_track_num == 2 &&
- single_toc.last_track_num == 2 /* CD-I */ ) {
- sony_toc.tracks[totaltracks].address = 1;
- sony_toc.tracks[totaltracks].control = 4; /* force data tracks */
- sony_toc.tracks[totaltracks].track = 1;
- sony_toc.tracks[totaltracks].
- track_start_msf[0] = 0;
- sony_toc.tracks[totaltracks].
- track_start_msf[1] = 2;
- sony_toc.tracks[totaltracks].
- track_start_msf[2] = 0;
- mint = maxt = 1;
- totaltracks++;
- } else
- /* gather track entries from this session */
- {
- int i;
- for (i = 0;
- i <
- 1 +
- bcd_to_int(single_toc.last_track_num)
- -
- bcd_to_int(single_toc.
- first_track_num);
- i++, totaltracks++) {
- sony_toc.tracks[totaltracks].
- address =
- single_toc.tracks[i].address;
- sony_toc.tracks[totaltracks].
- control =
- single_toc.tracks[i].control;
- sony_toc.tracks[totaltracks].
- track =
- bcd_to_int(single_toc.
- tracks[i].track);
- sony_toc.tracks[totaltracks].
- track_start_msf[0] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[0]);
- sony_toc.tracks[totaltracks].
- track_start_msf[1] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[1]);
- sony_toc.tracks[totaltracks].
- track_start_msf[2] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[2]);
- if (i == 0)
- single_toc.
- start_track_lba =
- msf_to_log(sony_toc.
- tracks
- [totaltracks].
- track_start_msf);
- if (mint >
- sony_toc.tracks[totaltracks].
- track)
- mint =
- sony_toc.
- tracks[totaltracks].
- track;
- if (maxt <
- sony_toc.tracks[totaltracks].
- track)
- maxt =
- sony_toc.
- tracks[totaltracks].
- track;
- }
- }
- sony_toc.first_track_num = mint;
- sony_toc.last_track_num = maxt;
- /* Disk type of last session wins. For example:
- CD-Extra has disk type 0 for the first session, so
- a dumb HiFi CD player thinks it is a plain audio CD.
- We are interested in the disk type of the last session,
- which is 0x20 (XA) for CD-Extra, so we can access the
- data track ... */
- sony_toc.disk_type = single_toc.disk_type;
- sony_toc.sessions = session;
-
- /* don't believe everything :-) */
- if (session == 1)
- single_toc.start_track_lba = 0;
- sony_toc.start_track_lba =
- single_toc.start_track_lba;
-
- if (session > 1 && single_toc.pointb0 == 0xb0 &&
- sony_toc.lead_out_start_lba ==
- single_toc.lead_out_start_lba) {
- break;
- }
-
- /* Let's not get carried away... */
- if (session > 40) {
- printk(KERN_NOTICE PFX "too many sessions: "
- "%d\n", session);
- break;
- }
- session++;
- }
- sony_toc.track_entries = totaltracks;
- /* add one entry for the LAST track with track number CDROM_LEADOUT */
- sony_toc.tracks[totaltracks].address = single_toc.address2;
- sony_toc.tracks[totaltracks].control = single_toc.control2;
- sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;
- sony_toc.tracks[totaltracks].track_start_msf[0] =
- sony_toc.lead_out_start_msf[0];
- sony_toc.tracks[totaltracks].track_start_msf[1] =
- sony_toc.lead_out_start_msf[1];
- sony_toc.tracks[totaltracks].track_start_msf[2] =
- sony_toc.lead_out_start_msf[2];
-
- sony_toc_read = 1;
-
- pr_debug(PFX "Disk session %d, start track: %d, "
- "stop track: %d\n",
- session, single_toc.start_track_lba,
- single_toc.lead_out_start_lba);
- }
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-
-/*
- * Uniform cdrom interface function
- * return multisession offset and sector information
- */
-static int scd_get_last_session(struct cdrom_device_info *cdi,
- struct cdrom_multisession *ms_info)
-{
- if (ms_info == NULL)
- return 1;
-
- if (!sony_toc_read) {
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- sony_get_toc();
- up(&sony_sem);
- }
-
- ms_info->addr_format = CDROM_LBA;
- ms_info->addr.lba = sony_toc.start_track_lba;
- ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE ||
- sony_toc.disk_type == 0x10 /* CDI */ ;
-
- return 0;
-}
-
-/*
- * Search for a specific track in the table of contents.
- */
-static int find_track(int track)
-{
- int i;
-
- for (i = 0; i <= sony_toc.track_entries; i++) {
- if (sony_toc.tracks[i].track == track) {
- return i;
- }
- }
-
- return -1;
-}
-
-
-/*
- * Read the subcode and put it in last_sony_subcode for future use.
- */
-static int read_subcode(void)
-{
- unsigned int res_size;
-
-
- do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
- NULL,
- 0, (unsigned char *) &last_sony_subcode, &res_size);
- if ((res_size < 2)
- || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n",
- translate_error(last_sony_subcode.exec_status[1]));
- return -EIO;
- }
-
- last_sony_subcode.track_num =
- bcd_to_int(last_sony_subcode.track_num);
- last_sony_subcode.index_num =
- bcd_to_int(last_sony_subcode.index_num);
- last_sony_subcode.abs_msf[0] =
- bcd_to_int(last_sony_subcode.abs_msf[0]);
- last_sony_subcode.abs_msf[1] =
- bcd_to_int(last_sony_subcode.abs_msf[1]);
- last_sony_subcode.abs_msf[2] =
- bcd_to_int(last_sony_subcode.abs_msf[2]);
-
- last_sony_subcode.rel_msf[0] =
- bcd_to_int(last_sony_subcode.rel_msf[0]);
- last_sony_subcode.rel_msf[1] =
- bcd_to_int(last_sony_subcode.rel_msf[1]);
- last_sony_subcode.rel_msf[2] =
- bcd_to_int(last_sony_subcode.rel_msf[2]);
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * return the media catalog number found on some older audio cds
- */
-static int
-scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- unsigned char resbuffer[2 + 14];
- unsigned char *mcnp = mcn->medium_catalog_number;
- unsigned char *resp = resbuffer + 3;
- unsigned int res_size;
-
- memset(mcn->medium_catalog_number, 0, 14);
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
- NULL, 0, resbuffer, &res_size);
- up(&sony_sem);
- if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
- else {
- /* packed bcd to single ASCII digits */
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- }
- *mcnp = '\0';
- return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing). If the drive is paused or completed, the subcode information has
- * already been stored, just use that. The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int sony_get_subchnl_info(struct cdrom_subchnl *schi)
-{
- /* Get attention stuff */
- while (handle_sony_cd_attention());
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
-
- switch (sony_audio_status) {
- case CDROM_AUDIO_NO_STATUS:
- case CDROM_AUDIO_PLAY:
- if (read_subcode() < 0) {
- return -EIO;
- }
- break;
-
- case CDROM_AUDIO_PAUSED:
- case CDROM_AUDIO_COMPLETED:
- break;
-
-#if 0
- case CDROM_AUDIO_NO_STATUS:
- schi->cdsc_audiostatus = sony_audio_status;
- return 0;
- break;
-#endif
- case CDROM_AUDIO_INVALID:
- case CDROM_AUDIO_ERROR:
- default:
- return -EIO;
- }
-
- schi->cdsc_audiostatus = sony_audio_status;
- schi->cdsc_adr = last_sony_subcode.address;
- schi->cdsc_ctrl = last_sony_subcode.control;
- schi->cdsc_trk = last_sony_subcode.track_num;
- schi->cdsc_ind = last_sony_subcode.index_num;
- if (schi->cdsc_format == CDROM_MSF) {
- schi->cdsc_absaddr.msf.minute =
- last_sony_subcode.abs_msf[0];
- schi->cdsc_absaddr.msf.second =
- last_sony_subcode.abs_msf[1];
- schi->cdsc_absaddr.msf.frame =
- last_sony_subcode.abs_msf[2];
-
- schi->cdsc_reladdr.msf.minute =
- last_sony_subcode.rel_msf[0];
- schi->cdsc_reladdr.msf.second =
- last_sony_subcode.rel_msf[1];
- schi->cdsc_reladdr.msf.frame =
- last_sony_subcode.rel_msf[2];
- } else if (schi->cdsc_format == CDROM_LBA) {
- schi->cdsc_absaddr.lba =
- msf_to_log(last_sony_subcode.abs_msf);
- schi->cdsc_reladdr.lba =
- msf_to_log(last_sony_subcode.rel_msf);
- }
-
- return 0;
-}
-
-/* Get audio data from the drive. This is fairly complex because I
- am looking for status and data at the same time, but if I get status
- then I just look for data. I need to get the status immediately so
- the switch from audio to data tracks will happen quickly. */
-static void
-read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
-{
- unsigned long retry_count;
- int result_read;
-
-
- res_reg[0] = 0;
- res_reg[1] = 0;
- *res_size = 0;
- result_read = 0;
-
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- continue_read_audio_wait:
- while (time_before(jiffies, retry_count) && !(is_data_ready())
- && !(is_result_ready() || result_read)) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
- if (!(is_data_ready())) {
- if (is_result_ready() && !result_read) {
- get_result(res_reg, res_size);
-
- /* Read block status and continue waiting for data. */
- if ((res_reg[0] & 0xf0) == 0x50) {
- result_read = 1;
- goto continue_read_audio_wait;
- }
- /* Invalid data from the drive. Shut down the operation. */
- else if ((res_reg[0] & 0xf0) != 0x20) {
- printk(KERN_WARNING PFX "Got result that "
- "should have been error: %d\n",
- res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- abort_read();
- } else {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- }
- } else {
- clear_data_ready();
-
- /* If data block, then get 2340 bytes offset by 12. */
- if (sony_raw_data_mode) {
- insb(sony_cd_read_reg, buffer + CD_XA_HEAD,
- CD_FRAMESIZE_RAW1);
- } else {
- /* Audio gets the whole 2352 bytes. */
- insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW);
- }
-
- /* If I haven't already gotten the result, get it now. */
- if (!result_read) {
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && !(is_result_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
-
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- return;
- } else {
- get_result(res_reg, res_size);
- }
- }
-
- if ((res_reg[0] & 0xf0) == 0x50) {
- if ((res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) {
- /* Ok, nothing to do. */
- } else {
- printk(KERN_ERR PFX "Data block error: 0x%x\n",
- res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- } else if ((res_reg[0] & 0xf0) != 0x20) {
- /* The drive gave me bad status, I don't know what to do.
- Reset the driver and return an error. */
- printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n",
- res_reg[0]);
- restart_on_error();
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- }
-}
-
-/* Perform a raw data read. This will automatically detect the
- track type and read the proper data (audio or data). */
-static int read_audio(struct cdrom_read_audio *ra)
-{
- int retval;
- unsigned char params[2];
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned int cframe;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (!sony_spun_up)
- scd_spinup();
-
- /* Set the drive to do raw operations. */
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x06 | sony_raw_data_mode;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- goto out_up;
- }
-
- /* From here down, we have to goto exit_read_audio instead of returning
- because the drive parameters have to be set back to data before
- return. */
-
- retval = 0;
- if (start_request(ra->addr.lba, ra->nframes)) {
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* For every requested frame. */
- cframe = 0;
- while (cframe < ra->nframes) {
- read_audio_data(audio_buffer, res_reg, &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- if (res_reg[1] == SONY_BAD_DATA_ERR) {
- printk(KERN_ERR PFX "Data error on audio "
- "sector %d\n",
- ra->addr.lba + cframe);
- } else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) {
- /* Illegal track type, change track types and start over. */
- sony_raw_data_mode =
- (sony_raw_data_mode) ? 0 : 1;
-
- /* Set the drive mode. */
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x06 | sony_raw_data_mode;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params,
- 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to set "
- "decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* Restart the request on the current frame. */
- if (start_request
- (ra->addr.lba + cframe,
- ra->nframes - cframe)) {
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* Don't go back to the top because don't want to get into
- and infinite loop. A lot of code gets duplicated, but
- that's no big deal, I don't guess. */
- read_audio_data(audio_buffer, res_reg,
- &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- if (res_reg[1] ==
- SONY_BAD_DATA_ERR) {
- printk(KERN_ERR PFX "Data error"
- " on audio sector %d\n",
- ra->addr.lba +
- cframe);
- } else {
- printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n",
- ra->addr.lba + cframe,
- translate_error
- (res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
- } else if (copy_to_user(ra->buf +
- (CD_FRAMESIZE_RAW
- * cframe),
- audio_buffer,
- CD_FRAMESIZE_RAW)) {
- retval = -EFAULT;
- goto exit_read_audio;
- }
- } else {
- printk(KERN_ERR PFX "Error reading audio "
- "data on sector %d: %s\n",
- ra->addr.lba + cframe,
- translate_error(res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
- } else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe),
- (char *)audio_buffer,
- CD_FRAMESIZE_RAW)) {
- retval = -EFAULT;
- goto exit_read_audio;
- }
-
- cframe++;
- }
-
- get_result(res_reg, &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- printk(KERN_ERR PFX "Error return from audio read: %s\n",
- translate_error(res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
-
- exit_read_audio:
-
- /* Set the drive mode back to the proper one for the disk. */
- params[0] = SONY_SD_DECODE_PARAM;
- if (!sony_xa_mode) {
- params[1] = 0x0f;
- } else {
- params[1] = 0x07;
- }
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- }
-
- out_up:
- up(&sony_sem);
-
- return retval;
-}
-
-static int
-do_sony_cd_cmd_chk(const char *name,
- unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer, unsigned int *result_size)
-{
- do_sony_cd_cmd(cmd, params, num_params, result_buffer,
- result_size);
- if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Error %s (CDROM%s)\n",
- translate_error(result_buffer[1]), name);
- return -EIO;
- }
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * open the tray
- */
-static int scd_tray_move(struct cdrom_device_info *cdi, int position)
-{
- int retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (position == 1 /* open tray */ ) {
- unsigned char res_reg[12];
- unsigned int res_size;
-
- do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size);
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
-
- sony_audio_status = CDROM_AUDIO_INVALID;
- retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
- res_reg, &res_size);
- } else {
- if (0 == scd_spinup())
- sony_spun_up = 1;
- retval = 0;
- }
- up(&sony_sem);
- return retval;
-}
-
-/*
- * The big ugly ioctl handler.
- */
-static int scd_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[7];
- int i, retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
- 0, res_reg, &res_size);
- break;
-
- case CDROMSTOP: /* Spin down the drive */
- do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /*
- * Spin the drive down, ignoring the error if the disk was
- * already not spinning.
- */
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
- 0, res_reg, &res_size);
- break;
-
- case CDROMPAUSE: /* Pause the drive */
- if (do_sony_cd_cmd_chk
- ("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size)) {
- retval = -EIO;
- break;
- }
- /* Get the current position and save it for resuming */
- if (read_subcode() < 0) {
- retval = -EIO;
- break;
- }
- cur_pos_msf[0] = last_sony_subcode.abs_msf[0];
- cur_pos_msf[1] = last_sony_subcode.abs_msf[1];
- cur_pos_msf[2] = last_sony_subcode.abs_msf[2];
- sony_audio_status = CDROM_AUDIO_PAUSED;
- retval = 0;
- break;
-
- case CDROMRESUME: /* Start the drive after being paused */
- if (sony_audio_status != CDROM_AUDIO_PAUSED) {
- retval = -EINVAL;
- break;
- }
-
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* Start the drive at the saved position. */
- params[1] = int_to_bcd(cur_pos_msf[0]);
- params[2] = int_to_bcd(cur_pos_msf[1]);
- params[3] = int_to_bcd(cur_pos_msf[2]);
- params[4] = int_to_bcd(final_pos_msf[0]);
- params[5] = int_to_bcd(final_pos_msf[1]);
- params[6] = int_to_bcd(final_pos_msf[2]);
- params[0] = 0x03;
- if (do_sony_cd_cmd_chk
- ("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg,
- &res_size) < 0) {
- retval = -EIO;
- break;
- }
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
-
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* The parameters are given in int, must be converted */
- for (i = 1; i < 7; i++) {
- params[i] =
- int_to_bcd(((unsigned char *) arg)[i - 1]);
- }
- params[0] = 0x03;
- if (do_sony_cd_cmd_chk
- ("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7,
- res_reg, &res_size) < 0) {
- retval = -EIO;
- break;
- }
-
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = bcd_to_int(params[4]);
- final_pos_msf[1] = bcd_to_int(params[5]);
- final_pos_msf[2] = bcd_to_int(params[6]);
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- {
- struct cdrom_tochdr *hdr;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- hdr = (struct cdrom_tochdr *) arg;
- hdr->cdth_trk0 = sony_toc.first_track_num;
- hdr->cdth_trk1 = sony_toc.last_track_num;
- }
- retval = 0;
- break;
-
- case CDROMREADTOCENTRY: /* Read a given table of contents entry */
- {
- struct cdrom_tocentry *entry;
- int track_idx;
- unsigned char *msf_val = NULL;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- entry = (struct cdrom_tocentry *) arg;
-
- track_idx = find_track(entry->cdte_track);
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
-
- entry->cdte_adr =
- sony_toc.tracks[track_idx].address;
- entry->cdte_ctrl =
- sony_toc.tracks[track_idx].control;
- msf_val =
- sony_toc.tracks[track_idx].track_start_msf;
-
- /* Logical buffer address or MSF format requested? */
- if (entry->cdte_format == CDROM_LBA) {
- entry->cdte_addr.lba = msf_to_log(msf_val);
- } else if (entry->cdte_format == CDROM_MSF) {
- entry->cdte_addr.msf.minute = *msf_val;
- entry->cdte_addr.msf.second =
- *(msf_val + 1);
- entry->cdte_addr.msf.frame =
- *(msf_val + 2);
- }
- }
- retval = 0;
- break;
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- {
- struct cdrom_ti *ti = (struct cdrom_ti *) arg;
- int track_idx;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- if ((ti->cdti_trk0 < sony_toc.first_track_num)
- || (ti->cdti_trk0 > sony_toc.last_track_num)
- || (ti->cdti_trk1 < ti->cdti_trk0)) {
- retval = -EINVAL;
- break;
- }
-
- track_idx = find_track(ti->cdti_trk0);
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
- params[1] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[0]);
- params[2] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[1]);
- params[3] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[2]);
-
- /*
- * If we want to stop after the last track, use the lead-out
- * MSF to do that.
- */
- if (ti->cdti_trk1 >= sony_toc.last_track_num) {
- track_idx = find_track(CDROM_LEADOUT);
- } else {
- track_idx = find_track(ti->cdti_trk1 + 1);
- }
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
- params[4] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[0]);
- params[5] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[1]);
- params[6] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[2]);
- params[0] = 0x03;
-
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7,
- res_reg, &res_size);
-
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX
- "Params: %x %x %x %x %x %x %x\n",
- params[0], params[1], params[2],
- params[3], params[4], params[5],
- params[6]);
- printk(KERN_ERR PFX
- "Error %s (CDROMPLAYTRKIND)\n",
- translate_error(res_reg[1]));
- retval = -EIO;
- break;
- }
-
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = bcd_to_int(params[4]);
- final_pos_msf[1] = bcd_to_int(params[5]);
- final_pos_msf[2] = bcd_to_int(params[6]);
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
- }
-
- case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
- {
- struct cdrom_volctrl *volctrl =
- (struct cdrom_volctrl *) arg;
-
- params[0] = SONY_SD_AUDIO_VOLUME;
- params[1] = volctrl->channel0;
- params[2] = volctrl->channel1;
- retval = do_sony_cd_cmd_chk("VOLCTRL",
- SONY_SET_DRIVE_PARAM_CMD,
- params, 3, res_reg,
- &res_size);
- break;
- }
- case CDROMSUBCHNL: /* Get subchannel info */
- retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg);
- break;
-
- default:
- retval = -EINVAL;
- break;
- }
- up(&sony_sem);
- return retval;
-}
-
-static int scd_read_audio(struct cdrom_device_info *cdi,
- unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- switch (cmd) {
- case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte
- raw data tracks. */
- {
- struct cdrom_read_audio ra;
-
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- if (copy_from_user(&ra, argp, sizeof(ra))) {
- retval = -EFAULT;
- break;
- }
-
- if (ra.nframes == 0) {
- retval = 0;
- break;
- }
-
- if (!access_ok(VERIFY_WRITE, ra.buf,
- CD_FRAMESIZE_RAW * ra.nframes))
- return -EFAULT;
-
- if (ra.addr_format == CDROM_LBA) {
- if ((ra.addr.lba >=
- sony_toc.lead_out_start_lba)
- || (ra.addr.lba + ra.nframes >=
- sony_toc.lead_out_start_lba)) {
- retval = -EINVAL;
- break;
- }
- } else if (ra.addr_format == CDROM_MSF) {
- if ((ra.addr.msf.minute >= 75)
- || (ra.addr.msf.second >= 60)
- || (ra.addr.msf.frame >= 75)) {
- retval = -EINVAL;
- break;
- }
-
- ra.addr.lba = ((ra.addr.msf.minute * 4500)
- + (ra.addr.msf.second * 75)
- + ra.addr.msf.frame);
- if ((ra.addr.lba >=
- sony_toc.lead_out_start_lba)
- || (ra.addr.lba + ra.nframes >=
- sony_toc.lead_out_start_lba)) {
- retval = -EINVAL;
- break;
- }
-
- /* I know, this can go negative on an unsigned. However,
- the first thing done to the data is to add this value,
- so this should compensate and allow direct msf access. */
- ra.addr.lba -= LOG_START_OFFSET;
- } else {
- retval = -EINVAL;
- break;
- }
-
- retval = read_audio(&ra);
- break;
- }
- retval = 0;
- break;
-
- default:
- retval = -EINVAL;
- }
- up(&sony_sem);
- return retval;
-}
-
-static int scd_spinup(void)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- int num_spin_ups;
-
- num_spin_ups = 0;
-
- respinup_on_open:
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- printk(KERN_ERR PFX "%s error (scd_open, spin up)\n",
- translate_error(res_reg[1]));
- return 1;
- }
-
- do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- /* If the drive is already playing, it's ok. */
- if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
- || (res_reg[1] == 0)) {
- return 0;
- }
-
- /* If the drive says it is not spun up (even though we just did it!)
- then retry the operation at least a few times. */
- if ((res_reg[1] == SONY_NOT_SPIN_ERR)
- && (num_spin_ups < MAX_CDU31A_RETRIES)) {
- num_spin_ups++;
- goto respinup_on_open;
- }
-
- printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n",
- translate_error(res_reg[1]));
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
- return 1;
- }
- return 0;
-}
-
-/*
- * Open the drive for operations. Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int scd_open(struct cdrom_device_info *cdi, int purpose)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[2];
-
- if (purpose == 1) {
- /* Open for IOCTLs only - no media check */
- sony_usage++;
- return 0;
- }
-
- if (sony_usage == 0) {
- if (scd_spinup() != 0)
- return -EIO;
- sony_get_toc();
- if (!sony_toc_read) {
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0,
- res_reg, &res_size);
- return -EIO;
- }
-
- /* For XA on the CDU31A only, we have to do special reads.
- The CDU33A handles XA automagically. */
- /* if ( (sony_toc.disk_type == SONY_XA_DISK_TYPE) */
- if ((sony_toc.disk_type != 0x00)
- && (!is_double_speed)) {
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x07;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_WARNING PFX "Unable to set "
- "XA params: 0x%2.2x\n", res_reg[1]);
- }
- sony_xa_mode = 1;
- }
- /* A non-XA disk. Set the parms back if necessary. */
- else if (sony_xa_mode) {
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x0f;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_WARNING PFX "Unable to reset "
- "XA params: 0x%2.2x\n", res_reg[1]);
- }
- sony_xa_mode = 0;
- }
-
- sony_spun_up = 1;
- }
-
- sony_usage++;
-
- return 0;
-}
-
-
-/*
- * Close the drive. Spin it down if no task is using it. The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static void scd_release(struct cdrom_device_info *cdi)
-{
- if (sony_usage == 1) {
- unsigned char res_reg[12];
- unsigned int res_size;
-
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
-
- sony_spun_up = 0;
- }
- sony_usage--;
-}
-
-static struct cdrom_device_ops scd_dops = {
- .open = scd_open,
- .release = scd_release,
- .drive_status = scd_drive_status,
- .media_changed = scd_media_changed,
- .tray_move = scd_tray_move,
- .lock_door = scd_lock_door,
- .select_speed = scd_select_speed,
- .get_last_session = scd_get_last_session,
- .get_mcn = scd_get_mcn,
- .reset = scd_reset,
- .audio_ioctl = scd_audio_ioctl,
- .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
- CDC_SELECT_SPEED | CDC_MULTI_SESSION |
- CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
- CDC_RESET | CDC_DRIVE_STATUS,
- .n_minors = 1,
-};
-
-static struct cdrom_device_info scd_info = {
- .ops = &scd_dops,
- .speed = 2,
- .capacity = 1,
- .name = "cdu31a"
-};
-
-static int scd_block_open(struct inode *inode, struct file *file)
-{
- return cdrom_open(&scd_info, inode, file);
-}
-
-static int scd_block_release(struct inode *inode, struct file *file)
-{
- return cdrom_release(&scd_info, file);
-}
-
-static int scd_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- int retval;
-
- /* The eject and close commands should be handled by Uniform CD-ROM
- * driver - but I always got hard lockup instead of eject
- * until I put this here.
- */
- switch (cmd) {
- case CDROMEJECT:
- scd_lock_door(&scd_info, 0);
- retval = scd_tray_move(&scd_info, 1);
- break;
- case CDROMCLOSETRAY:
- retval = scd_tray_move(&scd_info, 0);
- break;
- case CDROMREADAUDIO:
- retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg);
- break;
- default:
- retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
- }
- return retval;
-}
-
-static int scd_block_media_changed(struct gendisk *disk)
-{
- return cdrom_media_changed(&scd_info);
-}
-
-static struct block_device_operations scd_bdops =
-{
- .owner = THIS_MODULE,
- .open = scd_block_open,
- .release = scd_block_release,
- .ioctl = scd_block_ioctl,
- .media_changed = scd_block_media_changed,
-};
-
-static struct gendisk *scd_gendisk;
-
-/* The different types of disc loading mechanisms supported */
-static char *load_mech[] __initdata =
- { "caddy", "tray", "pop-up", "unknown" };
-
-static int __init
-get_drive_configuration(unsigned short base_io,
- unsigned char res_reg[], unsigned int *res_size)
-{
- unsigned long retry_count;
-
-
- if (!request_region(base_io, 4, "cdu31a"))
- return 0;
-
- /* Set the base address */
- cdu31a_port = base_io;
-
- /* Set up all the register locations */
- sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET;
- sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET;
- sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET;
- sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET;
- sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET;
- sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET;
- sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET;
- sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET;
-
- /*
- * Check to see if anything exists at the status register location.
- * I don't know if this is a good way to check, but it seems to work
- * ok for me.
- */
- if (read_status_register() != 0xff) {
- /*
- * Reset the drive and wait for attention from it (to say it's reset).
- * If you don't wait, the next operation will probably fail.
- */
- reset_drive();
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && (!is_attention())) {
- sony_sleep();
- }
-
-#if 0
- /* If attention is never seen probably not a CDU31a present */
- if (!is_attention()) {
- res_reg[0] = 0x20;
- goto out_err;
- }
-#endif
-
- /*
- * Get the drive configuration.
- */
- do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
- NULL,
- 0, (unsigned char *) res_reg, res_size);
- if (*res_size <= 2 || (res_reg[0] & 0xf0) != 0)
- goto out_err;
- return 1;
- }
-
- /* Return an error */
- res_reg[0] = 0x20;
-out_err:
- release_region(cdu31a_port, 4);
- cdu31a_port = 0;
- return 0;
-}
-
-#ifndef MODULE
-/*
- * Set up base I/O and interrupts, called from main.c.
- */
-
-static int __init cdu31a_setup(char *strings)
-{
- int ints[4];
-
- (void) get_options(strings, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0) {
- cdu31a_port = ints[1];
- }
- if (ints[0] > 1) {
- cdu31a_irq = ints[2];
- }
- if ((strings != NULL) && (*strings != '\0')) {
- if (strcmp(strings, "PAS") == 0) {
- sony_pas_init = 1;
- } else {
- printk(KERN_NOTICE PFX "Unknown interface type: %s\n",
- strings);
- }
- }
-
- return 1;
-}
-
-__setup("cdu31a=", cdu31a_setup);
-
-#endif
-
-/*
- * Initialize the driver.
- */
-int __init cdu31a_init(void)
-{
- struct s_sony_drive_config drive_config;
- struct gendisk *disk;
- int deficiency = 0;
- unsigned int res_size;
- char msg[255];
- char buf[40];
- int i;
- int tmp_irq;
-
- /*
- * According to Alex Freed (freed@europa.orion.adobe.com), this is
- * required for the Fusion CD-16 package. If the sound driver is
- * loaded, it should work fine, but just in case...
- *
- * The following turn on the CD-ROM interface for a Fusion CD-16.
- */
- if (sony_pas_init) {
- outb(0xbc, 0x9a01);
- outb(0xe2, 0x9a01);
- }
-
- /* Setting the base I/O address to 0xffff will disable it. */
- if (cdu31a_port == 0xffff)
- goto errout3;
-
- if (cdu31a_port != 0) {
- /* Need IRQ 0 because we can't sleep here. */
- tmp_irq = cdu31a_irq;
- cdu31a_irq = 0;
- if (!get_drive_configuration(cdu31a_port,
- drive_config.exec_status,
- &res_size))
- goto errout3;
- cdu31a_irq = tmp_irq;
- } else {
- cdu31a_irq = 0;
- for (i = 0; cdu31a_addresses[i].base; i++) {
- if (get_drive_configuration(cdu31a_addresses[i].base,
- drive_config.exec_status,
- &res_size)) {
- cdu31a_irq = cdu31a_addresses[i].int_num;
- break;
- }
- }
- if (!cdu31a_port)
- goto errout3;
- }
-
- if (register_blkdev(MAJOR_NR, "cdu31a"))
- goto errout2;
-
- disk = alloc_disk(1);
- if (!disk)
- goto errout1;
- disk->major = MAJOR_NR;
- disk->first_minor = 0;
- sprintf(disk->disk_name, "cdu31a");
- disk->fops = &scd_bdops;
- disk->flags = GENHD_FL_CD;
-
- if (SONY_HWC_DOUBLE_SPEED(drive_config))
- is_double_speed = 1;
-
- tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */
- cdu31a_irq = 0;
-
- sony_speed = is_double_speed; /* Set 2X drives to 2X by default */
- set_drive_params(sony_speed);
-
- cdu31a_irq = tmp_irq;
-
- if (cdu31a_irq > 0) {
- if (request_irq
- (cdu31a_irq, cdu31a_interrupt, IRQF_DISABLED,
- "cdu31a", NULL)) {
- printk(KERN_WARNING PFX "Unable to grab IRQ%d for "
- "the CDU31A driver\n", cdu31a_irq);
- cdu31a_irq = 0;
- }
- }
-
- sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
- drive_config.vendor_id,
- drive_config.product_id,
- drive_config.product_rev_level);
- sprintf(buf, " Capabilities: %s",
- load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
- strcat(msg, buf);
- if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
- strcat(msg, ", audio");
- else
- deficiency |= CDC_PLAY_AUDIO;
- if (SONY_HWC_EJECT(drive_config))
- strcat(msg, ", eject");
- else
- deficiency |= CDC_OPEN_TRAY;
- if (SONY_HWC_LED_SUPPORT(drive_config))
- strcat(msg, ", LED");
- if (SONY_HWC_ELECTRIC_VOLUME(drive_config))
- strcat(msg, ", elec. Vol");
- if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config))
- strcat(msg, ", sep. Vol");
- if (is_double_speed)
- strcat(msg, ", double speed");
- else
- deficiency |= CDC_SELECT_SPEED;
- if (cdu31a_irq > 0) {
- sprintf(buf, ", irq %d", cdu31a_irq);
- strcat(msg, buf);
- }
- strcat(msg, "\n");
- printk(KERN_INFO PFX "%s",msg);
-
- cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock);
- if (!cdu31a_queue)
- goto errout0;
- blk_queue_hardsect_size(cdu31a_queue, 2048);
-
- init_timer(&cdu31a_abort_timer);
- cdu31a_abort_timer.function = handle_abort_timeout;
-
- scd_info.mask = deficiency;
- scd_gendisk = disk;
- if (register_cdrom(&scd_info))
- goto err;
- disk->queue = cdu31a_queue;
- add_disk(disk);
-
- disk_changed = 1;
- return 0;
-
-err:
- blk_cleanup_queue(cdu31a_queue);
-errout0:
- if (cdu31a_irq)
- free_irq(cdu31a_irq, NULL);
- printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n");
- put_disk(disk);
-errout1:
- if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
- printk(KERN_WARNING PFX "Can't unregister block device\n");
- }
-errout2:
- release_region(cdu31a_port, 4);
-errout3:
- return -EIO;
-}
-
-
-static void __exit cdu31a_exit(void)
-{
- del_gendisk(scd_gendisk);
- put_disk(scd_gendisk);
- if (unregister_cdrom(&scd_info)) {
- printk(KERN_WARNING PFX "Can't unregister from Uniform "
- "cdrom driver\n");
- return;
- }
- if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
- printk(KERN_WARNING PFX "Can't unregister\n");
- return;
- }
-
- blk_cleanup_queue(cdu31a_queue);
-
- if (cdu31a_irq > 0)
- free_irq(cdu31a_irq, NULL);
-
- release_region(cdu31a_port, 4);
- printk(KERN_INFO PFX "module released.\n");
-}
-
-#ifdef MODULE
-module_init(cdu31a_init);
-#endif
-module_exit(cdu31a_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU31A_CDROM_MAJOR);
diff --git a/drivers/cdrom/cdu31a.h b/drivers/cdrom/cdu31a.h
deleted file mode 100644
index 61d4768c412e..000000000000
--- a/drivers/cdrom/cdu31a.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Definitions for a Sony interface CDROM drive.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com)
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/*
- * General defines.
- */
-#define SONY_XA_DISK_TYPE 0x20
-
-/*
- * Offsets (from the base address) and bits for the various write registers
- * of the drive.
- */
-#define SONY_CMD_REG_OFFSET 0
-#define SONY_PARAM_REG_OFFSET 1
-#define SONY_WRITE_REG_OFFSET 2
-#define SONY_CONTROL_REG_OFFSET 3
-# define SONY_ATTN_CLR_BIT 0x01
-# define SONY_RES_RDY_CLR_BIT 0x02
-# define SONY_DATA_RDY_CLR_BIT 0x04
-# define SONY_ATTN_INT_EN_BIT 0x08
-# define SONY_RES_RDY_INT_EN_BIT 0x10
-# define SONY_DATA_RDY_INT_EN_BIT 0x20
-# define SONY_PARAM_CLR_BIT 0x40
-# define SONY_DRIVE_RESET_BIT 0x80
-
-/*
- * Offsets (from the base address) and bits for the various read registers
- * of the drive.
- */
-#define SONY_STATUS_REG_OFFSET 0
-# define SONY_ATTN_BIT 0x01
-# define SONY_RES_RDY_BIT 0x02
-# define SONY_DATA_RDY_BIT 0x04
-# define SONY_ATTN_INT_ST_BIT 0x08
-# define SONY_RES_RDY_INT_ST_BIT 0x10
-# define SONY_DATA_RDY_INT_ST_BIT 0x20
-# define SONY_DATA_REQUEST_BIT 0x40
-# define SONY_BUSY_BIT 0x80
-#define SONY_RESULT_REG_OFFSET 1
-#define SONY_READ_REG_OFFSET 2
-#define SONY_FIFOST_REG_OFFSET 3
-# define SONY_PARAM_WRITE_RDY_BIT 0x01
-# define SONY_PARAM_REG_EMPTY_BIT 0x02
-# define SONY_RES_REG_NOT_EMP_BIT 0x04
-# define SONY_RES_REG_FULL_BIT 0x08
-
-#define LOG_START_OFFSET 150 /* Offset of first logical sector */
-
-#define SONY_DETECT_TIMEOUT (8*HZ/10) /* Maximum amount of time
- that drive detection code
- will wait for response
- from drive (in 1/100th's
- of seconds). */
-
-#define SONY_JIFFIES_TIMEOUT (10*HZ) /* Maximum number of times the
- drive will wait/try for an
- operation */
-#define SONY_RESET_TIMEOUT HZ /* Maximum number of times the
- drive will wait/try a reset
- operation */
-#define SONY_READY_RETRIES 20000 /* How many times to retry a
- spin waiting for a register
- to come ready */
-
-#define MAX_CDU31A_RETRIES 3 /* How many times to retry an
- operation */
-
-/* Commands to request or set drive control parameters and disc information */
-#define SONY_REQ_DRIVE_CONFIG_CMD 0x00 /* Returns s_sony_drive_config */
-#define SONY_REQ_DRIVE_MODE_CMD 0x01
-#define SONY_REQ_DRIVE_PARAM_CMD 0x02
-#define SONY_REQ_MECH_STATUS_CMD 0x03
-#define SONY_REQ_AUDIO_STATUS_CMD 0x04
-#define SONY_SET_DRIVE_PARAM_CMD 0x10
-#define SONY_REQ_TOC_DATA_CMD 0x20 /* Returns s_sony_toc */
-#define SONY_REQ_SUBCODE_ADDRESS_CMD 0x21 /* Returns s_sony_subcode */
-#define SONY_REQ_UPC_EAN_CMD 0x22
-#define SONY_REQ_ISRC_CMD 0x23
-#define SONY_REQ_TOC_DATA_SPEC_CMD 0x24 /* Returns s_sony_session_toc */
-
-/* Commands to request information from the drive */
-#define SONY_READ_TOC_CMD 0x30 /* let the drive firmware grab the TOC */
-#define SONY_SEEK_CMD 0x31
-#define SONY_READ_CMD 0x32
-#define SONY_READ_BLKERR_STAT_CMD 0x34
-#define SONY_ABORT_CMD 0x35
-#define SONY_READ_TOC_SPEC_CMD 0x36
-
-/* Commands to control audio */
-#define SONY_AUDIO_PLAYBACK_CMD 0x40
-#define SONY_AUDIO_STOP_CMD 0x41
-#define SONY_AUDIO_SCAN_CMD 0x42
-
-/* Miscellaneous control commands */
-#define SONY_EJECT_CMD 0x50
-#define SONY_SPIN_UP_CMD 0x51
-#define SONY_SPIN_DOWN_CMD 0x52
-
-/* Diagnostic commands */
-#define SONY_WRITE_BUFFER_CMD 0x60
-#define SONY_READ_BUFFER_CMD 0x61
-#define SONY_DIAGNOSTICS_CMD 0x62
-
-
-/*
- * The following are command parameters for the set drive parameter command
- */
-#define SONY_SD_DECODE_PARAM 0x00
-#define SONY_SD_INTERFACE_PARAM 0x01
-#define SONY_SD_BUFFERING_PARAM 0x02
-#define SONY_SD_AUDIO_PARAM 0x03
-#define SONY_SD_AUDIO_VOLUME 0x04
-#define SONY_SD_MECH_CONTROL 0x05
-#define SONY_SD_AUTO_SPIN_DOWN_TIME 0x06
-
-/*
- * The following are parameter bits for the mechanical control command
- */
-#define SONY_AUTO_SPIN_UP_BIT 0x01
-#define SONY_AUTO_EJECT_BIT 0x02
-#define SONY_DOUBLE_SPEED_BIT 0x04
-
-/*
- * The following extract information from the drive configuration about
- * the drive itself.
- */
-#define SONY_HWC_GET_LOAD_MECH(c) (c.hw_config[0] & 0x03)
-#define SONY_HWC_EJECT(c) (c.hw_config[0] & 0x04)
-#define SONY_HWC_LED_SUPPORT(c) (c.hw_config[0] & 0x08)
-#define SONY_HWC_DOUBLE_SPEED(c) (c.hw_config[0] & 0x10)
-#define SONY_HWC_GET_BUF_MEM_SIZE(c) ((c.hw_config[0] & 0xc0) >> 6)
-#define SONY_HWC_AUDIO_PLAYBACK(c) (c.hw_config[1] & 0x01)
-#define SONY_HWC_ELECTRIC_VOLUME(c) (c.hw_config[1] & 0x02)
-#define SONY_HWC_ELECTRIC_VOLUME_CTL(c) (c.hw_config[1] & 0x04)
-
-#define SONY_HWC_CADDY_LOAD_MECH 0x00
-#define SONY_HWC_TRAY_LOAD_MECH 0x01
-#define SONY_HWC_POPUP_LOAD_MECH 0x02
-#define SONY_HWC_UNKWN_LOAD_MECH 0x03
-
-#define SONY_HWC_8KB_BUFFER 0x00
-#define SONY_HWC_32KB_BUFFER 0x01
-#define SONY_HWC_64KB_BUFFER 0x02
-#define SONY_HWC_UNKWN_BUFFER 0x03
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s_sony_drive_config
-{
- unsigned char exec_status[2];
- char vendor_id[8];
- char product_id[16];
- char product_rev_level[8];
- unsigned char hw_config[2];
-};
-
-/* The following is returned from the request subcode address command */
-struct s_sony_subcode
-{
- unsigned char exec_status[2];
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track_num;
- unsigned char index_num;
- unsigned char rel_msf[3];
- unsigned char reserved1;
- unsigned char abs_msf[3];
-};
-
-#define MAX_TRACKS 100 /* The maximum tracks a disk may have. */
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s_sony_toc
-{
- unsigned char exec_status[2];
- unsigned char address0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char disk_type;
- unsigned char dummy0;
- unsigned char address1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char address2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int lead_out_start_lba;
-};
-
-struct s_sony_session_toc
-{
- unsigned char exec_status[2];
- unsigned char session_number;
- unsigned char address0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char disk_type;
- unsigned char dummy0;
- unsigned char address1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char address2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- unsigned char addressb0 :4;
- unsigned char controlb0 :4;
- unsigned char pointb0;
- unsigned char next_poss_prog_area_msf[3];
- unsigned char num_mode_5_pointers;
- unsigned char max_start_outer_leadout_msf[3];
- unsigned char addressb1 :4;
- unsigned char controlb1 :4;
- unsigned char pointb1;
- unsigned char dummyb0_1[4];
- unsigned char num_skip_interval_pointers;
- unsigned char num_skip_track_assignments;
- unsigned char dummyb0_2;
- unsigned char addressb2 :4;
- unsigned char controlb2 :4;
- unsigned char pointb2;
- unsigned char tracksb2[7];
- unsigned char addressb3 :4;
- unsigned char controlb3 :4;
- unsigned char pointb3;
- unsigned char tracksb3[7];
- unsigned char addressb4 :4;
- unsigned char controlb4 :4;
- unsigned char pointb4;
- unsigned char tracksb4[7];
- unsigned char addressc0 :4;
- unsigned char controlc0 :4;
- unsigned char pointc0;
- unsigned char dummyc0[7];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int start_track_lba;
- unsigned int lead_out_start_lba;
- unsigned int mint;
- unsigned int maxt;
-};
-
-struct s_all_sessions_toc
-{
- unsigned char sessions;
- unsigned int track_entries;
- unsigned char first_track_num;
- unsigned char last_track_num;
- unsigned char disk_type;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int start_track_lba;
- unsigned int lead_out_start_lba;
-};
-
-
-/*
- * The following are errors returned from the drive.
- */
-
-/* Command error group */
-#define SONY_ILL_CMD_ERR 0x10
-#define SONY_ILL_PARAM_ERR 0x11
-
-/* Mechanism group */
-#define SONY_NOT_LOAD_ERR 0x20
-#define SONY_NO_DISK_ERR 0x21
-#define SONY_NOT_SPIN_ERR 0x22
-#define SONY_SPIN_ERR 0x23
-#define SONY_SPINDLE_SERVO_ERR 0x25
-#define SONY_FOCUS_SERVO_ERR 0x26
-#define SONY_EJECT_MECH_ERR 0x29
-#define SONY_AUDIO_PLAYING_ERR 0x2a
-#define SONY_EMERGENCY_EJECT_ERR 0x2c
-
-/* Seek error group */
-#define SONY_FOCUS_ERR 0x30
-#define SONY_FRAME_SYNC_ERR 0x31
-#define SONY_SUBCODE_ADDR_ERR 0x32
-#define SONY_BLOCK_SYNC_ERR 0x33
-#define SONY_HEADER_ADDR_ERR 0x34
-
-/* Read error group */
-#define SONY_ILL_TRACK_R_ERR 0x40
-#define SONY_MODE_0_R_ERR 0x41
-#define SONY_ILL_MODE_R_ERR 0x42
-#define SONY_ILL_BLOCK_SIZE_R_ERR 0x43
-#define SONY_MODE_R_ERR 0x44
-#define SONY_FORM_R_ERR 0x45
-#define SONY_LEAD_OUT_R_ERR 0x46
-#define SONY_BUFFER_OVERRUN_R_ERR 0x47
-
-/* Data error group */
-#define SONY_UNREC_CIRC_ERR 0x53
-#define SONY_UNREC_LECC_ERR 0x57
-
-/* Subcode error group */
-#define SONY_NO_TOC_ERR 0x60
-#define SONY_SUBCODE_DATA_NVAL_ERR 0x61
-#define SONY_FOCUS_ON_TOC_READ_ERR 0x63
-#define SONY_FRAME_SYNC_ON_TOC_READ_ERR 0x64
-#define SONY_TOC_DATA_ERR 0x65
-
-/* Hardware failure group */
-#define SONY_HW_FAILURE_ERR 0x70
-#define SONY_LEAD_IN_A_ERR 0x91
-#define SONY_LEAD_OUT_A_ERR 0x92
-#define SONY_DATA_TRACK_A_ERR 0x93
-
-/*
- * The following are returned from the Read With Block Error Status command.
- * They are not errors but information (Errors from the 0x5x group above may
- * also be returned
- */
-#define SONY_NO_CIRC_ERR_BLK_STAT 0x50
-#define SONY_NO_LECC_ERR_BLK_STAT 0x54
-#define SONY_RECOV_LECC_ERR_BLK_STAT 0x55
-#define SONY_NO_ERR_DETECTION_STAT 0x59
-
-/*
- * The following is not an error returned by the drive, but by the code
- * that talks to the drive. It is returned because of a timeout.
- */
-#define SONY_TIMEOUT_OP_ERR 0x01
-#define SONY_SIGNAL_OP_ERR 0x02
-#define SONY_BAD_DATA_ERR 0x03
-
-
-/*
- * The following are attention code for asynchronous events from the drive.
- */
-
-/* Standard attention group */
-#define SONY_EMER_EJECT_ATTN 0x2c
-#define SONY_HW_FAILURE_ATTN 0x70
-#define SONY_MECH_LOADED_ATTN 0x80
-#define SONY_EJECT_PUSHED_ATTN 0x81
-
-/* Audio attention group */
-#define SONY_AUDIO_PLAY_DONE_ATTN 0x90
-#define SONY_LEAD_IN_ERR_ATTN 0x91
-#define SONY_LEAD_OUT_ERR_ATTN 0x92
-#define SONY_DATA_TRACK_ERR_ATTN 0x93
-#define SONY_AUDIO_PLAYBACK_ERR_ATTN 0x94
-
-/* Auto spin up group */
-#define SONY_SPIN_UP_COMPLETE_ATTN 0x24
-#define SONY_SPINDLE_SERVO_ERR_ATTN 0x25
-#define SONY_FOCUS_SERVO_ERR_ATTN 0x26
-#define SONY_TOC_READ_DONE_ATTN 0x62
-#define SONY_FOCUS_ON_TOC_READ_ERR_ATTN 0x63
-#define SONY_SYNC_ON_TOC_READ_ERR_ATTN 0x65
-
-/* Auto eject group */
-#define SONY_SPIN_DOWN_COMPLETE_ATTN 0x27
-#define SONY_EJECT_COMPLETE_ATTN 0x28
-#define SONY_EJECT_MECH_ERR_ATTN 0x29
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
deleted file mode 100644
index 230131163240..000000000000
--- a/drivers/cdrom/cm206.c
+++ /dev/null
@@ -1,1594 +0,0 @@
-/* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
- Copyright (c) 1995--1997 David A. van Leeuwen.
- $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-History:
- Started 25 jan 1994. Waiting for documentation...
- 22 feb 1995: 0.1a first reasonably safe polling driver.
- Two major bugs, one in read_sector and one in
- do_cm206_request, happened to cancel!
- 25 feb 1995: 0.2a first reasonable interrupt driven version of above.
- uart writes are still done in polling mode.
- 25 feb 1995: 0.21a writes also in interrupt mode, still some
- small bugs to be found... Larger buffer.
- 2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in
- initialization), read_ahead of 16. Timeouts implemented.
- unclear if they do something...
- 7 mrt 1995: 0.23 Start of background read-ahead.
- 18 mrt 1995: 0.24 Working background read-ahead. (still problems)
- 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
- Statistics implemented, though separate stats206.h.
- Accessible through ioctl 0x1000 (just a number).
- Hard to choose between v1.2 development and 1.1.75.
- Bottom-half doesn't work with 1.2...
- 0.25a: fixed... typo. Still problems...
- 1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n.
- 5 apr 1995: 0.27 Auto-probe for the adapter card base address.
- Auto-probe for the adaptor card irq line.
- 7 apr 1995: 0.28 Added lilo setup support for base address and irq.
- Use major number 32 (not in this source), officially
- assigned to this driver.
- 9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause,
- resume, eject. Play_track ignores track info, because we can't
- read a table-of-contents entry. Toc_entry is implemented
- as a `placebo' function: always returns start of disc.
- 3 may 1995: 0.30 Audio support completed. The get_toc_entry function
- is implemented as a binary search.
- 15 may 1995: 0.31 More work on audio stuff. Workman is not easy to
- satisfy; changed binary search into linear search.
- Auto-probe for base address somewhat relaxed.
- 1 jun 1995: 0.32 Removed probe_irq_on/off for module version.
- 10 jun 1995: 0.33 Workman still behaves funny, but you should be
- able to eject and substitute another disc.
-
- An adaptation of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg
-
- 18 jul 1995: 0.34 Patch by Heiko Eissfeldt included, mainly considering
- verify_area's in the ioctls. Some bugs introduced by
- EM considering the base port and irq fixed.
-
- 18 dec 1995: 0.35 Add some code for error checking... no luck...
-
- We jump to reach our goal: version 1.0 in the next stable linux kernel.
-
- 19 mar 1996: 0.95 Different implementation of CDROM_GET_UPC, on
- request of Thomas Quinot.
- 25 mar 1996: 0.96 Interpretation of opening with O_WRONLY or O_RDWR:
- open only for ioctl operation, e.g., for operation of
- tray etc.
- 4 apr 1996: 0.97 First implementation of layer between VFS and cdrom
- driver, a generic interface. Much of the functionality
- of cm206_open() and cm206_ioctl() is transferred to a
- new file cdrom.c and its header ucdrom.h.
-
- Upgrade to Linux kernel 1.3.78.
-
- 11 apr 1996 0.98 Upgrade to Linux kernel 1.3.85
- More code moved to cdrom.c
-
- 0.99 Some more small changes to decrease number
- of oopses at module load;
-
- 27 jul 1996 0.100 Many hours of debugging, kernel change from 1.2.13
- to 2.0.7 seems to have introduced some weird behavior
- in (interruptible_)sleep_on(&cd->data): the process
- seems to be woken without any explicit wake_up in my own
- code. Patch to try 100x in case such untriggered wake_up's
- occur.
-
- 28 jul 1996 0.101 Rewriting of the code that receives the command echo,
- using a fifo to store echoed bytes.
-
- Branch from 0.99:
-
- 0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
- (emoenke) various typos found by others. extra
- module-load oops protection.
-
- 0.99.1.1 Initialization constant cdrom_dops.speed
- changed from float (2.0) to int (2); Cli()-sti() pair
- around cm260_reset() in module initialization code.
-
- 0.99.1.2 Changes literally as proposed by Scott Snyder
- <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which
- have to do mainly with the poor minor support i had. The
- major new concept is to change a cdrom driver's
- operations struct from the capabilities struct. This
- reflects the fact that there is one major for a driver,
- whilst there can be many minors whith completely
- different capabilities.
-
- 0.99.1.3 More changes for operations/info separation.
-
- 0.99.1.4 Added speed selection (someone had to do this
- first).
-
- 23 jan 1997 0.99.1.5 MODULE_PARMS call added.
-
- 23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as
- 0.99.1.1--0.99.1.5. I get too many complaints about the
- drive making read errors. What't wrong with the 2.0+
- kernel line? Why get i (and othe cm206 owners) weird
- results? Why were things good in the good old 1.1--1.2
- era? Why don't i throw away the drive?
-
- 2 feb 1997 0.102 Added `volatile' to values in cm206_struct. Seems to
- reduce many of the problems. Rewrote polling routines
- to use fixed delays between polls.
- 0.103 Changed printk behavior.
- 0.104 Added a 0.100 -> 0.100.1.1 change
-
-11 feb 1997 0.105 Allow auto_probe during module load, disable
- with module option "auto_probe=0". Moved some debugging
- statements to lower priority. Implemented select_speed()
- function.
-
-13 feb 1997 1.0 Final version for 2.0 kernel line.
-
- All following changes will be for the 2.1 kernel line.
-
-15 feb 1997 1.1 Keep up with kernel 2.1.26, merge in changes from
- cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS.
-
-14 sep 1997 1.2 Upgrade to Linux 2.1.55. Added blksize_size[], patch
- sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>.
-
-21 dec 1997 1.4 Upgrade to Linux 2.1.72.
-
-24 jan 1998 Removed the cm206_disc_status() function, as it was now dead
- code. The Uniform CDROM driver now provides this functionality.
-
-9 Nov. 1999 Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
- *
- * Parts of the code are based upon lmscd.c written by Kai Petzke,
- * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
- * Harriss, but any off-the-shelf dynamic programming algorithm won't
- * be able to find them.
- *
- * The cm206 drive interface and the cm260 adapter card seem to be
- * sufficiently different from their cm205/cm250 counterparts
- * in order to write a complete new driver.
- *
- * I call all routines connected to the Linux kernel something
- * with `cm206' in it, as this stuff is too series-dependent.
- *
- * Currently, my limited knowledge is based on:
- * - The Linux Kernel Hacker's guide, v. 0.5, by Michael K. Johnson
- * - Linux Kernel Programmierung, by Michael Beck and others
- * - Philips/LMS cm206 and cm226 product specification
- * - Philips/LMS cm260 product specification
- *
- * David van Leeuwen, david@tm.tno.nl. */
-#define REVISION "$Revision: 1.5 $"
-
-#include <linux/module.h>
-
-#include <linux/errno.h> /* These include what we really need */
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-/* #include <linux/ucdrom.h> */
-
-#include <asm/io.h>
-
-#define MAJOR_NR CM206_CDROM_MAJOR
-
-#include <linux/blkdev.h>
-
-#undef DEBUG
-#define STATISTICS /* record times and frequencies of events */
-#define AUTO_PROBE_MODULE
-#define USE_INSW
-
-#include "cm206.h"
-
-/* This variable defines whether or not to probe for adapter base port
- address and interrupt request. It can be overridden by the boot
- parameter `auto'.
-*/
-static int auto_probe = 1; /* Yes, why not? */
-
-static int cm206_base = CM206_BASE;
-static int cm206_irq = CM206_IRQ;
-#ifdef MODULE
-static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */
-module_param_array(cm206, int, NULL, 0); /* base,irq or irq,base */
-#endif
-
-module_param(cm206_base, int, 0); /* base */
-module_param(cm206_irq, int, 0); /* irq */
-module_param(auto_probe, bool, 0); /* auto probe base and irq */
-MODULE_LICENSE("GPL");
-
-#define POLLOOP 100 /* milliseconds */
-#define READ_AHEAD 1 /* defines private buffer, waste! */
-#define BACK_AHEAD 1 /* defines adapter-read ahead */
-#define DATA_TIMEOUT (3*HZ) /* measured in jiffies (10 ms) */
-#define UART_TIMEOUT (5*HZ/100)
-#define DSB_TIMEOUT (7*HZ) /* time for the slowest command to finish */
-#define UR_SIZE 4 /* uart receive buffer fifo size */
-
-#define LINUX_BLOCK_SIZE 512 /* WHERE is this defined? */
-#define RAW_SECTOR_SIZE 2352 /* ok, is also defined in cdrom.h */
-#define ISO_SECTOR_SIZE 2048
-#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE) /* 4 */
-#define CD_SYNC_HEAD 16 /* CD_SYNC + CD_HEAD */
-
-#ifdef STATISTICS /* keep track of errors in counters */
-#define stats(i) { ++cd->stats[st_ ## i]; \
- cd->last_stat[st_ ## i] = cd->stat_counter++; \
- }
-#else
-#define stats(i) (void) 0;
-#endif
-
-#define Debug(a) {printk (KERN_DEBUG); printk a;}
-#ifdef DEBUG
-#define debug(a) Debug(a)
-#else
-#define debug(a) (void) 0;
-#endif
-
-typedef unsigned char uch; /* 8-bits */
-typedef unsigned short ush; /* 16-bits */
-
-struct toc_struct { /* private copy of Table of Contents */
- uch track, fsm[3], q0;
-};
-
-struct cm206_struct {
- volatile ush intr_ds; /* data status read on last interrupt */
- volatile ush intr_ls; /* uart line status read on last interrupt */
- volatile uch ur[UR_SIZE]; /* uart receive buffer fifo */
- volatile uch ur_w, ur_r; /* write/read buffer index */
- volatile uch dsb, cc; /* drive status byte and condition (error) code */
- int command; /* command to be written to the uart */
- int openfiles;
- ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2]; /* buffered cd-sector */
- int sector_first, sector_last; /* range of these sectors */
- wait_queue_head_t uart; /* wait queues for interrupt */
- wait_queue_head_t data;
- struct timer_list timer; /* time-out */
- char timed_out;
- signed char max_sectors; /* number of sectors that fit in adapter mem */
- char wait_back; /* we're waiting for a background-read */
- char background; /* is a read going on in the background? */
- int adapter_first; /* if so, that's the starting sector */
- int adapter_last;
- char fifo_overflowed;
- uch disc_status[7]; /* result of get_disc_status command */
-#ifdef STATISTICS
- int stats[NR_STATS];
- int last_stat[NR_STATS]; /* `time' at which stat was stat */
- int stat_counter;
-#endif
- struct toc_struct toc[101]; /* The whole table of contents + lead-out */
- uch q[10]; /* Last read q-channel info */
- uch audio_status[5]; /* last read position on pause */
- uch media_changed; /* record if media changed */
-};
-
-#define DISC_STATUS cd->disc_status[0]
-#define FIRST_TRACK cd->disc_status[1]
-#define LAST_TRACK cd->disc_status[2]
-#define PAUSED cd->audio_status[0] /* misuse this memory byte! */
-#define PLAY_TO cd->toc[0] /* toc[0] records end-time in play */
-
-static struct cm206_struct *cd; /* the main memory structure */
-static struct request_queue *cm206_queue;
-static DEFINE_SPINLOCK(cm206_lock);
-
-/* First, we define some polling functions. These are actually
- only being used in the initialization. */
-
-static void send_command_polled(int command)
-{
- int loop = POLLOOP;
- while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
- && loop > 0) {
- mdelay(1); /* one millisec delay */
- --loop;
- }
- outw(command, r_uart_transmit);
-}
-
-static uch receive_echo_polled(void)
-{
- int loop = POLLOOP;
- while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
- mdelay(1);
- --loop;
- }
- return ((uch) inw(r_uart_receive));
-}
-
-static uch send_receive_polled(int command)
-{
- send_command_polled(command);
- return receive_echo_polled();
-}
-
-static inline void clear_ur(void)
-{
- if (cd->ur_r != cd->ur_w) {
- debug(("Deleting bytes from fifo:"));
- for (; cd->ur_r != cd->ur_w;
- cd->ur_r++, cd->ur_r %= UR_SIZE)
- debug((" 0x%x", cd->ur[cd->ur_r]));
- debug(("\n"));
- }
-}
-
-static struct tasklet_struct cm206_tasklet;
-
-/* The interrupt handler. When the cm260 generates an interrupt, very
- much care has to be taken in reading out the registers in the right
- order; in case of a receive_buffer_full interrupt, first the
- uart_receive must be read, and then the line status again to
- de-assert the interrupt line. It took me a couple of hours to find
- this out:-(
-
- The function reset_cm206 appears to cause an interrupt, because
- pulling up the INIT line clears both the uart-write-buffer /and/
- the uart-write-buffer-empty mask. We call this a `lost interrupt,'
- as there seems so reason for this to happen.
-*/
-
-static irqreturn_t cm206_interrupt(int sig, void *dev_id)
-{
- volatile ush fool;
- cd->intr_ds = inw(r_data_status); /* resets data_ready, data_error,
- crc_error, sync_error, toc_ready
- interrupts */
- cd->intr_ls = inw(r_line_status); /* resets overrun bit */
- debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
- cd->background));
- if (cd->intr_ls & ls_attention)
- stats(attention);
- /* receive buffer full? */
- if (cd->intr_ls & ls_receive_buffer_full) {
- cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */
- cd->intr_ls = inw(r_line_status); /* resets rbf interrupt */
- debug(("receiving #%d: 0x%x\n", cd->ur_w,
- cd->ur[cd->ur_w]));
- cd->ur_w++;
- cd->ur_w %= UR_SIZE;
- if (cd->ur_w == cd->ur_r)
- debug(("cd->ur overflow!\n"));
- if (waitqueue_active(&cd->uart) && cd->background < 2) {
- del_timer(&cd->timer);
- wake_up_interruptible(&cd->uart);
- }
- }
- /* data ready in fifo? */
- else if (cd->intr_ds & ds_data_ready) {
- if (cd->background)
- ++cd->adapter_last;
- if (waitqueue_active(&cd->data)
- && (cd->wait_back || !cd->background)) {
- del_timer(&cd->timer);
- wake_up_interruptible(&cd->data);
- }
- stats(data_ready);
- }
- /* ready to issue a write command? */
- else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
- outw(dc_normal | (inw(r_data_status) & 0x7f),
- r_data_control);
- outw(cd->command, r_uart_transmit);
- cd->command = 0;
- if (!cd->background)
- wake_up_interruptible(&cd->uart);
- }
- /* now treat errors (at least, identify them for debugging) */
- else if (cd->intr_ds & ds_fifo_overflow) {
- debug(("Fifo overflow at sectors 0x%x\n",
- cd->sector_first));
- fool = inw(r_fifo_output_buffer); /* de-assert the interrupt */
- cd->fifo_overflowed = 1; /* signal one word less should be read */
- stats(fifo_overflow);
- } else if (cd->intr_ds & ds_data_error) {
- debug(("Data error at sector 0x%x\n", cd->sector_first));
- stats(data_error);
- } else if (cd->intr_ds & ds_crc_error) {
- debug(("CRC error at sector 0x%x\n", cd->sector_first));
- stats(crc_error);
- } else if (cd->intr_ds & ds_sync_error) {
- debug(("Sync at sector 0x%x\n", cd->sector_first));
- stats(sync_error);
- } else if (cd->intr_ds & ds_toc_ready) {
- /* do something appropriate */
- }
- /* couldn't see why this interrupt, maybe due to init */
- else {
- outw(dc_normal | READ_AHEAD, r_data_control);
- stats(lost_intr);
- }
- if (cd->background
- && (cd->adapter_last - cd->adapter_first == cd->max_sectors
- || cd->fifo_overflowed))
- tasklet_schedule(&cm206_tasklet); /* issue a stop read command */
- stats(interrupt);
- return IRQ_HANDLED;
-}
-
-/* we have put the address of the wait queue in who */
-static void cm206_timeout(unsigned long who)
-{
- cd->timed_out = 1;
- debug(("Timing out\n"));
- wake_up_interruptible((wait_queue_head_t *) who);
-}
-
-/* This function returns 1 if a timeout occurred, 0 if an interrupt
- happened */
-static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
-{
- cd->timed_out = 0;
- init_timer(&cd->timer);
- cd->timer.data = (unsigned long) wait;
- cd->timer.expires = jiffies + timeout;
- add_timer(&cd->timer);
- debug(("going to sleep\n"));
- interruptible_sleep_on(wait);
- del_timer(&cd->timer);
- if (cd->timed_out) {
- cd->timed_out = 0;
- return 1;
- } else
- return 0;
-}
-
-static void send_command(int command)
-{
- debug(("Sending 0x%x\n", command));
- if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
- cd->command = command;
- cli(); /* don't interrupt before sleep */
- outw(dc_mask_sync_error | dc_no_stop_on_error |
- (inw(r_data_status) & 0x7f), r_data_control);
- /* interrupt routine sends command */
- if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
- debug(("Time out on write-buffer\n"));
- stats(write_timeout);
- outw(command, r_uart_transmit);
- }
- debug(("Write commmand delayed\n"));
- } else
- outw(command, r_uart_transmit);
-}
-
-static uch receive_byte(int timeout)
-{
- uch ret;
- cli();
- debug(("cli\n"));
- ret = cd->ur[cd->ur_r];
- if (cd->ur_r != cd->ur_w) {
- sti();
- debug(("returning #%d: 0x%x\n", cd->ur_r,
- cd->ur[cd->ur_r]));
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- return ret;
- } else if (sleep_or_timeout(&cd->uart, timeout)) { /* does sti() */
- debug(("Time out on receive-buffer\n"));
-#ifdef STATISTICS
- if (timeout == UART_TIMEOUT)
- stats(receive_timeout) /* no `;'! */
- else
- stats(dsb_timeout);
-#endif
- return 0xda;
- }
- ret = cd->ur[cd->ur_r];
- debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
- cd->ur[cd->ur_r]));
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- return ret;
-}
-
-static inline uch receive_echo(void)
-{
- return receive_byte(UART_TIMEOUT);
-}
-
-static inline uch send_receive(int command)
-{
- send_command(command);
- return receive_echo();
-}
-
-static inline uch wait_dsb(void)
-{
- return receive_byte(DSB_TIMEOUT);
-}
-
-static int type_0_command(int command, int expect_dsb)
-{
- int e;
- clear_ur();
- if (command != (e = send_receive(command))) {
- debug(("command 0x%x echoed as 0x%x\n", command, e));
- stats(echo);
- return -1;
- }
- if (expect_dsb) {
- cd->dsb = wait_dsb(); /* wait for command to finish */
- }
- return 0;
-}
-
-static int type_1_command(int command, int bytes, uch * status)
-{ /* returns info */
- int i;
- if (type_0_command(command, 0))
- return -1;
- for (i = 0; i < bytes; i++)
- status[i] = send_receive(c_gimme);
- return 0;
-}
-
-/* This function resets the adapter card. We'd better not do this too
- * often, because it tends to generate `lost interrupts.' */
-static void reset_cm260(void)
-{
- outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
- udelay(10); /* 3.3 mu sec minimum */
- outw(dc_normal | READ_AHEAD, r_data_control);
-}
-
-/* fsm: frame-sec-min from linear address; one of many */
-static void fsm(int lba, uch * fsm)
-{
- fsm[0] = lba % 75;
- lba /= 75;
- lba += 2;
- fsm[1] = lba % 60;
- fsm[2] = lba / 60;
-}
-
-static inline int fsm2lba(uch * fsm)
-{
- return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
-}
-
-static inline int f_s_m2lba(uch f, uch s, uch m)
-{
- return f + 75 * (s - 2 + 60 * m);
-}
-
-static int start_read(int start)
-{
- uch read_sector[4] = { c_read_data, };
- int i, e;
-
- fsm(start, &read_sector[1]);
- clear_ur();
- for (i = 0; i < 4; i++)
- if (read_sector[i] != (e = send_receive(read_sector[i]))) {
- debug(("read_sector: %x echoes %x\n",
- read_sector[i], e));
- stats(echo);
- if (e == 0xff) { /* this seems to happen often */
- e = receive_echo();
- debug(("Second try %x\n", e));
- if (e != read_sector[i])
- return -1;
- }
- }
- return 0;
-}
-
-static int stop_read(void)
-{
- int e;
- type_0_command(c_stop, 0);
- if ((e = receive_echo()) != 0xff) {
- debug(("c_stop didn't send 0xff, but 0x%x\n", e));
- stats(stop_0xff);
- return -1;
- }
- return 0;
-}
-
-/* This function starts to read sectors in adapter memory, the
- interrupt routine should stop the read. In fact, the bottom_half
- routine takes care of this. Set a flag `background' in the cd
- struct to indicate the process. */
-
-static int read_background(int start, int reading)
-{
- if (cd->background)
- return -1; /* can't do twice */
- outw(dc_normal | BACK_AHEAD, r_data_control);
- if (!reading && start_read(start))
- return -2;
- cd->adapter_first = cd->adapter_last = start;
- cd->background = 1; /* flag a read is going on */
- return 0;
-}
-
-#ifdef USE_INSW
-#define transport_data insw
-#else
-/* this routine implements insw(,,). There was a time i had the
- impression that there would be any difference in error-behaviour. */
-void transport_data(int port, ush * dest, int count)
-{
- int i;
- ush *d;
- for (i = 0, d = dest; i < count; i++, d++)
- *d = inw(port);
-}
-#endif
-
-
-#define MAX_TRIES 100
-static int read_sector(int start)
-{
- int tries = 0;
- if (cd->background) {
- cd->background = 0;
- cd->adapter_last = -1; /* invalidate adapter memory */
- stop_read();
- }
- cd->fifo_overflowed = 0;
- reset_cm260(); /* empty fifo etc. */
- if (start_read(start))
- return -1;
- do {
- if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
- debug(("Read timed out sector 0x%x\n", start));
- stats(read_timeout);
- stop_read();
- return -3;
- }
- tries++;
- } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
- if (tries > 1)
- debug(("Took me some tries\n"))
- else
- if (tries == MAX_TRIES)
- debug(("MAX_TRIES tries for read sector\n"));
- transport_data(r_fifo_output_buffer, cd->sector,
- READ_AHEAD * RAW_SECTOR_SIZE / 2);
- if (read_background(start + READ_AHEAD, 1))
- stats(read_background);
- cd->sector_first = start;
- cd->sector_last = start + READ_AHEAD;
- stats(read_restarted);
- return 0;
-}
-
-/* The function of bottom-half is to send a stop command to the drive
- This isn't easy because the routine is not `owned' by any process;
- we can't go to sleep! The variable cd->background gives the status:
- 0 no read pending
- 1 a read is pending
- 2 c_stop waits for write_buffer_empty
- 3 c_stop waits for receive_buffer_full: echo
- 4 c_stop waits for receive_buffer_full: 0xff
-*/
-
-static void cm206_tasklet_func(unsigned long ignore)
-{
- debug(("bh: %d\n", cd->background));
- switch (cd->background) {
- case 1:
- stats(bh);
- if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
- cd->command = c_stop;
- outw(dc_mask_sync_error | dc_no_stop_on_error |
- (inw(r_data_status) & 0x7f), r_data_control);
- cd->background = 2;
- break; /* we'd better not time-out here! */
- } else
- outw(c_stop, r_uart_transmit);
- /* fall into case 2: */
- case 2:
- /* the write has been satisfied by interrupt routine */
- cd->background = 3;
- break;
- case 3:
- if (cd->ur_r != cd->ur_w) {
- if (cd->ur[cd->ur_r] != c_stop) {
- debug(("cm206_bh: c_stop echoed 0x%x\n",
- cd->ur[cd->ur_r]));
- stats(echo);
- }
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- }
- cd->background++;
- break;
- case 4:
- if (cd->ur_r != cd->ur_w) {
- if (cd->ur[cd->ur_r] != 0xff) {
- debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
- stats(stop_0xff);
- }
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- }
- cd->background = 0;
- }
-}
-
-static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
-
-/* This command clears the dsb_possible_media_change flag, so we must
- * retain it.
- */
-static void get_drive_status(void)
-{
- uch status[2];
- type_1_command(c_drive_status, 2, status); /* this might be done faster */
- cd->dsb = status[0];
- cd->cc = status[1];
- cd->media_changed |=
- !!(cd->dsb & (dsb_possible_media_change |
- dsb_drive_not_ready | dsb_tray_not_closed));
-}
-
-static void get_disc_status(void)
-{
- if (type_1_command(c_disc_status, 7, cd->disc_status)) {
- debug(("get_disc_status: error\n"));
- }
-}
-
-/* The new open. The real opening strategy is defined in cdrom.c. */
-
-static int cm206_open(struct cdrom_device_info *cdi, int purpose)
-{
- if (!cd->openfiles) { /* reset only first time */
- cd->background = 0;
- reset_cm260();
- cd->adapter_last = -1; /* invalidate adapter memory */
- cd->sector_last = -1;
- }
- ++cd->openfiles;
- stats(open);
- return 0;
-}
-
-static void cm206_release(struct cdrom_device_info *cdi)
-{
- if (cd->openfiles == 1) {
- if (cd->background) {
- cd->background = 0;
- stop_read();
- }
- cd->sector_last = -1; /* Make our internal buffer invalid */
- FIRST_TRACK = 0; /* No valid disc status */
- }
- --cd->openfiles;
-}
-
-/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
- * and then reads a sector in kernel memory. */
-static void empty_buffer(int sectors)
-{
- while (sectors >= 0) {
- transport_data(r_fifo_output_buffer,
- cd->sector + cd->fifo_overflowed,
- RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
- --sectors;
- ++cd->adapter_first; /* update the current adapter sector */
- cd->fifo_overflowed = 0; /* reset overflow bit */
- stats(sector_transferred);
- }
- cd->sector_first = cd->adapter_first - 1;
- cd->sector_last = cd->adapter_first; /* update the buffer sector */
-}
-
-/* try_adapter. This function determines if the requested sector is
- in adapter memory, or will appear there soon. Returns 0 upon
- success */
-static int try_adapter(int sector)
-{
- if (cd->adapter_first <= sector && sector < cd->adapter_last) {
- /* sector is in adapter memory */
- empty_buffer(sector - cd->adapter_first);
- return 0;
- } else if (cd->background == 1 && cd->adapter_first <= sector
- && sector < cd->adapter_first + cd->max_sectors) {
- /* a read is going on, we can wait for it */
- cd->wait_back = 1;
- while (sector >= cd->adapter_last) {
- if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
- debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
- stats(back_read_timeout);
- cd->wait_back = 0;
- return -1;
- }
- }
- cd->wait_back = 0;
- empty_buffer(sector - cd->adapter_first);
- return 0;
- } else
- return -2;
-}
-
-/* This is not a very smart implementation. We could optimize for
- consecutive block numbers. I'm not convinced this would really
- bring down the processor load. */
-static void do_cm206_request(request_queue_t * q)
-{
- long int i, cd_sec_no;
- int quarter, error;
- uch *source, *dest;
- struct request *req;
-
- while (1) { /* repeat until all requests have been satisfied */
- req = elv_next_request(q);
- if (!req)
- return;
-
- if (req->cmd != READ) {
- debug(("Non-read command %d on cdrom\n", req->cmd));
- end_request(req, 0);
- continue;
- }
- spin_unlock_irq(q->queue_lock);
- error = 0;
- for (i = 0; i < req->nr_sectors; i++) {
- int e1, e2;
- cd_sec_no = (req->sector + i) / BLOCKS_ISO; /* 4 times 512 bytes */
- quarter = (req->sector + i) % BLOCKS_ISO;
- dest = req->buffer + i * LINUX_BLOCK_SIZE;
- /* is already in buffer memory? */
- if (cd->sector_first <= cd_sec_no
- && cd_sec_no < cd->sector_last) {
- source =
- ((uch *) cd->sector) + 16 +
- quarter * LINUX_BLOCK_SIZE +
- (cd_sec_no -
- cd->sector_first) * RAW_SECTOR_SIZE;
- memcpy(dest, source, LINUX_BLOCK_SIZE);
- } else if (!(e1 = try_adapter(cd_sec_no)) ||
- !(e2 = read_sector(cd_sec_no))) {
- source =
- ((uch *) cd->sector) + 16 +
- quarter * LINUX_BLOCK_SIZE;
- memcpy(dest, source, LINUX_BLOCK_SIZE);
- } else {
- error = 1;
- debug(("cm206_request: %d %d\n", e1, e2));
- }
- }
- spin_lock_irq(q->queue_lock);
- end_request(req, !error);
- }
-}
-
-/* Audio support. I've tried very hard, but the cm206 drive doesn't
- seem to have a get_toc (table-of-contents) function, while i'm
- pretty sure it must read the toc upon disc insertion. Therefore
- this function has been implemented through a binary search
- strategy. All track starts that happen to be found are stored in
- cd->toc[], for future use.
-
- I've spent a whole day on a bug that only shows under Workman---
- I don't get it. Tried everything, nothing works. If workman asks
- for track# 0xaa, it'll get the wrong time back. Any other program
- receives the correct value. I'm stymied.
-*/
-
-/* seek seeks to address lba. It does wait to arrive there. */
-static void seek(int lba)
-{
- int i;
- uch seek_command[4] = { c_seek, };
-
- fsm(lba, &seek_command[1]);
- for (i = 0; i < 4; i++)
- type_0_command(seek_command[i], 0);
- cd->dsb = wait_dsb();
-}
-
-static uch bcdbin(unsigned char bcd)
-{ /* stolen from mcd.c! */
- return (bcd >> 4) * 10 + (bcd & 0xf);
-}
-
-static inline uch normalize_track(uch track)
-{
- if (track < 1)
- return 1;
- if (track > LAST_TRACK)
- return LAST_TRACK + 1;
- return track;
-}
-
-/* This function does a binary search for track start. It records all
- * tracks seen in the process. Input $track$ must be between 1 and
- * #-of-tracks+1. Note that the start of the disc must be in toc[1].fsm.
- */
-static int get_toc_lba(uch track)
-{
- int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
- int i, lba, l, old_lba = 0;
- uch *q = cd->q;
- uch ct; /* current track */
- int binary = 0;
- const int skip = 3 * 60 * 75; /* 3 minutes */
-
- for (i = track; i > 0; i--)
- if (cd->toc[i].track) {
- min = fsm2lba(cd->toc[i].fsm);
- break;
- }
- lba = min + skip;
- do {
- seek(lba);
- type_1_command(c_read_current_q, 10, q);
- ct = normalize_track(q[1]);
- if (!cd->toc[ct].track) {
- l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
- bcdbin(q[4]) - 2 +
- 60 * (q[7] -
- bcdbin(q
- [3])));
- cd->toc[ct].track = q[1]; /* lead out still 0xaa */
- fsm(l, cd->toc[ct].fsm);
- cd->toc[ct].q0 = q[0]; /* contains adr and ctrl info */
- if (ct == track)
- return l;
- }
- old_lba = lba;
- if (binary) {
- if (ct < track)
- min = lba;
- else
- max = lba;
- lba = (min + max) / 2;
- } else {
- if (ct < track)
- lba += skip;
- else {
- binary = 1;
- max = lba;
- min = lba - skip;
- lba = (min + max) / 2;
- }
- }
- } while (lba != old_lba);
- return lba;
-}
-
-static void update_toc_entry(uch track)
-{
- track = normalize_track(track);
- if (!cd->toc[track].track)
- get_toc_lba(track);
-}
-
-/* return 0 upon success */
-static int read_toc_header(struct cdrom_tochdr *hp)
-{
- if (!FIRST_TRACK)
- get_disc_status();
- if (hp) {
- int i;
- hp->cdth_trk0 = FIRST_TRACK;
- hp->cdth_trk1 = LAST_TRACK;
- /* fill in first track position */
- for (i = 0; i < 3; i++)
- cd->toc[1].fsm[i] = cd->disc_status[3 + i];
- update_toc_entry(LAST_TRACK + 1); /* find most entries */
- return 0;
- }
- return -1;
-}
-
-static void play_from_to_msf(struct cdrom_msf *msfp)
-{
- uch play_command[] = { c_play,
- msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
- msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
- 2
- };
- int i;
- for (i = 0; i < 9; i++)
- type_0_command(play_command[i], 0);
- for (i = 0; i < 3; i++)
- PLAY_TO.fsm[i] = play_command[i + 4];
- PLAY_TO.track = 0; /* say no track end */
- cd->dsb = wait_dsb();
-}
-
-static void play_from_to_track(int from, int to)
-{
- uch play_command[8] = { c_play, };
- int i;
-
- if (from == 0) { /* continue paused play */
- for (i = 0; i < 3; i++) {
- play_command[i + 1] = cd->audio_status[i + 2];
- play_command[i + 4] = PLAY_TO.fsm[i];
- }
- } else {
- update_toc_entry(from);
- update_toc_entry(to + 1);
- for (i = 0; i < 3; i++) {
- play_command[i + 1] = cd->toc[from].fsm[i];
- PLAY_TO.fsm[i] = play_command[i + 4] =
- cd->toc[to + 1].fsm[i];
- }
- PLAY_TO.track = to;
- }
- for (i = 0; i < 7; i++)
- type_0_command(play_command[i], 0);
- for (i = 0; i < 2; i++)
- type_0_command(0x2, 0); /* volume */
- cd->dsb = wait_dsb();
-}
-
-static int get_current_q(struct cdrom_subchnl *qp)
-{
- int i;
- uch *q = cd->q;
- if (type_1_command(c_read_current_q, 10, q))
- return 0;
-/* q[0] = bcdbin(q[0]); Don't think so! */
- for (i = 2; i < 6; i++)
- q[i] = bcdbin(q[i]);
- qp->cdsc_adr = q[0] & 0xf;
- qp->cdsc_ctrl = q[0] >> 4; /* from mcd.c */
- qp->cdsc_trk = q[1];
- qp->cdsc_ind = q[2];
- if (qp->cdsc_format == CDROM_MSF) {
- qp->cdsc_reladdr.msf.minute = q[3];
- qp->cdsc_reladdr.msf.second = q[4];
- qp->cdsc_reladdr.msf.frame = q[5];
- qp->cdsc_absaddr.msf.minute = q[7];
- qp->cdsc_absaddr.msf.second = q[8];
- qp->cdsc_absaddr.msf.frame = q[9];
- } else {
- qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
- qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
- }
- get_drive_status();
- if (cd->dsb & dsb_play_in_progress)
- qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
- else if (PAUSED)
- qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
- else
- qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
- return 0;
-}
-
-static void invalidate_toc(void)
-{
- memset(cd->toc, 0, sizeof(cd->toc));
- memset(cd->disc_status, 0, sizeof(cd->disc_status));
-}
-
-/* cdrom.c guarantees that cdte_format == CDROM_MSF */
-static void get_toc_entry(struct cdrom_tocentry *ep)
-{
- uch track = normalize_track(ep->cdte_track);
- update_toc_entry(track);
- ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
- ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
- ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
- ep->cdte_adr = cd->toc[track].q0 & 0xf;
- ep->cdte_ctrl = cd->toc[track].q0 >> 4;
- ep->cdte_datamode = 0;
-}
-
-/* Audio ioctl. Ioctl commands connected to audio are in such an
- * idiosyncratic i/o format, that we leave these untouched. Return 0
- * upon success. Memory checking has been done by cdrom_ioctl(), the
- * calling function, as well as LBA/MSF sanitization.
-*/
-static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg)
-{
- switch (cmd) {
- case CDROMREADTOCHDR:
- return read_toc_header((struct cdrom_tochdr *) arg);
- case CDROMREADTOCENTRY:
- get_toc_entry((struct cdrom_tocentry *) arg);
- return 0;
- case CDROMPLAYMSF:
- play_from_to_msf((struct cdrom_msf *) arg);
- return 0;
- case CDROMPLAYTRKIND: /* admittedly, not particularly beautiful */
- play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
- ((struct cdrom_ti *) arg)->cdti_trk1);
- return 0;
- case CDROMSTOP:
- PAUSED = 0;
- if (cd->dsb & dsb_play_in_progress)
- return type_0_command(c_stop, 1);
- else
- return 0;
- case CDROMPAUSE:
- get_drive_status();
- if (cd->dsb & dsb_play_in_progress) {
- type_0_command(c_stop, 1);
- type_1_command(c_audio_status, 5,
- cd->audio_status);
- PAUSED = 1; /* say we're paused */
- }
- return 0;
- case CDROMRESUME:
- if (PAUSED)
- play_from_to_track(0, 0);
- PAUSED = 0;
- return 0;
- case CDROMSTART:
- case CDROMVOLCTRL:
- return 0;
- case CDROMSUBCHNL:
- return get_current_q((struct cdrom_subchnl *) arg);
- default:
- return -EINVAL;
- }
-}
-
-static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- if (cd != NULL) {
- int r;
- get_drive_status(); /* ensure cd->media_changed OK */
- r = cd->media_changed;
- cd->media_changed = 0; /* clear bit */
- return r;
- } else
- return -EIO;
-}
-
-/* The new generic cdrom support. Routines should be concise, most of
- the logic should be in cdrom.c */
-
-
-/* controls tray movement */
-static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
-{
- if (position) { /* 1: eject */
- type_0_command(c_open_tray, 1);
- invalidate_toc();
- } else
- type_0_command(c_close_tray, 1); /* 0: close */
- return 0;
-}
-
-/* gives current state of the drive */
-static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- get_drive_status();
- if (cd->dsb & dsb_tray_not_closed)
- return CDS_TRAY_OPEN;
- if (!(cd->dsb & dsb_disc_present))
- return CDS_NO_DISC;
- if (cd->dsb & dsb_drive_not_ready)
- return CDS_DRIVE_NOT_READY;
- return CDS_DISC_OK;
-}
-
-/* locks or unlocks door lock==1: lock; return 0 upon success */
-static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- uch command = (lock) ? c_lock_tray : c_unlock_tray;
- type_0_command(command, 1); /* wait and get dsb */
- /* the logic calculates the success, 0 means successful */
- return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
-}
-
-/* Although a session start should be in LBA format, we return it in
- MSF format because it is slightly easier, and the new generic ioctl
- will take care of the necessary conversion. */
-static int cm206_get_last_session(struct cdrom_device_info *cdi,
- struct cdrom_multisession *mssp)
-{
- if (!FIRST_TRACK)
- get_disc_status();
- if (mssp != NULL) {
- if (DISC_STATUS & cds_multi_session) { /* multi-session */
- mssp->addr.msf.frame = cd->disc_status[3];
- mssp->addr.msf.second = cd->disc_status[4];
- mssp->addr.msf.minute = cd->disc_status[5];
- mssp->addr_format = CDROM_MSF;
- mssp->xa_flag = 1;
- } else {
- mssp->xa_flag = 0;
- }
- return 1;
- }
- return 0;
-}
-
-static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- uch upc[10];
- char *ret = mcn->medium_catalog_number;
- int i;
-
- if (type_1_command(c_read_upc, 10, upc))
- return -EIO;
- for (i = 0; i < 13; i++) {
- int w = i / 2 + 1, r = i % 2;
- if (r)
- ret[i] = 0x30 | (upc[w] & 0x0f);
- else
- ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
- }
- ret[13] = '\0';
- return 0;
-}
-
-static int cm206_reset(struct cdrom_device_info *cdi)
-{
- stop_read();
- reset_cm260();
- outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
- mdelay(1); /* 750 musec minimum */
- outw(dc_normal | READ_AHEAD, r_data_control);
- cd->sector_last = -1; /* flag no data buffered */
- cd->adapter_last = -1;
- invalidate_toc();
- return 0;
-}
-
-static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- int r;
- switch (speed) {
- case 0:
- r = type_0_command(c_auto_mode, 1);
- break;
- case 1:
- r = type_0_command(c_force_1x, 1);
- break;
- case 2:
- r = type_0_command(c_force_2x, 1);
- break;
- default:
- return -1;
- }
- if (r < 0)
- return r;
- else
- return 1;
-}
-
-static struct cdrom_device_ops cm206_dops = {
- .open = cm206_open,
- .release = cm206_release,
- .drive_status = cm206_drive_status,
- .media_changed = cm206_media_changed,
- .tray_move = cm206_tray_move,
- .lock_door = cm206_lock_door,
- .select_speed = cm206_select_speed,
- .get_last_session = cm206_get_last_session,
- .get_mcn = cm206_get_upc,
- .reset = cm206_reset,
- .audio_ioctl = cm206_audio_ioctl,
- .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
- CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
- CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
- CDC_DRIVE_STATUS,
- .n_minors = 1,
-};
-
-
-static struct cdrom_device_info cm206_info = {
- .ops = &cm206_dops,
- .speed = 2,
- .capacity = 1,
- .name = "cm206",
-};
-
-static int cm206_block_open(struct inode *inode, struct file *file)
-{
- return cdrom_open(&cm206_info, inode, file);
-}
-
-static int cm206_block_release(struct inode *inode, struct file *file)
-{
- return cdrom_release(&cm206_info, file);
-}
-
-static int cm206_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- switch (cmd) {
-#ifdef STATISTICS
- case CM206CTL_GET_STAT:
- if (arg >= NR_STATS)
- return -EINVAL;
- return cd->stats[arg];
- case CM206CTL_GET_LAST_STAT:
- if (arg >= NR_STATS)
- return -EINVAL;
- return cd->last_stat[arg];
-#endif
- default:
- break;
- }
-
- return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
-}
-
-static int cm206_block_media_changed(struct gendisk *disk)
-{
- return cdrom_media_changed(&cm206_info);
-}
-
-static struct block_device_operations cm206_bdops =
-{
- .owner = THIS_MODULE,
- .open = cm206_block_open,
- .release = cm206_block_release,
- .ioctl = cm206_block_ioctl,
- .media_changed = cm206_block_media_changed,
-};
-
-static struct gendisk *cm206_gendisk;
-
-/* This function probes for the adapter card. It returns the base
- address if it has found the adapter card. One can specify a base
- port to probe specifically, or 0 which means span all possible
- bases.
-
- Linus says it is too dangerous to use writes for probing, so we
- stick with pure reads for a while. Hope that 8 possible ranges,
- request_region, 15 bits of one port and 6 of another make things
- likely enough to accept the region on the first hit...
- */
-static int __init probe_base_port(int base)
-{
- int b = 0x300, e = 0x370; /* this is the range of start addresses */
- volatile int fool, i;
-
- if (base)
- b = e = base;
- for (base = b; base <= e; base += 0x10) {
- if (!request_region(base, 0x10,"cm206"))
- continue;
- for (i = 0; i < 3; i++)
- fool = inw(base + 2); /* empty possibly uart_receive_buffer */
- if ((inw(base + 6) & 0xffef) != 0x0001 || /* line_status */
- (inw(base) & 0xad00) != 0) { /* data status */
- release_region(base,0x10);
- continue;
- }
- return (base);
- }
- return 0;
-}
-
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-static int __init probe_irq(int nr)
-{
- int irqs, irq;
- outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */
- sti();
- irqs = probe_irq_on();
- reset_cm260(); /* causes interrupt */
- udelay(100); /* wait for it */
- irq = probe_irq_off(irqs);
- outw(dc_normal | READ_AHEAD, r_data_control); /* services interrupt */
- if (nr && irq != nr && irq > 0)
- return 0; /* wrong interrupt happened */
- else
- return irq;
-}
-#endif
-
-int __init cm206_init(void)
-{
- uch e = 0;
- long int size = sizeof(struct cm206_struct);
- struct gendisk *disk;
-
- printk(KERN_INFO "cm206 cdrom driver " REVISION);
- cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
- if (!cm206_base) {
- printk(" can't find adapter!\n");
- return -EIO;
- }
- printk(" adapter at 0x%x", cm206_base);
- cd = kmalloc(size, GFP_KERNEL);
- if (!cd)
- goto out_base;
- /* Now we have found the adaptor card, try to reset it. As we have
- * found out earlier, this process generates an interrupt as well,
- * so we might just exploit that fact for irq probing! */
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
- cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
- if (cm206_irq <= 0) {
- printk("can't find IRQ!\n");
- goto out_probe;
- } else
- printk(" IRQ %d found\n", cm206_irq);
-#else
- cli();
- reset_cm260();
- /* Now, the problem here is that reset_cm260 can generate an
- interrupt. It seems that this can cause a kernel oops some time
- later. So we wait a while and `service' this interrupt. */
- mdelay(1);
- outw(dc_normal | READ_AHEAD, r_data_control);
- sti();
- printk(" using IRQ %d\n", cm206_irq);
-#endif
- if (send_receive_polled(c_drive_configuration) !=
- c_drive_configuration) {
- printk(KERN_INFO " drive not there\n");
- goto out_probe;
- }
- e = send_receive_polled(c_gimme);
- printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
- if (e & dcf_transfer_rate)
- printk(" double");
- else
- printk(" single");
- printk(" speed drive");
- if (e & dcf_motorized_tray)
- printk(", motorized tray");
- if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
- printk("\nUnable to reserve IRQ---aborted\n");
- goto out_probe;
- }
- printk(".\n");
-
- if (register_blkdev(MAJOR_NR, "cm206"))
- goto out_blkdev;
-
- disk = alloc_disk(1);
- if (!disk)
- goto out_disk;
- disk->major = MAJOR_NR;
- disk->first_minor = 0;
- sprintf(disk->disk_name, "cm206cd");
- disk->fops = &cm206_bdops;
- disk->flags = GENHD_FL_CD;
- cm206_gendisk = disk;
- if (register_cdrom(&cm206_info) != 0) {
- printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
- goto out_cdrom;
- }
- cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock);
- if (!cm206_queue)
- goto out_queue;
-
- blk_queue_hardsect_size(cm206_queue, 2048);
- disk->queue = cm206_queue;
- add_disk(disk);
-
- memset(cd, 0, sizeof(*cd)); /* give'm some reasonable value */
- cd->sector_last = -1; /* flag no data buffered */
- cd->adapter_last = -1;
- init_timer(&cd->timer);
- cd->timer.function = cm206_timeout;
- cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
- printk(KERN_INFO "%d kB adapter memory available, "
- " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
- size);
- return 0;
-
-out_queue:
- unregister_cdrom(&cm206_info);
-out_cdrom:
- put_disk(disk);
-out_disk:
- unregister_blkdev(MAJOR_NR, "cm206");
-out_blkdev:
- free_irq(cm206_irq, NULL);
-out_probe:
- kfree(cd);
-out_base:
- release_region(cm206_base, 16);
- return -EIO;
-}
-
-#ifdef MODULE
-
-
-static void __init parse_options(void)
-{
- int i;
- for (i = 0; i < 2; i++) {
- if (0x300 <= cm206[i] && i <= 0x370
- && cm206[i] % 0x10 == 0) {
- cm206_base = cm206[i];
- auto_probe = 0;
- } else if (3 <= cm206[i] && cm206[i] <= 15) {
- cm206_irq = cm206[i];
- auto_probe = 0;
- }
- }
-}
-
-static int __init __cm206_init(void)
-{
- parse_options();
-#if !defined(AUTO_PROBE_MODULE)
- auto_probe = 0;
-#endif
- return cm206_init();
-}
-
-static void __exit cm206_exit(void)
-{
- del_gendisk(cm206_gendisk);
- put_disk(cm206_gendisk);
- if (unregister_cdrom(&cm206_info)) {
- printk("Can't unregister cdrom cm206\n");
- return;
- }
- if (unregister_blkdev(MAJOR_NR, "cm206")) {
- printk("Can't unregister major cm206\n");
- return;
- }
- blk_cleanup_queue(cm206_queue);
- free_irq(cm206_irq, NULL);
- kfree(cd);
- release_region(cm206_base, 16);
- printk(KERN_INFO "cm206 removed\n");
-}
-
-module_init(__cm206_init);
-module_exit(cm206_exit);
-
-#else /* !MODULE */
-
-/* This setup function accepts either `auto' or numbers in the range
- * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
-
-static int __init cm206_setup(char *s)
-{
- int i, p[4];
-
- (void) get_options(s, ARRAY_SIZE(p), p);
-
- if (!strcmp(s, "auto"))
- auto_probe = 1;
- for (i = 1; i <= p[0]; i++) {
- if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
- cm206_base = p[i];
- auto_probe = 0;
- } else if (3 <= p[i] && p[i] <= 15) {
- cm206_irq = p[i];
- auto_probe = 0;
- }
- }
- return 1;
-}
-
-__setup("cm206=", cm206_setup);
-
-#endif /* !MODULE */
-MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR);
-
diff --git a/drivers/cdrom/cm206.h b/drivers/cdrom/cm206.h
deleted file mode 100644
index 0ae51c1a0dac..000000000000
--- a/drivers/cdrom/cm206.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* cm206.h Header file for cm206.c.
- Copyright (c) 1995 David van Leeuwen
-*/
-
-#ifndef LINUX_CM206_H
-#define LINUX_CM206_H
-
-#include <linux/ioctl.h>
-
-/* First, the cm260 stuff */
-/* The ports and irq used. Although CM206_BASE and CM206_IRQ are defined
- below, the values are not used unless autoprobing is turned off and
- no LILO boot options or module command line options are given. Change
- these values to your own as last resort if autoprobing and options
- don't work. */
-
-#define CM206_BASE 0x340
-#define CM206_IRQ 11
-
-#define r_data_status (cm206_base)
-#define r_uart_receive (cm206_base+0x2)
-#define r_fifo_output_buffer (cm206_base+0x4)
-#define r_line_status (cm206_base+0x6)
-#define r_data_control (cm206_base+0x8)
-#define r_uart_transmit (cm206_base+0xa)
-#define r_test_clock (cm206_base+0xc)
-#define r_test_control (cm206_base+0xe)
-
-/* the data_status flags */
-#define ds_ram_size 0x4000
-#define ds_toc_ready 0x2000
-#define ds_fifo_empty 0x1000
-#define ds_sync_error 0x800
-#define ds_crc_error 0x400
-#define ds_data_error 0x200
-#define ds_fifo_overflow 0x100
-#define ds_data_ready 0x80
-
-/* the line_status flags */
-#define ls_attention 0x10
-#define ls_parity_error 0x8
-#define ls_overrun 0x4
-#define ls_receive_buffer_full 0x2
-#define ls_transmitter_buffer_empty 0x1
-
-/* the data control register flags */
-#define dc_read_q_channel 0x4000
-#define dc_mask_sync_error 0x2000
-#define dc_toc_enable 0x1000
-#define dc_no_stop_on_error 0x800
-#define dc_break 0x400
-#define dc_initialize 0x200
-#define dc_mask_transmit_ready 0x100
-#define dc_flag_enable 0x80
-
-/* Define the default data control register flags here */
-#define dc_normal (dc_mask_sync_error | dc_no_stop_on_error | \
- dc_mask_transmit_ready)
-
-/* now some constants related to the cm206 */
-/* another drive status byte, echoed by the cm206 on most commands */
-
-#define dsb_error_condition 0x1
-#define dsb_play_in_progress 0x4
-#define dsb_possible_media_change 0x8
-#define dsb_disc_present 0x10
-#define dsb_drive_not_ready 0x20
-#define dsb_tray_locked 0x40
-#define dsb_tray_not_closed 0x80
-
-#define dsb_not_useful (dsb_drive_not_ready | dsb_tray_not_closed)
-
-/* the cm206 command set */
-
-#define c_close_tray 0
-#define c_lock_tray 0x01
-#define c_unlock_tray 0x04
-#define c_open_tray 0x05
-#define c_seek 0x10
-#define c_read_data 0x20
-#define c_force_1x 0x21
-#define c_force_2x 0x22
-#define c_auto_mode 0x23
-#define c_play 0x30
-#define c_set_audio_mode 0x31
-#define c_read_current_q 0x41
-#define c_stream_q 0x42
-#define c_drive_status 0x50
-#define c_disc_status 0x51
-#define c_audio_status 0x52
-#define c_drive_configuration 0x53
-#define c_read_upc 0x60
-#define c_stop 0x70
-#define c_calc_checksum 0xe5
-
-#define c_gimme 0xf8
-
-/* finally, the (error) condition that the drive can be in *
- * OK, this is not always an error, but let's prefix it with e_ */
-
-#define e_none 0
-#define e_illegal_command 0x01
-#define e_sync 0x02
-#define e_seek 0x03
-#define e_parity 0x04
-#define e_focus 0x05
-#define e_header_sync 0x06
-#define e_code_incompatibility 0x07
-#define e_reset_done 0x08
-#define e_bad_parameter 0x09
-#define e_radial 0x0a
-#define e_sub_code 0x0b
-#define e_no_data_track 0x0c
-#define e_scan 0x0d
-#define e_tray_open 0x0f
-#define e_no_disc 0x10
-#define e_tray stalled 0x11
-
-/* drive configuration masks */
-
-#define dcf_revision_code 0x7
-#define dcf_transfer_rate 0x60
-#define dcf_motorized_tray 0x80
-
-/* disc status byte */
-
-#define cds_multi_session 0x2
-#define cds_all_audio 0x8
-#define cds_xa_mode 0xf0
-
-/* finally some ioctls for the driver */
-
-#define CM206CTL_GET_STAT _IO( 0x20, 0 )
-#define CM206CTL_GET_LAST_STAT _IO( 0x20, 1 )
-
-#ifdef STATISTICS
-
-/* This is an ugly way to guarantee that the names of the statistics
- * are the same in the code and in the diagnostics program. */
-
-#ifdef __KERNEL__
-#define x(a) st_ ## a
-#define y enum
-#else
-#define x(a) #a
-#define y char * stats_name[] =
-#endif
-
-y {x(interrupt), x(data_ready), x(fifo_overflow), x(data_error),
- x(crc_error), x(sync_error), x(lost_intr), x(echo),
- x(write_timeout), x(receive_timeout), x(read_timeout),
- x(dsb_timeout), x(stop_0xff), x(back_read_timeout),
- x(sector_transferred), x(read_restarted), x(read_background),
- x(bh), x(open), x(ioctl_multisession), x(attention)
-#ifdef __KERNEL__
- , x(last_entry)
-#endif
- };
-
-#ifdef __KERNEL__
-#define NR_STATS st_last_entry
-#else
-#define NR_STATS (sizeof(stats_name)/sizeof(char*))
-#endif
-
-#undef y
-#undef x
-
-#endif /* STATISTICS */
-
-#endif /* LINUX_CM206_H */
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
deleted file mode 100644
index b3ab6e9b8df1..000000000000
--- a/drivers/cdrom/gscd.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-#define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
-
-/*
- linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
-
- Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- based upon pre-works by Eberhard Moenkeberg <emoenke@gwdg.de>
-
-
- For all kind of other information about the GoldStar CDROM
- and this Linux device driver I installed a WWW-URL:
- http://linux.rz.fh-hannover.de/~raupach
-
-
- If you are the editor of a Linux CD, you should
- enable gscd.c within your boot floppy kernel and
- send me one of your CDs for free.
-
-
- --------------------------------------------------------------------
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- --------------------------------------------------------------------
-
- 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-
-*/
-
-/* These settings are for various debug-level. Leave they untouched ... */
-#define NO_GSCD_DEBUG
-#define NO_IOCTL_DEBUG
-#define NO_MODULE_DEBUG
-#define NO_FUTURE_WORK
-/*------------------------*/
-
-#include <linux/module.h>
-
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#include <linux/blkdev.h>
-#include "gscd.h"
-
-static int gscdPresent = 0;
-
-static unsigned char gscd_buf[2048]; /* buffer for block size conversion */
-static int gscd_bn = -1;
-static short gscd_port = GSCD_BASE_ADDR;
-module_param_named(gscd, gscd_port, short, 0);
-
-/* Kommt spaeter vielleicht noch mal dran ...
- * static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
- */
-
-static void gscd_read_cmd(struct request *req);
-static void gscd_hsg2msf(long hsg, struct msf *msf);
-static void gscd_bin2bcd(unsigned char *p);
-
-/* Schnittstellen zum Kern/FS */
-
-static void __do_gscd_request(unsigned long dummy);
-static int gscd_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
-static int gscd_open(struct inode *, struct file *);
-static int gscd_release(struct inode *, struct file *);
-static int check_gscd_med_chg(struct gendisk *disk);
-
-/* GoldStar Funktionen */
-
-static void cmd_out(int, char *, char *, int);
-static void cmd_status(void);
-static void init_cd_drive(int);
-
-static int get_status(void);
-static void clear_Audio(void);
-static void cc_invalidate(void);
-
-/* some things for the next version */
-#ifdef FUTURE_WORK
-static void update_state(void);
-static long gscd_msf2hsg(struct msf *mp);
-static int gscd_bcd2bin(unsigned char bcd);
-#endif
-
-
-/* lo-level cmd-Funktionen */
-
-static void cmd_info_in(char *, int);
-static void cmd_end(void);
-static void cmd_read_b(char *, int, int);
-static void cmd_read_w(char *, int, int);
-static int cmd_unit_alive(void);
-static void cmd_write_cmd(char *);
-
-
-/* GoldStar Variablen */
-
-static int curr_drv_state;
-static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-static int drv_mode;
-static int disk_state;
-static int speed;
-static int ndrives;
-
-static unsigned char drv_num_read;
-static unsigned char f_dsk_valid;
-static unsigned char current_drive;
-static unsigned char f_drv_ok;
-
-
-static char f_AudioPlay;
-static char f_AudioPause;
-static int AudioStart_m;
-static int AudioStart_f;
-static int AudioEnd_m;
-static int AudioEnd_f;
-
-static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
-static DEFINE_SPINLOCK(gscd_lock);
-static struct request_queue *gscd_queue;
-
-static struct block_device_operations gscd_fops = {
- .owner = THIS_MODULE,
- .open = gscd_open,
- .release = gscd_release,
- .ioctl = gscd_ioctl,
- .media_changed = check_gscd_med_chg,
-};
-
-/*
- * Checking if the media has been changed
- * (not yet implemented)
- */
-static int check_gscd_med_chg(struct gendisk *disk)
-{
-#ifdef GSCD_DEBUG
- printk("gscd: check_med_change\n");
-#endif
- return 0;
-}
-
-
-#ifndef MODULE
-/* Using new interface for kernel-parameters */
-
-static int __init gscd_setup(char *str)
-{
- int ints[2];
- (void) get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0) {
- gscd_port = ints[1];
- }
- return 1;
-}
-
-__setup("gscd=", gscd_setup);
-
-#endif
-
-static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- unsigned char to_do[10];
- unsigned char dummy;
-
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- /* Don't think we can do this. Even if we could,
- * I think the drive times out and stops after a while
- * anyway. For now, ignore it.
- */
- return 0;
-
- case CDROMRESUME: /* keine Ahnung was das ist */
- return 0;
-
-
- case CDROMEJECT:
- cmd_status();
- to_do[0] = CMD_TRAY_CTL;
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
- return 0;
-
- default:
- return -EINVAL;
- }
-
-}
-
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static void gscd_transfer(struct request *req)
-{
- while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) {
- long offs = (req->sector & 3) * 512;
- memcpy(req->buffer, gscd_buf + offs, 512);
- req->nr_sectors--;
- req->sector++;
- req->buffer += 512;
- }
-}
-
-
-/*
- * I/O request routine called from Linux kernel.
- */
-
-static void do_gscd_request(request_queue_t * q)
-{
- __do_gscd_request(0);
-}
-
-static void __do_gscd_request(unsigned long dummy)
-{
- struct request *req;
- unsigned int block;
- unsigned int nsect;
-
-repeat:
- req = elv_next_request(gscd_queue);
- if (!req)
- return;
-
- block = req->sector;
- nsect = req->nr_sectors;
-
- if (req->sector == -1)
- goto out;
-
- if (req->cmd != READ) {
- printk("GSCD: bad cmd %u\n", rq_data_dir(req));
- end_request(req, 0);
- goto repeat;
- }
-
- gscd_transfer(req);
-
- /* if we satisfied the request from the buffer, we're done. */
-
- if (req->nr_sectors == 0) {
- end_request(req, 1);
- goto repeat;
- }
-#ifdef GSCD_DEBUG
- printk("GSCD: block %d, nsect %d\n", block, nsect);
-#endif
- gscd_read_cmd(req);
-out:
- return;
-}
-
-
-
-/*
- * Check the result of the set-mode command. On success, send the
- * read-data command.
- */
-
-static void gscd_read_cmd(struct request *req)
-{
- long block;
- struct gscd_Play_msf gscdcmd;
- char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 }; /* cmd mode M-S-F secth sectl */
-
- cmd_status();
- if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
- printk("GSCD: no disk or door open\n");
- end_request(req, 0);
- } else {
- if (disk_state & ST_INVALID) {
- printk("GSCD: disk invalid\n");
- end_request(req, 0);
- } else {
- gscd_bn = -1; /* purge our buffer */
- block = req->sector / 4;
- gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */
-
- cmd[2] = gscdcmd.start.min;
- cmd[3] = gscdcmd.start.sec;
- cmd[4] = gscdcmd.start.frame;
-
-#ifdef GSCD_DEBUG
- printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3],
- cmd[4]);
-#endif
- cmd_out(TYPE_DATA, (char *) &cmd,
- (char *) &gscd_buf[0], 1);
-
- gscd_bn = req->sector / 4;
- gscd_transfer(req);
- end_request(req, 1);
- }
- }
- SET_TIMER(__do_gscd_request, 1);
-}
-
-
-/*
- * Open the device special file. Check that a disk is in.
- */
-
-static int gscd_open(struct inode *ip, struct file *fp)
-{
- int st;
-
-#ifdef GSCD_DEBUG
- printk("GSCD: open\n");
-#endif
-
- if (gscdPresent == 0)
- return -ENXIO; /* no hardware */
-
- get_status();
- st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
- if (st) {
- printk("GSCD: no disk or door open\n");
- return -ENXIO;
- }
-
-/* if (updateToc() < 0)
- return -EIO;
-*/
-
- return 0;
-}
-
-
-/*
- * On close, we flush all gscd blocks from the buffer cache.
- */
-
-static int gscd_release(struct inode *inode, struct file *file)
-{
-
-#ifdef GSCD_DEBUG
- printk("GSCD: release\n");
-#endif
-
- gscd_bn = -1;
-
- return 0;
-}
-
-
-static int get_status(void)
-{
- int status;
-
- cmd_status();
- status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
-
- if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) {
- cc_invalidate();
- return 1;
- } else {
- return 0;
- }
-}
-
-
-static void cc_invalidate(void)
-{
- drv_num_read = 0xFF;
- f_dsk_valid = 0xFF;
- current_drive = 0xFF;
- f_drv_ok = 0xFF;
-
- clear_Audio();
-
-}
-
-static void clear_Audio(void)
-{
-
- f_AudioPlay = 0;
- f_AudioPause = 0;
- AudioStart_m = 0;
- AudioStart_f = 0;
- AudioEnd_m = 0;
- AudioEnd_f = 0;
-
-}
-
-/*
- * waiting ?
- */
-
-static int wait_drv_ready(void)
-{
- int found, read;
-
- do {
- found = inb(GSCDPORT(0));
- found &= 0x0f;
- read = inb(GSCDPORT(0));
- read &= 0x0f;
- } while (read != found);
-
-#ifdef GSCD_DEBUG
- printk("Wait for: %d\n", read);
-#endif
-
- return read;
-}
-
-static void cc_Ident(char *respons)
-{
- char to_do[] = { CMD_IDENT, 0, 0 };
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E);
-
-}
-
-static void cc_SetSpeed(void)
-{
- char to_do[] = { CMD_SETSPEED, 0, 0 };
- char dummy;
-
- if (speed > 0) {
- to_do[1] = speed & 0x0F;
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
- }
-}
-
-static void cc_Reset(void)
-{
- char to_do[] = { CMD_RESET, 0 };
- char dummy;
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-}
-
-static void cmd_status(void)
-{
- char to_do[] = { CMD_STATUS, 0 };
- char dummy;
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-#ifdef GSCD_DEBUG
- printk("GSCD: Status: %d\n", disk_state);
-#endif
-
-}
-
-static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
-{
- int result;
-
-
- result = wait_drv_ready();
- if (result != drv_mode) {
- unsigned long test_loops = 0xFFFF;
- int i, dummy;
-
- outb(curr_drv_state, GSCDPORT(0));
-
- /* LOCLOOP_170 */
- do {
- result = wait_drv_ready();
- test_loops--;
- } while ((result != drv_mode) && (test_loops > 0));
-
- if (result != drv_mode) {
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
-
- /* ...and waiting */
- for (i = 1, dummy = 1; i < 0xFFFF; i++) {
- dummy *= i;
- }
- }
-
- /* LOC_172 */
- /* check the unit */
- /* and wake it up */
- if (cmd_unit_alive() != 0x08) {
- /* LOC_174 */
- /* game over for this unit */
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
-
- /* LOC_176 */
-#ifdef GSCD_DEBUG
- printk("LOC_176 ");
-#endif
- if (drv_mode == 0x09) {
- /* magic... */
- printk("GSCD: magic ...\n");
- outb(result, GSCDPORT(2));
- }
-
- /* write the command to the drive */
- cmd_write_cmd(cmd);
-
- /* LOC_178 */
- for (;;) {
- result = wait_drv_ready();
- if (result != drv_mode) {
- /* LOC_179 */
- if (result == 0x04) { /* Mode 4 */
- /* LOC_205 */
-#ifdef GSCD_DEBUG
- printk("LOC_205 ");
-#endif
- disk_state = inb(GSCDPORT(2));
-
- do {
- result = wait_drv_ready();
- } while (result != drv_mode);
- return;
-
- } else {
- if (result == 0x06) { /* Mode 6 */
- /* LOC_181 */
-#ifdef GSCD_DEBUG
- printk("LOC_181 ");
-#endif
-
- if (cmd_type == TYPE_DATA) {
- /* read data */
- /* LOC_184 */
- if (drv_mode == 9) {
- /* read the data to the buffer (word) */
-
- /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
- cmd_read_w
- (respo_buf,
- respo_count,
- CD_FRAMESIZE /
- 2);
- return;
- } else {
- /* read the data to the buffer (byte) */
-
- /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */
- cmd_read_b
- (respo_buf,
- respo_count,
- CD_FRAMESIZE);
- return;
- }
- } else {
- /* read the info to the buffer */
- cmd_info_in(respo_buf,
- respo_count);
- return;
- }
-
- return;
- }
- }
-
- } else {
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
- } /* for (;;) */
-
-
-#ifdef GSCD_DEBUG
- printk("\n");
-#endif
-}
-
-
-static void cmd_write_cmd(char *pstr)
-{
- int i, j;
-
- /* LOC_177 */
-#ifdef GSCD_DEBUG
- printk("LOC_177 ");
-#endif
-
- /* calculate the number of parameter */
- j = *pstr & 0x0F;
-
- /* shift it out */
- for (i = 0; i < j; i++) {
- outb(*pstr, GSCDPORT(2));
- pstr++;
- }
-}
-
-
-static int cmd_unit_alive(void)
-{
- int result;
- unsigned long max_test_loops;
-
-
- /* LOC_172 */
-#ifdef GSCD_DEBUG
- printk("LOC_172 ");
-#endif
-
- outb(curr_drv_state, GSCDPORT(0));
- max_test_loops = 0xFFFF;
-
- do {
- result = wait_drv_ready();
- max_test_loops--;
- } while ((result != 0x08) && (max_test_loops > 0));
-
- return result;
-}
-
-
-static void cmd_info_in(char *pb, int count)
-{
- int result;
- char read;
-
-
- /* read info */
- /* LOC_182 */
-#ifdef GSCD_DEBUG
- printk("LOC_182 ");
-#endif
-
- do {
- read = inb(GSCDPORT(2));
- if (count > 0) {
- *pb = read;
- pb++;
- count--;
- }
-
- /* LOC_183 */
- do {
- result = wait_drv_ready();
- } while (result == 0x0E);
- } while (result == 6);
-
- cmd_end();
- return;
-}
-
-
-static void cmd_read_b(char *pb, int count, int size)
-{
- int result;
- int i;
-
-
- /* LOC_188 */
- /* LOC_189 */
-#ifdef GSCD_DEBUG
- printk("LOC_189 ");
-#endif
-
- do {
- do {
- result = wait_drv_ready();
- } while (result != 6 || result == 0x0E);
-
- if (result != 6) {
- cmd_end();
- return;
- }
-#ifdef GSCD_DEBUG
- printk("LOC_191 ");
-#endif
-
- for (i = 0; i < size; i++) {
- *pb = inb(GSCDPORT(2));
- pb++;
- }
- count--;
- } while (count > 0);
-
- cmd_end();
- return;
-}
-
-
-static void cmd_end(void)
-{
- int result;
-
-
- /* LOC_204 */
-#ifdef GSCD_DEBUG
- printk("LOC_204 ");
-#endif
-
- do {
- result = wait_drv_ready();
- if (result == drv_mode) {
- return;
- }
- } while (result != 4);
-
- /* LOC_205 */
-#ifdef GSCD_DEBUG
- printk("LOC_205 ");
-#endif
-
- disk_state = inb(GSCDPORT(2));
-
- do {
- result = wait_drv_ready();
- } while (result != drv_mode);
- return;
-
-}
-
-
-static void cmd_read_w(char *pb, int count, int size)
-{
- int result;
- int i;
-
-
-#ifdef GSCD_DEBUG
- printk("LOC_185 ");
-#endif
-
- do {
- /* LOC_185 */
- do {
- result = wait_drv_ready();
- } while (result != 6 || result == 0x0E);
-
- if (result != 6) {
- cmd_end();
- return;
- }
-
- for (i = 0; i < size; i++) {
- /* na, hier muss ich noch mal drueber nachdenken */
- *pb = inw(GSCDPORT(2));
- pb++;
- }
- count--;
- } while (count > 0);
-
- cmd_end();
- return;
-}
-
-static int __init find_drives(void)
-{
- int *pdrv;
- int drvnum;
- int subdrv;
- int i;
-
- speed = 0;
- pdrv = (int *) &drv_states;
- curr_drv_state = 0xFE;
- subdrv = 0;
- drvnum = 0;
-
- for (i = 0; i < 8; i++) {
- subdrv++;
- cmd_status();
- disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
- if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
- /* LOC_240 */
- *pdrv = curr_drv_state;
- init_cd_drive(drvnum);
- pdrv++;
- drvnum++;
- } else {
- if (subdrv < 2) {
- continue;
- } else {
- subdrv = 0;
- }
- }
-
-/* curr_drv_state<<1; <-- das geht irgendwie nicht */
-/* muss heissen: curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
- curr_drv_state *= 2;
- curr_drv_state |= 1;
-#ifdef GSCD_DEBUG
- printk("DriveState: %d\n", curr_drv_state);
-#endif
- }
-
- ndrives = drvnum;
- return drvnum;
-}
-
-static void __init init_cd_drive(int num)
-{
- char resp[50];
- int i;
-
- printk("GSCD: init unit %d\n", num);
- cc_Ident((char *) &resp);
-
- printk("GSCD: identification: ");
- for (i = 0; i < 0x1E; i++) {
- printk("%c", resp[i]);
- }
- printk("\n");
-
- cc_SetSpeed();
-
-}
-
-#ifdef FUTURE_WORK
-/* return_done */
-static void update_state(void)
-{
- unsigned int AX;
-
-
- if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
- if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
- AX = ST_INVALID;
- }
-
- if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
- == 0) {
- invalidate();
- f_drv_ok = 0;
- }
-
- AX |= 0x8000;
- }
-
- if (disk_state & ST_PLAYING) {
- AX |= 0x200;
- }
-
- AX |= 0x100;
- /* pkt_esbx = AX; */
-
- disk_state = 0;
-
-}
-#endif
-
-static struct gendisk *gscd_disk;
-
-static void __exit gscd_exit(void)
-{
- CLEAR_TIMER;
-
- del_gendisk(gscd_disk);
- put_disk(gscd_disk);
- if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
- printk("What's that: can't unregister GoldStar-module\n");
- return;
- }
- blk_cleanup_queue(gscd_queue);
- release_region(gscd_port, GSCD_IO_EXTENT);
- printk(KERN_INFO "GoldStar-module released.\n");
-}
-
-/* This is the common initialisation for the GoldStar drive. */
-/* It is called at boot time AND for module init. */
-static int __init gscd_init(void)
-{
- int i;
- int result;
- int ret=0;
-
- printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
- printk(KERN_INFO
- "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n",
- gscd_port);
-
- if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) {
- printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already"
- " in use.\n", gscd_port);
- return -EIO;
- }
-
-
- /* check for card */
- result = wait_drv_ready();
- if (result == 0x09) {
- printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n");
- ret = -EIO;
- goto err_out1;
- }
-
- if (result == 0x0b) {
- drv_mode = result;
- i = find_drives();
- if (i == 0) {
- printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is"
- " not found.\n");
- ret = -EIO;
- goto err_out1;
- }
- }
-
- if ((result != 0x0b) && (result != 0x09)) {
- printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not "
- "exist or H/W error\n");
- ret = -EIO;
- goto err_out1;
- }
-
- /* reset all drives */
- i = 0;
- while (drv_states[i] != 0) {
- curr_drv_state = drv_states[i];
- printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
- cc_Reset();
- printk("done\n");
- i++;
- }
-
- gscd_disk = alloc_disk(1);
- if (!gscd_disk)
- goto err_out1;
- gscd_disk->major = MAJOR_NR;
- gscd_disk->first_minor = 0;
- gscd_disk->fops = &gscd_fops;
- sprintf(gscd_disk->disk_name, "gscd");
-
- if (register_blkdev(MAJOR_NR, "gscd")) {
- ret = -EIO;
- goto err_out2;
- }
-
- gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock);
- if (!gscd_queue) {
- ret = -ENOMEM;
- goto err_out3;
- }
-
- disk_state = 0;
- gscdPresent = 1;
-
- gscd_disk->queue = gscd_queue;
- add_disk(gscd_disk);
-
- printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
- return 0;
-
-err_out3:
- unregister_blkdev(MAJOR_NR, "gscd");
-err_out2:
- put_disk(gscd_disk);
-err_out1:
- release_region(gscd_port, GSCD_IO_EXTENT);
- return ret;
-}
-
-static void gscd_hsg2msf(long hsg, struct msf *msf)
-{
- hsg += CD_MSF_OFFSET;
- msf->min = hsg / (CD_FRAMES * CD_SECS);
- hsg %= CD_FRAMES * CD_SECS;
- msf->sec = hsg / CD_FRAMES;
- msf->frame = hsg % CD_FRAMES;
-
- gscd_bin2bcd(&msf->min); /* convert to BCD */
- gscd_bin2bcd(&msf->sec);
- gscd_bin2bcd(&msf->frame);
-}
-
-
-static void gscd_bin2bcd(unsigned char *p)
-{
- int u, t;
-
- u = *p % 10;
- t = *p / 10;
- *p = u | (t << 4);
-}
-
-
-#ifdef FUTURE_WORK
-static long gscd_msf2hsg(struct msf *mp)
-{
- return gscd_bcd2bin(mp->frame)
- + gscd_bcd2bin(mp->sec) * CD_FRAMES
- + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
-}
-
-static int gscd_bcd2bin(unsigned char bcd)
-{
- return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-#endif
-
-MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
-MODULE_LICENSE("GPL");
-module_init(gscd_init);
-module_exit(gscd_exit);
-MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR);
diff --git a/drivers/cdrom/gscd.h b/drivers/cdrom/gscd.h
deleted file mode 100644
index a41e64bfc061..000000000000
--- a/drivers/cdrom/gscd.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Definitions for a GoldStar R420 CD-ROM interface
- *
- * Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- * Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- * Published under the GPL.
- *
- */
-
-
-/* The Interface Card default address is 0x340. This will work for most
- applications. Address selection is accomplished by jumpers PN801-1 to
- PN801-4 on the GoldStar Interface Card.
- Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
- 0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0 */
-
-/* insert here the I/O port address and extent */
-#define GSCD_BASE_ADDR 0x340
-#define GSCD_IO_EXTENT 4
-
-
-/************** nothing to set up below here *********************/
-
-/* port access macro */
-#define GSCDPORT(x) (gscd_port + (x))
-
-/*
- * commands
- * the lower nibble holds the command length
- */
-#define CMD_STATUS 0x01
-#define CMD_READSUBQ 0x02 /* 1: ?, 2: UPC, 5: ? */
-#define CMD_SEEK 0x05 /* read_mode M-S-F */
-#define CMD_READ 0x07 /* read_mode M-S-F nsec_h nsec_l */
-#define CMD_RESET 0x11
-#define CMD_SETMODE 0x15
-#define CMD_PLAY 0x17 /* M-S-F M-S-F */
-#define CMD_LOCK_CTL 0x22 /* 0: unlock, 1: lock */
-#define CMD_IDENT 0x31
-#define CMD_SETSPEED 0x32 /* 0: auto */ /* ??? */
-#define CMD_GETMODE 0x41
-#define CMD_PAUSE 0x51
-#define CMD_READTOC 0x61
-#define CMD_DISKINFO 0x71
-#define CMD_TRAY_CTL 0x81
-
-/*
- * disk_state:
- */
-#define ST_PLAYING 0x80
-#define ST_UNLOCKED 0x40
-#define ST_NO_DISK 0x20
-#define ST_DOOR_OPEN 0x10
-#define ST_x08 0x08
-#define ST_x04 0x04
-#define ST_INVALID 0x02
-#define ST_x01 0x01
-
-/*
- * cmd_type:
- */
-#define TYPE_INFO 0x01
-#define TYPE_DATA 0x02
-
-/*
- * read_mode:
- */
-#define MOD_POLLED 0x80
-#define MOD_x08 0x08
-#define MOD_RAW 0x04
-
-#define READ_DATA(port, buf, nr) insb(port, buf, nr)
-
-#define SET_TIMER(func, jifs) \
- ((mod_timer(&gscd_timer, jiffies + jifs)), \
- (gscd_timer.function = func))
-
-#define CLEAR_TIMER del_timer_sync(&gscd_timer)
-
-#define MAX_TRACKS 104
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct gscd_Play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct gscd_DiskInfo {
- unsigned char first;
- unsigned char last;
- struct msf diskLength;
- struct msf firstTrack;
-};
-
-struct gscd_Toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char pointIndex;
- struct msf trackTime;
- struct msf diskTime;
-};
-
diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c
deleted file mode 100644
index db0fd9a240e3..000000000000
--- a/drivers/cdrom/isp16.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* -- ISP16 cdrom detection and configuration
- *
- * Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
- *
- * Version 0.6
- *
- * History:
- * 0.5 First release.
- * Was included in the sjcd and optcd cdrom drivers.
- * 0.6 First "stand-alone" version.
- * Removed sound configuration.
- * Added "module" support.
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 19 June 2004 -- check_region() converted to request_region()
- * and return statement cleanups.
- * - Jesper Juhl
- *
- * Detect cdrom interface on ISP16 sound card.
- * Configure cdrom interface.
- *
- * Algorithm for the card with OPTi 82C928 taken
- * from the CDSETUP.SYS driver for MSDOS,
- * by OPTi Computers, version 2.03.
- * Algorithm for the card with OPTi 82C929 as communicated
- * to me by Vadim Model and Leo Spiekman.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define ISP16_VERSION_MAJOR 0
-#define ISP16_VERSION_MINOR 6
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include "isp16.h"
-
-static short isp16_detect(void);
-static short isp16_c928__detect(void);
-static short isp16_c929__detect(void);
-static short isp16_cdi_config(int base, u_char drive_type, int irq,
- int dma);
-static short isp16_type; /* dependent on type of interface card */
-static u_char isp16_ctrl;
-static u_short isp16_enable_port;
-
-static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
-static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
-static int isp16_cdrom_dma = ISP16_CDROM_DMA;
-static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
-
-module_param(isp16_cdrom_base, int, 0);
-module_param(isp16_cdrom_irq, int, 0);
-module_param(isp16_cdrom_dma, int, 0);
-module_param(isp16_cdrom_type, charp, 0);
-
-#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
-#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
-
-#ifndef MODULE
-
-static int
-__init isp16_setup(char *str)
-{
- int ints[4];
-
- (void) get_options(str, ARRAY_SIZE(ints), ints);
- if (ints[0] > 0)
- isp16_cdrom_base = ints[1];
- if (ints[0] > 1)
- isp16_cdrom_irq = ints[2];
- if (ints[0] > 2)
- isp16_cdrom_dma = ints[3];
- if (str)
- isp16_cdrom_type = str;
-
- return 1;
-}
-
-__setup("isp16=", isp16_setup);
-
-#endif /* MODULE */
-
-/*
- * ISP16 initialisation.
- *
- */
-static int __init isp16_init(void)
-{
- u_char expected_drive;
-
- printk(KERN_INFO
- "ISP16: configuration cdrom interface, version %d.%d.\n",
- ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR);
-
- if (!strcmp(isp16_cdrom_type, "noisp16")) {
- printk("ISP16: no cdrom interface configured.\n");
- return 0;
- }
-
- if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) {
- printk("ISP16: i/o ports already in use.\n");
- goto out;
- }
-
- if ((isp16_type = isp16_detect()) < 0) {
- printk("ISP16: no cdrom interface found.\n");
- goto cleanup_out;
- }
-
- printk(KERN_INFO
- "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n",
- (isp16_type == 2) ? 9 : 8);
-
- if (!strcmp(isp16_cdrom_type, "Sanyo"))
- expected_drive =
- (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
- else if (!strcmp(isp16_cdrom_type, "Sony"))
- expected_drive = ISP16_SONY;
- else if (!strcmp(isp16_cdrom_type, "Panasonic"))
- expected_drive =
- (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
- else if (!strcmp(isp16_cdrom_type, "Mitsumi"))
- expected_drive = ISP16_MITSUMI;
- else {
- printk("ISP16: %s not supported by cdrom interface.\n",
- isp16_cdrom_type);
- goto cleanup_out;
- }
-
- if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
- isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
- printk
- ("ISP16: cdrom interface has not been properly configured.\n");
- goto cleanup_out;
- }
- printk(KERN_INFO
- "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
- " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq,
- isp16_cdrom_dma, isp16_cdrom_type);
- return 0;
-
-cleanup_out:
- release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-out:
- return -EIO;
-}
-
-static short __init isp16_detect(void)
-{
-
- if (isp16_c929__detect() >= 0)
- return 2;
- else
- return (isp16_c928__detect());
-}
-
-static short __init isp16_c928__detect(void)
-{
- u_char ctrl;
- u_char enable_cdrom;
- u_char io;
- short i = -1;
-
- isp16_ctrl = ISP16_C928__CTRL;
- isp16_enable_port = ISP16_C928__ENABLE_PORT;
-
- /* read' and write' are a special read and write, respectively */
-
- /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
- ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC;
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- /* read' 3,4 and 5-bit from the cdrom enable port */
- enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38;
-
- if (!(enable_cdrom & 0x20)) { /* 5-bit not set */
- /* read' last 2 bits of ISP16_IO_SET_PORT */
- io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03;
- if (((io & 0x01) << 1) == (io & 0x02)) { /* bits are the same */
- if (io == 0) { /* ...the same and 0 */
- i = 0;
- enable_cdrom |= 0x20;
- } else { /* ...the same and 1 *//* my card, first time 'round */
- i = 1;
- enable_cdrom |= 0x28;
- }
- ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
- } else { /* bits are not the same */
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
- return i; /* -> not detected: possibly incorrect conclusion */
- }
- } else if (enable_cdrom == 0x20)
- i = 0;
- else if (enable_cdrom == 0x28) /* my card, already initialised */
- i = 1;
-
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- return i;
-}
-
-static short __init isp16_c929__detect(void)
-{
- u_char ctrl;
- u_char tmp;
-
- isp16_ctrl = ISP16_C929__CTRL;
- isp16_enable_port = ISP16_C929__ENABLE_PORT;
-
- /* read' and write' are a special read and write, respectively */
-
- /* read' ISP16_CTRL_PORT and save */
- ctrl = ISP16_IN(ISP16_CTRL_PORT);
-
- /* write' zero to the ctrl port and get response */
- ISP16_OUT(ISP16_CTRL_PORT, 0);
- tmp = ISP16_IN(ISP16_CTRL_PORT);
-
- if (tmp != 2) /* isp16 with 82C929 not detected */
- return -1;
-
- /* restore ctrl port value */
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- return 2;
-}
-
-static short __init
-isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
-{
- u_char base_code;
- u_char irq_code;
- u_char dma_code;
- u_char i;
-
- if ((drive_type == ISP16_MITSUMI) && (dma != 0))
- printk("ISP16: Mitsumi cdrom drive has no dma support.\n");
-
- switch (base) {
- case 0x340:
- base_code = ISP16_BASE_340;
- break;
- case 0x330:
- base_code = ISP16_BASE_330;
- break;
- case 0x360:
- base_code = ISP16_BASE_360;
- break;
- case 0x320:
- base_code = ISP16_BASE_320;
- break;
- default:
- printk
- ("ISP16: base address 0x%03X not supported by cdrom interface.\n",
- base);
- return -1;
- }
- switch (irq) {
- case 0:
- irq_code = ISP16_IRQ_X;
- break; /* disable irq */
- case 5:
- irq_code = ISP16_IRQ_5;
- printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
- " due to possible conflicts with the sound card.\n");
- break;
- case 7:
- irq_code = ISP16_IRQ_7;
- printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
- " due to possible conflicts with the sound card.\n");
- break;
- case 3:
- irq_code = ISP16_IRQ_3;
- break;
- case 9:
- irq_code = ISP16_IRQ_9;
- break;
- case 10:
- irq_code = ISP16_IRQ_10;
- break;
- case 11:
- irq_code = ISP16_IRQ_11;
- break;
- default:
- printk("ISP16: irq %d not supported by cdrom interface.\n",
- irq);
- return -1;
- }
- switch (dma) {
- case 0:
- dma_code = ISP16_DMA_X;
- break; /* disable dma */
- case 1:
- printk("ISP16: dma 1 cannot be used by cdrom interface,"
- " due to conflict with the sound card.\n");
- return -1;
- break;
- case 3:
- dma_code = ISP16_DMA_3;
- break;
- case 5:
- dma_code = ISP16_DMA_5;
- break;
- case 6:
- dma_code = ISP16_DMA_6;
- break;
- case 7:
- dma_code = ISP16_DMA_7;
- break;
- default:
- printk("ISP16: dma %d not supported by cdrom interface.\n",
- dma);
- return -1;
- }
-
- if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
- drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
- drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
- drive_type != ISP16_DRIVE_X) {
- printk
- ("ISP16: drive type (code 0x%02X) not supported by cdrom"
- " interface.\n", drive_type);
- return -1;
- }
-
- /* set type of interface */
- i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */
- ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type);
-
- /* enable cdrom on interface with 82C929 chip */
- if (isp16_type > 1)
- ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM);
-
- /* set base address, irq and dma */
- i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */
- ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
-
- return 0;
-}
-
-static void __exit isp16_exit(void)
-{
- release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
- printk(KERN_INFO "ISP16: module released.\n");
-}
-
-module_init(isp16_init);
-module_exit(isp16_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/cdrom/isp16.h b/drivers/cdrom/isp16.h
deleted file mode 100644
index 5bd22c8f7a96..000000000000
--- a/drivers/cdrom/isp16.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -- isp16.h
- *
- * Header for detection and initialisation of cdrom interface (only) on
- * ISP16 (MAD16, Mozart) sound card.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/* These are the default values */
-#define ISP16_CDROM_TYPE "Sanyo"
-#define ISP16_CDROM_IO_BASE 0x340
-#define ISP16_CDROM_IRQ 0
-#define ISP16_CDROM_DMA 0
-
-/* Some (Media)Magic */
-/* define types of drive the interface on an ISP16 card may be looking at */
-#define ISP16_DRIVE_X 0x00
-#define ISP16_SONY 0x02
-#define ISP16_PANASONIC0 0x02
-#define ISP16_SANYO0 0x02
-#define ISP16_MITSUMI 0x04
-#define ISP16_PANASONIC1 0x06
-#define ISP16_SANYO1 0x06
-#define ISP16_DRIVE_NOT_USED 0x08 /* not used */
-#define ISP16_DRIVE_SET_MASK 0xF1 /* don't change 0-bit or 4-7-bits*/
-/* ...for port */
-#define ISP16_DRIVE_SET_PORT 0xF8D
-/* set io parameters */
-#define ISP16_BASE_340 0x00
-#define ISP16_BASE_330 0x40
-#define ISP16_BASE_360 0x80
-#define ISP16_BASE_320 0xC0
-#define ISP16_IRQ_X 0x00
-#define ISP16_IRQ_5 0x04 /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_7 0x08 /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_3 0x0C
-#define ISP16_IRQ_9 0x10
-#define ISP16_IRQ_10 0x14
-#define ISP16_IRQ_11 0x18
-#define ISP16_DMA_X 0x03
-#define ISP16_DMA_3 0x00
-#define ISP16_DMA_5 0x00
-#define ISP16_DMA_6 0x01
-#define ISP16_DMA_7 0x02
-#define ISP16_IO_SET_MASK 0x20 /* don't change 5-bit */
-/* ...for port */
-#define ISP16_IO_SET_PORT 0xF8E
-/* enable the card */
-#define ISP16_C928__ENABLE_PORT 0xF90 /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__ENABLE_PORT 0xF91 /* ISP16 with OPTi 82C929 chip */
-#define ISP16_ENABLE_CDROM 0x80 /* seven bit */
-
-/* the magic stuff */
-#define ISP16_CTRL_PORT 0xF8F
-#define ISP16_C928__CTRL 0xE2 /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__CTRL 0xE3 /* ISP16 with OPTi 82C929 chip */
-
-#define ISP16_IO_BASE 0xF8D
-#define ISP16_IO_SIZE 5 /* ports used from 0xF8D up to 0xF91 */
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
deleted file mode 100644
index 4310cc84dfed..000000000000
--- a/drivers/cdrom/mcdx.c
+++ /dev/null
@@ -1,1943 +0,0 @@
-/*
- * The Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.14(hs)
- *
- * ... anyway, I'm back again, thanks to Marcin, he adopted
- * large portions of my code (at least the parts containing
- * my main thoughts ...)
- *
- ****************** H E L P *********************************
- * If you ever plan to update your CD ROM drive and perhaps
- * want to sell or simply give away your Mitsumi FX-001[DS]
- * -- Please --
- * mail me (heiko@lotte.sax.de). When my last drive goes
- * ballistic no more driver support will be available from me!
- *************************************************************
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- * The Linux Community at all and ...
- * Martin Harriss (he wrote the first Mitsumi Driver)
- * Eberhard Moenkeberg (he gave me much support and the initial kick)
- * Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
- * improved the original driver)
- * Jon Tombs, Bjorn Ekwall (module support)
- * Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- * Gerd Knorr (he lent me his PhotoCD)
- * Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- * Andreas Kies (testing the mysterious hang-ups)
- * Heiko Eissfeldt (VERIFY_READ/WRITE)
- * Marcin Dalecki (improved performance, shortened code)
- * ... somebody forgotten?
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- */
-
-
-#ifdef RCS
-static const char *mcdx_c_version
- = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $";
-#endif
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-
-#include <linux/major.h>
-#define MAJOR_NR MITSUMI_X_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#include "mcdx.h"
-
-#ifndef HZ
-#error HZ not defined
-#endif
-
-#define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args)
-
-#if !MCDX_QUIET
-#define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args)
-#else
-#define xinfo(fmt, args...) { ; }
-#endif
-
-#if MCDX_DEBUG
-#define xtrace(lvl, fmt, args...) \
- { if (lvl > 0) \
- { printk(KERN_DEBUG MCDX ":: " fmt, ## args); } }
-#define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args)
-#else
-#define xtrace(lvl, fmt, args...) { ; }
-#define xdebug(fmt, args...) { ; }
-#endif
-
-/* CONSTANTS *******************************************************/
-
-/* Following are the number of sectors we _request_ from the drive
- every time an access outside the already requested range is done.
- The _direct_ size is the number of sectors we're allowed to skip
- directly (performing a read instead of requesting the new sector
- needed */
-static const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */
-static const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */
-
-enum drivemodes { TOC, DATA, RAW, COOKED };
-enum datamodes { MODE0, MODE1, MODE2 };
-enum resetmodes { SOFT, HARD };
-
-static const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */
-static const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */
-static const int DOOR = 0x04; /* door locking capability */
-static const int MULTI = 0x08; /* multi session capability */
-
-static const unsigned char READ1X = 0xc0;
-static const unsigned char READ2X = 0xc1;
-
-
-/* DECLARATIONS ****************************************************/
-struct s_subqcode {
- unsigned char control;
- unsigned char tno;
- unsigned char index;
- struct cdrom_msf0 tt;
- struct cdrom_msf0 dt;
-};
-
-struct s_diskinfo {
- unsigned int n_first;
- unsigned int n_last;
- struct cdrom_msf0 msf_leadout;
- struct cdrom_msf0 msf_first;
-};
-
-struct s_multi {
- unsigned char multi;
- struct cdrom_msf0 msf_last;
-};
-
-struct s_version {
- unsigned char code;
- unsigned char ver;
-};
-
-/* Per drive/controller stuff **************************************/
-
-struct s_drive_stuff {
- /* waitqueues */
- wait_queue_head_t busyq;
- wait_queue_head_t lockq;
- wait_queue_head_t sleepq;
-
- /* flags */
- volatile int introk; /* status of last irq operation */
- volatile int busy; /* drive performs an operation */
- volatile int lock; /* exclusive usage */
-
- /* cd infos */
- struct s_diskinfo di;
- struct s_multi multi;
- struct s_subqcode *toc; /* first entry of the toc array */
- struct s_subqcode start;
- struct s_subqcode stop;
- int xa; /* 1 if xa disk */
- int audio; /* 1 if audio disk */
- int audiostatus;
-
- /* `buffer' control */
- volatile int valid; /* pending, ..., values are valid */
- volatile int pending; /* next sector to be read */
- volatile int low_border; /* first sector not to be skipped direct */
- volatile int high_border; /* first sector `out of area' */
-#ifdef AK2
- volatile int int_err;
-#endif /* AK2 */
-
- /* adds and odds */
- unsigned wreg_data; /* w data */
- unsigned wreg_reset; /* w hardware reset */
- unsigned wreg_hcon; /* w hardware conf */
- unsigned wreg_chn; /* w channel */
- unsigned rreg_data; /* r data */
- unsigned rreg_status; /* r status */
-
- int irq; /* irq used by this drive */
- int present; /* drive present and its capabilities */
- unsigned char readcmd; /* read cmd depends on single/double speed */
- unsigned char playcmd; /* play should always be single speed */
- unsigned int xxx; /* set if changed, reset while open */
- unsigned int yyy; /* set if changed, reset by media_changed */
- int users; /* keeps track of open/close */
- int lastsector; /* last block accessible */
- int status; /* last operation's error / status */
- int readerrs; /* # of blocks read w/o error */
- struct cdrom_device_info info;
- struct gendisk *disk;
-};
-
-
-/* Prototypes ******************************************************/
-
-/* The following prototypes are already declared elsewhere. They are
- repeated here to show what's going on. And to sense, if they're
- changed elsewhere. */
-
-static int mcdx_init(void);
-
-static int mcdx_block_open(struct inode *inode, struct file *file)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_open(&p->info, inode, file);
-}
-
-static int mcdx_block_release(struct inode *inode, struct file *file)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_release(&p->info, file);
-}
-
-static int mcdx_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_ioctl(file, &p->info, inode, cmd, arg);
-}
-
-static int mcdx_block_media_changed(struct gendisk *disk)
-{
- struct s_drive_stuff *p = disk->private_data;
- return cdrom_media_changed(&p->info);
-}
-
-static struct block_device_operations mcdx_bdops =
-{
- .owner = THIS_MODULE,
- .open = mcdx_block_open,
- .release = mcdx_block_release,
- .ioctl = mcdx_block_ioctl,
- .media_changed = mcdx_block_media_changed,
-};
-
-
-/* Indirect exported functions. These functions are exported by their
- addresses, such as mcdx_open and mcdx_close in the
- structure mcdx_dops. */
-
-/* exported by file_ops */
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose);
-static void mcdx_close(struct cdrom_device_info *cdi);
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr);
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position);
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock);
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg);
-
-/* misc internal support functions */
-static void log2msf(unsigned int, struct cdrom_msf0 *);
-static unsigned int msf2log(const struct cdrom_msf0 *);
-static unsigned int uint2bcd(unsigned int);
-static unsigned int bcd2uint(unsigned char);
-static unsigned port(int *);
-static int irq(int *);
-static void mcdx_delay(struct s_drive_stuff *, long jifs);
-static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
- int nr_sectors);
-static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector,
- int nr_sectors);
-
-static int mcdx_config(struct s_drive_stuff *, int);
-static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *,
- int);
-static int mcdx_stop(struct s_drive_stuff *, int);
-static int mcdx_hold(struct s_drive_stuff *, int);
-static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int);
-static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int);
-static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int);
-static int mcdx_requestsubqcode(struct s_drive_stuff *,
- struct s_subqcode *, int);
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *,
- struct s_multi *, int);
-static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *,
- int);
-static int mcdx_getstatus(struct s_drive_stuff *, int);
-static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *);
-static int mcdx_talk(struct s_drive_stuff *,
- const unsigned char *cmd, size_t,
- void *buffer, size_t size, unsigned int timeout, int);
-static int mcdx_readtoc(struct s_drive_stuff *);
-static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *);
-static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *);
-static int mcdx_setattentuator(struct s_drive_stuff *,
- struct cdrom_volctrl *, int);
-
-/* static variables ************************************************/
-
-static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
-static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
-static DEFINE_SPINLOCK(mcdx_lock);
-static struct request_queue *mcdx_queue;
-
-/* You can only set the first two pairs, from old MODULE_PARM code. */
-static int mcdx_set(const char *val, struct kernel_param *kp)
-{
- get_options((char *)val, 4, (int *)mcdx_drive_map);
- return 0;
-}
-module_param_call(mcdx, mcdx_set, NULL, NULL, 0);
-
-static struct cdrom_device_ops mcdx_dops = {
- .open = mcdx_open,
- .release = mcdx_close,
- .media_changed = mcdx_media_changed,
- .tray_move = mcdx_tray_move,
- .lock_door = mcdx_lockdoor,
- .audio_ioctl = mcdx_audio_ioctl,
- .capability = CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED |
- CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
-};
-
-/* KERNEL INTERFACE FUNCTIONS **************************************/
-
-
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
-
- if (!stuffp->present)
- return -ENXIO;
-
- if (stuffp->xxx) {
- if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
- stuffp->lastsector = -1;
- } else {
- stuffp->lastsector = (CD_FRAMESIZE / 512)
- * msf2log(&stuffp->di.msf_leadout) - 1;
- }
-
- if (stuffp->toc) {
- kfree(stuffp->toc);
- stuffp->toc = NULL;
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
- }
-
- stuffp->xxx = 0;
- }
-
- switch (cmd) {
- case CDROMSTART:{
- xtrace(IOCTL, "ioctl() START\n");
- /* Spin up the drive. Don't think we can do this.
- * For now, ignore it.
- */
- return 0;
- }
-
- case CDROMSTOP:{
- xtrace(IOCTL, "ioctl() STOP\n");
- stuffp->audiostatus = CDROM_AUDIO_INVALID;
- if (-1 == mcdx_stop(stuffp, 1))
- return -EIO;
- return 0;
- }
-
- case CDROMPLAYTRKIND:{
- struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-
- xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
- if ((ti->cdti_trk0 < stuffp->di.n_first)
- || (ti->cdti_trk0 > stuffp->di.n_last)
- || (ti->cdti_trk1 < stuffp->di.n_first))
- return -EINVAL;
- if (ti->cdti_trk1 > stuffp->di.n_last)
- ti->cdti_trk1 = stuffp->di.n_last;
- xtrace(PLAYTRK, "ioctl() track %d to %d\n",
- ti->cdti_trk0, ti->cdti_trk1);
- return mcdx_playtrk(stuffp, ti);
- }
-
- case CDROMPLAYMSF:{
- struct cdrom_msf *msf = (struct cdrom_msf *) arg;
-
- xtrace(IOCTL, "ioctl() PLAYMSF\n");
-
- if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
- && (-1 == mcdx_hold(stuffp, 1)))
- return -EIO;
-
- msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
- msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
- msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
-
- msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
- msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
- msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
-
- stuffp->stop.dt.minute = msf->cdmsf_min1;
- stuffp->stop.dt.second = msf->cdmsf_sec1;
- stuffp->stop.dt.frame = msf->cdmsf_frame1;
-
- return mcdx_playmsf(stuffp, msf);
- }
-
- case CDROMRESUME:{
- xtrace(IOCTL, "ioctl() RESUME\n");
- return mcdx_playtrk(stuffp, NULL);
- }
-
- case CDROMREADTOCENTRY:{
- struct cdrom_tocentry *entry =
- (struct cdrom_tocentry *) arg;
- struct s_subqcode *tp = NULL;
- xtrace(IOCTL, "ioctl() READTOCENTRY\n");
-
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
- if (entry->cdte_track == CDROM_LEADOUT)
- tp = &stuffp->toc[stuffp->di.n_last -
- stuffp->di.n_first + 1];
- else if (entry->cdte_track > stuffp->di.n_last
- || entry->cdte_track < stuffp->di.n_first)
- return -EINVAL;
- else
- tp = &stuffp->toc[entry->cdte_track -
- stuffp->di.n_first];
-
- if (NULL == tp)
- return -EIO;
- entry->cdte_adr = tp->control;
- entry->cdte_ctrl = tp->control >> 4;
- /* Always return stuff in MSF, and let the Uniform cdrom driver
- worry about what the user actually wants */
- entry->cdte_addr.msf.minute =
- bcd2uint(tp->dt.minute);
- entry->cdte_addr.msf.second =
- bcd2uint(tp->dt.second);
- entry->cdte_addr.msf.frame =
- bcd2uint(tp->dt.frame);
- return 0;
- }
-
- case CDROMSUBCHNL:{
- struct cdrom_subchnl *sub =
- (struct cdrom_subchnl *) arg;
- struct s_subqcode q;
-
- xtrace(IOCTL, "ioctl() SUBCHNL\n");
-
- if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
- return -EIO;
-
- xtrace(SUBCHNL, "audiostatus: %x\n",
- stuffp->audiostatus);
- sub->cdsc_audiostatus = stuffp->audiostatus;
- sub->cdsc_adr = q.control;
- sub->cdsc_ctrl = q.control >> 4;
- sub->cdsc_trk = bcd2uint(q.tno);
- sub->cdsc_ind = bcd2uint(q.index);
-
- xtrace(SUBCHNL, "trk %d, ind %d\n",
- sub->cdsc_trk, sub->cdsc_ind);
- /* Always return stuff in MSF, and let the Uniform cdrom driver
- worry about what the user actually wants */
- sub->cdsc_absaddr.msf.minute =
- bcd2uint(q.dt.minute);
- sub->cdsc_absaddr.msf.second =
- bcd2uint(q.dt.second);
- sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
- sub->cdsc_reladdr.msf.minute =
- bcd2uint(q.tt.minute);
- sub->cdsc_reladdr.msf.second =
- bcd2uint(q.tt.second);
- sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
- xtrace(SUBCHNL,
- "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
- sub->cdsc_absaddr.msf.minute,
- sub->cdsc_absaddr.msf.second,
- sub->cdsc_absaddr.msf.frame,
- sub->cdsc_reladdr.msf.minute,
- sub->cdsc_reladdr.msf.second,
- sub->cdsc_reladdr.msf.frame);
-
- return 0;
- }
-
- case CDROMREADTOCHDR:{
- struct cdrom_tochdr *toc =
- (struct cdrom_tochdr *) arg;
-
- xtrace(IOCTL, "ioctl() READTOCHDR\n");
- toc->cdth_trk0 = stuffp->di.n_first;
- toc->cdth_trk1 = stuffp->di.n_last;
- xtrace(TOCHDR,
- "ioctl() track0 = %d, track1 = %d\n",
- stuffp->di.n_first, stuffp->di.n_last);
- return 0;
- }
-
- case CDROMPAUSE:{
- xtrace(IOCTL, "ioctl() PAUSE\n");
- if (stuffp->audiostatus != CDROM_AUDIO_PLAY)
- return -EINVAL;
- if (-1 == mcdx_stop(stuffp, 1))
- return -EIO;
- stuffp->audiostatus = CDROM_AUDIO_PAUSED;
- if (-1 ==
- mcdx_requestsubqcode(stuffp, &stuffp->start,
- 1))
- return -EIO;
- return 0;
- }
-
- case CDROMMULTISESSION:{
- struct cdrom_multisession *ms =
- (struct cdrom_multisession *) arg;
- xtrace(IOCTL, "ioctl() MULTISESSION\n");
- /* Always return stuff in LBA, and let the Uniform cdrom driver
- worry about what the user actually wants */
- ms->addr.lba = msf2log(&stuffp->multi.msf_last);
- ms->xa_flag = !!stuffp->multi.multi;
- xtrace(MS,
- "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
- ms->xa_flag, ms->addr.lba,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
-
- return 0;
- }
-
- case CDROMEJECT:{
- xtrace(IOCTL, "ioctl() EJECT\n");
- if (stuffp->users > 1)
- return -EBUSY;
- return (mcdx_tray_move(cdi, 1));
- }
-
- case CDROMCLOSETRAY:{
- xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
- return (mcdx_tray_move(cdi, 0));
- }
-
- case CDROMVOLCTRL:{
- struct cdrom_volctrl *volctrl =
- (struct cdrom_volctrl *) arg;
- xtrace(IOCTL, "ioctl() VOLCTRL\n");
-
-#if 0 /* not tested! */
- /* adjust for the weirdness of workman (md) */
- /* can't test it (hs) */
- volctrl.channel2 = volctrl.channel1;
- volctrl.channel1 = volctrl.channel3 = 0x00;
-#endif
- return mcdx_setattentuator(stuffp, volctrl, 2);
- }
-
- default:
- return -EINVAL;
- }
-}
-
-static void do_mcdx_request(request_queue_t * q)
-{
- struct s_drive_stuff *stuffp;
- struct request *req;
-
- again:
-
- req = elv_next_request(q);
- if (!req)
- return;
-
- stuffp = req->rq_disk->private_data;
-
- if (!stuffp->present) {
- xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
- xtrace(REQUEST, "end_request(0): bad device\n");
- end_request(req, 0);
- return;
- }
-
- if (stuffp->audio) {
- xwarn("do_request() attempt to read from audio cd\n");
- xtrace(REQUEST, "end_request(0): read from audio\n");
- end_request(req, 0);
- return;
- }
-
- xtrace(REQUEST, "do_request() (%lu + %lu)\n",
- req->sector, req->nr_sectors);
-
- if (req->cmd != READ) {
- xwarn("do_request(): non-read command to cd!!\n");
- xtrace(REQUEST, "end_request(0): write\n");
- end_request(req, 0);
- return;
- }
- else {
- stuffp->status = 0;
- while (req->nr_sectors) {
- int i;
-
- i = mcdx_transfer(stuffp,
- req->buffer,
- req->sector,
- req->nr_sectors);
-
- if (i == -1) {
- end_request(req, 0);
- goto again;
- }
- req->sector += i;
- req->nr_sectors -= i;
- req->buffer += (i * 512);
- }
- end_request(req, 1);
- goto again;
-
- xtrace(REQUEST, "end_request(1)\n");
- end_request(req, 1);
- }
-
- goto again;
-}
-
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
-{
- struct s_drive_stuff *stuffp;
- xtrace(OPENCLOSE, "open()\n");
- stuffp = cdi->handle;
- if (!stuffp->present)
- return -ENXIO;
-
- /* Make the modules looking used ... (thanx bjorn).
- * But we shouldn't forget to decrement the module counter
- * on error return */
-
- /* this is only done to test if the drive talks with us */
- if (-1 == mcdx_getstatus(stuffp, 1))
- return -EIO;
-
- if (stuffp->xxx) {
-
- xtrace(OPENCLOSE, "open() media changed\n");
- stuffp->audiostatus = CDROM_AUDIO_INVALID;
- stuffp->readcmd = 0;
- xtrace(OPENCLOSE, "open() Request multisession info\n");
- if (-1 ==
- mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6))
- xinfo("No multidiskinfo\n");
- } else {
- /* multisession ? */
- if (!stuffp->multi.multi)
- stuffp->multi.msf_last.second = 2;
-
- xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
- stuffp->multi.multi,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
-
- {;
- } /* got multisession information */
- /* request the disks table of contents (aka diskinfo) */
- if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-
- stuffp->lastsector = -1;
-
- } else {
-
- stuffp->lastsector = (CD_FRAMESIZE / 512)
- * msf2log(&stuffp->di.msf_leadout) - 1;
-
- xtrace(OPENCLOSE,
- "open() start %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_first,
- stuffp->di.msf_first.minute,
- stuffp->di.msf_first.second,
- stuffp->di.msf_first.frame,
- msf2log(&stuffp->di.msf_first));
- xtrace(OPENCLOSE,
- "open() last %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_last,
- stuffp->di.msf_leadout.minute,
- stuffp->di.msf_leadout.second,
- stuffp->di.msf_leadout.frame,
- msf2log(&stuffp->di.msf_leadout));
- }
-
- if (stuffp->toc) {
- xtrace(MALLOC, "open() free old toc @ %p\n",
- stuffp->toc);
- kfree(stuffp->toc);
-
- stuffp->toc = NULL;
- }
-
- xtrace(OPENCLOSE, "open() init irq generation\n");
- if (-1 == mcdx_config(stuffp, 1))
- return -EIO;
-#ifdef FALLBACK
- /* Set the read speed */
- xwarn("AAA %x AAA\n", stuffp->readcmd);
- if (stuffp->readerrs)
- stuffp->readcmd = READ1X;
- else
- stuffp->readcmd =
- stuffp->present | SINGLE ? READ1X : READ2X;
- xwarn("XXX %x XXX\n", stuffp->readcmd);
-#else
- stuffp->readcmd =
- stuffp->present | SINGLE ? READ1X : READ2X;
-#endif
-
- /* try to get the first sector, iff any ... */
- if (stuffp->lastsector >= 0) {
- char buf[512];
- int ans;
- int tries;
-
- stuffp->xa = 0;
- stuffp->audio = 0;
-
- for (tries = 6; tries; tries--) {
-
- stuffp->introk = 1;
-
- xtrace(OPENCLOSE, "open() try as %s\n",
- stuffp->xa ? "XA" : "normal");
- /* set data mode */
- if (-1 == (ans = mcdx_setdatamode(stuffp,
- stuffp->
- xa ?
- MODE2 :
- MODE1,
- 1))) {
- /* return -EIO; */
- stuffp->xa = 0;
- break;
- }
-
- if ((stuffp->audio = e_audio(ans)))
- break;
-
- while (0 ==
- (ans =
- mcdx_transfer(stuffp, buf, 0, 1)));
-
- if (ans == 1)
- break;
- stuffp->xa = !stuffp->xa;
- }
- }
- /* xa disks will be read in raw mode, others not */
- if (-1 == mcdx_setdrivemode(stuffp,
- stuffp->xa ? RAW : COOKED,
- 1))
- return -EIO;
- if (stuffp->audio) {
- xinfo("open() audio disk found\n");
- } else if (stuffp->lastsector >= 0) {
- xinfo("open() %s%s disk found\n",
- stuffp->xa ? "XA / " : "",
- stuffp->multi.
- multi ? "Multi Session" : "Single Session");
- }
- }
- stuffp->xxx = 0;
- stuffp->users++;
- return 0;
-}
-
-static void mcdx_close(struct cdrom_device_info *cdi)
-{
- struct s_drive_stuff *stuffp;
-
- xtrace(OPENCLOSE, "close()\n");
-
- stuffp = cdi->handle;
-
- --stuffp->users;
-}
-
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-/* Return: 1 if media changed since last call to this function
- 0 otherwise */
-{
- struct s_drive_stuff *stuffp;
-
- xinfo("mcdx_media_changed called for device %s\n", cdi->name);
-
- stuffp = cdi->handle;
- mcdx_getstatus(stuffp, 1);
-
- if (stuffp->yyy == 0)
- return 0;
-
- stuffp->yyy = 0;
- return 1;
-}
-
-#ifndef MODULE
-static int __init mcdx_setup(char *str)
-{
- int pi[4];
- (void) get_options(str, ARRAY_SIZE(pi), pi);
-
- if (pi[0] > 0)
- mcdx_drive_map[0][0] = pi[1];
- if (pi[0] > 1)
- mcdx_drive_map[0][1] = pi[2];
- return 1;
-}
-
-__setup("mcdx=", mcdx_setup);
-
-#endif
-
-/* DIRTY PART ******************************************************/
-
-static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
-/* This routine is used for sleeping.
- * A jifs value <0 means NO sleeping,
- * =0 means minimal sleeping (let the kernel
- * run for other processes)
- * >0 means at least sleep for that amount.
- * May be we could use a simple count loop w/ jumps to itself, but
- * I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
-{
- if (jifs < 0)
- return;
-
- xtrace(SLEEP, "*** delay: sleepq\n");
- interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
- xtrace(SLEEP, "delay awoken\n");
- if (signal_pending(current)) {
- xtrace(SLEEP, "got signal\n");
- }
-}
-
-static irqreturn_t mcdx_intr(int irq, void *dev_id)
-{
- struct s_drive_stuff *stuffp = dev_id;
- unsigned char b;
-
-#ifdef AK2
- if (!stuffp->busy && stuffp->pending)
- stuffp->int_err = 1;
-
-#endif /* AK2 */
- /* get the interrupt status */
- b = inb(stuffp->rreg_status);
- stuffp->introk = ~b & MCDX_RBIT_DTEN;
-
- /* NOTE: We only should get interrupts if the data we
- * requested are ready to transfer.
- * But the drive seems to generate ``asynchronous'' interrupts
- * on several error conditions too. (Despite the err int enable
- * setting during initialisation) */
-
- /* if not ok, read the next byte as the drives status */
- if (!stuffp->introk) {
- xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
- if (~b & MCDX_RBIT_STEN) {
- xinfo("intr() irq %d status 0x%02x\n",
- irq, inb(stuffp->rreg_data));
- } else {
- xinfo("intr() irq %d ambiguous hw status\n", irq);
- }
- } else {
- xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);
- }
-
- stuffp->busy = 0;
- wake_up_interruptible(&stuffp->busyq);
- return IRQ_HANDLED;
-}
-
-
-static int mcdx_talk(struct s_drive_stuff *stuffp,
- const unsigned char *cmd, size_t cmdlen,
- void *buffer, size_t size, unsigned int timeout, int tries)
-/* Send a command to the drive, wait for the result.
- * returns -1 on timeout, drive status otherwise
- * If buffer is not zero, the result (length size) is stored there.
- * If buffer is zero the size should be the number of bytes to read
- * from the drive. These bytes are discarded.
- */
-{
- int st;
- char c;
- int discard;
-
- /* Somebody wants the data read? */
- if ((discard = (buffer == NULL)))
- buffer = &c;
-
- while (stuffp->lock) {
- xtrace(SLEEP, "*** talk: lockq\n");
- interruptible_sleep_on(&stuffp->lockq);
- xtrace(SLEEP, "talk: awoken\n");
- }
-
- stuffp->lock = 1;
-
- /* An operation other then reading data destroys the
- * data already requested and remembered in stuffp->request, ... */
- stuffp->valid = 0;
-
-#if MCDX_DEBUG & TALK
- {
- unsigned char i;
- xtrace(TALK,
- "talk() %d / %d tries, res.size %d, command 0x%02x",
- tries, timeout, size, (unsigned char) cmd[0]);
- for (i = 1; i < cmdlen; i++)
- xtrace(TALK, " 0x%02x", cmd[i]);
- xtrace(TALK, "\n");
- }
-#endif
-
- /* give up if all tries are done (bad) or if the status
- * st != -1 (good) */
- for (st = -1; st == -1 && tries; tries--) {
-
- char *bp = (char *) buffer;
- size_t sz = size;
-
- outsb(stuffp->wreg_data, cmd, cmdlen);
- xtrace(TALK, "talk() command sent\n");
-
- /* get the status byte */
- if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
- xinfo("talk() %02x timed out (status), %d tr%s left\n",
- cmd[0], tries - 1, tries == 2 ? "y" : "ies");
- continue;
- }
- st = *bp;
- sz--;
- if (!discard)
- bp++;
-
- xtrace(TALK, "talk() got status 0x%02x\n", st);
-
- /* command error? */
- if (e_cmderr(st)) {
- xwarn("command error cmd = %02x %s \n",
- cmd[0], cmdlen > 1 ? "..." : "");
- st = -1;
- continue;
- }
-
- /* audio status? */
- if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
- stuffp->audiostatus =
- e_audiobusy(st) ? CDROM_AUDIO_PLAY :
- CDROM_AUDIO_NO_STATUS;
- else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
- && e_audiobusy(st) == 0)
- stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
-
- /* media change? */
- if (e_changed(st)) {
- xinfo("talk() media changed\n");
- stuffp->xxx = stuffp->yyy = 1;
- }
-
- /* now actually get the data */
- while (sz--) {
- if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
- xinfo("talk() %02x timed out (data), %d tr%s left\n",
- cmd[0], tries - 1,
- tries == 2 ? "y" : "ies");
- st = -1;
- break;
- }
- if (!discard)
- bp++;
- xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));
- }
- }
-
-#if !MCDX_QUIET
- if (!tries && st == -1)
- xinfo("talk() giving up\n");
-#endif
-
- stuffp->lock = 0;
- wake_up_interruptible(&stuffp->lockq);
-
- xtrace(TALK, "talk() done with 0x%02x\n", st);
- return st;
-}
-
-/* MODULE STUFF ***********************************************************/
-
-static int __init __mcdx_init(void)
-{
- int i;
- int drives = 0;
-
- mcdx_init();
- for (i = 0; i < MCDX_NDRIVES; i++) {
- if (mcdx_stuffp[i]) {
- xtrace(INIT, "init_module() drive %d stuff @ %p\n",
- i, mcdx_stuffp[i]);
- drives++;
- }
- }
-
- if (!drives)
- return -EIO;
-
- return 0;
-}
-
-static void __exit mcdx_exit(void)
-{
- int i;
-
- xinfo("cleanup_module called\n");
-
- for (i = 0; i < MCDX_NDRIVES; i++) {
- struct s_drive_stuff *stuffp = mcdx_stuffp[i];
- if (!stuffp)
- continue;
- del_gendisk(stuffp->disk);
- if (unregister_cdrom(&stuffp->info)) {
- printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
- continue;
- }
- put_disk(stuffp->disk);
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- free_irq(stuffp->irq, NULL);
- if (stuffp->toc) {
- xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
- stuffp->toc);
- kfree(stuffp->toc);
- }
- xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",
- stuffp);
- mcdx_stuffp[i] = NULL;
- kfree(stuffp);
- }
-
- if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
- xwarn("cleanup() unregister_blkdev() failed\n");
- }
-#if !MCDX_QUIET
- else
- xinfo("cleanup() succeeded\n");
-#endif
- blk_cleanup_queue(mcdx_queue);
-}
-
-#ifdef MODULE
-module_init(__mcdx_init);
-#endif
-module_exit(mcdx_exit);
-
-
-/* Support functions ************************************************/
-
-static int __init mcdx_init_drive(int drive)
-{
- struct s_version version;
- struct gendisk *disk;
- struct s_drive_stuff *stuffp;
- int size = sizeof(*stuffp);
- char msg[80];
-
- xtrace(INIT, "init() try drive %d\n", drive);
-
- xtrace(INIT, "kmalloc space for stuffpt's\n");
- xtrace(MALLOC, "init() malloc %d bytes\n", size);
- if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
- xwarn("init() malloc failed\n");
- return 1;
- }
-
- disk = alloc_disk(1);
- if (!disk) {
- xwarn("init() malloc failed\n");
- kfree(stuffp);
- return 1;
- }
-
- xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
- sizeof(*stuffp), stuffp);
-
- /* set default values */
- stuffp->present = 0; /* this should be 0 already */
- stuffp->toc = NULL; /* this should be NULL already */
-
- /* setup our irq and i/o addresses */
- stuffp->irq = irq(mcdx_drive_map[drive]);
- stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
- stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
- stuffp->wreg_hcon = stuffp->wreg_reset + 1;
- stuffp->wreg_chn = stuffp->wreg_hcon + 1;
-
- init_waitqueue_head(&stuffp->busyq);
- init_waitqueue_head(&stuffp->lockq);
- init_waitqueue_head(&stuffp->sleepq);
-
- /* check if i/o addresses are available */
- if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
- xwarn("0x%03x,%d: Init failed. "
- "I/O ports (0x%03x..0x%03x) already in use.\n",
- stuffp->wreg_data, stuffp->irq,
- stuffp->wreg_data,
- stuffp->wreg_data + MCDX_IO_SIZE - 1);
- xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
- kfree(stuffp);
- put_disk(disk);
- xtrace(INIT, "init() continue at next drive\n");
- return 0; /* next drive */
- }
-
- xtrace(INIT, "init() i/o port is available at 0x%03x\n"
- stuffp->wreg_data);
- xtrace(INIT, "init() hardware reset\n");
- mcdx_reset(stuffp, HARD, 1);
-
- xtrace(INIT, "init() get version\n");
- if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
- /* failed, next drive */
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
- MCDX, stuffp->wreg_data, stuffp->irq);
- xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
- kfree(stuffp);
- put_disk(disk);
- xtrace(INIT, "init() continue at next drive\n");
- return 0;
- }
-
- switch (version.code) {
- case 'D':
- stuffp->readcmd = READ2X;
- stuffp->present = DOUBLE | DOOR | MULTI;
- break;
- case 'F':
- stuffp->readcmd = READ1X;
- stuffp->present = SINGLE | DOOR | MULTI;
- break;
- case 'M':
- stuffp->readcmd = READ1X;
- stuffp->present = SINGLE;
- break;
- default:
- stuffp->present = 0;
- break;
- }
-
- stuffp->playcmd = READ1X;
-
- if (!stuffp->present) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
- MCDX, stuffp->wreg_data, stuffp->irq);
- kfree(stuffp);
- put_disk(disk);
- return 0; /* next drive */
- }
-
- xtrace(INIT, "init() register blkdev\n");
- if (register_blkdev(MAJOR_NR, "mcdx")) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- return 1;
- }
-
- mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
- if (!mcdx_queue) {
- unregister_blkdev(MAJOR_NR, "mcdx");
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- return 1;
- }
-
- xtrace(INIT, "init() subscribe irq and i/o\n");
- if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
- MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
- stuffp->irq = 0;
- blk_cleanup_queue(mcdx_queue);
- kfree(stuffp);
- put_disk(disk);
- return 0;
- }
-
- xtrace(INIT, "init() get garbage\n");
- {
- int i;
- mcdx_delay(stuffp, HZ / 2);
- for (i = 100; i; i--)
- (void) inb(stuffp->rreg_status);
- }
-
-
-#ifdef WE_KNOW_WHY
- /* irq 11 -> channel register */
- outb(0x50, stuffp->wreg_chn);
-#endif
-
- xtrace(INIT, "init() set non dma but irq mode\n");
- mcdx_config(stuffp, 1);
-
- stuffp->info.ops = &mcdx_dops;
- stuffp->info.speed = 2;
- stuffp->info.capacity = 1;
- stuffp->info.handle = stuffp;
- sprintf(stuffp->info.name, "mcdx%d", drive);
- disk->major = MAJOR_NR;
- disk->first_minor = drive;
- strcpy(disk->disk_name, stuffp->info.name);
- disk->fops = &mcdx_bdops;
- disk->flags = GENHD_FL_CD;
- stuffp->disk = disk;
-
- sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
- " (Firmware version %c %x)\n",
- stuffp->wreg_data, stuffp->irq, version.code, version.ver);
- mcdx_stuffp[drive] = stuffp;
- xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
- if (register_cdrom(&stuffp->info) != 0) {
- printk("Cannot register Mitsumi CD-ROM!\n");
- free_irq(stuffp->irq, NULL);
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
- xwarn("cleanup() unregister_blkdev() failed\n");
- blk_cleanup_queue(mcdx_queue);
- return 2;
- }
- disk->private_data = stuffp;
- disk->queue = mcdx_queue;
- add_disk(disk);
- printk(msg);
- return 0;
-}
-
-static int __init mcdx_init(void)
-{
- int drive;
- xwarn("Version 2.14(hs) \n");
-
- xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
-
- /* zero the pointer array */
- for (drive = 0; drive < MCDX_NDRIVES; drive++)
- mcdx_stuffp[drive] = NULL;
-
- /* do the initialisation */
- for (drive = 0; drive < MCDX_NDRIVES; drive++) {
- switch (mcdx_init_drive(drive)) {
- case 2:
- return -EIO;
- case 1:
- break;
- }
- }
- return 0;
-}
-
-static int mcdx_transfer(struct s_drive_stuff *stuffp,
- char *p, int sector, int nr_sectors)
-/* This seems to do the actually transfer. But it does more. It
- keeps track of errors occurred and will (if possible) fall back
- to single speed on error.
- Return: -1 on timeout or other error
- else status byte (as in stuff->st) */
-{
- int ans;
-
- ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
- return ans;
-#ifdef FALLBACK
- if (-1 == ans)
- stuffp->readerrs++;
- else
- return ans;
-
- if (stuffp->readerrs && stuffp->readcmd == READ1X) {
- xwarn("XXX Already reading 1x -- no chance\n");
- return -1;
- }
-
- xwarn("XXX Fallback to 1x\n");
-
- stuffp->readcmd = READ1X;
- return mcdx_transfer(stuffp, p, sector, nr_sectors);
-#endif
-
-}
-
-
-static int mcdx_xfer(struct s_drive_stuff *stuffp,
- char *p, int sector, int nr_sectors)
-/* This does actually the transfer from the drive.
- Return: -1 on timeout or other error
- else status byte (as in stuff->st) */
-{
- int border;
- int done = 0;
- long timeout;
-
- if (stuffp->audio) {
- xwarn("Attempt to read from audio CD.\n");
- return -1;
- }
-
- if (!stuffp->readcmd) {
- xinfo("Can't transfer from missing disk.\n");
- return -1;
- }
-
- while (stuffp->lock) {
- interruptible_sleep_on(&stuffp->lockq);
- }
-
- if (stuffp->valid && (sector >= stuffp->pending)
- && (sector < stuffp->low_border)) {
-
- /* All (or at least a part of the sectors requested) seems
- * to be already requested, so we don't need to bother the
- * drive with new requests ...
- * Wait for the drive become idle, but first
- * check for possible occurred errors --- the drive
- * seems to report them asynchronously */
-
-
- border = stuffp->high_border < (border =
- sector + nr_sectors)
- ? stuffp->high_border : border;
-
- stuffp->lock = current->pid;
-
- do {
-
- while (stuffp->busy) {
-
- timeout =
- interruptible_sleep_on_timeout
- (&stuffp->busyq, 5 * HZ);
-
- if (!stuffp->introk) {
- xtrace(XFER,
- "error via interrupt\n");
- } else if (!timeout) {
- xtrace(XFER, "timeout\n");
- } else if (signal_pending(current)) {
- xtrace(XFER, "signal\n");
- } else
- continue;
-
- stuffp->lock = 0;
- stuffp->busy = 0;
- stuffp->valid = 0;
-
- wake_up_interruptible(&stuffp->lockq);
- xtrace(XFER, "transfer() done (-1)\n");
- return -1;
- }
-
- /* check if we need to set the busy flag (as we
- * expect an interrupt */
- stuffp->busy = (3 == (stuffp->pending & 3));
-
- /* Test if it's the first sector of a block,
- * there we have to skip some bytes as we read raw data */
- if (stuffp->xa && (0 == (stuffp->pending & 3))) {
- const int HEAD =
- CD_FRAMESIZE_RAW - CD_XA_TAIL -
- CD_FRAMESIZE;
- insb(stuffp->rreg_data, p, HEAD);
- }
-
- /* now actually read the data */
- insb(stuffp->rreg_data, p, 512);
-
- /* test if it's the last sector of a block,
- * if so, we have to handle XA special */
- if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
- char dummy[CD_XA_TAIL];
- insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL);
- }
-
- if (stuffp->pending == sector) {
- p += 512;
- done++;
- sector++;
- }
- } while (++(stuffp->pending) < border);
-
- stuffp->lock = 0;
- wake_up_interruptible(&stuffp->lockq);
-
- } else {
-
- /* The requested sector(s) is/are out of the
- * already requested range, so we have to bother the drive
- * with a new request. */
-
- static unsigned char cmd[] = {
- 0,
- 0, 0, 0,
- 0, 0, 0
- };
-
- cmd[0] = stuffp->readcmd;
-
- /* The numbers held in ->pending, ..., should be valid */
- stuffp->valid = 1;
- stuffp->pending = sector & ~3;
-
- /* do some sanity checks */
- if (stuffp->pending > stuffp->lastsector) {
- xwarn
- ("transfer() sector %d from nirvana requested.\n",
- stuffp->pending);
- stuffp->status = MCDX_ST_EOM;
- stuffp->valid = 0;
- xtrace(XFER, "transfer() done (-1)\n");
- return -1;
- }
-
- if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
- > stuffp->lastsector + 1) {
- xtrace(XFER, "cut low_border\n");
- stuffp->low_border = stuffp->lastsector + 1;
- }
- if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
- > stuffp->lastsector + 1) {
- xtrace(XFER, "cut high_border\n");
- stuffp->high_border = stuffp->lastsector + 1;
- }
-
- { /* Convert the sector to be requested to MSF format */
- struct cdrom_msf0 pending;
- log2msf(stuffp->pending / 4, &pending);
- cmd[1] = pending.minute;
- cmd[2] = pending.second;
- cmd[3] = pending.frame;
- }
-
- cmd[6] =
- (unsigned
- char) ((stuffp->high_border - stuffp->pending) / 4);
- xtrace(XFER, "[%2d]\n", cmd[6]);
-
- stuffp->busy = 1;
- /* Now really issue the request command */
- outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
- }
-#ifdef AK2
- if (stuffp->int_err) {
- stuffp->valid = 0;
- stuffp->int_err = 0;
- return -1;
- }
-#endif /* AK2 */
-
- stuffp->low_border = (stuffp->low_border +=
- done) <
- stuffp->high_border ? stuffp->low_border : stuffp->high_border;
-
- return done;
-}
-
-
-/* Access to elements of the mcdx_drive_map members */
-
-static unsigned port(int *ip)
-{
- return ip[0];
-}
-static int irq(int *ip)
-{
- return ip[1];
-}
-
-/* Misc number converters */
-
-static unsigned int bcd2uint(unsigned char c)
-{
- return (c >> 4) * 10 + (c & 0x0f);
-}
-
-static unsigned int uint2bcd(unsigned int ival)
-{
- return ((ival / 10) << 4) | (ival % 10);
-}
-
-static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
-{
- l += CD_MSF_OFFSET;
- pmsf->minute = uint2bcd(l / 4500), l %= 4500;
- pmsf->second = uint2bcd(l / 75);
- pmsf->frame = uint2bcd(l % 75);
-}
-
-static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
-{
- return bcd2uint(pmsf->frame)
- + bcd2uint(pmsf->second) * 75
- + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
-}
-
-int mcdx_readtoc(struct s_drive_stuff *stuffp)
-/* Read the toc entries from the CD,
- * Return: -1 on failure, else 0 */
-{
-
- if (stuffp->toc) {
- xtrace(READTOC, "ioctl() toc already read\n");
- return 0;
- }
-
- xtrace(READTOC, "ioctl() readtoc for %d tracks\n",
- stuffp->di.n_last - stuffp->di.n_first + 1);
-
- if (-1 == mcdx_hold(stuffp, 1))
- return -1;
-
- xtrace(READTOC, "ioctl() tocmode\n");
- if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
- return -EIO;
-
- /* all seems to be ok so far ... malloc */
- {
- int size;
- size =
- sizeof(struct s_subqcode) * (stuffp->di.n_last -
- stuffp->di.n_first + 2);
-
- xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);
- stuffp->toc = kmalloc(size, GFP_KERNEL);
- if (!stuffp->toc) {
- xwarn("Cannot malloc %d bytes for toc\n", size);
- mcdx_setdrivemode(stuffp, DATA, 1);
- return -EIO;
- }
- }
-
- /* now read actually the index */
- {
- int trk;
- int retries;
-
- for (trk = 0;
- trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
- trk++)
- stuffp->toc[trk].index = 0;
-
- for (retries = 300; retries; retries--) { /* why 300? */
- struct s_subqcode q;
- unsigned int idx;
-
- if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
- mcdx_setdrivemode(stuffp, DATA, 1);
- return -EIO;
- }
-
- idx = bcd2uint(q.index);
-
- if ((idx > 0)
- && (idx <= stuffp->di.n_last)
- && (q.tno == 0)
- && (stuffp->toc[idx - stuffp->di.n_first].
- index == 0)) {
- stuffp->toc[idx - stuffp->di.n_first] = q;
- xtrace(READTOC,
- "ioctl() toc idx %d (trk %d)\n",
- idx, trk);
- trk--;
- }
- if (trk == 0)
- break;
- }
- memset(&stuffp->
- toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
- sizeof(stuffp->toc[0]));
- stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
- 1].dt = stuffp->di.msf_leadout;
- }
-
- /* unset toc mode */
- xtrace(READTOC, "ioctl() undo toc mode\n");
- if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
- return -EIO;
-
-#if MCDX_DEBUG && READTOC
- {
- int trk;
- for (trk = 0;
- trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
- trk++)
- xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
- " %02x:%02x.%02x %02x:%02x.%02x\n",
- trk + stuffp->di.n_first,
- stuffp->toc[trk].control,
- stuffp->toc[trk].tno,
- stuffp->toc[trk].index,
- stuffp->toc[trk].tt.minute,
- stuffp->toc[trk].tt.second,
- stuffp->toc[trk].tt.frame,
- stuffp->toc[trk].dt.minute,
- stuffp->toc[trk].dt.second,
- stuffp->toc[trk].dt.frame);
- }
-#endif
-
- return 0;
-}
-
-static int
-mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
-{
- unsigned char cmd[7] = {
- 0, 0, 0, 0, 0, 0, 0
- };
-
- if (!stuffp->readcmd) {
- xinfo("Can't play from missing disk.\n");
- return -1;
- }
-
- cmd[0] = stuffp->playcmd;
-
- cmd[1] = msf->cdmsf_min0;
- cmd[2] = msf->cdmsf_sec0;
- cmd[3] = msf->cdmsf_frame0;
- cmd[4] = msf->cdmsf_min1;
- cmd[5] = msf->cdmsf_sec1;
- cmd[6] = msf->cdmsf_frame1;
-
- xtrace(PLAYMSF, "ioctl(): play %x "
- "%02x:%02x:%02x -- %02x:%02x:%02x\n",
- cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
-
- outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
- if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
- xwarn("playmsf() timeout\n");
- return -1;
- }
-
- stuffp->audiostatus = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-static int
-mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
-{
- struct s_subqcode *p;
- struct cdrom_msf msf;
-
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
-
- if (ti)
- p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
- else
- p = &stuffp->start;
-
- msf.cdmsf_min0 = p->dt.minute;
- msf.cdmsf_sec0 = p->dt.second;
- msf.cdmsf_frame0 = p->dt.frame;
-
- if (ti) {
- p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
- stuffp->stop = *p;
- } else
- p = &stuffp->stop;
-
- msf.cdmsf_min1 = p->dt.minute;
- msf.cdmsf_sec1 = p->dt.second;
- msf.cdmsf_frame1 = p->dt.frame;
-
- return mcdx_playmsf(stuffp, &msf);
-}
-
-
-/* Drive functions ************************************************/
-
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
-
- if (!stuffp->present)
- return -ENXIO;
- if (!(stuffp->present & DOOR))
- return -ENOSYS;
-
- if (position) /* 1: eject */
- return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
- else /* 0: close */
- return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
- return 1;
-}
-
-static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
- struct s_subqcode *sub, int tries)
-{
- char buf[11];
- int ans;
-
- if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf),
- 2 * HZ, tries)))
- return -1;
- sub->control = buf[1];
- sub->tno = buf[2];
- sub->index = buf[3];
- sub->tt.minute = buf[4];
- sub->tt.second = buf[5];
- sub->tt.frame = buf[6];
- sub->dt.minute = buf[8];
- sub->dt.second = buf[9];
- sub->dt.frame = buf[10];
-
- return ans;
-}
-
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
- struct s_multi *multi, int tries)
-{
- char buf[5];
- int ans;
-
- if (stuffp->present & MULTI) {
- ans =
- mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ,
- tries);
- multi->multi = buf[1];
- multi->msf_last.minute = buf[2];
- multi->msf_last.second = buf[3];
- multi->msf_last.frame = buf[4];
- return ans;
- } else {
- multi->multi = 0;
- return 0;
- }
-}
-
-static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
- int tries)
-{
- char buf[9];
- int ans;
- ans =
- mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);
- if (ans == -1) {
- info->n_first = 0;
- info->n_last = 0;
- } else {
- info->n_first = bcd2uint(buf[1]);
- info->n_last = bcd2uint(buf[2]);
- info->msf_leadout.minute = buf[3];
- info->msf_leadout.second = buf[4];
- info->msf_leadout.frame = buf[5];
- info->msf_first.minute = buf[6];
- info->msf_first.second = buf[7];
- info->msf_first.frame = buf[8];
- }
- return ans;
-}
-
-static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
- int tries)
-{
- char cmd[2];
- int ans;
-
- xtrace(HW, "setdrivemode() %d\n", mode);
-
- if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
- return -1;
-
- switch (mode) {
- case TOC:
- cmd[1] |= 0x04;
- break;
- case DATA:
- cmd[1] &= ~0x04;
- break;
- case RAW:
- cmd[1] |= 0x40;
- break;
- case COOKED:
- cmd[1] &= ~0x40;
- break;
- default:
- break;
- }
- cmd[0] = 0x50;
- return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
- int tries)
-{
- unsigned char cmd[2] = { 0xa0 };
- xtrace(HW, "setdatamode() %d\n", mode);
- switch (mode) {
- case MODE0:
- cmd[1] = 0x00;
- break;
- case MODE1:
- cmd[1] = 0x01;
- break;
- case MODE2:
- cmd[1] = 0x02;
- break;
- default:
- return -EINVAL;
- }
- return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
-{
- char cmd[4];
-
- xtrace(HW, "config()\n");
-
- cmd[0] = 0x90;
-
- cmd[1] = 0x10; /* irq enable */
- cmd[2] = 0x05; /* pre, err irq enable */
-
- if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
- return -1;
-
- cmd[1] = 0x02; /* dma select */
- cmd[2] = 0x00; /* no dma */
-
- return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
-}
-
-static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
- int tries)
-{
- char buf[3];
- int ans;
-
- if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
- 1, buf, sizeof(buf), 2 * HZ, tries)))
- return ans;
-
- ver->code = buf[1];
- ver->ver = buf[2];
-
- return ans;
-}
-
-static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
-{
- if (mode == HARD) {
- outb(0, stuffp->wreg_chn); /* no dma, no irq -> hardware */
- outb(0, stuffp->wreg_reset); /* hw reset */
- return 0;
- } else
- return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
- char cmd[2] = { 0xfe };
-
- if (!(stuffp->present & DOOR))
- return -ENOSYS;
- if (stuffp->present & DOOR) {
- cmd[1] = lock ? 0x01 : 0x00;
- return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
- } else
- return 0;
-}
-
-static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int
-mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
-{
- unsigned long timeout = to + jiffies;
- char c;
-
- if (!buf)
- buf = &c;
-
- while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) {
- if (time_after(jiffies, timeout))
- return -1;
- mcdx_delay(stuffp, delay);
- }
-
- *buf = (unsigned char) inb(stuffp->rreg_data) & 0xff;
-
- return 0;
-}
-
-static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
- struct cdrom_volctrl *vol, int tries)
-{
- char cmd[5];
- cmd[0] = 0xae;
- cmd[1] = vol->channel0;
- cmd[2] = 0;
- cmd[3] = vol->channel1;
- cmd[4] = 0;
-
- return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR);
diff --git a/drivers/cdrom/mcdx.h b/drivers/cdrom/mcdx.h
deleted file mode 100644
index 83c364a74dc4..000000000000
--- a/drivers/cdrom/mcdx.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Definitions for the Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: @VERSION@
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- * The Linux Community at all and ...
- * Martin Harris (he wrote the first Mitsumi Driver)
- * Eberhard Moenkeberg (he gave me much support and the initial kick)
- * Bernd Huebner, Ruediger Helsch (Unifix-Software Gmbh, they
- * improved the original driver)
- * Jon Tombs, Bjorn Ekwall (module support)
- * Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- * Gerd Knorr (he lent me his PhotoCD)
- * Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- * Andreas Kies (testing the mysterious hang up's)
- * ... somebody forgotten?
- * Marcin Dalecki
- *
- */
-
-/*
- * The following lines are for user configuration
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * {0|1} -- 1 if you want the driver detect your drive, may crash and
- * needs a long time to seek. The higher the address the longer the
- * seek.
- *
- * WARNING: AUTOPROBE doesn't work.
- */
-#define MCDX_AUTOPROBE 0
-
-/*
- * Drive specific settings according to the jumpers on the controller
- * board(s).
- * o MCDX_NDRIVES : number of used entries of the following table
- * o MCDX_DRIVEMAP : table of {i/o base, irq} per controller
- *
- * NOTE: I didn't get a drive at irq 9(2) working. Not even alone.
- */
-#if MCDX_AUTOPROBE == 0
- #define MCDX_NDRIVES 1
- #define MCDX_DRIVEMAP { \
- {0x300, 11}, \
- {0x304, 05}, \
- {0x000, 00}, \
- {0x000, 00}, \
- {0x000, 00}, \
- }
-#else
- #error Autoprobing is not implemented yet.
-#endif
-
-#ifndef MCDX_QUIET
-#define MCDX_QUIET 1
-#endif
-
-#ifndef MCDX_DEBUG
-#define MCDX_DEBUG 0
-#endif
-
-/* *** make the following line uncommented, if you're sure,
- * *** all configuration is done */
-/* #define I_WAS_HERE */
-
-/* The name of the device */
-#define MCDX "mcdx"
-
-/* Flags for DEBUGGING */
-#define INIT 0
-#define MALLOC 0
-#define IOCTL 0
-#define PLAYTRK 0
-#define SUBCHNL 0
-#define TOCHDR 0
-#define MS 0
-#define PLAYMSF 0
-#define READTOC 0
-#define OPENCLOSE 0
-#define HW 0
-#define TALK 0
-#define IRQ 0
-#define XFER 0
-#define REQUEST 0
-#define SLEEP 0
-
-/* The following addresses are taken from the Mitsumi Reference
- * and describe the possible i/o range for the controller.
- */
-#define MCDX_IO_BEGIN ((char*) 0x300) /* first base of i/o addr */
-#define MCDX_IO_END ((char*) 0x3fc) /* last base of i/o addr */
-
-/* Per controller 4 bytes i/o are needed. */
-#define MCDX_IO_SIZE 4
-
-/*
- * Bits
- */
-
-/* The status byte, returned from every command, set if
- * the description is true */
-#define MCDX_RBIT_OPEN 0x80 /* door is open */
-#define MCDX_RBIT_DISKSET 0x40 /* disk set (recognised) */
-#define MCDX_RBIT_CHANGED 0x20 /* disk was changed */
-#define MCDX_RBIT_CHECK 0x10 /* disk rotates, servo is on */
-#define MCDX_RBIT_AUDIOTR 0x08 /* current track is audio */
-#define MCDX_RBIT_RDERR 0x04 /* read error, refer SENSE KEY */
-#define MCDX_RBIT_AUDIOBS 0x02 /* currently playing audio */
-#define MCDX_RBIT_CMDERR 0x01 /* command, param or format error */
-
-/* The I/O Register holding the h/w status of the drive,
- * can be read at i/o base + 1 */
-#define MCDX_RBIT_DOOR 0x10 /* door is open */
-#define MCDX_RBIT_STEN 0x04 /* if 0, i/o base contains drive status */
-#define MCDX_RBIT_DTEN 0x02 /* if 0, i/o base contains data */
-
-/*
- * The commands.
- */
-
-#define OPCODE 1 /* offset of opcode */
-#define MCDX_CMD_REQUEST_TOC 1, 0x10
-#define MCDX_CMD_REQUEST_STATUS 1, 0x40
-#define MCDX_CMD_RESET 1, 0x60
-#define MCDX_CMD_REQUEST_DRIVE_MODE 1, 0xc2
-#define MCDX_CMD_SET_INTERLEAVE 2, 0xc8, 0
-#define MCDX_CMD_DATAMODE_SET 2, 0xa0, 0
- #define MCDX_DATAMODE1 0x01
- #define MCDX_DATAMODE2 0x02
-#define MCDX_CMD_LOCK_DOOR 2, 0xfe, 0
-
-#define READ_AHEAD 4 /* 8 Sectors (4K) */
-
-/* Useful macros */
-#define e_door(x) ((x) & MCDX_RBIT_OPEN)
-#define e_check(x) (~(x) & MCDX_RBIT_CHECK)
-#define e_notset(x) (~(x) & MCDX_RBIT_DISKSET)
-#define e_changed(x) ((x) & MCDX_RBIT_CHANGED)
-#define e_audio(x) ((x) & MCDX_RBIT_AUDIOTR)
-#define e_audiobusy(x) ((x) & MCDX_RBIT_AUDIOBS)
-#define e_cmderr(x) ((x) & MCDX_RBIT_CMDERR)
-#define e_readerr(x) ((x) & MCDX_RBIT_RDERR)
-
-/** no drive specific */
-#define MCDX_CDBLK 2048 /* 2048 cooked data each blk */
-
-#define MCDX_DATA_TIMEOUT (HZ/10) /* 0.1 second */
-
-/*
- * Access to the msf array
- */
-#define MSF_MIN 0 /* minute */
-#define MSF_SEC 1 /* second */
-#define MSF_FRM 2 /* frame */
-
-/*
- * Errors
- */
-#define MCDX_E 1 /* unspec error */
-#define MCDX_ST_EOM 0x0100 /* end of media */
-#define MCDX_ST_DRV 0x00ff /* mask to query the drive status */
-
-#ifndef I_WAS_HERE
-#ifndef MODULE
-#warning You have not edited mcdx.h
-#warning Perhaps irq and i/o settings are wrong.
-#endif
-#endif
-
-/* ex:set ts=4 sw=4: */
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
deleted file mode 100644
index 3541690a77d4..000000000000
--- a/drivers/cdrom/optcd.c
+++ /dev/null
@@ -1,2105 +0,0 @@
-/* linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver
- $Id: optcd.c,v 1.11 1997/01/26 07:13:00 davem Exp $
-
- Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
- Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
- by Eberhard Moenkeberg (emoenke@gwdg.de).
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* Revision history
-
-
- 14-5-95 v0.0 Plays sound tracks. No reading of data CDs yet.
- Detection of disk change doesn't work.
- 21-5-95 v0.1 First ALPHA version. CD can be mounted. The
- device major nr is borrowed from the Aztech
- driver. Speed is around 240 kb/s, as measured
- with "time dd if=/dev/cdrom of=/dev/null \
- bs=2048 count=4096".
- 24-6-95 v0.2 Reworked the #defines for the command codes
- and the like, as well as the structure of
- the hardware communication protocol, to
- reflect the "official" documentation, kindly
- supplied by C.K. Tan, Optics Storage Pte. Ltd.
- Also tidied up the state machine somewhat.
- 28-6-95 v0.3 Removed the ISP-16 interface code, as this
- should go into its own driver. The driver now
- has its own major nr.
- Disk change detection now seems to work, too.
- This version became part of the standard
- kernel as of version 1.3.7
- 24-9-95 v0.4 Re-inserted ISP-16 interface code which I
- copied from sjcd.c, with a few changes.
- Updated README.optcd. Submitted for
- inclusion in 1.3.21
- 29-9-95 v0.4a Fixed bug that prevented compilation as module
- 25-10-95 v0.5 Started multisession code. Implementation
- copied from Werner Zimmermann, who copied it
- from Heiko Schlittermann's mcdx.
- 17-1-96 v0.6 Multisession works; some cleanup too.
- 18-4-96 v0.7 Increased some timing constants;
- thanks to Luke McFarlane. Also tidied up some
- printk behaviour. ISP16 initialization
- is now handled by a separate driver.
-
- 09-11-99 Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-*/
-
-/* Includes */
-
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <linux/blkdev.h>
-
-#include <linux/cdrom.h>
-#include "optcd.h"
-
-#include <asm/uaccess.h>
-
-#define MAJOR_NR OPTICS_CDROM_MAJOR
-#define QUEUE (opt_queue)
-#define CURRENT elv_next_request(opt_queue)
-
-
-/* Debug support */
-
-
-/* Don't forget to add new debug flags here. */
-#if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
- DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
-#define DEBUG(x) debug x
-static void debug(int debug_this, const char* fmt, ...)
-{
- char s[1024];
- va_list args;
-
- if (!debug_this)
- return;
-
- va_start(args, fmt);
- vsnprintf(s, sizeof(s), fmt, args);
- printk(KERN_DEBUG "optcd: %s\n", s);
- va_end(args);
-}
-#else
-#define DEBUG(x)
-#endif
-
-
-/* Drive hardware/firmware characteristics
- Identifiers in accordance with Optics Storage documentation */
-
-
-#define optcd_port optcd /* Needed for the modutils. */
-static short optcd_port = OPTCD_PORTBASE; /* I/O base of drive. */
-module_param(optcd_port, short, 0);
-/* Drive registers, read */
-#define DATA_PORT optcd_port /* Read data/status */
-#define STATUS_PORT optcd_port+1 /* Indicate data/status availability */
-
-/* Drive registers, write */
-#define COMIN_PORT optcd_port /* For passing command/parameter */
-#define RESET_PORT optcd_port+1 /* Write anything and wait 0.5 sec */
-#define HCON_PORT optcd_port+2 /* Host Xfer Configuration */
-
-
-/* Command completion/status read from DATA register */
-#define ST_DRVERR 0x80
-#define ST_DOOR_OPEN 0x40
-#define ST_MIXEDMODE_DISK 0x20
-#define ST_MODE_BITS 0x1c
-#define ST_M_STOP 0x00
-#define ST_M_READ 0x04
-#define ST_M_AUDIO 0x04
-#define ST_M_PAUSE 0x08
-#define ST_M_INITIAL 0x0c
-#define ST_M_ERROR 0x10
-#define ST_M_OTHERS 0x14
-#define ST_MODE2TRACK 0x02
-#define ST_DSK_CHG 0x01
-#define ST_L_LOCK 0x01
-#define ST_CMD_OK 0x00
-#define ST_OP_OK 0x01
-#define ST_PA_OK 0x02
-#define ST_OP_ERROR 0x05
-#define ST_PA_ERROR 0x06
-
-
-/* Error codes (appear as command completion code from DATA register) */
-/* Player related errors */
-#define ERR_ILLCMD 0x11 /* Illegal command to player module */
-#define ERR_ILLPARM 0x12 /* Illegal parameter to player module */
-#define ERR_SLEDGE 0x13
-#define ERR_FOCUS 0x14
-#define ERR_MOTOR 0x15
-#define ERR_RADIAL 0x16
-#define ERR_PLL 0x17 /* PLL lock error */
-#define ERR_SUB_TIM 0x18 /* Subcode timeout error */
-#define ERR_SUB_NF 0x19 /* Subcode not found error */
-#define ERR_TRAY 0x1a
-#define ERR_TOC 0x1b /* Table of Contents read error */
-#define ERR_JUMP 0x1c
-/* Data errors */
-#define ERR_MODE 0x21
-#define ERR_FORM 0x22
-#define ERR_HEADADDR 0x23 /* Header Address not found */
-#define ERR_CRC 0x24
-#define ERR_ECC 0x25 /* Uncorrectable ECC error */
-#define ERR_CRC_UNC 0x26 /* CRC error and uncorrectable error */
-#define ERR_ILLBSYNC 0x27 /* Illegal block sync error */
-#define ERR_VDST 0x28 /* VDST not found */
-/* Timeout errors */
-#define ERR_READ_TIM 0x31 /* Read timeout error */
-#define ERR_DEC_STP 0x32 /* Decoder stopped */
-#define ERR_DEC_TIM 0x33 /* Decoder interrupt timeout error */
-/* Function abort codes */
-#define ERR_KEY 0x41 /* Key -Detected abort */
-#define ERR_READ_FINISH 0x42 /* Read Finish */
-/* Second Byte diagnostic codes */
-#define ERR_NOBSYNC 0x01 /* No block sync */
-#define ERR_SHORTB 0x02 /* Short block */
-#define ERR_LONGB 0x03 /* Long block */
-#define ERR_SHORTDSP 0x04 /* Short DSP word */
-#define ERR_LONGDSP 0x05 /* Long DSP word */
-
-
-/* Status availability flags read from STATUS register */
-#define FL_EJECT 0x20
-#define FL_WAIT 0x10 /* active low */
-#define FL_EOP 0x08 /* active low */
-#define FL_STEN 0x04 /* Status available when low */
-#define FL_DTEN 0x02 /* Data available when low */
-#define FL_DRQ 0x01 /* active low */
-#define FL_RESET 0xde /* These bits are high after a reset */
-#define FL_STDT (FL_STEN|FL_DTEN)
-
-
-/* Transfer mode, written to HCON register */
-#define HCON_DTS 0x08
-#define HCON_SDRQB 0x04
-#define HCON_LOHI 0x02
-#define HCON_DMA16 0x01
-
-
-/* Drive command set, written to COMIN register */
-/* Quick response commands */
-#define COMDRVST 0x20 /* Drive Status Read */
-#define COMERRST 0x21 /* Error Status Read */
-#define COMIOCTLISTAT 0x22 /* Status Read; reset disk changed bit */
-#define COMINITSINGLE 0x28 /* Initialize Single Speed */
-#define COMINITDOUBLE 0x29 /* Initialize Double Speed */
-#define COMUNLOCK 0x30 /* Unlock */
-#define COMLOCK 0x31 /* Lock */
-#define COMLOCKST 0x32 /* Lock/Unlock Status */
-#define COMVERSION 0x40 /* Get Firmware Revision */
-#define COMVOIDREADMODE 0x50 /* Void Data Read Mode */
-/* Read commands */
-#define COMFETCH 0x60 /* Prefetch Data */
-#define COMREAD 0x61 /* Read */
-#define COMREADRAW 0x62 /* Read Raw Data */
-#define COMREADALL 0x63 /* Read All 2646 Bytes */
-/* Player control commands */
-#define COMLEADIN 0x70 /* Seek To Lead-in */
-#define COMSEEK 0x71 /* Seek */
-#define COMPAUSEON 0x80 /* Pause On */
-#define COMPAUSEOFF 0x81 /* Pause Off */
-#define COMSTOP 0x82 /* Stop */
-#define COMOPEN 0x90 /* Open Tray Door */
-#define COMCLOSE 0x91 /* Close Tray Door */
-#define COMPLAY 0xa0 /* Audio Play */
-#define COMPLAY_TNO 0xa2 /* Audio Play By Track Number */
-#define COMSUBQ 0xb0 /* Read Sub-q Code */
-#define COMLOCATION 0xb1 /* Read Head Position */
-/* Audio control commands */
-#define COMCHCTRL 0xc0 /* Audio Channel Control */
-/* Miscellaneous (test) commands */
-#define COMDRVTEST 0xd0 /* Write Test Bytes */
-#define COMTEST 0xd1 /* Diagnostic Test */
-
-/* Low level drive interface. Only here we do actual I/O
- Waiting for status / data available */
-
-
-/* Busy wait until FLAG goes low. Return 0 on timeout. */
-static inline int flag_low(int flag, unsigned long timeout)
-{
- int flag_high;
- unsigned long count = 0;
-
- while ((flag_high = (inb(STATUS_PORT) & flag)))
- if (++count >= timeout)
- break;
-
- DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
- flag, count, flag_high ? " timeout" : ""));
- return !flag_high;
-}
-
-
-/* Timed waiting for status or data */
-static int sleep_timeout; /* max # of ticks to sleep */
-static DECLARE_WAIT_QUEUE_HEAD(waitq);
-static void sleep_timer(unsigned long data);
-static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
-static DEFINE_SPINLOCK(optcd_lock);
-static struct request_queue *opt_queue;
-
-/* Timer routine: wake up when desired flag goes low,
- or when timeout expires. */
-static void sleep_timer(unsigned long data)
-{
- int flags = inb(STATUS_PORT) & FL_STDT;
-
- if (flags == FL_STDT && --sleep_timeout > 0) {
- mod_timer(&delay_timer, jiffies + HZ/100); /* multi-statement macro */
- } else
- wake_up(&waitq);
-}
-
-
-/* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */
-static int sleep_flag_low(int flag, unsigned long timeout)
-{
- int flag_high;
-
- DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
-
- sleep_timeout = timeout;
- flag_high = inb(STATUS_PORT) & flag;
- if (flag_high && sleep_timeout > 0) {
- mod_timer(&delay_timer, jiffies + HZ/100);
- sleep_on(&waitq);
- flag_high = inb(STATUS_PORT) & flag;
- }
-
- DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
- flag, timeout, flag_high ? " timeout" : ""));
- return !flag_high;
-}
-
-/* Low level drive interface. Only here we do actual I/O
- Sending commands and parameters */
-
-
-/* Errors in the command protocol */
-#define ERR_IF_CMD_TIMEOUT 0x100
-#define ERR_IF_ERR_TIMEOUT 0x101
-#define ERR_IF_RESP_TIMEOUT 0x102
-#define ERR_IF_DATA_TIMEOUT 0x103
-#define ERR_IF_NOSTAT 0x104
-
-
-/* Send command code. Return <0 indicates error */
-static int send_cmd(int cmd)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
-
- outb(HCON_DTS, HCON_PORT); /* Enable Suspend Data Transfer */
- outb(cmd, COMIN_PORT); /* Send command code */
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */
- return ack==ST_OP_OK ? 0 : -ack;
-}
-
-
-/* Send command parameters. Return <0 indicates error */
-static int send_params(struct cdrom_msf *params)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending parameters"
- " %02x:%02x:%02x"
- " %02x:%02x:%02x",
- params->cdmsf_min0,
- params->cdmsf_sec0,
- params->cdmsf_frame0,
- params->cdmsf_min1,
- params->cdmsf_sec1,
- params->cdmsf_frame1));
-
- outb(params->cdmsf_min0, COMIN_PORT);
- outb(params->cdmsf_sec0, COMIN_PORT);
- outb(params->cdmsf_frame0, COMIN_PORT);
- outb(params->cdmsf_min1, COMIN_PORT);
- outb(params->cdmsf_sec1, COMIN_PORT);
- outb(params->cdmsf_frame1, COMIN_PORT);
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Send parameters for SEEK command. Return <0 indicates error */
-static int send_seek_params(struct cdrom_msf *params)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
- " %02x:%02x:%02x",
- params->cdmsf_min0,
- params->cdmsf_sec0,
- params->cdmsf_frame0));
-
- outb(params->cdmsf_min0, COMIN_PORT);
- outb(params->cdmsf_sec0, COMIN_PORT);
- outb(params->cdmsf_frame0, COMIN_PORT);
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Wait for command execution status. Choice between busy waiting
- and sleeping. Return value <0 indicates timeout. */
-static inline int get_exec_status(int busy_waiting)
-{
- unsigned char exec_status;
-
- if (busy_waiting
- ? !flag_low(FL_STEN, BUSY_TIMEOUT)
- : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
- return -ERR_IF_CMD_TIMEOUT;
-
- exec_status = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
- return exec_status;
-}
-
-
-/* Wait busy for extra byte of data that a command returns.
- Return value <0 indicates timeout. */
-static inline int get_data(int short_timeout)
-{
- unsigned char data;
-
- if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
- return -ERR_IF_DATA_TIMEOUT;
-
- data = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
- return data;
-}
-
-
-/* Returns 0 if failed */
-static int reset_drive(void)
-{
- unsigned long count = 0;
- int flags;
-
- DEBUG((DEBUG_DRIVE_IF, "reset drive"));
-
- outb(0, RESET_PORT);
- while (++count < RESET_WAIT)
- inb(DATA_PORT);
-
- count = 0;
- while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
- if (++count >= BUSY_TIMEOUT)
- break;
-
- DEBUG((DEBUG_DRIVE_IF, "reset %s",
- flags == FL_RESET ? "succeeded" : "failed"));
-
- if (flags != FL_RESET)
- return 0; /* Reset failed */
- outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */
- return 1; /* Reset succeeded */
-}
-
-
-/* Facilities for asynchronous operation */
-
-/* Read status/data availability flags FL_STEN and FL_DTEN */
-static inline int stdt_flags(void)
-{
- return inb(STATUS_PORT) & FL_STDT;
-}
-
-
-/* Fetch status that has previously been waited for. <0 means not available */
-static inline int fetch_status(void)
-{
- unsigned char status;
-
- if (inb(STATUS_PORT) & FL_STEN)
- return -ERR_IF_NOSTAT;
-
- status = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
- return status;
-}
-
-
-/* Fetch data that has previously been waited for. */
-static inline void fetch_data(char *buf, int n)
-{
- insb(DATA_PORT, buf, n);
- DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
-}
-
-
-/* Flush status and data fifos */
-static inline void flush_data(void)
-{
- while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
- inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
-}
-
-/* Command protocol */
-
-
-/* Send a simple command and wait for response. Command codes < COMFETCH
- are quick response commands */
-static inline int exec_cmd(int cmd)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- return get_exec_status(cmd < COMFETCH);
-}
-
-
-/* Send a command with parameters. Don't wait for the response,
- * which consists of data blocks read from the CD. */
-static inline int exec_read_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- return send_params(params);
-}
-
-
-/* Send a seek command with parameters and wait for response */
-static inline int exec_seek_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- ack = send_seek_params(params);
- if (ack < 0)
- return ack;
- return 0;
-}
-
-
-/* Send a command with parameters and wait for response */
-static inline int exec_long_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = exec_read_cmd(cmd, params);
- if (ack < 0)
- return ack;
- return get_exec_status(0);
-}
-
-/* Address conversion routines */
-
-
-/* Binary to BCD (2 digits) */
-static inline void single_bin2bcd(u_char *p)
-{
- DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
- *p = (*p % 10) | ((*p / 10) << 4);
-}
-
-
-/* Convert entire msf struct */
-static void bin2bcd(struct cdrom_msf *msf)
-{
- single_bin2bcd(&msf->cdmsf_min0);
- single_bin2bcd(&msf->cdmsf_sec0);
- single_bin2bcd(&msf->cdmsf_frame0);
- single_bin2bcd(&msf->cdmsf_min1);
- single_bin2bcd(&msf->cdmsf_sec1);
- single_bin2bcd(&msf->cdmsf_frame1);
-}
-
-
-/* Linear block address to minute, second, frame form */
-#define CD_FPM (CD_SECS * CD_FRAMES) /* frames per minute */
-
-static void lba2msf(int lba, struct cdrom_msf *msf)
-{
- DEBUG((DEBUG_CONV, "lba2msf %d", lba));
- lba += CD_MSF_OFFSET;
- msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM;
- msf->cdmsf_sec0 = lba / CD_FRAMES;
- msf->cdmsf_frame0 = lba % CD_FRAMES;
- msf->cdmsf_min1 = 0;
- msf->cdmsf_sec1 = 0;
- msf->cdmsf_frame1 = 0;
- bin2bcd(msf);
-}
-
-
-/* Two BCD digits to binary */
-static inline u_char bcd2bin(u_char bcd)
-{
- DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
- return (bcd >> 4) * 10 + (bcd & 0x0f);
-}
-
-
-static void msf2lba(union cdrom_addr *addr)
-{
- addr->lba = addr->msf.minute * CD_FPM
- + addr->msf.second * CD_FRAMES
- + addr->msf.frame - CD_MSF_OFFSET;
-}
-
-
-/* Minute, second, frame address BCD to binary or to linear address,
- depending on MODE */
-static void msf_bcd2bin(union cdrom_addr *addr)
-{
- addr->msf.minute = bcd2bin(addr->msf.minute);
- addr->msf.second = bcd2bin(addr->msf.second);
- addr->msf.frame = bcd2bin(addr->msf.frame);
-}
-
-/* High level drive commands */
-
-
-static int audio_status = CDROM_AUDIO_NO_STATUS;
-static char toc_uptodate = 0;
-static char disk_changed = 1;
-
-/* Get drive status, flagging completion of audio play and disk changes. */
-static int drive_status(void)
-{
- int status;
-
- status = exec_cmd(COMIOCTLISTAT);
- DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
- if (status < 0)
- return status;
- if (status == 0xff) /* No status available */
- return -ERR_IF_NOSTAT;
-
- if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
- (audio_status == CDROM_AUDIO_PLAY)) {
- audio_status = CDROM_AUDIO_COMPLETED;
- }
-
- if (status & ST_DSK_CHG) {
- toc_uptodate = 0;
- disk_changed = 1;
- audio_status = CDROM_AUDIO_NO_STATUS;
- }
-
- return status;
-}
-
-
-/* Read the current Q-channel info. Also used for reading the
- table of contents. qp->cdsc_format must be set on entry to
- indicate the desired address format */
-static int get_q_channel(struct cdrom_subchnl *qp)
-{
- int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
-
- status = drive_status();
- if (status < 0)
- return status;
- qp->cdsc_audiostatus = audio_status;
-
- status = exec_cmd(COMSUBQ);
- if (status < 0)
- return status;
-
- d1 = get_data(0);
- if (d1 < 0)
- return d1;
- qp->cdsc_adr = d1;
- qp->cdsc_ctrl = d1 >> 4;
-
- d2 = get_data(0);
- if (d2 < 0)
- return d2;
- qp->cdsc_trk = bcd2bin(d2);
-
- d3 = get_data(0);
- if (d3 < 0)
- return d3;
- qp->cdsc_ind = bcd2bin(d3);
-
- d4 = get_data(0);
- if (d4 < 0)
- return d4;
- qp->cdsc_reladdr.msf.minute = d4;
-
- d5 = get_data(0);
- if (d5 < 0)
- return d5;
- qp->cdsc_reladdr.msf.second = d5;
-
- d6 = get_data(0);
- if (d6 < 0)
- return d6;
- qp->cdsc_reladdr.msf.frame = d6;
-
- d7 = get_data(0);
- if (d7 < 0)
- return d7;
- /* byte not used */
-
- d8 = get_data(0);
- if (d8 < 0)
- return d8;
- qp->cdsc_absaddr.msf.minute = d8;
-
- d9 = get_data(0);
- if (d9 < 0)
- return d9;
- qp->cdsc_absaddr.msf.second = d9;
-
- d10 = get_data(0);
- if (d10 < 0)
- return d10;
- qp->cdsc_absaddr.msf.frame = d10;
-
- DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
- d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
-
- msf_bcd2bin(&qp->cdsc_absaddr);
- msf_bcd2bin(&qp->cdsc_reladdr);
- if (qp->cdsc_format == CDROM_LBA) {
- msf2lba(&qp->cdsc_absaddr);
- msf2lba(&qp->cdsc_reladdr);
- }
-
- return 0;
-}
-
-/* Table of contents handling */
-
-
-/* Errors in table of contents */
-#define ERR_TOC_MISSINGINFO 0x120
-#define ERR_TOC_MISSINGENTRY 0x121
-
-
-struct cdrom_disk_info {
- unsigned char first;
- unsigned char last;
- struct cdrom_msf0 disk_length;
- struct cdrom_msf0 first_track;
- /* Multisession info: */
- unsigned char next;
- struct cdrom_msf0 next_session;
- struct cdrom_msf0 last_session;
- unsigned char multi;
- unsigned char xa;
- unsigned char audio;
-};
-static struct cdrom_disk_info disk_info;
-
-#define MAX_TRACKS 111
-static struct cdrom_subchnl toc[MAX_TRACKS];
-
-#define QINFO_FIRSTTRACK 100 /* bcd2bin(0xa0) */
-#define QINFO_LASTTRACK 101 /* bcd2bin(0xa1) */
-#define QINFO_DISKLENGTH 102 /* bcd2bin(0xa2) */
-#define QINFO_NEXTSESSION 110 /* bcd2bin(0xb0) */
-
-#define I_FIRSTTRACK 0x01
-#define I_LASTTRACK 0x02
-#define I_DISKLENGTH 0x04
-#define I_NEXTSESSION 0x08
-#define I_ALL (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
-
-
-#if DEBUG_TOC
-static void toc_debug_info(int i)
-{
- printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d"
- " %2d:%02d.%02d %2d:%02d.%02d\n",
- i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
- toc[i].cdsc_trk, toc[i].cdsc_ind,
- toc[i].cdsc_reladdr.msf.minute,
- toc[i].cdsc_reladdr.msf.second,
- toc[i].cdsc_reladdr.msf.frame,
- toc[i].cdsc_absaddr.msf.minute,
- toc[i].cdsc_absaddr.msf.second,
- toc[i].cdsc_absaddr.msf.frame);
-}
-#endif
-
-
-static int read_toc(void)
-{
- int status, limit, count;
- unsigned char got_info = 0;
- struct cdrom_subchnl q_info;
-#if DEBUG_TOC
- int i;
-#endif
-
- DEBUG((DEBUG_TOC, "starting read_toc"));
-
- count = 0;
- for (limit = 60; limit > 0; limit--) {
- int index;
-
- q_info.cdsc_format = CDROM_MSF;
- status = get_q_channel(&q_info);
- if (status < 0)
- return status;
-
- index = q_info.cdsc_ind;
- if (index > 0 && index < MAX_TRACKS
- && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
- toc[index] = q_info;
- DEBUG((DEBUG_TOC, "got %d", index));
- if (index < 100)
- count++;
-
- switch (q_info.cdsc_ind) {
- case QINFO_FIRSTTRACK:
- got_info |= I_FIRSTTRACK;
- break;
- case QINFO_LASTTRACK:
- got_info |= I_LASTTRACK;
- break;
- case QINFO_DISKLENGTH:
- got_info |= I_DISKLENGTH;
- break;
- case QINFO_NEXTSESSION:
- got_info |= I_NEXTSESSION;
- break;
- }
- }
-
- if ((got_info & I_ALL) == I_ALL
- && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
- >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
- break;
- }
-
- /* Construct disk_info from TOC */
- if (disk_info.first == 0) {
- disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
- disk_info.first_track.minute =
- toc[disk_info.first].cdsc_absaddr.msf.minute;
- disk_info.first_track.second =
- toc[disk_info.first].cdsc_absaddr.msf.second;
- disk_info.first_track.frame =
- toc[disk_info.first].cdsc_absaddr.msf.frame;
- }
- disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
- disk_info.disk_length.minute =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
- disk_info.disk_length.second =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
- disk_info.disk_length.frame =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
- disk_info.next_session.minute =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
- disk_info.next_session.second =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
- disk_info.next_session.frame =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
- disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
- disk_info.last_session.minute =
- toc[disk_info.next].cdsc_absaddr.msf.minute;
- disk_info.last_session.second =
- toc[disk_info.next].cdsc_absaddr.msf.second;
- disk_info.last_session.frame =
- toc[disk_info.next].cdsc_absaddr.msf.frame;
- toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
- disk_info.disk_length.minute;
- toc[disk_info.last + 1].cdsc_absaddr.msf.second =
- disk_info.disk_length.second;
- toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
- disk_info.disk_length.frame;
-#if DEBUG_TOC
- for (i = 1; i <= disk_info.last + 1; i++)
- toc_debug_info(i);
- toc_debug_info(QINFO_FIRSTTRACK);
- toc_debug_info(QINFO_LASTTRACK);
- toc_debug_info(QINFO_DISKLENGTH);
- toc_debug_info(QINFO_NEXTSESSION);
-#endif
-
- DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
- got_info, count));
- if ((got_info & I_ALL) != I_ALL
- || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
- < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
- return -ERR_TOC_MISSINGINFO;
- return 0;
-}
-
-
-#ifdef MULTISESSION
-static int get_multi_disk_info(void)
-{
- int sessions, status;
- struct cdrom_msf multi_index;
-
-
- for (sessions = 2; sessions < 10 /* %%for now */; sessions++) {
- int count;
-
- for (count = 100; count < MAX_TRACKS; count++)
- toc[count].cdsc_ind = 0;
-
- multi_index.cdmsf_min0 = disk_info.next_session.minute;
- multi_index.cdmsf_sec0 = disk_info.next_session.second;
- multi_index.cdmsf_frame0 = disk_info.next_session.frame;
- if (multi_index.cdmsf_sec0 >= 20)
- multi_index.cdmsf_sec0 -= 20;
- else {
- multi_index.cdmsf_sec0 += 40;
- multi_index.cdmsf_min0--;
- }
- DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
- multi_index.cdmsf_min0,
- multi_index.cdmsf_sec0,
- multi_index.cdmsf_frame0));
- bin2bcd(&multi_index);
- multi_index.cdmsf_min1 = 0;
- multi_index.cdmsf_sec1 = 0;
- multi_index.cdmsf_frame1 = 1;
-
- status = exec_read_cmd(COMREAD, &multi_index);
- if (status < 0) {
- DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
- -status));
- break;
- }
- status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
- 0 : -ERR_TOC_MISSINGINFO;
- flush_data();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
- break;
- }
-
- status = read_toc();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
- break;
- }
-
- disk_info.multi = 1;
- }
-
- exec_cmd(COMSTOP);
-
- if (status < 0)
- return -EIO;
- return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int update_toc(void)
-{
- int status, count;
-
- if (toc_uptodate)
- return 0;
-
- DEBUG((DEBUG_TOC, "starting update_toc"));
-
- disk_info.first = 0;
- for (count = 0; count < MAX_TRACKS; count++)
- toc[count].cdsc_ind = 0;
-
- status = exec_cmd(COMLEADIN);
- if (status < 0)
- return -EIO;
-
- status = read_toc();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
- return -EIO;
- }
-
- /* Audio disk detection. Look at first track. */
- disk_info.audio =
- (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
-
- /* XA detection */
- disk_info.xa = drive_status() & ST_MODE2TRACK;
-
- /* Multisession detection: if we want this, define MULTISESSION */
- disk_info.multi = 0;
-#ifdef MULTISESSION
- if (disk_info.xa)
- get_multi_disk_info(); /* Here disk_info.multi is set */
-#endif /* MULTISESSION */
- if (disk_info.multi)
- printk(KERN_WARNING "optcd: Multisession support experimental, "
- "see Documentation/cdrom/optcd\n");
-
- DEBUG((DEBUG_TOC, "exiting update_toc"));
-
- toc_uptodate = 1;
- return 0;
-}
-
-/* Request handling */
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-/* Buffers for block size conversion. */
-#define NOBUF -1
-
-static char buf[CD_FRAMESIZE * N_BUFS];
-static volatile int buf_bn[N_BUFS], next_bn;
-static volatile int buf_in = 0, buf_out = NOBUF;
-
-static inline void opt_invalidate_buffers(void)
-{
- int i;
-
- DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
-
- for (i = 0; i < N_BUFS; i++)
- buf_bn[i] = NOBUF;
- buf_out = NOBUF;
-}
-
-
-/* Take care of the different block sizes between cdrom and Linux.
- When Linux gets variable block sizes this will probably go away. */
-static void transfer(void)
-{
-#if DEBUG_BUFFERS | DEBUG_REQUEST
- printk(KERN_DEBUG "optcd: executing transfer\n");
-#endif
-
- if (!current_valid())
- return;
- while (CURRENT -> nr_sectors) {
- int bn = CURRENT -> sector / 4;
- int i, offs, nr_sectors;
- for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
-
- DEBUG((DEBUG_REQUEST, "found %d", i));
-
- if (i >= N_BUFS) {
- buf_out = NOBUF;
- break;
- }
-
- offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
- nr_sectors = 4 - (CURRENT -> sector & 3);
-
- if (buf_out != i) {
- buf_out = i;
- if (buf_bn[i] != bn) {
- buf_out = NOBUF;
- continue;
- }
- }
-
- if (nr_sectors > CURRENT -> nr_sectors)
- nr_sectors = CURRENT -> nr_sectors;
- memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
- CURRENT -> nr_sectors -= nr_sectors;
- CURRENT -> sector += nr_sectors;
- CURRENT -> buffer += nr_sectors * 512;
- }
-}
-
-
-/* State machine for reading disk blocks */
-
-enum state_e {
- S_IDLE, /* 0 */
- S_START, /* 1 */
- S_READ, /* 2 */
- S_DATA, /* 3 */
- S_STOP, /* 4 */
- S_STOPPING /* 5 */
-};
-
-static volatile enum state_e state = S_IDLE;
-#if DEBUG_STATE
-static volatile enum state_e state_old = S_STOP;
-static volatile int flags_old = 0;
-static volatile long state_n = 0;
-#endif
-
-
-/* Used as mutex to keep do_optcd_request (and other processes calling
- ioctl) out while some process is inside a VFS call.
- Reverse is accomplished by checking if state = S_IDLE upon entry
- of opt_ioctl and opt_media_change. */
-static int in_vfs = 0;
-
-
-static volatile int transfer_is_active = 0;
-static volatile int error = 0; /* %% do something with this?? */
-static int tries; /* ibid?? */
-static int timeout = 0;
-
-static void poll(unsigned long data);
-static struct timer_list req_timer = {.function = poll};
-
-
-static void poll(unsigned long data)
-{
- static volatile int read_count = 1;
- int flags;
- int loop_again = 1;
- int status = 0;
- int skip = 0;
-
- if (error) {
- printk(KERN_ERR "optcd: I/O error 0x%02x\n", error);
- opt_invalidate_buffers();
- if (!tries--) {
- printk(KERN_ERR "optcd: read block %d failed;"
- " Giving up\n", next_bn);
- if (transfer_is_active)
- loop_again = 0;
- if (current_valid())
- end_request(CURRENT, 0);
- tries = 5;
- }
- error = 0;
- state = S_STOP;
- }
-
- while (loop_again)
- {
- loop_again = 0; /* each case must flip this back to 1 if we want
- to come back up here */
-
-#if DEBUG_STATE
- if (state == state_old)
- state_n++;
- else {
- state_old = state;
- if (++state_n > 1)
- printk(KERN_DEBUG "optcd: %ld times "
- "in previous state\n", state_n);
- printk(KERN_DEBUG "optcd: state %d\n", state);
- state_n = 0;
- }
-#endif
-
- switch (state) {
- case S_IDLE:
- return;
- case S_START:
- if (in_vfs)
- break;
- if (send_cmd(COMDRVST)) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- state = S_READ;
- timeout = READ_TIMEOUT;
- break;
- case S_READ: {
- struct cdrom_msf msf;
- if (!skip) {
- status = fetch_status();
- if (status < 0)
- break;
- if (status & ST_DSK_CHG) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- }
- }
- skip = 0;
- if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- printk(KERN_WARNING "optcd: %s\n",
- (status & ST_DOOR_OPEN)
- ? "door open"
- : "disk removed");
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- if (!current_valid()) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- next_bn = CURRENT -> sector / 4;
- lba2msf(next_bn, &msf);
- read_count = N_BUFS;
- msf.cdmsf_frame1 = read_count; /* Not BCD! */
-
- DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
- msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0,
- msf.cdmsf_min1,
- msf.cdmsf_sec1,
- msf.cdmsf_frame1));
- DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
- " buf_out:%d buf_bn:%d",
- next_bn,
- buf_in,
- buf_out,
- buf_bn[buf_in]));
-
- exec_read_cmd(COMREAD, &msf);
- state = S_DATA;
- timeout = READ_TIMEOUT;
- break;
- }
- case S_DATA:
- flags = stdt_flags() & (FL_STEN|FL_DTEN);
-
-#if DEBUG_STATE
- if (flags != flags_old) {
- flags_old = flags;
- printk(KERN_DEBUG "optcd: flags:%x\n", flags);
- }
- if (flags == FL_STEN)
- printk(KERN_DEBUG "timeout cnt: %d\n", timeout);
-#endif
-
- switch (flags) {
- case FL_DTEN: /* only STEN low */
- if (!tries--) {
- printk(KERN_ERR
- "optcd: read block %d failed; "
- "Giving up\n", next_bn);
- if (transfer_is_active) {
- tries = 0;
- break;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- tries = 5;
- }
- state = S_START;
- timeout = READ_TIMEOUT;
- loop_again = 1;
- case (FL_STEN|FL_DTEN): /* both high */
- break;
- default: /* DTEN low */
- tries = 5;
- if (!current_valid() && buf_in == buf_out) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- if (read_count<=0)
- printk(KERN_WARNING
- "optcd: warning - try to read"
- " 0 frames\n");
- while (read_count) {
- buf_bn[buf_in] = NOBUF;
- if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
- /* should be no waiting here!?? */
- printk(KERN_ERR
- "read_count:%d "
- "CURRENT->nr_sectors:%ld "
- "buf_in:%d\n",
- read_count,
- CURRENT->nr_sectors,
- buf_in);
- printk(KERN_ERR
- "transfer active: %x\n",
- transfer_is_active);
- read_count = 0;
- state = S_STOP;
- loop_again = 1;
- end_request(CURRENT, 0);
- break;
- }
- fetch_data(buf+
- CD_FRAMESIZE*buf_in,
- CD_FRAMESIZE);
- read_count--;
-
- DEBUG((DEBUG_REQUEST,
- "S_DATA; ---I've read data- "
- "read_count: %d",
- read_count));
- DEBUG((DEBUG_REQUEST,
- "next_bn:%d buf_in:%d "
- "buf_out:%d buf_bn:%d",
- next_bn,
- buf_in,
- buf_out,
- buf_bn[buf_in]));
-
- buf_bn[buf_in] = next_bn++;
- if (buf_out == NOBUF)
- buf_out = buf_in;
- buf_in = buf_in + 1 ==
- N_BUFS ? 0 : buf_in + 1;
- }
- if (!transfer_is_active) {
- while (current_valid()) {
- transfer();
- if (CURRENT -> nr_sectors == 0)
- end_request(CURRENT, 1);
- else
- break;
- }
- }
-
- if (current_valid()
- && (CURRENT -> sector / 4 < next_bn ||
- CURRENT -> sector / 4 >
- next_bn + N_BUFS)) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- timeout = READ_TIMEOUT;
- if (read_count == 0) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- }
- break;
- case S_STOP:
- if (read_count != 0)
- printk(KERN_ERR
- "optcd: discard data=%x frames\n",
- read_count);
- flush_data();
- if (send_cmd(COMDRVST)) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- state = S_STOPPING;
- timeout = STOP_TIMEOUT;
- break;
- case S_STOPPING:
- status = fetch_status();
- if (status < 0 && timeout)
- break;
- if ((status >= 0) && (status & ST_DSK_CHG)) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- }
- if (current_valid()) {
- if (status >= 0) {
- state = S_READ;
- loop_again = 1;
- skip = 1;
- break;
- } else {
- state = S_START;
- timeout = 1;
- }
- } else {
- state = S_IDLE;
- return;
- }
- break;
- default:
- printk(KERN_ERR "optcd: invalid state %d\n", state);
- return;
- } /* case */
- } /* while */
-
- if (!timeout--) {
- printk(KERN_ERR "optcd: timeout in state %d\n", state);
- state = S_STOP;
- if (exec_cmd(COMSTOP) < 0) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- }
-
- mod_timer(&req_timer, jiffies + HZ/100);
-}
-
-
-static void do_optcd_request(request_queue_t * q)
-{
- DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
- CURRENT -> sector, CURRENT -> nr_sectors));
-
- if (disk_info.audio) {
- printk(KERN_WARNING "optcd: tried to mount an Audio CD\n");
- end_request(CURRENT, 0);
- return;
- }
-
- transfer_is_active = 1;
- while (current_valid()) {
- transfer(); /* First try to transfer block from buffers */
- if (CURRENT -> nr_sectors == 0) {
- end_request(CURRENT, 1);
- } else { /* Want to read a block not in buffer */
- buf_out = NOBUF;
- if (state == S_IDLE) {
- /* %% Should this block the request queue?? */
- if (update_toc() < 0) {
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- /* Start state machine */
- state = S_START;
- timeout = READ_TIMEOUT;
- tries = 5;
- /* %% why not start right away?? */
- mod_timer(&req_timer, jiffies + HZ/100);
- }
- break;
- }
- }
- transfer_is_active = 0;
-
- DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d buf_out:%d buf_bn:%d",
- next_bn, buf_in, buf_out, buf_bn[buf_in]));
- DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
-}
-
-/* IOCTLs */
-
-
-static char auto_eject = 0;
-
-static int cdrompause(void)
-{
- int status;
-
- if (audio_status != CDROM_AUDIO_PLAY)
- return -EINVAL;
-
- status = exec_cmd(COMPAUSEON);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
- return -EIO;
- }
- audio_status = CDROM_AUDIO_PAUSED;
- return 0;
-}
-
-
-static int cdromresume(void)
-{
- int status;
-
- if (audio_status != CDROM_AUDIO_PAUSED)
- return -EINVAL;
-
- status = exec_cmd(COMPAUSEOFF);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromplaymsf(void __user *arg)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- status = exec_long_cmd(COMPLAY, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromplaytrkind(void __user *arg)
-{
- int status;
- struct cdrom_ti ti;
- struct cdrom_msf msf;
-
- if (copy_from_user(&ti, arg, sizeof ti))
- return -EFAULT;
-
- if (ti.cdti_trk0 < disk_info.first
- || ti.cdti_trk0 > disk_info.last
- || ti.cdti_trk1 < ti.cdti_trk0)
- return -EINVAL;
- if (ti.cdti_trk1 > disk_info.last)
- ti.cdti_trk1 = disk_info.last;
-
- msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
- msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
- msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
- msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
- msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
- msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
-
- DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
- msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0,
- msf.cdmsf_min1,
- msf.cdmsf_sec1,
- msf.cdmsf_frame1));
-
- bin2bcd(&msf);
- status = exec_long_cmd(COMPLAY, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromreadtochdr(void __user *arg)
-{
- struct cdrom_tochdr tochdr;
-
- tochdr.cdth_trk0 = disk_info.first;
- tochdr.cdth_trk1 = disk_info.last;
-
- return copy_to_user(arg, &tochdr, sizeof tochdr) ? -EFAULT : 0;
-}
-
-
-static int cdromreadtocentry(void __user *arg)
-{
- struct cdrom_tocentry entry;
- struct cdrom_subchnl *tocptr;
-
- if (copy_from_user(&entry, arg, sizeof entry))
- return -EFAULT;
-
- if (entry.cdte_track == CDROM_LEADOUT)
- tocptr = &toc[disk_info.last + 1];
- else if (entry.cdte_track > disk_info.last
- || entry.cdte_track < disk_info.first)
- return -EINVAL;
- else
- tocptr = &toc[entry.cdte_track];
-
- entry.cdte_adr = tocptr->cdsc_adr;
- entry.cdte_ctrl = tocptr->cdsc_ctrl;
- entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
- entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
- entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
- /* %% What should go into entry.cdte_datamode? */
-
- if (entry.cdte_format == CDROM_LBA)
- msf2lba(&entry.cdte_addr);
- else if (entry.cdte_format != CDROM_MSF)
- return -EINVAL;
-
- return copy_to_user(arg, &entry, sizeof entry) ? -EFAULT : 0;
-}
-
-
-static int cdromvolctrl(void __user *arg)
-{
- int status;
- struct cdrom_volctrl volctrl;
- struct cdrom_msf msf;
-
- if (copy_from_user(&volctrl, arg, sizeof volctrl))
- return -EFAULT;
-
- msf.cdmsf_min0 = 0x10;
- msf.cdmsf_sec0 = 0x32;
- msf.cdmsf_frame0 = volctrl.channel0;
- msf.cdmsf_min1 = volctrl.channel1;
- msf.cdmsf_sec1 = volctrl.channel2;
- msf.cdmsf_frame1 = volctrl.channel3;
-
- status = exec_long_cmd(COMCHCTRL, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
- return -EIO;
- }
- return 0;
-}
-
-
-static int cdromsubchnl(void __user *arg)
-{
- int status;
- struct cdrom_subchnl subchnl;
-
- if (copy_from_user(&subchnl, arg, sizeof subchnl))
- return -EFAULT;
-
- if (subchnl.cdsc_format != CDROM_LBA
- && subchnl.cdsc_format != CDROM_MSF)
- return -EINVAL;
-
- status = get_q_channel(&subchnl);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
- return -EIO;
- }
-
- if (copy_to_user(arg, &subchnl, sizeof subchnl))
- return -EFAULT;
- return 0;
-}
-
-
-static struct gendisk *optcd_disk;
-
-
-static int cdromread(void __user *arg, int blocksize, int cmd)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- msf.cdmsf_min1 = 0;
- msf.cdmsf_sec1 = 0;
- msf.cdmsf_frame1 = 1; /* read only one frame */
- status = exec_read_cmd(cmd, &msf);
-
- DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
-
- if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
- return -EIO;
-
- fetch_data(optcd_disk->private_data, blocksize);
-
- if (copy_to_user(arg, optcd_disk->private_data, blocksize))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int cdromseek(void __user *arg)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- status = exec_seek_cmd(COMSEEK, &msf);
-
- DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
-
- if (status < 0)
- return -EIO;
- return 0;
-}
-
-
-#ifdef MULTISESSION
-static int cdrommultisession(void __user *arg)
-{
- struct cdrom_multisession ms;
-
- if (copy_from_user(&ms, arg, sizeof ms))
- return -EFAULT;
-
- ms.addr.msf.minute = disk_info.last_session.minute;
- ms.addr.msf.second = disk_info.last_session.second;
- ms.addr.msf.frame = disk_info.last_session.frame;
-
- if (ms.addr_format != CDROM_LBA
- && ms.addr_format != CDROM_MSF)
- return -EINVAL;
- if (ms.addr_format == CDROM_LBA)
- msf2lba(&ms.addr);
-
- ms.xa_flag = disk_info.xa;
-
- if (copy_to_user(arg, &ms, sizeof(struct cdrom_multisession)))
- return -EFAULT;
-
-#if DEBUG_MULTIS
- if (ms.addr_format == CDROM_MSF)
- printk(KERN_DEBUG
- "optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
- ms.xa_flag,
- ms.addr.msf.minute,
- ms.addr.msf.second,
- ms.addr.msf.frame);
- else
- printk(KERN_DEBUG
- "optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
- ms.xa_flag,
- ms.addr.lba,
- disk_info.last_session.minute,
- disk_info.last_session.second,
- disk_info.last_session.frame);
-#endif /* DEBUG_MULTIS */
-
- return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int cdromreset(void)
-{
- if (state != S_IDLE) {
- error = 1;
- tries = 0;
- }
-
- toc_uptodate = 0;
- disk_changed = 1;
- opt_invalidate_buffers();
- audio_status = CDROM_AUDIO_NO_STATUS;
-
- if (!reset_drive())
- return -EIO;
- return 0;
-}
-
-/* VFS calls */
-
-
-static int opt_ioctl(struct inode *ip, struct file *fp,
- unsigned int cmd, unsigned long arg)
-{
- int status, err, retval = 0;
- void __user *argp = (void __user *)arg;
-
- DEBUG((DEBUG_VFS, "starting opt_ioctl"));
-
- if (!ip)
- return -EINVAL;
-
- if (cmd == CDROMRESET)
- return cdromreset();
-
- /* is do_optcd_request or another ioctl busy? */
- if (state != S_IDLE || in_vfs)
- return -EBUSY;
-
- in_vfs = 1;
-
- status = drive_status();
- if (status < 0) {
- DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
- in_vfs = 0;
- return -EIO;
- }
-
- if (status & ST_DOOR_OPEN)
- switch (cmd) { /* Actions that can be taken with door open */
- case CDROMCLOSETRAY:
- /* We do this before trying to read the toc. */
- err = exec_cmd(COMCLOSE);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMCLOSE: %02x", -err));
- in_vfs = 0;
- return -EIO;
- }
- break;
- default: in_vfs = 0;
- return -EBUSY;
- }
-
- err = update_toc();
- if (err < 0) {
- DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
- in_vfs = 0;
- return -EIO;
- }
-
- DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
-
- switch (cmd) {
- case CDROMPAUSE: retval = cdrompause(); break;
- case CDROMRESUME: retval = cdromresume(); break;
- case CDROMPLAYMSF: retval = cdromplaymsf(argp); break;
- case CDROMPLAYTRKIND: retval = cdromplaytrkind(argp); break;
- case CDROMREADTOCHDR: retval = cdromreadtochdr(argp); break;
- case CDROMREADTOCENTRY: retval = cdromreadtocentry(argp); break;
-
- case CDROMSTOP: err = exec_cmd(COMSTOP);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMSTOP: %02x",
- -err));
- retval = -EIO;
- } else
- audio_status = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMSTART: break; /* This is a no-op */
- case CDROMEJECT: err = exec_cmd(COMUNLOCK);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMUNLOCK: %02x",
- -err));
- retval = -EIO;
- break;
- }
- err = exec_cmd(COMOPEN);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMOPEN: %02x",
- -err));
- retval = -EIO;
- }
- break;
-
- case CDROMVOLCTRL: retval = cdromvolctrl(argp); break;
- case CDROMSUBCHNL: retval = cdromsubchnl(argp); break;
-
- /* The drive detects the mode and automatically delivers the
- correct 2048 bytes, so we don't need these IOCTLs */
- case CDROMREADMODE2: retval = -EINVAL; break;
- case CDROMREADMODE1: retval = -EINVAL; break;
-
- /* Drive doesn't support reading audio */
- case CDROMREADAUDIO: retval = -EINVAL; break;
-
- case CDROMEJECT_SW: auto_eject = (char) arg;
- break;
-
-#ifdef MULTISESSION
- case CDROMMULTISESSION: retval = cdrommultisession(argp); break;
-#endif
-
- case CDROM_GET_MCN: retval = -EINVAL; break; /* not implemented */
- case CDROMVOLREAD: retval = -EINVAL; break; /* not implemented */
-
- case CDROMREADRAW:
- /* this drive delivers 2340 bytes in raw mode */
- retval = cdromread(argp, CD_FRAMESIZE_RAW1, COMREADRAW);
- break;
- case CDROMREADCOOKED:
- retval = cdromread(argp, CD_FRAMESIZE, COMREAD);
- break;
- case CDROMREADALL:
- retval = cdromread(argp, CD_FRAMESIZE_RAWER, COMREADALL);
- break;
-
- case CDROMSEEK: retval = cdromseek(argp); break;
- case CDROMPLAYBLK: retval = -EINVAL; break; /* not implemented */
- case CDROMCLOSETRAY: break; /* The action was taken earlier */
- default: retval = -EINVAL;
- }
- in_vfs = 0;
- return retval;
-}
-
-
-static int open_count = 0;
-
-/* Open device special file; check that a disk is in. */
-static int opt_open(struct inode *ip, struct file *fp)
-{
- DEBUG((DEBUG_VFS, "starting opt_open"));
-
- if (!open_count && state == S_IDLE) {
- int status;
- char *buf;
-
- buf = kmalloc(CD_FRAMESIZE_RAWER, GFP_KERNEL);
- if (!buf) {
- printk(KERN_INFO "optcd: cannot allocate read buffer\n");
- return -ENOMEM;
- }
- optcd_disk->private_data = buf; /* save read buffer */
-
- toc_uptodate = 0;
- opt_invalidate_buffers();
-
- status = exec_cmd(COMCLOSE); /* close door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status));
- }
-
- status = drive_status();
- if (status < 0) {
- DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
- goto err_out;
- }
- DEBUG((DEBUG_VFS, "status: %02x", status));
- if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
- printk(KERN_INFO "optcd: no disk or door open\n");
- goto err_out;
- }
- status = exec_cmd(COMLOCK); /* Lock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
- }
- status = update_toc(); /* Read table of contents */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
- status = exec_cmd(COMUNLOCK); /* Unlock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMUNLOCK: %02x", -status));
- }
- goto err_out;
- }
- open_count++;
- }
-
- DEBUG((DEBUG_VFS, "exiting opt_open"));
-
- return 0;
-
-err_out:
- return -EIO;
-}
-
-
-/* Release device special file; flush all blocks from the buffer cache */
-static int opt_release(struct inode *ip, struct file *fp)
-{
- int status;
-
- DEBUG((DEBUG_VFS, "executing opt_release"));
- DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
- ip, ip->i_bdev->bd_disk->disk_name, fp));
-
- if (!--open_count) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- status = exec_cmd(COMUNLOCK); /* Unlock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
- }
- if (auto_eject) {
- status = exec_cmd(COMOPEN);
- DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
- }
- kfree(optcd_disk->private_data);
- del_timer(&delay_timer);
- del_timer(&req_timer);
- }
- return 0;
-}
-
-
-/* Check if disk has been changed */
-static int opt_media_change(struct gendisk *disk)
-{
- DEBUG((DEBUG_VFS, "executing opt_media_change"));
- DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
- disk->disk_name, disk_changed));
-
- if (disk_changed) {
- disk_changed = 0;
- return 1;
- }
- return 0;
-}
-
-/* Driver initialisation */
-
-
-/* Returns 1 if a drive is detected with a version string
- starting with "DOLPHIN". Otherwise 0. */
-static int __init version_ok(void)
-{
- char devname[100];
- int count, i, ch, status;
-
- status = exec_cmd(COMVERSION);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
- return 0;
- }
- if ((count = get_data(1)) < 0) {
- DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
- return 0;
- }
- for (i = 0, ch = -1; count > 0; count--) {
- if ((ch = get_data(1)) < 0) {
- DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
- break;
- }
- if (i < 99)
- devname[i++] = ch;
- }
- devname[i] = '\0';
- if (ch < 0)
- return 0;
-
- printk(KERN_INFO "optcd: Device %s detected\n", devname);
- return ((devname[0] == 'D')
- && (devname[1] == 'O')
- && (devname[2] == 'L')
- && (devname[3] == 'P')
- && (devname[4] == 'H')
- && (devname[5] == 'I')
- && (devname[6] == 'N'));
-}
-
-
-static struct block_device_operations opt_fops = {
- .owner = THIS_MODULE,
- .open = opt_open,
- .release = opt_release,
- .ioctl = opt_ioctl,
- .media_changed = opt_media_change,
-};
-
-#ifndef MODULE
-/* Get kernel parameter when used as a kernel driver */
-static int optcd_setup(char *str)
-{
- int ints[4];
- (void)get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0)
- optcd_port = ints[1];
-
- return 1;
-}
-
-__setup("optcd=", optcd_setup);
-
-#endif /* MODULE */
-
-/* Test for presence of drive and initialize it. Called at boot time
- or during module initialisation. */
-static int __init optcd_init(void)
-{
- int status;
-
- if (optcd_port <= 0) {
- printk(KERN_INFO
- "optcd: no Optics Storage CDROM Initialization\n");
- return -EIO;
- }
- optcd_disk = alloc_disk(1);
- if (!optcd_disk) {
- printk(KERN_ERR "optcd: can't allocate disk\n");
- return -ENOMEM;
- }
- optcd_disk->major = MAJOR_NR;
- optcd_disk->first_minor = 0;
- optcd_disk->fops = &opt_fops;
- sprintf(optcd_disk->disk_name, "optcd");
-
- if (!request_region(optcd_port, 4, "optcd")) {
- printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n",
- optcd_port);
- put_disk(optcd_disk);
- return -EIO;
- }
-
- if (!reset_drive()) {
- printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port);
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
- if (!version_ok()) {
- printk(KERN_ERR "optcd: unknown drive detected; aborting\n");
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
- status = exec_cmd(COMINITDOUBLE);
- if (status < 0) {
- printk(KERN_ERR "optcd: cannot init double speed mode\n");
- release_region(optcd_port, 4);
- DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
- put_disk(optcd_disk);
- return -EIO;
- }
- if (register_blkdev(MAJOR_NR, "optcd")) {
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
-
-
- opt_queue = blk_init_queue(do_optcd_request, &optcd_lock);
- if (!opt_queue) {
- unregister_blkdev(MAJOR_NR, "optcd");
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -ENOMEM;
- }
-
- blk_queue_hardsect_size(opt_queue, 2048);
- optcd_disk->queue = opt_queue;
- add_disk(optcd_disk);
-
- printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
- return 0;
-}
-
-
-static void __exit optcd_exit(void)
-{
- del_gendisk(optcd_disk);
- put_disk(optcd_disk);
- if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
- printk(KERN_ERR "optcd: what's that: can't unregister\n");
- return;
- }
- blk_cleanup_queue(opt_queue);
- release_region(optcd_port, 4);
- printk(KERN_INFO "optcd: module released.\n");
-}
-
-module_init(optcd_init);
-module_exit(optcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR);
diff --git a/drivers/cdrom/optcd.h b/drivers/cdrom/optcd.h
deleted file mode 100644
index 1911bb92ee28..000000000000
--- a/drivers/cdrom/optcd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver
- $Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $
-
- Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
- Configuration file for linux/drivers/cdrom/optcd.c
-*/
-
-#ifndef _LINUX_OPTCD_H
-#define _LINUX_OPTCD_H
-
-
-/* I/O base of drive. Drive uses base to base+2.
- This setting can be overridden with the kernel or insmod command
- line option 'optcd=<portbase>'. Use address of 0 to disable driver. */
-#define OPTCD_PORTBASE 0x340
-
-
-/* enable / disable parts of driver by define / undef */
-#define MULTISESSION /* multisession support (ALPHA) */
-
-
-/* Change 0 to 1 to debug various parts of the driver */
-#define DEBUG_DRIVE_IF 0 /* Low level drive interface */
-#define DEBUG_CONV 0 /* Address conversions */
-#define DEBUG_BUFFERS 0 /* Buffering and block size conversion */
-#define DEBUG_REQUEST 0 /* Request mechanism */
-#define DEBUG_STATE 0 /* State machine */
-#define DEBUG_TOC 0 /* Q-channel and Table of Contents */
-#define DEBUG_MULTIS 0 /* Multisession code */
-#define DEBUG_VFS 0 /* VFS interface */
-
-
-/* Don't touch these unless you know what you're doing. */
-
-/* Various timeout loop repetition counts. */
-#define BUSY_TIMEOUT 10000000 /* for busy wait */
-#define FAST_TIMEOUT 100000 /* ibid. for probing */
-#define SLEEP_TIMEOUT 6000 /* for timer wait */
-#define MULTI_SEEK_TIMEOUT 1000 /* for timer wait */
-#define READ_TIMEOUT 6000 /* for poll wait */
-#define STOP_TIMEOUT 2000 /* for poll wait */
-#define RESET_WAIT 5000 /* busy wait at drive reset */
-
-/* # of buffers for block size conversion. 6 is optimal for my setup (P75),
- giving 280 kb/s, with 0.4% CPU usage. Experiment to find your optimal
- setting */
-#define N_BUFS 6
-
-
-#endif /* _LINUX_OPTCD_H */
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
deleted file mode 100644
index a1283b1ef989..000000000000
--- a/drivers/cdrom/sbpcd.c
+++ /dev/null
@@ -1,5966 +0,0 @@
-/*
- * sbpcd.c CD-ROM device driver for the whole family of traditional,
- * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives.
- * Works with SoundBlaster compatible cards and with "no-sound"
- * interface cards like Lasermate, Panasonic CI-101P, Teac, ...
- * Also for the Longshine LCS-7260 drive.
- * Also for the IBM "External ISA CD-Rom" drive.
- * Also for the CreativeLabs CD200 drive.
- * Also for the TEAC CD-55A drive.
- * Also for the ECS-AT "Vertos 100" drive.
- * Not for Sanyo drives (but for the H94A, sjcd is there...).
- * Not for any other Funai drives than the CD200 types (sometimes
- * labelled E2550UA or MK4015 or 2800F).
- */
-
-#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000"
-
-/* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * You should have received a copy of the GNU General Public License
- * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * If you change this software, you should mail a .diff file with some
- * description lines to emoenke@gwdg.de. I want to know about it.
- *
- * If you are the editor of a Linux CD, you should enable sbpcd.c within
- * your boot floppy kernel and send me one of your CDs for free.
- *
- * If you would like to port the driver to an other operating system (f.e.
- * FreeBSD or NetBSD) or use it as an information source, you shall not be
- * restricted by the GPL under the following conditions:
- * a) the source code of your work is freely available
- * b) my part of the work gets mentioned at all places where your
- * authorship gets mentioned
- * c) I receive a copy of your code together with a full installation
- * package of your operating system for free.
- *
- *
- * VERSION HISTORY
- *
- * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss)
- *
- * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for
- * end-of-request_queue (resulting in kernel panic).
- * Flow control seems stable, but throughput is not better.
- *
- * 0.3 interrupt locking totally eliminated (maybe "inb" and "outb"
- * are still locking) - 0.2 made keyboard-type-ahead losses.
- * check_sbpcd_media_change added (to use by isofs/inode.c)
- * - but it detects almost nothing.
- *
- * 0.4 use MAJOR 25 definitely.
- * Almost total re-design to support double-speed drives and
- * "naked" (no sound) interface cards ("LaserMate" interface type).
- * Flow control should be exact now.
- * Don't occupy the SbPro IRQ line (not needed either); will
- * live together with Hannu Savolainen's sndkit now.
- * Speeded up data transfer to 150 kB/sec, with help from Kai
- * Makisara, the "provider" of the "mt" tape utility.
- * Give "SpinUp" command if necessary.
- * First steps to support up to 4 drives (but currently only one).
- * Implemented audio capabilities - workman should work, xcdplayer
- * gives some problems.
- * This version is still consuming too much CPU time, and
- * sleeping still has to be worked on.
- * During "long" implied seeks, it seems possible that a
- * ReadStatus command gets ignored. That gives the message
- * "ResponseStatus timed out" (happens about 6 times here during
- * a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is
- * handled without data error, but it should get done better.
- *
- * 0.5 Free CPU during waits (again with help from Kai Makisara).
- * Made it work together with the LILO/kernel setup standard.
- * Included auto-probing code, as suggested by YGGDRASIL.
- * Formal redesign to add DDI debugging.
- * There are still flaws in IOCTL (workman with double speed drive).
- *
- * 1.0 Added support for all drive IDs (0...3, no longer only 0)
- * and up to 4 drives on one controller.
- * Added "#define MANY_SESSION" for "old" multi session CDs.
- *
- * 1.1 Do SpinUp for new drives, too.
- * Revised for clean compile under "old" kernels (0.99pl9).
- *
- * 1.2 Found the "workman with double-speed drive" bug: use the driver's
- * audio_state, not what the drive is reporting with ReadSubQ.
- *
- * 1.3 Minor cleanups.
- * Refinements regarding Workman.
- *
- * 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but only the first
- * session - no chance to fully access a "multi-session" CD).
- * This currently still is too slow (50 kB/sec) - but possibly
- * the old drives won't do it faster.
- * Implemented "door (un)lock" for new drives (still does not work
- * as wanted - no lock possible after an unlock).
- * Added some debugging printout for the UPC/EAN code - but my drives
- * return only zeroes. Is there no UPC/EAN code written?
- *
- * 1.5 Laborate with UPC/EAN code (not better yet).
- * Adapt to kernel 1.1.8 change (have to explicitly include
- * <linux/string.h> now).
- *
- * 1.6 Trying to read audio frames as data. Impossible with the current
- * drive firmware levels, as it seems. Awaiting any hint. ;-)
- * Changed "door unlock": repeat it until success.
- * Changed CDROMSTOP routine (stop somewhat "softer" so that Workman
- * won't get confused).
- * Added a third interface type: Sequoia S-1000, as used with the SPEA
- * Media FX sound card. This interface (usable for Sony and Mitsumi
- * drives, too) needs a special configuration setup and behaves like a
- * LaserMate type after that. Still experimental - I do not have such
- * an interface.
- * Use the "variable BLOCK_SIZE" feature (2048). But it does only work
- * if you give the mount option "block=2048".
- * The media_check routine is currently disabled; now that it gets
- * called as it should I fear it must get synchronized for not to
- * disturb the normal driver's activity.
- *
- * 2.0 Version number bumped - two reasons:
- * - reading audio tracks as data works now with CR-562 and CR-563. We
- * currently do it by an IOCTL (yet has to get standardized), one frame
- * at a time; that is pretty slow. But it works.
- * - we are maintaining now up to 4 interfaces (each up to 4 drives):
- * did it the easy way - a different MAJOR (25, 26, ...) and a different
- * copy of the driver (sbpcd.c, sbpcd2.c, sbpcd3.c, sbpcd4.c - only
- * distinguished by the value of SBPCD_ISSUE and the driver's name),
- * and a common sbpcd.h file.
- * Bettered the "ReadCapacity error" problem with old CR-52x drives (the
- * drives sometimes need a manual "eject/insert" before work): just
- * reset the drive and do again. Needs lots of resets here and sometimes
- * that does not cure, so this can't be the solution.
- *
- * 2.1 Found bug with multisession CDs (accessing frame 16).
- * "read audio" works now with address type CDROM_MSF, too.
- * Bigger audio frame buffer: allows reading max. 4 frames at time; this
- * gives a significant speedup, but reading more than one frame at once
- * gives missing chunks at each single frame boundary.
- *
- * 2.2 Kernel interface cleanups: timers, init, setup, media check.
- *
- * 2.3 Let "door lock" and "eject" live together.
- * Implemented "close tray" (done automatically during open).
- *
- * 2.4 Use different names for device registering.
- *
- * 2.5 Added "#if EJECT" code (default: enabled) to automatically eject
- * the tray during last call to "sbpcd_release".
- * Added "#if JUKEBOX" code (default: disabled) to automatically eject
- * the tray during call to "sbpcd_open" if no disk is in.
- * Turn on the CD volume of "compatible" sound cards, too; just define
- * SOUND_BASE (in sbpcd.h) accordingly (default: disabled).
- *
- * 2.6 Nothing new.
- *
- * 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly:
- * 0 disables, 1 enables auto-ejecting. Useful to keep the tray in
- * during shutdown.
- *
- * 2.8 Added first support (still BETA, I need feedback or a drive) for
- * the Longshine LCS-7260 drives. They appear as double-speed drives
- * using the "old" command scheme, extended by tray control and door
- * lock functions.
- * Found (and fixed preliminary) a flaw with some multisession CDs: we
- * have to re-direct not only the accesses to frame 16 (the isofs
- * routines drive it up to max. 100), but also those to the continuation
- * (repetition) frames (as far as they exist - currently set fix as
- * 16..20).
- * Changed default of the "JUKEBOX" define. If you use this default,
- * your tray will eject if you try to mount without a disk in. Next
- * mount command will insert the tray - so, just fill in a disk. ;-)
- *
- * 2.9 Fulfilled the Longshine LCS-7260 support; with great help and
- * experiments by Serge Robyns.
- * First attempts to support the TEAC CD-55A drives; but still not
- * usable yet.
- * Implemented the CDROMMULTISESSION ioctl; this is an attempt to handle
- * multi session CDs more "transparent" (redirection handling has to be
- * done within the isofs routines, and only for the special purpose of
- * obtaining the "right" volume descriptor; accesses to the raw device
- * should not get redirected).
- *
- * 3.0 Just a "normal" increment, with some provisions to do it better. ;-)
- * Introduced "#define READ_AUDIO" to specify the maximum number of
- * audio frames to grab with one request. This defines a buffer size
- * within kernel space; a value of 0 will reserve no such space and
- * disable the CDROMREADAUDIO ioctl. A value of 75 enables the reading
- * of a whole second with one command, but will use a buffer of more
- * than 172 kB.
- * Started CD200 support. Drive detection should work, but nothing
- * more.
- *
- * 3.1 Working to support the CD200 and the Teac CD-55A drives.
- * AT-BUS style device numbering no longer used: use SCSI style now.
- * So, the first "found" device has MINOR 0, regardless of the
- * jumpered drive ID. This implies modifications to the /dev/sbpcd*
- * entries for some people, but will help the DAU (german TLA, english:
- * "newbie", maybe ;-) to install his "first" system from a CD.
- *
- * 3.2 Still testing with CD200 and CD-55A drives.
- *
- * 3.3 Working with CD200 support.
- *
- * 3.4 Auto-probing stops if an address of 0 is seen (to be entered with
- * the kernel command line).
- * Made the driver "loadable". If used as a module, "audio copy" is
- * disabled, and the internal read ahead data buffer has a reduced size
- * of 4 kB; so, throughput may be reduced a little bit with slow CPUs.
- *
- * 3.5 Provisions to handle weird photoCDs which have an interrupted
- * "formatting" immediately after the last frames of some files: simply
- * never "read ahead" with MultiSession CDs. By this, CPU usage may be
- * increased with those CDs, and there may be a loss in speed.
- * Re-structured the messaging system.
- * The "loadable" version no longer has a limited READ_AUDIO buffer
- * size.
- * Removed "MANY_SESSION" handling for "old" multi session CDs.
- * Added "private" IOCTLs CDROMRESET and CDROMVOLREAD.
- * Started again to support the TEAC CD-55A drives, now that I found
- * the money for "my own" drive. ;-)
- * The TEAC CD-55A support is fairly working now.
- * I have measured that the drive "delivers" at 600 kB/sec (even with
- * bigger requests than the drive's 64 kB buffer can satisfy), but
- * the "real" rate does not exceed 520 kB/sec at the moment.
- * Caused by the various changes to build in TEAC support, the timed
- * loops are de-optimized at the moment (less throughput with CR-52x
- * drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64).
- *
- * 3.6 Fixed TEAC data read problems with SbPro interfaces.
- * Initial size of the READ_AUDIO buffer is 0. Can get set to any size
- * during runtime.
- *
- * 3.7 Introduced MAX_DRIVES for some poor interface cards (seen with TEAC
- * drives) which allow only one drive (ID 0); this avoids repetitive
- * detection under IDs 1..3.
- * Elongated cmd_out_T response waiting; necessary for photo CDs with
- * a lot of sessions.
- * Bettered the sbpcd_open() behavior with TEAC drives.
- *
- * 3.8 Elongated max_latency for CR-56x drives.
- *
- * 3.9 Finally fixed the long-known SoundScape/SPEA/Sequoia S-1000 interface
- * configuration bug.
- * Now Corey, Heiko, Ken, Leo, Vadim/Eric & Werner are invited to copy
- * the config_spea() routine into their drivers. ;-)
- *
- * 4.0 No "big step" - normal version increment.
- * Adapted the benefits from 1.3.33.
- * Fiddled with CDROMREADAUDIO flaws.
- * Avoid ReadCapacity command with CD200 drives (the MKE 1.01 version
- * seems not to support it).
- * Fulfilled "read audio" for CD200 drives, with help of Pete Heist
- * (heistp@rpi.edu).
- *
- * 4.1 Use loglevel KERN_INFO with printk().
- * Added support for "Vertos 100" drive ("ECS-AT") - it is very similar
- * to the Longshine LCS-7260. Give feedback if you can - I never saw
- * such a drive, and I have no specs.
- *
- * 4.2 Support for Teac 16-bit interface cards. Can't get auto-detected,
- * so you have to jumper your card to 0x2C0. Still not 100% - come
- * in contact if you can give qualified feedback.
- * Use loglevel KERN_NOTICE with printk(). If you get annoyed by a
- * flood of unwanted messages and the accompanied delay, try to read
- * my documentation. Especially the Linux CDROM drivers have to do an
- * important job for the newcomers, so the "distributed" version has
- * to fit some special needs. Since generations, the flood of messages
- * is user-configurable (even at runtime), but to get aware of this, one
- * needs a special mental quality: the ability to read.
- *
- * 4.3 CD200F does not like to receive a command while the drive is
- * reading the ToC; still trying to solve it.
- * Removed some redundant verify_area calls (yes, Heiko Eissfeldt
- * is visiting all the Linux CDROM drivers ;-).
- *
- * 4.4 Adapted one idea from tiensivu@pilot.msu.edu's "stripping-down"
- * experiments: "KLOGD_PAUSE".
- * Inhibited "play audio" attempts with data CDs. Provisions for a
- * "data-safe" handling of "mixed" (data plus audio) Cds.
- *
- * 4.5 Meanwhile Gonzalo Tornaria <tornaria@cmat.edu.uy> (GTL) built a
- * special end_request routine: we seem to have to take care for not
- * to have two processes working at the request list. My understanding
- * was and is that ll_rw_blk should not call do_sbpcd_request as long
- * as there is still one call active (the first call will care for all
- * outstanding I/Os, and if a second call happens, that is a bug in
- * ll_rw_blk.c).
- * "Check media change" without touching any drive.
- *
- * 4.6 Use a semaphore to synchronize multi-activity; elaborated by Rob
- * Riggs <rriggs@tesser.com>. At the moment, we simply block "read"
- * against "ioctl" and vice versa. This could be refined further, but
- * I guess with almost no performance increase.
- * Experiments to speed up the CD-55A; again with help of Rob Riggs
- * (to be true, he gave both, idea & code. ;-)
- *
- * 4.61 Ported to Uniform CD-ROM driver by
- * Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- * changes by Erik Andersen <andersee@debian.org>
- *
- * 4.62 Fix a bug where playing audio left the drive in an unusable state.
- * Heiko Eissfeldt <heiko@colossus.escape.de>
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer.
- * Annoying things fixed:
- * TOC reread on automated disk changes
- * TOC reread on manual cd changes
- * Play IOCTL tries to play CD before it's actually ready... sometimes.
- * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play.
- * Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000
- *
- * 4.64 Fix module parameters - were being completely ignored.
- * Can also specify max_drives=N as a setup int to get rid of
- * "ghost" drives on crap hardware (aren't they all?) Paul Gortmaker
- *
- * TODO
- * implement "read all subchannel data" (96 bytes per frame)
- * remove alot of the virtual status bits and deal with hardware status
- * move the change of cd for audio to a better place
- * add debug levels to insmod parameters (trivial)
- *
- * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
- * elaborated speed-up experiments (and the fabulous results!), for
- * the "push" towards load-free wait loops, and for the extensive mail
- * thread which brought additional hints and bug fixes.
- *
- */
-
-/*
- * Trying to merge requests breaks this driver horribly (as in it goes
- * boom and apparently has done so since 2.3.41). As it is a legacy
- * driver for a horribly slow double speed CD on a hideous interface
- * designed for polled operation, I won't lose any sleep in simply
- * disallowing merging. Paul G. 02/2001
- *
- * Thu May 30 14:14:47 CEST 2002:
- *
- * I have presumably found the reson for the above - there was a bogous
- * end_request substitute, which was manipulating the request queues
- * incorrectly. If someone has access to the actual hardware, and it's
- * still operations - well please free to test it.
- *
- * Marcin Dalecki
- */
-
-/*
- * Add bio/kdev_t changes for 2.5.x required to make it work again.
- * Still room for improvement in the request handling here if anyone
- * actually cares. Bring your own chainsaw. Paul G. 02/2002
- */
-
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <stdarg.h>
-#include "sbpcd.h"
-
-#define MAJOR_NR MATSUSHITA_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-/*==========================================================================*/
-#if SBPCD_DIS_IRQ
-# define SBPCD_CLI cli()
-# define SBPCD_STI sti()
-#else
-# define SBPCD_CLI
-# define SBPCD_STI
-#endif
-
-/*==========================================================================*/
-/*
- * auto-probing address list
- * inspired by Adam J. Richter from Yggdrasil
- *
- * still not good enough - can cause a hang.
- * example: a NE 2000 ethernet card at 300 will cause a hang probing 310.
- * if that happens, reboot and use the LILO (kernel) command line.
- * The possibly conflicting ethernet card addresses get NOT probed
- * by default - to minimize the hang possibilities.
- *
- * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to
- * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx.
- *
- * send mail to emoenke@gwdg.de if your interface card is not FULLY
- * represented here.
- */
-static int sbpcd[] =
-{
- CDROM_PORT, SBPRO, /* probe with user's setup first */
-#if DISTRIBUTION
- 0x230, 1, /* Soundblaster Pro and 16 (default) */
-#if 0
- 0x300, 0, /* CI-101P (default), WDH-7001C (default),
- Galaxy (default), Reveal (one default) */
- 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */
- 0x2C0, 3, /* Teac 16-bit cards */
- 0x260, 1, /* OmniCD */
- 0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default),
- Longshine LCS-6853 (default) */
- 0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */
- 0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */
- 0x360, 0, /* Lasermate, CI-101P */
- 0x270, 1, /* Soundblaster 16 */
- 0x670, 0, /* "sound card #9" */
- 0x690, 0, /* "sound card #9" */
- 0x338, 2, /* SPEA Media FX, Ensonic SoundScape (default) */
- 0x328, 2, /* SPEA Media FX */
- 0x348, 2, /* SPEA Media FX */
- 0x634, 0, /* some newer sound cards */
- 0x638, 0, /* some newer sound cards */
- 0x230, 1, /* some newer sound cards */
- /* due to incomplete address decoding of the SbPro card, these must be last */
- 0x630, 0, /* "sound card #9" (default) */
- 0x650, 0, /* "sound card #9" */
-#ifdef MODULE
- /*
- * some "hazardous" locations (no harm with the loadable version)
- * (will stop the bus if a NE2000 ethernet card resides at offset -0x10)
- */
- 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
- 0x350, 0, /* Lasermate, CI-101P */
- 0x358, 2, /* SPEA Media FX */
- 0x370, 0, /* Lasermate, CI-101P */
- 0x290, 1, /* Soundblaster 16 */
- 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
-#endif /* MODULE */
-#endif
-#endif /* DISTRIBUTION */
-};
-
-/*
- * Protects access to global structures etc.
- */
-static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock);
-static struct request_queue *sbpcd_queue;
-
-/* You can only set the first pair, from old MODULE_PARM code. */
-static int sbpcd_set(const char *val, struct kernel_param *kp)
-{
- get_options((char *)val, 2, (int *)sbpcd);
- return 0;
-}
-module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0);
-
-#define NUM_PROBE (sizeof(sbpcd) / sizeof(int))
-
-/*==========================================================================*/
-
-#define INLINE inline
-
-/*==========================================================================*/
-/*
- * the forward references:
- */
-static void sbp_sleep(u_int);
-static void mark_timeout_delay(u_long);
-static void mark_timeout_data(u_long);
-#if 0
-static void mark_timeout_audio(u_long);
-#endif
-static void sbp_read_cmd(struct request *req);
-static int sbp_data(struct request *req);
-static int cmd_out(void);
-static int DiskInfo(void);
-
-/*==========================================================================*/
-
-/*
- * pattern for printk selection:
- *
- * (1<<DBG_INF) necessary information
- * (1<<DBG_BSZ) BLOCK_SIZE trace
- * (1<<DBG_REA) "read" status trace
- * (1<<DBG_CHK) "media check" trace
- * (1<<DBG_TIM) datarate timer test
- * (1<<DBG_INI) initialization trace
- * (1<<DBG_TOC) tell TocEntry values
- * (1<<DBG_IOC) ioctl trace
- * (1<<DBG_STA) "ResponseStatus" trace
- * (1<<DBG_ERR) "cc_ReadError" trace
- * (1<<DBG_CMD) "cmd_out" trace
- * (1<<DBG_WRN) give explanation before auto-probing
- * (1<<DBG_MUL) multi session code test
- * (1<<DBG_IDX) "drive_id != 0" test code
- * (1<<DBG_IOX) some special information
- * (1<<DBG_DID) drive ID test
- * (1<<DBG_RES) drive reset info
- * (1<<DBG_SPI) SpinUp test info
- * (1<<DBG_IOS) ioctl trace: "subchannel"
- * (1<<DBG_IO2) ioctl trace: general
- * (1<<DBG_UPC) show UPC info
- * (1<<DBG_XA1) XA mode debugging
- * (1<<DBG_LCK) door (un)lock info
- * (1<<DBG_SQ1) dump SubQ frame
- * (1<<DBG_AUD) "read audio" debugging
- * (1<<DBG_SEQ) Sequoia interface configuration trace
- * (1<<DBG_LCS) Longshine LCS-7260 debugging trace
- * (1<<DBG_CD2) MKE/Funai CD200 debugging trace
- * (1<<DBG_TEA) TEAC CD-55A debugging trace
- * (1<<DBG_ECS) ECS-AT (Vertos-100) debugging trace
- * (1<<DBG_000) unnecessary information
- */
-#if DISTRIBUTION
-static int sbpcd_debug = (1<<DBG_INF);
-#else
-static int sbpcd_debug = 0 & ((1<<DBG_INF) |
- (1<<DBG_TOC) |
- (1<<DBG_MUL) |
- (1<<DBG_UPC));
-#endif /* DISTRIBUTION */
-
-static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */
-static int sbpro_type = SBPRO;
-static unsigned char f_16bit;
-static unsigned char do_16bit;
-static int CDo_command, CDo_reset;
-static int CDo_sel_i_d, CDo_enable;
-static int CDi_info, CDi_status, CDi_data;
-static struct cdrom_msf msf;
-static struct cdrom_ti ti;
-static struct cdrom_tochdr tochdr;
-static struct cdrom_tocentry tocentry;
-static struct cdrom_subchnl SC;
-static struct cdrom_volctrl volctrl;
-static struct cdrom_read_audio read_audio;
-
-static unsigned char msgnum;
-static char msgbuf[80];
-
-static int max_drives = MAX_DRIVES;
-module_param(max_drives, int, 0);
-#ifndef MODULE
-static unsigned char setup_done;
-static const char *str_sb_l = "soundblaster";
-static const char *str_sp_l = "spea";
-static const char *str_ss_l = "soundscape";
-static const char *str_t16_l = "teac16bit";
-static const char *str_ss = "SoundScape";
-#endif
-static const char *str_sb = "SoundBlaster";
-static const char *str_lm = "LaserMate";
-static const char *str_sp = "SPEA";
-static const char *str_t16 = "Teac16bit";
-static const char *type;
-static const char *major_name="sbpcd";
-
-/*==========================================================================*/
-
-#ifdef FUTURE
-static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq);
-#endif /* FUTURE */
-
-static int teac=SBP_TEAC_SPEED;
-static int buffers=SBP_BUFFER_FRAMES;
-
-static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */
-static u_char family1[]="CR-56"; /* MKE CR-562, CR-563 */
-static u_char family2[]="CD200"; /* MKE CD200, Funai CD200F */
-static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */
-static u_char familyT[]="CD-55"; /* TEAC CD-55A */
-static u_char familyV[]="ECS-AT"; /* ECS Vertos 100 */
-
-static u_int recursion; /* internal testing only */
-static u_int fatal_err; /* internal testing only */
-static u_int response_count;
-static u_int flags_cmd_out;
-static u_char cmd_type;
-static u_char drvcmd[10];
-static u_char infobuf[20];
-static u_char xa_head_buf[CD_XA_HEAD];
-static u_char xa_tail_buf[CD_XA_TAIL];
-
-#if OLD_BUSY
-static volatile u_char busy_data;
-static volatile u_char busy_audio; /* true semaphores would be safer */
-#endif /* OLD_BUSY */
-static DECLARE_MUTEX(ioctl_read_sem);
-static u_long timeout;
-static volatile u_char timed_out_delay;
-static volatile u_char timed_out_data;
-#if 0
-static volatile u_char timed_out_audio;
-#endif
-static u_int datarate= 1000000;
-static u_int maxtim16=16000000;
-static u_int maxtim04= 4000000;
-static u_int maxtim02= 2000000;
-static u_int maxtim_8= 30000;
-#if LONG_TIMING
-static u_int maxtim_data= 9000;
-#else
-static u_int maxtim_data= 3000;
-#endif /* LONG_TIMING */
-#if DISTRIBUTION
-static int n_retries=6;
-#else
-static int n_retries=6;
-#endif
-/*==========================================================================*/
-
-static int ndrives;
-static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto};
-
-/*==========================================================================*/
-/*
- * drive space begins here (needed separate for each unit)
- */
-static struct sbpcd_drive {
- char drv_id; /* "jumpered" drive ID or -1 */
- char drv_sel; /* drive select lines bits */
-
- char drive_model[9];
- u_char firmware_version[4];
- char f_eject; /* auto-eject flag: 0 or 1 */
- u_char *sbp_buf; /* Pointer to internal data buffer,
- space allocated during sbpcd_init() */
- u_int sbp_bufsiz; /* size of sbp_buf (# of frames) */
- int sbp_first_frame; /* First frame in buffer */
- int sbp_last_frame; /* Last frame in buffer */
- int sbp_read_frames; /* Number of frames being read to buffer */
- int sbp_current; /* Frame being currently read */
-
- u_char mode; /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */
- u_char *aud_buf; /* Pointer to audio data buffer,
- space allocated during sbpcd_init() */
- u_int sbp_audsiz; /* size of aud_buf (# of raw frames) */
- u_int drv_type;
- u_char drv_options;
- int status_bits;
- u_char diskstate_flags;
- u_char sense_byte;
-
- u_char CD_changed;
- char open_count;
- u_char error_byte;
-
- u_char f_multisession;
- u_int lba_multi;
- int first_session;
- int last_session;
- int track_of_last_session;
-
- u_char audio_state;
- u_int pos_audio_start;
- u_int pos_audio_end;
- char vol_chan0;
- u_char vol_ctrl0;
- char vol_chan1;
- u_char vol_ctrl1;
-#if 000 /* no supported drive has it */
- char vol_chan2;
- u_char vol_ctrl2;
- char vol_chan3;
- u_char vol_ctrl3;
-#endif /*000 */
- u_char volume_control; /* TEAC on/off bits */
-
- u_char SubQ_ctl_adr;
- u_char SubQ_trk;
- u_char SubQ_pnt_idx;
- u_int SubQ_run_tot;
- u_int SubQ_run_trk;
- u_char SubQ_whatisthis;
-
- u_char UPC_ctl_adr;
- u_char UPC_buf[7];
-
- int frame_size;
- int CDsize_frm;
-
- u_char xa_byte; /* 0x20: XA capabilities */
- u_char n_first_track; /* binary */
- u_char n_last_track; /* binary (not bcd), 0x01...0x63 */
- u_int size_msf; /* time of whole CD, position of LeadOut track */
- u_int size_blk;
-
- u_char TocEnt_nixbyte; /* em */
- u_char TocEnt_ctl_adr;
- u_char TocEnt_number;
- u_char TocEnt_format; /* em */
- u_int TocEnt_address;
-#ifdef SAFE_MIXED
- char has_data;
-#endif /* SAFE_MIXED */
- u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */
-
- struct {
- u_char nixbyte; /* em */
- u_char ctl_adr; /* 0x4x: data, 0x0x: audio */
- u_char number;
- u_char format; /* em */ /* 0x00: lba, 0x01: msf */
- u_int address;
- } TocBuffer[MAX_TRACKS+1]; /* last entry faked */
-
- int in_SpinUp; /* CR-52x test flag */
- int n_bytes; /* TEAC awaited response count */
- u_char error_state, b3, b4; /* TEAC command error state */
- u_char f_drv_error; /* TEAC command error flag */
- u_char speed_byte;
- int frmsiz;
- u_char f_XA; /* 1: XA */
- u_char type_byte; /* 0, 1, 3 */
- u_char mode_xb_6;
- u_char mode_yb_7;
- u_char mode_xb_8;
- u_char delay;
- struct cdrom_device_info *sbpcd_infop;
- struct gendisk *disk;
-} D_S[NR_SBPCD];
-
-static struct sbpcd_drive *current_drive = D_S;
-
-/*
- * drive space ends here (needed separate for each unit)
- */
-/*==========================================================================*/
-#if 0
-unsigned long cli_sti; /* for saving the processor flags */
-#endif
-/*==========================================================================*/
-static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
-static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
-#if 0
-static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0);
-#endif
-/*==========================================================================*/
-/*
- * DDI interface
- */
-static void msg(int level, const char *fmt, ...)
-{
-#if DISTRIBUTION
-#define MSG_LEVEL KERN_NOTICE
-#else
-#define MSG_LEVEL KERN_INFO
-#endif /* DISTRIBUTION */
-
- char buf[256];
- va_list args;
-
- if (!(sbpcd_debug&(1<<level))) return;
-
- msgnum++;
- if (msgnum>99) msgnum=0;
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- printk(MSG_LEVEL "%s-%d [%02d]: %s", major_name, current_drive - D_S, msgnum, buf);
-#if KLOGD_PAUSE
- sbp_sleep(KLOGD_PAUSE); /* else messages get lost */
-#endif /* KLOGD_PAUSE */
- return;
-}
-/*==========================================================================*/
-/*
- * DDI interface: runtime trace bit pattern maintenance
- */
-static int sbpcd_dbg_ioctl(unsigned long arg, int level)
-{
- switch(arg)
- {
- case 0: /* OFF */
- sbpcd_debug = DBG_INF;
- break;
-
- default:
- if (arg>=128) sbpcd_debug &= ~(1<<(arg-128));
- else sbpcd_debug |= (1<<arg);
- }
- return (arg);
-}
-/*==========================================================================*/
-static void mark_timeout_delay(u_long i)
-{
- timed_out_delay=1;
-#if 0
- msg(DBG_TIM,"delay timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-static void mark_timeout_data(u_long i)
-{
- timed_out_data=1;
-#if 0
- msg(DBG_TIM,"data timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-#if 0
-static void mark_timeout_audio(u_long i)
-{
- timed_out_audio=1;
-#if 0
- msg(DBG_TIM,"audio timer expired.\n");
-#endif
-}
-#endif
-/*==========================================================================*/
-/*
- * Wait a little while (used for polling the drive).
- */
-static void sbp_sleep(u_int time)
-{
- sti();
- schedule_timeout_interruptible(time);
- sti();
-}
-/*==========================================================================*/
-#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);}
-/*==========================================================================*/
-/*
- * convert logical_block_address to m-s-f_number (3 bytes only)
- */
-static INLINE void lba2msf(int lba, u_char *msf)
-{
- lba += CD_MSF_OFFSET;
- msf[0] = lba / (CD_SECS*CD_FRAMES);
- lba %= CD_SECS*CD_FRAMES;
- msf[1] = lba / CD_FRAMES;
- msf[2] = lba % CD_FRAMES;
-}
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * convert msf-bin to msf-bcd
- */
-static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */
-{
- *p=((*p/10)<<4)|(*p%10);
-}
-/*==========================================================================*/
-static INLINE u_int blk2msf(u_int blk)
-{
- MSF msf;
- u_int mm;
-
- msf.c[3] = 0;
- msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES);
- mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES);
- msf.c[1] = mm / CD_FRAMES;
- msf.c[0] = mm % CD_FRAMES;
- return (msf.n);
-}
-/*==========================================================================*/
-static INLINE u_int make16(u_char rh, u_char rl)
-{
- return ((rh<<8)|rl);
-}
-/*==========================================================================*/
-static INLINE u_int make32(u_int rh, u_int rl)
-{
- return ((rh<<16)|rl);
-}
-/*==========================================================================*/
-static INLINE u_char swap_nibbles(u_char i)
-{
- return ((i<<4)|(i>>4));
-}
-/*==========================================================================*/
-static INLINE u_char byt2bcd(u_char i)
-{
- return (((i/10)<<4)+i%10);
-}
-/*==========================================================================*/
-static INLINE u_char bcd2bin(u_char bcd)
-{
- return ((bcd>>4)*10+(bcd&0x0F));
-}
-/*==========================================================================*/
-static INLINE int msf2blk(int msfx)
-{
- MSF msf;
- int i;
-
- msf.n=msfx;
- i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET;
- if (i<0) return (0);
- return (i);
-}
-/*==========================================================================*/
-/*
- * convert m-s-f_number (3 bytes only) to logical_block_address
- */
-static INLINE int msf2lba(u_char *msf)
-{
- int i;
-
- i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET;
- if (i<0) return (0);
- return (i);
-}
-/*==========================================================================*/
-/* evaluate cc_ReadError code */
-static int sta2err(int sta)
-{
- if (famT_drive)
- {
- if (sta==0x00) return (0);
- if (sta==0x01) return (-604); /* CRC error */
- if (sta==0x02) return (-602); /* drive not ready */
- if (sta==0x03) return (-607); /* unknown media */
- if (sta==0x04) return (-612); /* general failure */
- if (sta==0x05) return (0);
- if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */
- if (sta==0x0b) return (-612); /* general failure */
- if (sta==0xff) return (-612); /* general failure */
- return (0);
- }
- else
- {
- if (sta<=2) return (sta);
- if (sta==0x05) return (-604); /* CRC error */
- if (sta==0x06) return (-606); /* seek error */
- if (sta==0x0d) return (-606); /* seek error */
- if (sta==0x0e) return (-603); /* unknown command */
- if (sta==0x14) return (-603); /* unknown command */
- if (sta==0x0c) return (-611); /* read fault */
- if (sta==0x0f) return (-611); /* read fault */
- if (sta==0x10) return (-611); /* read fault */
- if (sta>=0x16) return (-612); /* general failure */
- if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */
- if (famL_drive)
- if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */
- return (-602); /* drive not ready */
- }
-}
-/*==========================================================================*/
-static INLINE void clr_cmdbuf(void)
-{
- int i;
-
- for (i=0;i<10;i++) drvcmd[i]=0;
- cmd_type=0;
-}
-/*==========================================================================*/
-static void flush_status(void)
-{
- int i;
-
- sbp_sleep(15*HZ/10);
- for (i=maxtim_data;i!=0;i--) inb(CDi_status);
-}
-/*====================================================================*/
-/*
- * CDi status loop for Teac CD-55A (Rob Riggs)
- *
- * This is needed because for some strange reason
- * the CD-55A can take a real long time to give a
- * status response. This seems to happen after we
- * issue a READ command where a long seek is involved.
- *
- * I tried to ensure that we get max throughput with
- * minimal busy waiting. We busy wait at first, then
- * "switch gears" and start sleeping. We sleep for
- * longer periods of time the longer we wait.
- *
- */
-static int CDi_stat_loop_T(void)
-{
- int i, gear=1;
- u_long timeout_1, timeout_2, timeout_3, timeout_4;
-
- timeout_1 = jiffies + HZ / 50; /* sbp_sleep(0) for a short period */
- timeout_2 = jiffies + HZ / 5; /* nap for no more than 200ms */
- timeout_3 = jiffies + 5 * HZ; /* sleep for up to 5s */
- timeout_4 = jiffies + 45 * HZ; /* long sleep for up to 45s. */
- do
- {
- i = inb(CDi_status);
- if (!(i&s_not_data_ready)) return (i);
- if (!(i&s_not_result_ready)) return (i);
- switch(gear)
- {
- case 4:
- sbp_sleep(HZ);
- if (time_after(jiffies, timeout_4)) gear++;
- msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
- break;
- case 3:
- sbp_sleep(HZ/10);
- if (time_after(jiffies, timeout_3)) gear++;
- break;
- case 2:
- sbp_sleep(HZ/100);
- if (time_after(jiffies, timeout_2)) gear++;
- break;
- case 1:
- sbp_sleep(0);
- if (time_after(jiffies, timeout_1)) gear++;
- }
- } while (gear < 5);
- return -1;
-}
-/*==========================================================================*/
-static int CDi_stat_loop(void)
-{
- int i,j;
-
- for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) return (j);
- if (!(j&s_not_result_ready)) return (j);
- if (fam0L_drive) if (j&s_attention) return (j);
- }
- sbp_sleep(1);
- i = 1;
- }
- msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
- return (-1);
-}
-/*==========================================================================*/
-#if 00000
-/*==========================================================================*/
-static int tst_DataReady(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_not_data_ready) return (0);
- return (1);
-}
-/*==========================================================================*/
-static int tst_ResultReady(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_not_result_ready) return (0);
- return (1);
-}
-/*==========================================================================*/
-static int tst_Attention(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_attention) return (1);
- return (0);
-}
-/*==========================================================================*/
-#endif
-/*==========================================================================*/
-static int ResponseInfo(void)
-{
- int i,j,st=0;
- u_long timeout;
-
- for (i=0,timeout=jiffies+HZ;i<response_count;i++)
- {
- for (j=maxtim_data; ; )
- {
- for ( ;j!=0;j-- )
- {
- st=inb(CDi_status);
- if (!(st&s_not_result_ready)) break;
- }
- if ((j!=0)||time_after_eq(jiffies, timeout)) break;
- sbp_sleep(1);
- j = 1;
- }
- if (time_after_eq(jiffies, timeout)) break;
- infobuf[i]=inb(CDi_info);
- }
-#if 000
- while (!(inb(CDi_status)&s_not_result_ready))
- {
- infobuf[i++]=inb(CDi_info);
- }
- j=i-response_count;
- if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);
-#endif /* 000 */
- for (j=0;j<i;j++)
- sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i);
- j=response_count-i;
- if (j>0) return (-j);
- else return (i);
-}
-/*==========================================================================*/
-static void EvaluateStatus(int st)
-{
- current_drive->status_bits=0;
- if (fam1_drive) current_drive->status_bits=st|p_success;
- else if (fam0_drive)
- {
- if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in;
- if (st&p_spinning) current_drive->status_bits |= p_spinning;
- if (st&p_check) current_drive->status_bits |= p_check;
- if (st&p_success_old) current_drive->status_bits |= p_success;
- if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
- if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok;
- }
- else if (famLV_drive)
- {
- current_drive->status_bits |= p_success;
- if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in;
- if (st&p_spinning) current_drive->status_bits |= p_spinning;
- if (st&p_check) current_drive->status_bits |= p_check;
- if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
- if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed;
- if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked;
- }
- else if (fam2_drive)
- {
- current_drive->status_bits |= p_success;
- if (st&p2_check) current_drive->status_bits |= p1_check;
- if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
- if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
- if (st&p2_busy1) current_drive->status_bits |= p1_busy;
- if (st&p2_busy2) current_drive->status_bits |= p1_busy;
- if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
- if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
- if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
- }
- else if (famT_drive)
- {
- return; /* still needs to get coded */
- current_drive->status_bits |= p_success;
- if (st&p2_check) current_drive->status_bits |= p1_check;
- if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
- if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
- if (st&p2_busy1) current_drive->status_bits |= p1_busy;
- if (st&p2_busy2) current_drive->status_bits |= p1_busy;
- if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
- if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
- if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
- }
- return;
-}
-/*==========================================================================*/
-static int cmd_out_T(void);
-
-static int get_state_T(void)
-{
- int i;
-
- clr_cmdbuf();
- current_drive->n_bytes=1;
- drvcmd[0]=CMDT_STATUS;
- i=cmd_out_T();
- if (i>=0) i=infobuf[0];
- else
- {
- msg(DBG_TEA,"get_state_T error %d\n", i);
- return (i);
- }
- if (i>=0)
- /* 2: closed, disk in */
- current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok;
- else if (current_drive->error_state==6)
- {
- /* 3: closed, disk in, changed ("06 xx xx") */
- current_drive->status_bits=p1_door_closed|p1_disk_in;
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~toc_bit;
- }
- else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00))
- {
- /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */
- current_drive->status_bits=p1_door_closed;
- current_drive->open_count=0;
- }
- else if (current_drive->b4==0x01)
- {
- /* 0: open ("02 3A 01") */
- current_drive->status_bits=0;
- current_drive->open_count=0;
- }
- else
- {
- /* 1: closed, no disk ("02 3A xx") */
- current_drive->status_bits=p1_door_closed;
- current_drive->open_count=0;
- }
- return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static int ResponseStatus(void)
-{
- int i,j;
- u_long timeout;
-
- msg(DBG_STA,"doing ResponseStatus...\n");
- if (famT_drive) return (get_state_T());
- if (flags_cmd_out & f_respo3) timeout = jiffies;
- else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ;
- else timeout = jiffies + 4*HZ;
- j=maxtim_8;
- do
- {
- for ( ;j!=0;j--)
- {
- i=inb(CDi_status);
- if (!(i&s_not_result_ready)) break;
- }
- if ((j!=0)||time_after(jiffies, timeout)) break;
- sbp_sleep(1);
- j = 1;
- }
- while (1);
- if (j==0)
- {
- if ((flags_cmd_out & f_respo3) == 0)
- msg(DBG_STA,"ResponseStatus: timeout.\n");
- current_drive->status_bits=0;
- return (-401);
- }
- i=inb(CDi_info);
- msg(DBG_STA,"ResponseStatus: response %02X.\n", i);
- EvaluateStatus(i);
- msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i);
- return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static void cc_ReadStatus(void)
-{
- int i;
-
- msg(DBG_STA,"giving cc_ReadStatus command\n");
- if (famT_drive) return;
- SBPCD_CLI;
- if (fam0LV_drive) OUT(CDo_command,CMD0_STATUS);
- else if (fam1_drive) OUT(CDo_command,CMD1_STATUS);
- else if (fam2_drive) OUT(CDo_command,CMD2_STATUS);
- if (!fam0LV_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
- SBPCD_STI;
-}
-/*==========================================================================*/
-static int cc_ReadError(void)
-{
- int i;
-
- clr_cmdbuf();
- msg(DBG_ERR,"giving cc_ReadError command.\n");
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_ERR;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READ_ERR;
- response_count=6;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ_ERR;
- response_count=6;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- response_count=5;
- drvcmd[0]=CMDT_READ_ERR;
- }
- i=cmd_out();
- current_drive->error_byte=0;
- msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i);
- if (i<0) return (i);
- if (fam0V_drive) i=1;
- else i=2;
- current_drive->error_byte=infobuf[i];
- msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte);
- i=sta2err(infobuf[i]);
- if (i==-ERR_DISKCHANGE)
- {
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~toc_bit;
- }
- return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void);
-
-static int cmd_out_T(void)
-{
-#undef CMDT_TRIES
-#define CMDT_TRIES 1000
-#define TEST_FALSE_FF 1
-
- int i, j, l=0, m, ntries;
- unsigned long flags;
-
- current_drive->error_state=0;
- current_drive->b3=0;
- current_drive->b4=0;
- current_drive->f_drv_error=0;
- for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]);
- msgbuf[i*3]=0;
- msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf);
-
- OUT(CDo_sel_i_d,0);
- OUT(CDo_enable,current_drive->drv_sel);
- i=inb(CDi_status);
- do_16bit=0;
- if ((f_16bit)&&(!(i&0x80)))
- {
- do_16bit=1;
- msg(DBG_TEA,"cmd_out_T: do_16bit set.\n");
- }
- if (!(i&s_not_result_ready))
- do
- {
- j=inb(CDi_info);
- i=inb(CDi_status);
- sbp_sleep(0);
- msg(DBG_TEA,"cmd_out_T: spurious !s_not_result_ready. (%02X)\n", j);
- }
- while (!(i&s_not_result_ready));
- save_flags(flags); cli();
- for (i=0;i<10;i++) OUT(CDo_command,drvcmd[i]);
- restore_flags(flags);
- for (ntries=CMDT_TRIES;ntries>0;ntries--)
- {
- if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */
-#if 01
- OUT(CDo_sel_i_d,1);
-#endif /* 01 */
- if (teac==2)
- {
- if ((i=CDi_stat_loop_T()) == -1) break;
- }
- else
- {
-#if 0
- OUT(CDo_sel_i_d,1);
-#endif /* 0 */
- i=inb(CDi_status);
- }
- if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */
- {
- OUT(CDo_sel_i_d,1);
- if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
- if (drvcmd[0]==CMDT_DISKINFO)
- {
- l=0;
- do
- {
- if (do_16bit)
- {
- i=inw(CDi_data);
- infobuf[l++]=i&0x0ff;
- infobuf[l++]=i>>8;
-#if TEST_FALSE_FF
- if ((l==2)&&(infobuf[0]==0x0ff))
- {
- infobuf[0]=infobuf[1];
- l=1;
- msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n");
- }
-#endif /* TEST_FALSE_FF */
- }
- else infobuf[l++]=inb(CDi_data);
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- for (j=0;j<l;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"cmd_out_T data response:%s\n", msgbuf);
- }
- else
- {
- msg(DBG_TEA,"cmd_out_T: data response with cmd_%02X!\n",
- drvcmd[0]);
- j=0;
- do
- {
- if (do_16bit) i=inw(CDi_data);
- else i=inb(CDi_data);
- j++;
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- msg(DBG_TEA,"cmd_out_T: data response: discarded %d bytes/words.\n", j);
- fatal_err++;
- }
- }
- i=inb(CDi_status);
- if (!(i&s_not_result_ready))
- {
- OUT(CDo_sel_i_d,0);
- if (drvcmd[0]==CMDT_DISKINFO) m=l;
- else m=0;
- do
- {
- infobuf[m++]=inb(CDi_info);
- i=inb(CDi_status);
- }
- while (!(i&s_not_result_ready));
- for (j=0;j<m;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"cmd_out_T info response:%s\n", msgbuf);
- if (drvcmd[0]==CMDT_DISKINFO)
- {
- infobuf[0]=infobuf[l];
- if (infobuf[0]!=0x02) return (l); /* data length */
- }
- else if (infobuf[0]!=0x02) return (m); /* info length */
- do
- {
- ++recursion;
- if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion);
- clr_cmdbuf();
- drvcmd[0]=CMDT_READ_ERR;
- j=cmd_out_T(); /* !!! recursive here !!! */
- --recursion;
- sbp_sleep(1);
- }
- while (j<0);
- current_drive->error_state=infobuf[2];
- current_drive->b3=infobuf[3];
- current_drive->b4=infobuf[4];
- if (current_drive->f_drv_error)
- {
- current_drive->f_drv_error=0;
- cc_DriveReset();
- current_drive->error_state=2;
- }
- return (-current_drive->error_state-400);
- }
- if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
- if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10);
- else sbp_sleep(HZ/100);
- if (ntries>(CMDT_TRIES-50)) continue;
- msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
- }
- current_drive->f_drv_error=1;
- cc_DriveReset();
- current_drive->error_state=2;
- return (-99);
-}
-/*==========================================================================*/
-static int cmd_out(void)
-{
- int i=0;
-
- if (famT_drive) return(cmd_out_T());
-
- if (flags_cmd_out&f_putcmd)
- {
- unsigned long flags;
- for (i=0;i<7;i++)
- sprintf(&msgbuf[i*3], " %02X", drvcmd[i]);
- msgbuf[i*3]=0;
- msg(DBG_CMD,"cmd_out:%s\n", msgbuf);
- save_flags(flags); cli();
- for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
- restore_flags(flags);
- }
- if (response_count!=0)
- {
- if (cmd_type!=0)
- {
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- msg(DBG_INF,"misleaded to try ResponseData.\n");
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- return (-22);
- }
- else i=ResponseInfo();
- if (i<0) return (i);
- }
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n");
- if (flags_cmd_out&f_lopsta)
- {
- i=CDi_stat_loop();
- if ((i<0)||!(i&s_attention)) return (-8);
- }
- if (!(flags_cmd_out&f_getsta)) goto LOC_229;
-
- LOC_228:
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n");
- cc_ReadStatus();
-
- LOC_229:
- if (flags_cmd_out&f_ResponseStatus)
- {
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n");
- i=ResponseStatus();
- /* builds status_bits, returns orig. status or p_busy_new */
- if (i<0) return (i);
- if (flags_cmd_out&(f_bit1|f_wait_if_busy))
- {
- if (!st_check)
- {
- if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232;
- if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228;
- }
- }
- }
- LOC_232:
- if (!(flags_cmd_out&f_obey_p_check)) return (0);
- if (!st_check) return (0);
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n");
- i=cc_ReadError();
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n");
- msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i);
- return (i);
-}
-/*==========================================================================*/
-static int cc_Seek(u_int pos, char f_blk_msf)
-{
- int i;
-
- clr_cmdbuf();
- if (f_blk_msf>1) return (-3);
- if (fam0V_drive)
- {
- drvcmd[0]=CMD0_SEEK;
- if (f_blk_msf==1) pos=msf2blk(pos);
- drvcmd[2]=(pos>>16)&0x00FF;
- drvcmd[3]=(pos>>8)&0x00FF;
- drvcmd[4]=pos&0x00FF;
- if (fam0_drive)
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_bit1;
- else
- flags_cmd_out = f_putcmd;
- }
- else if (fam1L_drive)
- {
- drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */
- if (f_blk_msf==0) pos=blk2msf(pos);
- drvcmd[1]=(pos>>16)&0x00FF;
- drvcmd[2]=(pos>>8)&0x00FF;
- drvcmd[3]=pos&0x00FF;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_SEEK;
- if (f_blk_msf==0) pos=blk2msf(pos);
- drvcmd[2]=(pos>>24)&0x00FF;
- drvcmd[3]=(pos>>16)&0x00FF;
- drvcmd[4]=(pos>>8)&0x00FF;
- drvcmd[5]=pos&0x00FF;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_SEEK;
- if (f_blk_msf==1) pos=msf2blk(pos);
- drvcmd[2]=(pos>>24)&0x00FF;
- drvcmd[3]=(pos>>16)&0x00FF;
- drvcmd[4]=(pos>>8)&0x00FF;
- drvcmd[5]=pos&0x00FF;
- current_drive->n_bytes=1;
- }
- response_count=0;
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_SpinUp(void)
-{
- int i;
-
- msg(DBG_SPI,"SpinUp.\n");
- current_drive->in_SpinUp = 1;
- clr_cmdbuf();
- if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_SPINUP;
- if (fam0L_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
- f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_SPINUP;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[4]=0x01; /* "spinup" */
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */
- }
- response_count=0;
- i=cmd_out();
- current_drive->in_SpinUp = 0;
- return (i);
-}
-/*==========================================================================*/
-static int cc_SpinDown(void)
-{
- int i;
-
- if (fam0_drive) return (0);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SPINDOWN;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[4]=0x02; /* "eject" */
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famL_drive)
- {
- drvcmd[0]=CMDL_SPINDOWN;
- drvcmd[1]=1;
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (famV_drive)
- {
- drvcmd[0]=CMDV_SPINDOWN;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x02; /* "eject" */
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_get_mode_T(void)
-{
- int i;
-
- clr_cmdbuf();
- response_count=10;
- drvcmd[0]=CMDT_GETMODE;
- drvcmd[4]=response_count;
- i=cmd_out_T();
- return (i);
-}
-/*==========================================================================*/
-static int cc_set_mode_T(void)
-{
- int i;
-
- clr_cmdbuf();
- response_count=1;
- drvcmd[0]=CMDT_SETMODE;
- drvcmd[1]=current_drive->speed_byte;
- drvcmd[2]=current_drive->frmsiz>>8;
- drvcmd[3]=current_drive->frmsiz&0x0FF;
- drvcmd[4]=current_drive->f_XA; /* 1: XA */
- drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */
- drvcmd[6]=current_drive->mode_xb_6;
- drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control;
- drvcmd[8]=current_drive->mode_xb_8;
- drvcmd[9]=current_drive->delay;
- i=cmd_out_T();
- return (i);
-}
-/*==========================================================================*/
-static int cc_prep_mode_T(void)
-{
- int i, j;
-
- i=cc_get_mode_T();
- if (i<0) return (i);
- for (i=0;i<10;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
- current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */
- current_drive->frmsiz=make16(infobuf[2],infobuf[3]);
- current_drive->f_XA=infobuf[4];
- if (current_drive->f_XA==0) current_drive->type_byte=0;
- else current_drive->type_byte=1;
- current_drive->mode_xb_6=infobuf[6];
- current_drive->mode_yb_7=1;
- current_drive->mode_xb_8=infobuf[8];
- current_drive->delay=0; /* 0, 1, 2, 3 */
- j=cc_set_mode_T();
- i=cc_get_mode_T();
- for (i=0;i<10;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
- return (j);
-}
-/*==========================================================================*/
-static int cc_SetSpeed(u_char speed, u_char x1, u_char x2)
-{
- int i;
-
- if (fam0LV_drive) return (0);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x03;
- drvcmd[2]=speed;
- drvcmd[3]=x1;
- drvcmd[4]=x2;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_SETSPEED;
- if (speed&speed_auto)
- {
- drvcmd[2]=0xFF;
- drvcmd[3]=0xFF;
- }
- else
- {
- drvcmd[2]=0;
- drvcmd[3]=150;
- }
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- return (0);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_SetVolume(void)
-{
- int i;
- u_char channel0,channel1,volume0,volume1;
- u_char control0,value0,control1,value1;
-
- current_drive->diskstate_flags &= ~volume_bit;
- clr_cmdbuf();
- channel0=current_drive->vol_chan0;
- volume0=current_drive->vol_ctrl0;
- channel1=control1=current_drive->vol_chan1;
- volume1=value1=current_drive->vol_ctrl1;
- control0=value0=0;
-
- if (famV_drive) return (0);
-
- if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211))
- {
- if ((volume0!=0)&&(volume1==0))
- {
- volume1=volume0;
- channel1=channel0;
- }
- else if ((volume0==0)&&(volume1!=0))
- {
- volume0=volume1;
- channel0=channel1;
- }
- }
- if (channel0>1)
- {
- channel0=0;
- volume0=0;
- }
- if (channel1>1)
- {
- channel1=1;
- volume1=0;
- }
-
- if (fam1_drive)
- {
- control0=channel0+1;
- control1=channel1+1;
- value0=(volume0>volume1)?volume0:volume1;
- value1=value0;
- if (volume0==0) control0=0;
- if (volume1==0) control1=0;
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x05;
- drvcmd[3]=control0;
- drvcmd[4]=value0;
- drvcmd[5]=control1;
- drvcmd[6]=value1;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- control0=channel0+1;
- control1=channel1+1;
- value0=(volume0>volume1)?volume0:volume1;
- value1=value0;
- if (volume0==0) control0=0;
- if (volume1==0) control1=0;
- drvcmd[0]=CMD2_SETMODE;
- drvcmd[1]=0x0E;
- drvcmd[3]=control0;
- drvcmd[4]=value0;
- drvcmd[5]=control1;
- drvcmd[6]=value1;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famL_drive)
- {
- if ((volume0==0)||(channel0!=0)) control0 |= 0x80;
- if ((volume1==0)||(channel1!=1)) control0 |= 0x40;
- if (volume0|volume1) value0=0x80;
- drvcmd[0]=CMDL_SETMODE;
- drvcmd[1]=0x03;
- drvcmd[4]=control0;
- drvcmd[5]=value0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam0_drive) /* different firmware levels */
- {
- if (current_drive->drv_type>=drv_300)
- {
- control0=volume0&0xFC;
- value0=volume1&0xFC;
- if ((volume0!=0)&&(volume0<4)) control0 |= 0x04;
- if ((volume1!=0)&&(volume1<4)) value0 |= 0x04;
- if (channel0!=0) control0 |= 0x01;
- if (channel1==1) value0 |= 0x01;
- }
- else
- {
- value0=(volume0>volume1)?volume0:volume1;
- if (current_drive->drv_type<drv_211)
- {
- if (channel0!=0)
- {
- i=channel1;
- channel1=channel0;
- channel0=i;
- i=volume1;
- volume1=volume0;
- volume0=i;
- }
- if (channel0==channel1)
- {
- if (channel0==0)
- {
- channel1=1;
- volume1=0;
- volume0=value0;
- }
- else
- {
- channel0=0;
- volume0=0;
- volume1=value0;
- }
- }
- }
-
- if ((volume0!=0)&&(volume1!=0))
- {
- if (volume0==0xFF) volume1=0xFF;
- else if (volume1==0xFF) volume0=0xFF;
- }
- else if (current_drive->drv_type<drv_201) volume0=volume1=value0;
-
- if (current_drive->drv_type>=drv_201)
- {
- if (volume0==0) control0 |= 0x80;
- if (volume1==0) control0 |= 0x40;
- }
- if (current_drive->drv_type>=drv_211)
- {
- if (channel0!=0) control0 |= 0x20;
- if (channel1!=1) control0 |= 0x10;
- }
- }
- drvcmd[0]=CMD0_SETMODE;
- drvcmd[1]=0x83;
- drvcmd[4]=control0;
- drvcmd[5]=value0;
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- current_drive->volume_control=0;
- if (!volume0) current_drive->volume_control|=0x10;
- if (!volume1) current_drive->volume_control|=0x20;
- i=cc_prep_mode_T();
- if (i<0) return (i);
- }
- if (!famT_drive)
- {
- response_count=0;
- i=cmd_out();
- if (i<0) return (i);
- }
- current_drive->diskstate_flags |= volume_bit;
- return (0);
-}
-/*==========================================================================*/
-static int GetStatus(void)
-{
- int i;
-
- if (famT_drive) return (0);
- flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check;
- response_count=0;
- cmd_type=0;
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void)
-{
- int i;
-
- msg(DBG_RES,"cc_DriveReset called.\n");
- clr_cmdbuf();
- response_count=0;
- if (fam0LV_drive) OUT(CDo_reset,0x00);
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_RESET;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_RESET;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- OUT(CDo_reset,0x00);
- }
- else if (famT_drive)
- {
- OUT(CDo_sel_i_d,0);
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_command,CMDT_RESET);
- for (i=1;i<10;i++) OUT(CDo_command,0);
- }
- if (fam0LV_drive) sbp_sleep(5*HZ); /* wait 5 seconds */
- else sbp_sleep(1*HZ); /* wait a second */
-#if 1
- if (famT_drive)
- {
- msg(DBG_TEA, "================CMDT_RESET given=================.\n");
- sbp_sleep(3*HZ);
- }
-#endif /* 1 */
- flush_status();
- i=GetStatus();
- if (i<0) return i;
- if (!famT_drive)
- if (current_drive->error_byte!=aud_12) return -501;
- return (0);
-}
-
-/*==========================================================================*/
-static int SetSpeed(void)
-{
- int i, speed;
-
- if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0);
- speed=speed_auto;
- if (!(current_drive->drv_options&speed_auto))
- {
- speed |= speed_300;
- if (!(current_drive->drv_options&speed_300)) speed=0;
- }
- i=cc_SetSpeed(speed,0,0);
- return (i);
-}
-
-static void switch_drive(struct sbpcd_drive *);
-
-static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- struct sbpcd_drive *p = cdi->handle;
- if (p != current_drive)
- switch_drive(p);
-
- return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
-}
-
-/*==========================================================================*/
-static int DriveReset(void)
-{
- int i;
-
- i=cc_DriveReset();
- if (i<0) return (-22);
- do
- {
- i=GetStatus();
- if ((i<0)&&(i!=-ERR_DISKCHANGE)) {
- return (-2); /* from sta2err */
- }
- if (!st_caddy_in) break;
- sbp_sleep(1);
- }
- while (!st_diskok);
-#if 000
- current_drive->CD_changed=1;
-#endif
- if ((st_door_closed) && (st_caddy_in))
- {
- i=DiskInfo();
- if (i<0) return (-23);
- }
- return (0);
-}
-
-static int sbpcd_reset(struct cdrom_device_info *cdi)
-{
- struct sbpcd_drive *p = cdi->handle;
- if (p != current_drive)
- switch_drive(p);
- return DriveReset();
-}
-
-/*==========================================================================*/
-static int cc_PlayAudio(int pos_audio_start,int pos_audio_end)
-{
- int i, j, n;
-
- if (current_drive->audio_state==audio_playing) return (-EINVAL);
- clr_cmdbuf();
- response_count=0;
- if (famLV_drive)
- {
- drvcmd[0]=CMDL_PLAY;
- i=msf2blk(pos_audio_start);
- n=msf2blk(pos_audio_end)+1-i;
- drvcmd[1]=(i>>16)&0x00FF;
- drvcmd[2]=(i>>8)&0x00FF;
- drvcmd[3]=i&0x00FF;
- drvcmd[4]=(n>>16)&0x00FF;
- drvcmd[5]=(n>>8)&0x00FF;
- drvcmd[6]=n&0x00FF;
- if (famL_drive)
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
- else
- flags_cmd_out = f_putcmd;
- }
- else
- {
- j=1;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
- f_obey_p_check | f_wait_if_busy;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_ResponseStatus | f_obey_p_check;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_PLAY_MSF;
- j=3;
- response_count=1;
- }
- else if (fam0_drive)
- {
- drvcmd[0]=CMD0_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
- }
- drvcmd[j]=(pos_audio_start>>16)&0x00FF;
- drvcmd[j+1]=(pos_audio_start>>8)&0x00FF;
- drvcmd[j+2]=pos_audio_start&0x00FF;
- drvcmd[j+3]=(pos_audio_end>>16)&0x00FF;
- drvcmd[j+4]=(pos_audio_end>>8)&0x00FF;
- drvcmd[j+5]=pos_audio_end&0x00FF;
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_Pause_Resume(int pau_res)
-{
- int i;
-
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_PAU_RES;
- if (pau_res!=1) drvcmd[1]=0x80;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_PAU_RES;
- if (pau_res!=1) drvcmd[2]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_PAU_RES;
- if (pau_res!=1) drvcmd[1]=0x80;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
- f_obey_p_check|f_bit1;
- else if (famV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
- f_obey_p_check;
- }
- else if (famT_drive)
- {
- if (pau_res==3) return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end));
- else if (pau_res==1) drvcmd[0]=CMDT_PAUSE;
- else return (-56);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_LockDoor(char lock)
-{
- int i;
-
- if (fam0_drive) return (0);
- msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S);
- msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_LOCK_CTL;
- if (lock==1) drvcmd[1]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_LOCK_CTL;
- if (lock==1) drvcmd[4]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_LOCK_CTL;
- if (lock==1) drvcmd[1]=0x01;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_LOCK_CTL;
- if (lock==1) drvcmd[4]=0x01;
- }
- i=cmd_out();
- msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked);
- return (i);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int UnLockDoor(void)
-{
- int i,j;
-
- j=20;
- do
- {
- i=cc_LockDoor(0);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- if (i<0)
- {
- cc_DriveReset();
- return -84;
- }
- return (0);
-}
-/*==========================================================================*/
-static int LockDoor(void)
-{
- int i,j;
-
- j=20;
- do
- {
- i=cc_LockDoor(1);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- if (j==0)
- {
- cc_DriveReset();
- j=20;
- do
- {
- i=cc_LockDoor(1);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- }
- return (i);
-}
-
-static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- return lock ? LockDoor() : UnLockDoor();
-}
-
-/*==========================================================================*/
-static int cc_CloseTray(void)
-{
- int i;
-
- if (fam0_drive) return (0);
- msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S);
- msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed);
-
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_TRAY_CTL;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[1]=0x01;
- drvcmd[4]=0x03; /* "insert" */
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_TRAY_CTL;
- if (famLV_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
- f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x03; /* "insert" */
- }
- i=cmd_out();
- msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed);
-
- i=cc_ReadError();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus(); /* command: give 1-byte status */
- i=ResponseStatus();
- if (famT_drive&&(i<0))
- {
- cc_DriveReset();
- i=ResponseStatus();
-#if 0
- sbp_sleep(HZ);
-#endif /* 0 */
- i=ResponseStatus();
- }
- if (i<0)
- {
- msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i);
- }
- if (!(famT_drive))
- {
- if (!st_spinning)
- {
- cc_SpinUp();
- if (st_check) i=cc_ReadError();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus();
- i=ResponseStatus();
- } else {
- }
- }
- i=DiskInfo();
- return (i);
-}
-
-static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
-{
- int retval=0;
- switch_drive(cdi->handle);
- /* DUH! --AJK */
- if(current_drive->CD_changed != 0xFF) {
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~cd_size_bit;
- }
- if (position == 1) {
- cc_SpinDown();
- } else {
- retval=cc_CloseTray();
- }
- return retval;
-}
-
-/*==========================================================================*/
-static int cc_ReadSubQ(void)
-{
- int i,j;
-
- current_drive->diskstate_flags &= ~subq_bit;
- for (j=255;j>0;j--)
- {
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READSUBQ;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- response_count=11;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READSUBQ;
- drvcmd[1]=0x02;
- drvcmd[3]=0x01;
- flags_cmd_out=f_putcmd;
- response_count=10;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READSUBQ;
- drvcmd[1]=0x02;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- response_count=13;
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_READSUBQ;
- drvcmd[1]=0x02;
- drvcmd[2]=0x40;
- drvcmd[3]=0x01;
- drvcmd[8]=response_count;
- }
- i=cmd_out();
- if (i<0) return (i);
- for (i=0;i<response_count;i++)
- {
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_SQ1,"cc_ReadSubQ:%s\n", msgbuf);
- }
- if (famT_drive) break;
- if (infobuf[0]!=0) break;
- if ((!st_spinning) || (j==1))
- {
- current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0;
- current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0;
- return (0);
- }
- }
- if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1];
- else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]);
- current_drive->SubQ_trk=byt2bcd(infobuf[2]);
- current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]);
- if (fam0LV_drive) i=5;
- else if (fam12_drive) i=4;
- else if (famT_drive) i=8;
- current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
- i=7;
- if (fam0LV_drive) i=9;
- else if (fam12_drive) i=7;
- else if (famT_drive) i=4;
- current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
- current_drive->SubQ_whatisthis=infobuf[i+3];
- current_drive->diskstate_flags |= subq_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ModeSense(void)
-{
- int i;
-
- if (fam2_drive) return (0);
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~frame_size_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- response_count=5;
- drvcmd[0]=CMD1_GETMODE;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- response_count=2;
- drvcmd[0]=CMD0_GETMODE;
- if (famL_drive) flags_cmd_out=f_putcmd;
- else flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- response_count=10;
- drvcmd[0]=CMDT_GETMODE;
- drvcmd[4]=response_count;
- }
- i=cmd_out();
- if (i<0) return (i);
- i=0;
- current_drive->sense_byte=0;
- if (fam1_drive) current_drive->sense_byte=infobuf[i++];
- else if (famT_drive)
- {
- if (infobuf[4]==0x01) current_drive->xa_byte=0x20;
- else current_drive->xa_byte=0;
- i=2;
- }
- current_drive->frame_size=make16(infobuf[i],infobuf[i+1]);
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf);
-
- current_drive->diskstate_flags |= frame_size_bit;
- return (0);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int cc_ModeSelect(int framesize)
-{
- int i;
-
- if (fam2_drive) return (0);
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~frame_size_bit;
- clr_cmdbuf();
- current_drive->frame_size=framesize;
- if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82;
- else current_drive->sense_byte=0x00;
-
- msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n",
- current_drive->sense_byte, current_drive->frame_size);
-
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x00;
- drvcmd[2]=current_drive->sense_byte;
- drvcmd[3]=(current_drive->frame_size>>8)&0xFF;
- drvcmd[4]=current_drive->frame_size&0xFF;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_SETMODE;
- drvcmd[1]=0x00;
- drvcmd[2]=(current_drive->frame_size>>8)&0xFF;
- drvcmd[3]=current_drive->frame_size&0xFF;
- drvcmd[4]=0x00;
- if(famL_drive)
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- return (-1);
- }
- response_count=0;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->diskstate_flags |= frame_size_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_GetVolume(void)
-{
- int i;
- u_char switches;
- u_char chan0=0;
- u_char vol0=0;
- u_char chan1=1;
- u_char vol1=0;
-
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~volume_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_GETMODE;
- drvcmd[1]=0x05;
- response_count=5;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_GETMODE;
- drvcmd[1]=0x0E;
- response_count=5;
- flags_cmd_out=f_putcmd;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_GETMODE;
- drvcmd[1]=0x03;
- response_count=2;
- if(famL_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- i=cc_get_mode_T();
- if (i<0) return (i);
- }
- if (!famT_drive)
- {
- i=cmd_out();
- if (i<0) return (i);
- }
- if (fam1_drive)
- {
- chan0=infobuf[1]&0x0F;
- vol0=infobuf[2];
- chan1=infobuf[3]&0x0F;
- vol1=infobuf[4];
- if (chan0==0)
- {
- chan0=1;
- vol0=0;
- }
- if (chan1==0)
- {
- chan1=2;
- vol1=0;
- }
- chan0 >>= 1;
- chan1 >>= 1;
- }
- else if (fam2_drive)
- {
- chan0=infobuf[1];
- vol0=infobuf[2];
- chan1=infobuf[3];
- vol1=infobuf[4];
- }
- else if (famL_drive)
- {
- chan0=0;
- chan1=1;
- vol0=vol1=infobuf[1];
- switches=infobuf[0];
- if ((switches&0x80)!=0) chan0=1;
- if ((switches&0x40)!=0) chan1=0;
- }
- else if (fam0_drive) /* different firmware levels */
- {
- chan0=0;
- chan1=1;
- vol0=vol1=infobuf[1];
- if (current_drive->drv_type>=drv_201)
- {
- if (current_drive->drv_type<drv_300)
- {
- switches=infobuf[0];
- if ((switches&0x80)!=0) vol0=0;
- if ((switches&0x40)!=0) vol1=0;
- if (current_drive->drv_type>=drv_211)
- {
- if ((switches&0x20)!=0) chan0=1;
- if ((switches&0x10)!=0) chan1=0;
- }
- }
- else
- {
- vol0=infobuf[0];
- if ((vol0&0x01)!=0) chan0=1;
- if ((vol1&0x01)==0) chan1=0;
- vol0 &= 0xFC;
- vol1 &= 0xFC;
- if (vol0!=0) vol0 += 3;
- if (vol1!=0) vol1 += 3;
- }
- }
- }
- else if (famT_drive)
- {
- current_drive->volume_control=infobuf[7];
- chan0=0;
- chan1=1;
- if (current_drive->volume_control&0x10) vol0=0;
- else vol0=0xff;
- if (current_drive->volume_control&0x20) vol1=0;
- else vol1=0xff;
- }
- current_drive->vol_chan0=chan0;
- current_drive->vol_ctrl0=vol0;
- current_drive->vol_chan1=chan1;
- current_drive->vol_ctrl1=vol1;
-#if 000
- current_drive->vol_chan2=2;
- current_drive->vol_ctrl2=0xFF;
- current_drive->vol_chan3=3;
- current_drive->vol_ctrl3=0xFF;
-#endif /* 000 */
- current_drive->diskstate_flags |= volume_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadCapacity(void)
-{
- int i, j;
-
- if (fam2_drive) return (0); /* some firmware lacks this command */
- if (famLV_drive) return (0); /* some firmware lacks this command */
- if (famT_drive) return (0); /* done with cc_ReadTocDescr() */
- current_drive->diskstate_flags &= ~cd_size_bit;
- for (j=3;j>0;j--)
- {
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_CAPACITY;
- response_count=5;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
-#if 00
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_CAPACITY;
- response_count=8;
- flags_cmd_out=f_putcmd;
- }
-#endif
- else if (fam0_drive)
- {
- drvcmd[0]=CMD0_CAPACITY;
- response_count=5;
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- i=cmd_out();
- if (i>=0) break;
- msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i);
- cc_ReadError();
- }
- if (j==0) return (i);
- if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET;
- else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
-#if 00
- else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
-#endif
- current_drive->diskstate_flags |= cd_size_bit;
- msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocDescr(void)
-{
- int i;
-
- current_drive->diskstate_flags &= ~toc_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_DISKINFO;
- response_count=6;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_DISKINFO;
- response_count=6;
- if(famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- /* possibly longer timeout periods necessary */
- current_drive->f_multisession=0;
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAB;
- drvcmd[3]=0xFF; /* session */
- response_count=8;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- current_drive->f_multisession=0;
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=CDROM_LEADOUT;
- drvcmd[8]=response_count;
- drvcmd[9]=0x00;
- }
- i=cmd_out();
- if (i<0) return (i);
- if ((famT_drive)&&(i<response_count)) return (-100-i);
- if ((fam1_drive)||(fam2_drive)||(fam0LV_drive))
- current_drive->xa_byte=infobuf[0];
- if (fam2_drive)
- {
- current_drive->first_session=infobuf[1];
- current_drive->last_session=infobuf[2];
- current_drive->n_first_track=infobuf[3];
- current_drive->n_last_track=infobuf[4];
- if (current_drive->first_session!=current_drive->last_session)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
- }
-#if 0
- if (current_drive->first_session!=current_drive->last_session)
- {
- if (current_drive->last_session<=20)
- zwanzig=current_drive->last_session+1;
- else zwanzig=20;
- for (count=current_drive->first_session;count<zwanzig;count++)
- {
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAB;
- drvcmd[3]=count;
- response_count=8;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
- }
- current_drive->diskstate_flags |= multisession_bit;
- }
-#endif
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAA;
- drvcmd[3]=0xFF;
- response_count=5;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- current_drive->CDsize_frm=current_drive->size_blk+1;
- }
- else if (famT_drive)
- {
- current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- current_drive->CDsize_frm=current_drive->size_blk+1;
- current_drive->n_first_track=infobuf[2];
- current_drive->n_last_track=infobuf[3];
- }
- else
- {
- current_drive->n_first_track=infobuf[1];
- current_drive->n_last_track=infobuf[2];
- current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1;
- }
- current_drive->diskstate_flags |= toc_bit;
- msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n",
- current_drive->xa_byte,
- current_drive->n_first_track,
- current_drive->n_last_track,
- current_drive->size_msf,
- current_drive->first_session,
- current_drive->last_session);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocEntry(int num)
-{
- int i;
-
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READTOC;
- drvcmd[2]=num;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- /* possibly longer timeout periods necessary */
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=num;
- response_count=5;
- flags_cmd_out=f_putcmd;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READTOC;
- drvcmd[1]=0x02;
- drvcmd[2]=num;
- response_count=8;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=num;
- drvcmd[8]=response_count;
- drvcmd[9]=0x00;
- }
- i=cmd_out();
- if (i<0) return (i);
- if ((famT_drive)&&(i<response_count)) return (-100-i);
- if ((fam1_drive)||(fam0LV_drive))
- {
- current_drive->TocEnt_nixbyte=infobuf[0];
- i=1;
- }
- else if (fam2_drive) i=0;
- else if (famT_drive) i=5;
- current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
- if ((fam1_drive)||(fam0L_drive))
- {
- current_drive->TocEnt_number=infobuf[i++];
- current_drive->TocEnt_format=infobuf[i];
- }
- else
- {
- current_drive->TocEnt_number=num;
- current_drive->TocEnt_format=0;
- }
- if (fam1_drive) i=4;
- else if (fam0LV_drive) i=5;
- else if (fam2_drive) i=2;
- else if (famT_drive) i=9;
- current_drive->TocEnt_address=make32(make16(0,infobuf[i]),
- make16(infobuf[i+1],infobuf[i+2]));
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"TocEntry:%s\n", msgbuf);
- msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n",
- current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr,
- current_drive->TocEnt_number, current_drive->TocEnt_format,
- current_drive->TocEnt_address);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadPacket(void)
-{
- int i;
-
- clr_cmdbuf();
- drvcmd[0]=CMD0_PACKET;
- drvcmd[1]=response_count;
- if(famL_drive) flags_cmd_out=f_putcmd;
- else if (fam01_drive)
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- else if (fam2_drive) return (-1); /* not implemented yet */
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int convert_UPC(u_char *p)
-{
- int i;
-
- p++;
- if (fam0L_drive) p[13]=0;
- for (i=0;i<7;i++)
- {
- if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++);
- else if (fam0L_drive)
- {
- current_drive->UPC_buf[i]=((*p++)<<4)&0xFF;
- current_drive->UPC_buf[i] |= *p++;
- }
- else if (famT_drive)
- {
- return (-1);
- }
- else /* CD200 */
- {
- return (-1);
- }
- }
- current_drive->UPC_buf[6] &= 0xF0;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadUPC(void)
-{
- int i;
-#if TEST_UPC
- int block, checksum;
-#endif /* TEST_UPC */
-
- if (fam2_drive) return (0); /* not implemented yet */
- if (famT_drive) return (0); /* not implemented yet */
- if (famV_drive) return (0); /* not implemented yet */
-#if 1
- if (fam0_drive) return (0); /* but it should work */
-#endif
-
- current_drive->diskstate_flags &= ~upc_bit;
-#if TEST_UPC
- for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++)
- {
-#endif /* TEST_UPC */
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_UPC;
-#if TEST_UPC
- drvcmd[1]=(block>>16)&0xFF;
- drvcmd[2]=(block>>8)&0xFF;
- drvcmd[3]=block&0xFF;
-#endif /* TEST_UPC */
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_READ_UPC;
-#if TEST_UPC
- drvcmd[2]=(block>>16)&0xFF;
- drvcmd[3]=(block>>8)&0xFF;
- drvcmd[4]=block&0xFF;
-#endif /* TEST_UPC */
- response_count=0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam2_drive)
- {
- return (-1);
- }
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
- return (i);
- }
- if (fam0L_drive)
- {
- response_count=16;
- if (famL_drive) flags_cmd_out=f_putcmd;
- i=cc_ReadPacket();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
- return (i);
- }
- }
-#if TEST_UPC
- checksum=0;
-#endif /* TEST_UPC */
- for (i=0;i<(fam1_drive?8:16);i++)
- {
-#if TEST_UPC
- checksum |= infobuf[i];
-#endif /* TEST_UPC */
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- }
- msgbuf[i*3]=0;
- msg(DBG_UPC,"UPC info:%s\n", msgbuf);
-#if TEST_UPC
- if ((checksum&0x7F)!=0) break;
- }
-#endif /* TEST_UPC */
- current_drive->UPC_ctl_adr=0;
- if (fam1_drive) i=0;
- else i=2;
- if ((infobuf[i]&0x80)!=0)
- {
- convert_UPC(&infobuf[i]);
- current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02;
- }
- for (i=0;i<7;i++)
- sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]);
- sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr);
- msgbuf[i*3+5]=0;
- msg(DBG_UPC,"UPC code:%s\n", msgbuf);
- current_drive->diskstate_flags |= upc_bit;
- return (0);
-}
-
-static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- int i;
- unsigned char *mcnp = mcn->medium_catalog_number;
- unsigned char *resp;
-
- current_drive->diskstate_flags &= ~upc_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_UPC;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_READ_UPC;
- response_count=0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam2_drive)
- {
- return (-1);
- }
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
- return (i);
- }
- if (fam0L_drive)
- {
- response_count=16;
- if (famL_drive) flags_cmd_out=f_putcmd;
- i=cc_ReadPacket();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
- return (i);
- }
- }
- current_drive->UPC_ctl_adr=0;
- if (fam1_drive) i=0;
- else i=2;
-
- resp = infobuf + i;
- if (*resp++ == 0x80) {
- /* packed bcd to single ASCII digits */
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- }
- *mcnp = '\0';
-
- current_drive->diskstate_flags |= upc_bit;
- return (0);
-}
-
-/*==========================================================================*/
-static int cc_CheckMultiSession(void)
-{
- int i;
-
- if (fam2_drive) return (0);
- current_drive->f_multisession=0;
- current_drive->lba_multi=0;
- if (fam0_drive) return (0);
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_MULTISESS;
- response_count=6;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- i=cmd_out();
- if (i<0) return (i);
- if ((infobuf[0]&0x80)!=0)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]),
- make16(infobuf[2],infobuf[3])));
- }
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_MULTISESS;
- drvcmd[1]=3;
- drvcmd[2]=1;
- response_count=8;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),
- make16(infobuf[6],infobuf[7])));
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=0;
- drvcmd[8]=response_count;
- drvcmd[9]=0x40;
- i=cmd_out();
- if (i<0) return (i);
- if (i<response_count) return (-100-i);
- current_drive->first_session=infobuf[2];
- current_drive->last_session=infobuf[3];
- current_drive->track_of_last_session=infobuf[6];
- if (current_drive->first_session!=current_drive->last_session)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
- }
- }
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi);
- if (current_drive->lba_multi>200)
- {
- current_drive->f_multisession=1;
- msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi);
- }
- return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-static int cc_SubChanInfo(int frame, int count, u_char *buffer)
- /* "frame" is a RED BOOK (msf-bin) address */
-{
- int i;
-
- if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */
- if (famT_drive)
- {
- return (-1);
- }
-#if 0
- if (current_drive->audio_state!=audio_playing) return (-ENODATA);
-#endif
- clr_cmdbuf();
- drvcmd[0]=CMD1_SUBCHANINF;
- drvcmd[1]=(frame>>16)&0xFF;
- drvcmd[2]=(frame>>8)&0xFF;
- drvcmd[3]=frame&0xFF;
- drvcmd[5]=(count>>8)&0xFF;
- drvcmd[6]=count&0xFF;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- cmd_type=READ_SC;
- current_drive->frame_size=CD_FRAMESIZE_SUB;
- i=cmd_out(); /* which buffer to use? */
- return (i);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-static void __init check_datarate(void)
-{
- int i=0;
-
- msg(DBG_IOX,"check_datarate entered.\n");
- datarate=0;
-#if TEST_STI
- for (i=0;i<=1000;i++) printk(".");
-#endif
- /* set a timer to make (timed_out_delay!=0) after 1.1 seconds */
-#if 1
- del_timer(&delay_timer);
-#endif
- delay_timer.expires=jiffies+11*HZ/10;
- timed_out_delay=0;
- add_timer(&delay_timer);
-#if 0
- msg(DBG_TIM,"delay timer started (11*HZ/10).\n");
-#endif
- do
- {
- i=inb(CDi_status);
- datarate++;
-#if 1
- if (datarate>0x6FFFFFFF) break;
-#endif
- }
- while (!timed_out_delay);
- del_timer(&delay_timer);
-#if 0
- msg(DBG_TIM,"datarate: %04X\n", datarate);
-#endif
- if (datarate<65536) datarate=65536;
- maxtim16=datarate*16;
- maxtim04=datarate*4;
- maxtim02=datarate*2;
- maxtim_8=datarate/32;
-#if LONG_TIMING
- maxtim_data=datarate/100;
-#else
- maxtim_data=datarate/300;
-#endif /* LONG_TIMING */
-#if 0
- msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data);
-#endif
-}
-/*==========================================================================*/
-#if 0
-static int c2_ReadError(int fam)
-{
- int i;
-
- clr_cmdbuf();
- response_count=9;
- clr_respo_buf(9);
- if (fam==1)
- {
- drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
- i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus);
- }
- else if (fam==2)
- {
- drvcmd[0]=CMD2_READ_ERR;
- i=do_cmd(f_putcmd);
- }
- else return (-1);
- return (i);
-}
-#endif
-/*==========================================================================*/
-static void __init ask_mail(void)
-{
- int i;
-
- msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de\n");
- msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n");
- msg(DBG_INF, "%s\n", VERSION);
- msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n",
- CDo_command, type, current_drive->drive_model, current_drive->drv_id);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_INF,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_INF,"infobuf =%s\n", msgbuf);
-}
-/*==========================================================================*/
-static int __init check_version(void)
-{
- int i, j, l;
- int teac_possible=0;
-
- msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S);
- current_drive->drv_type=0;
-
- /* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */
- /* clear any pending error state */
- clr_cmdbuf();
- drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
- response_count=9;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).\n",i);
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */
- response_count=12; /* fam1: only 11 */
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i);
- if (i==-11) teac_possible++;
- j=0;
- for (i=0;i<12;i++) j+=infobuf[i];
- if (j)
- {
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"infobuf =%s\n", msgbuf);
- }
- for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break;
- if (i==4)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='R';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]=infobuf[i++];
- current_drive->drive_model[5]=infobuf[i++];
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_fam1;
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break;
- if (i==8)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='R';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]='2';
- current_drive->drive_model[5]='x';
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_fam0;
- }
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break;
- if (i==8)
- {
- for (j=0;j<8;j++)
- current_drive->drive_model[j]=infobuf[j];
- current_drive->drive_model[8]=0;
- current_drive->drv_type=drv_famL;
- }
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break;
- if (i==6)
- {
- for (j=0;j<6;j++)
- current_drive->drive_model[j]=infobuf[j];
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_famV;
- i+=2; /* 2 blanks before version */
- }
- }
- if (!current_drive->drv_type)
- {
- /* check for CD200 */
- clr_cmdbuf();
- drvcmd[0]=CMD2_READ_ERR;
- response_count=9;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i);
- if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i);
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-#if 0
- OUT(CDo_reset,0);
- sbp_sleep(6*HZ);
- OUT(CDo_enable,current_drive->drv_sel);
-#endif
- drvcmd[0]=CMD2_READ_VER;
- response_count=12;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i);
- if (i==-7) teac_possible++;
- j=0;
- for (i=0;i<12;i++) j+=infobuf[i];
- if (j)
- {
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_IDX,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_IDX,"infobuf =%s\n", msgbuf);
- }
- if (i>=0)
- {
- for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break;
- if (i==5)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='D';
- current_drive->drive_model[2]='2';
- current_drive->drive_model[3]='0';
- current_drive->drive_model[4]='0';
- current_drive->drive_model[5]=infobuf[i++];
- current_drive->drive_model[6]=infobuf[i++];
- current_drive->drive_model[7]=0;
- current_drive->drv_type=drv_fam2;
- }
- }
- }
- if (!current_drive->drv_type)
- {
- /* check for TEAC CD-55A */
- msg(DBG_TEA,"teac_possible: %d\n",teac_possible);
- for (j=1;j<=((current_drive->drv_id==0)?3:1);j++)
- {
- for (l=1;l<=((current_drive->drv_id==0)?10:1);l++)
- {
- msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l);
- if (sbpro_type==1) OUT(CDo_reset,0);
- else
- {
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_sel_i_d,0);
- OUT(CDo_command,CMDT_RESET);
- for (i=0;i<9;i++) OUT(CDo_command,0);
- }
- sbp_sleep(5*HZ/10);
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_sel_i_d,0);
- i=inb(CDi_status);
- msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i);
-#if 0
- if (i&s_not_result_ready) continue; /* drive not present or ready */
-#endif
- i=inb(CDi_info);
- msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i);
- if (i==0x55) break; /* drive found */
- }
- if (i==0x55) break; /* drive found */
- }
- if (i==0x55) /* drive found */
- {
- msg(DBG_TEA,"TEAC drive found.\n");
- clr_cmdbuf();
- flags_cmd_out=f_putcmd;
- response_count=12;
- drvcmd[0]=CMDT_READ_VER;
- drvcmd[4]=response_count;
- for (i=0;i<12;i++) infobuf[i]=0;
- i=cmd_out_T();
- if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i);
- for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break;
- if (i==6)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='D';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]='5';
- current_drive->drive_model[5]=0;
- current_drive->drv_type=drv_famT;
- }
- }
- }
- if (!current_drive->drv_type)
- {
- msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id);
- return (-522);
- }
- for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j];
- if (famL_drive)
- {
- u_char lcs_firm_e1[]="A E1";
- u_char lcs_firm_f4[]="A4F4";
-
- for (j=0;j<4;j++)
- if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break;
- if (j==4) current_drive->drv_type=drv_e1;
-
- for (j=0;j<4;j++)
- if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break;
- if (j==4) current_drive->drv_type=drv_f4;
-
- if (current_drive->drv_type==drv_famL) ask_mail();
- }
- else if (famT_drive)
- {
- j=infobuf[4]; /* one-byte version??? - here: 0x15 */
- if (j=='5')
- {
- current_drive->firmware_version[0]=infobuf[7];
- current_drive->firmware_version[1]=infobuf[8];
- current_drive->firmware_version[2]=infobuf[10];
- current_drive->firmware_version[3]=infobuf[11];
- }
- else
- {
- if (j!=0x15) ask_mail();
- current_drive->firmware_version[0]='0';
- current_drive->firmware_version[1]='.';
- current_drive->firmware_version[2]='0'+(j>>4);
- current_drive->firmware_version[3]='0'+(j&0x0f);
- }
- }
- else /* CR-52x, CR-56x, CD200, ECS-AT */
- {
- j = (current_drive->firmware_version[0] & 0x0F) * 100 +
- (current_drive->firmware_version[2] & 0x0F) *10 +
- (current_drive->firmware_version[3] & 0x0F);
- if (fam0_drive)
- {
- if (j<200) current_drive->drv_type=drv_199;
- else if (j<201) current_drive->drv_type=drv_200;
- else if (j<210) current_drive->drv_type=drv_201;
- else if (j<211) current_drive->drv_type=drv_210;
- else if (j<300) current_drive->drv_type=drv_211;
- else if (j>=300) current_drive->drv_type=drv_300;
- }
- else if (fam1_drive)
- {
- if (j<100) current_drive->drv_type=drv_099;
- else
- {
- current_drive->drv_type=drv_100;
- if ((j!=500)&&(j!=102)) ask_mail();
- }
- }
- else if (fam2_drive)
- {
- if (current_drive->drive_model[5]=='F')
- {
- if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210))
- ask_mail(); /* unknown version at time */
- }
- else
- {
- msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.\n");
- if ((j!=101)&&(j!=35))
- ask_mail(); /* unknown version at time */
- }
- }
- else if (famV_drive)
- {
- if ((j==100)||(j==150)) current_drive->drv_type=drv_at;
- ask_mail(); /* hopefully we get some feedback by this */
- }
- }
- msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type);
- msg(DBG_INI,"check_version done.\n");
- return (0);
-}
-/*==========================================================================*/
-static void switch_drive(struct sbpcd_drive *p)
-{
- current_drive = p;
- OUT(CDo_enable,current_drive->drv_sel);
- msg(DBG_DID,"drive %d (ID=%d) activated.\n",
- current_drive - D_S, current_drive->drv_id);
- return;
-}
-/*==========================================================================*/
-#ifdef PATH_CHECK
-/*
- * probe for the presence of an interface card
- */
-static int __init check_card(int port)
-{
-#undef N_RESPO
-#define N_RESPO 20
- int i, j, k;
- u_char response[N_RESPO];
- u_char save_port0;
- u_char save_port3;
-
- msg(DBG_INI,"check_card entered.\n");
- save_port0=inb(port+0);
- save_port3=inb(port+3);
-
- for (j=0;j<NR_SBPCD;j++)
- {
- OUT(port+3,j) ; /* enable drive #j */
- OUT(port+0,CMD0_PATH_CHECK);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=10000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
- OUT(port+0,CMD0_PATH_CHECK);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0xFF;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=10000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-
- if (response[0]==0xAA)
- if (response[1]==0x55)
- return (0);
- }
- for (j=0;j<NR_SBPCD;j++)
- {
- OUT(port+3,j) ; /* enable drive #j */
- OUT(port+0,CMD2_READ_VER);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=1000000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
- OUT(port+0,CMD2_READ_VER);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0xFF;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=1000000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
- if (response[0]==0xAA)
- if (response[1]==0x55)
- return (0);
- }
- OUT(port+0,save_port0);
- OUT(port+3,save_port3);
- return (0); /* in any case - no real "function" at time */
-}
-#endif /* PATH_CHECK */
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * probe for the presence of drives on the selected controller
- */
-static int __init check_drives(void)
-{
- int i, j;
-
- msg(DBG_INI,"check_drives entered.\n");
- ndrives=0;
- for (j=0;j<max_drives;j++)
- {
- struct sbpcd_drive *p = D_S + ndrives;
- p->drv_id=j;
- if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1;
- else p->drv_sel=j;
- switch_drive(p);
- msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
- msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
- i=check_version();
- if (i<0) msg(DBG_INI,"check_version returns %d.\n",i);
- else
- {
- current_drive->drv_options=drv_pattern[j];
- if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150);
- msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n",
- current_drive - D_S,
- current_drive->drv_id,
- current_drive->drive_model,
- current_drive->firmware_version,
- CDo_command,
- sbpro_type);
- ndrives++;
- }
- }
- for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1;
- if (ndrives==0) return (-1);
- return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- * obtain if requested service disturbs current audio state
- */
-static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc)
-{
- switch (audio_state) /* audio status from controller */
- {
- case aud_11: /* "audio play in progress" */
- case audx11:
- switch (func) /* DOS command code */
- {
- case cmd_07: /* input flush */
- case cmd_0d: /* open device */
- case cmd_0e: /* close device */
- case cmd_0c: /* ioctl output */
- return (1);
- case cmd_03: /* ioctl input */
- switch (subfunc)
- /* DOS ioctl input subfunction */
- {
- case cxi_00:
- case cxi_06:
- case cxi_09:
- return (1);
- default:
- return (ERROR15);
- }
- return (1);
- default:
- return (ERROR15);
- }
- return (1);
- case aud_12: /* "audio play paused" */
- case audx12:
- return (1);
- default:
- return (2);
- }
-}
-/*==========================================================================*/
-/* allowed is only
- * ioctl_o, flush_input, open_device, close_device,
- * tell_address, tell_volume, tell_capabiliti,
- * tell_framesize, tell_CD_changed, tell_audio_posi
- */
-static int check_allowed1(u_char func1, u_char func2)
-{
-#if 000
- if (func1==ioctl_o) return (0);
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1==audio_pause) return (-1);
- if (func1==audio_resume) return (-1);
- if (func1!=ioctl_i) return (0);
- if (func2==tell_SubQ_run_tot) return (-1);
- if (func2==tell_cdsize) return (-1);
- if (func2==tell_TocDescrip) return (-1);
- if (func2==tell_TocEntry) return (-1);
- if (func2==tell_subQ_info) return (-1);
- if (fam1_drive) if (func2==tell_SubChanInfo) return (-1);
- if (func2==tell_UPC) return (-1);
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed2(u_char func1, u_char func2)
-{
-#if 000
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1!=ioctl_o) return (0);
- if (fam1_drive)
- {
- if (func2==EjectDisk) return (-1);
- if (func2==CloseTray) return (-1);
- }
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed3(u_char func1, u_char func2)
-{
-#if 000
- if (func1==ioctl_i)
- {
- if (func2==tell_address) return (0);
- if (func2==tell_capabiliti) return (0);
- if (func2==tell_CD_changed) return (0);
- if (fam0L_drive) if (func2==tell_SubChanInfo) return (0);
- return (-1);
- }
- if (func1==ioctl_o)
- {
- if (func2==DriveReset) return (0);
- if (fam0L_drive)
- {
- if (func2==EjectDisk) return (0);
- if (func2==LockDoor) return (0);
- if (func2==CloseTray) return (0);
- }
- return (-1);
- }
- if (func1==flush_input) return (-1);
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1==audio_pause) return (-1);
- if (func1==audio_resume) return (-1);
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int seek_pos_audio_end(void)
-{
- int i;
-
- i=msf2blk(current_drive->pos_audio_end)-1;
- if (i<0) return (-1);
- i=cc_Seek(i,0);
- return (i);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-static int ReadToC(void)
-{
- int i, j;
- current_drive->diskstate_flags &= ~toc_bit;
- current_drive->ored_ctl_adr=0;
- /* special handling of CD-I HE */
- if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) ||
- current_drive->xa_byte == 0x10)
- {
- current_drive->TocBuffer[1].nixbyte=0;
- current_drive->TocBuffer[1].ctl_adr=0x40;
- current_drive->TocBuffer[1].number=1;
- current_drive->TocBuffer[1].format=0;
- current_drive->TocBuffer[1].address=blk2msf(0);
- current_drive->ored_ctl_adr |= 0x40;
- current_drive->n_first_track = 1;
- current_drive->n_last_track = 1;
- current_drive->xa_byte = 0x10;
- j = 2;
- } else
- for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++)
- {
- i=cc_ReadTocEntry(j);
- if (i<0)
- {
- msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i);
- return (i);
- }
- current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte;
- current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr;
- current_drive->TocBuffer[j].number=current_drive->TocEnt_number;
- current_drive->TocBuffer[j].format=current_drive->TocEnt_format;
- current_drive->TocBuffer[j].address=current_drive->TocEnt_address;
- current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr;
- }
- /* fake entry for LeadOut Track */
- current_drive->TocBuffer[j].nixbyte=0;
- current_drive->TocBuffer[j].ctl_adr=0;
- current_drive->TocBuffer[j].number=CDROM_LEADOUT;
- current_drive->TocBuffer[j].format=0;
- current_drive->TocBuffer[j].address=current_drive->size_msf;
-
- current_drive->diskstate_flags |= toc_bit;
- return (0);
-}
-/*==========================================================================*/
-static int DiskInfo(void)
-{
- int i, j;
-
- current_drive->mode=READ_M1;
-
-#undef LOOP_COUNT
-#define LOOP_COUNT 10 /* needed for some "old" drives */
-
- msg(DBG_000,"DiskInfo entered.\n");
- for (j=1;j<LOOP_COUNT;j++)
- {
-#if 0
- i=SetSpeed();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: SetSpeed returns %d\n", i);
- continue;
- }
- i=cc_ModeSense();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i);
- continue;
- }
-#endif
- i=cc_ReadCapacity();
- if (i>=0) break;
- msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i);
-#if 0
- i=cc_DriveReset();
-#endif
- if (!fam0_drive && j == 2) break;
- }
- if (j==LOOP_COUNT) return (-33); /* give up */
-
- i=cc_ReadTocDescr();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i);
- return (i);
- }
- i=ReadToC();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i);
- return (i);
- }
- i=cc_CheckMultiSession();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i);
- return (i);
- }
- if (current_drive->f_multisession) current_drive->sbp_bufsiz=1; /* possibly a weird PhotoCD */
- else current_drive->sbp_bufsiz=buffers;
- i=cc_ReadTocEntry(current_drive->n_first_track);
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i);
- return (i);
- }
- i=cc_ReadUPC();
- if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i);
- if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10))
- {
- /* XA disk with old drive */
- cc_ModeSelect(CD_FRAMESIZE_RAW1);
- cc_ModeSense();
- }
- if (famT_drive) cc_prep_mode_T();
- msg(DBG_000,"DiskInfo done.\n");
- return (0);
-}
-
-static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- struct sbpcd_drive *p = cdi->handle;
- int st;
-
- if (CDSL_CURRENT != slot_nr) {
- /* we have no changer support */
- return -EINVAL;
- }
-
- cc_ReadStatus();
- st=ResponseStatus();
- if (st<0)
- {
- msg(DBG_INF,"sbpcd_drive_status: timeout.\n");
- return (0);
- }
- msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
- msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
- msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
- msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
- msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
- msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-
-#if 0
- if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN;
- if (p->status_bits & p_disk_ok) return CDS_DISC_OK;
- if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
-
- return CDS_NO_DISC;
-#else
- if (p->status_bits & p_spinning) return CDS_DISC_OK;
-/* return CDS_TRAY_OPEN; */
- return CDS_NO_DISC;
-
-#endif
-
-}
-
-
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- * called always if driver gets entered
- * returns 0 or ERROR2 or ERROR15
- */
-static int prepare(u_char func, u_char subfunc)
-{
- int i;
-
- if (fam0L_drive)
- {
- i=inb(CDi_status);
- if (i&s_attention) GetStatus();
- }
- else if (fam1_drive) GetStatus();
- else if (fam2_drive) GetStatus();
- else if (famT_drive) GetStatus();
- if (current_drive->CD_changed==0xFF)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- if (!st_diskok)
- {
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- else
- {
- i=check_allowed3(func,subfunc);
- if (i<0)
- {
- current_drive->CD_changed=1;
- return (-15);
- }
- }
- }
- else
- {
- if (!st_diskok)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- else
- {
- if (st_busy)
- {
- if (current_drive->audio_state!=audio_pausing)
- {
- i=check_allowed2(func,subfunc);
- if (i<0) return (-2);
- }
- }
- else
- {
- if (current_drive->audio_state==audio_playing) seek_pos_audio_end();
- current_drive->audio_state=0;
- }
- if (!frame_size_valid)
- {
- i=DiskInfo();
- if (i<0)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- }
- }
- }
- return (0);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * Check the results of the "get status" command.
- */
-static int sbp_status(void)
-{
- int st;
-
- st=ResponseStatus();
- if (st<0)
- {
- msg(DBG_INF,"sbp_status: timeout.\n");
- return (0);
- }
-
- if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n");
-
- if (st_check)
- {
- msg(DBG_INF,"st_check detected - retrying.\n");
- return (0);
- }
- if (!st_door_closed)
- {
- msg(DBG_INF,"door is open - retrying.\n");
- return (0);
- }
- if (!st_caddy_in)
- {
- msg(DBG_INF,"disk removed - retrying.\n");
- return (0);
- }
- if (!st_diskok)
- {
- msg(DBG_INF,"!st_diskok detected - retrying.\n");
- return (0);
- }
- if (st_busy)
- {
- msg(DBG_INF,"st_busy detected - retrying.\n");
- return (0);
- }
- return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
-{
- struct sbpcd_drive *p = cdi->handle;
- ms_infp->addr_format = CDROM_LBA;
- ms_infp->addr.lba = p->lba_multi;
- if (p->f_multisession)
- ms_infp->xa_flag=1; /* valid redirection address */
- else
- ms_infp->xa_flag=0; /* invalid redirection address */
-
- return 0;
-}
-
-static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
- void * arg)
-{
- struct sbpcd_drive *p = cdi->handle;
- int i, st, j;
-
- msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
- if (p->drv_id==-1) {
- msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
- return (-ENXIO); /* no such drive */
- }
- down(&ioctl_read_sem);
- if (p != current_drive)
- switch_drive(p);
-
- msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
- switch (cmd) /* Sun-compatible */
- {
-
- case CDROMPAUSE: /* Pause the drive */
- msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
- /* pause the drive unit when it is currently in PLAY mode, */
- /* or reset the starting and ending locations when in PAUSED mode. */
- /* If applicable, at the next stopping point it reaches */
- /* the drive will discontinue playing. */
- switch (current_drive->audio_state)
- {
- case audio_playing:
- if (famL_drive) i=cc_ReadSubQ();
- else i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- if (famL_drive) i=cc_Pause_Resume(1);
- else i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- current_drive->pos_audio_start=current_drive->SubQ_run_tot;
- current_drive->audio_state=audio_pausing;
- RETURN_UP(0);
- case audio_pausing:
- i=cc_Seek(current_drive->pos_audio_start,1);
- if (i<0) RETURN_UP(-EIO);
- RETURN_UP(0);
- default:
- RETURN_UP(-EINVAL);
- }
-
- case CDROMRESUME: /* resume paused audio play */
- msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n");
- /* resume playing audio tracks when a previous PLAY AUDIO call has */
- /* been paused with a PAUSE command. */
- /* It will resume playing from the location saved in SubQ_run_tot. */
- if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
- if (famL_drive)
- i=cc_PlayAudio(current_drive->pos_audio_start,
- current_drive->pos_audio_end);
- else i=cc_Pause_Resume(3);
- if (i<0) RETURN_UP(-EIO);
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYMSF:
- msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->audio_state==audio_playing)
- {
- i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- current_drive->pos_audio_start=current_drive->SubQ_run_tot;
- i=cc_Seek(current_drive->pos_audio_start,1);
- }
- memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
- /* values come as msf-bin */
- current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
- (msf.cdmsf_sec0<<8) |
- msf.cdmsf_frame0;
- current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
- (msf.cdmsf_sec1<<8) |
- msf.cdmsf_frame1;
- msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
- current_drive->pos_audio_start,current_drive->pos_audio_end);
- i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
- DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(-EIO);
- }
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->audio_state==audio_playing)
- {
- msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
-#if 1
- RETURN_UP(0); /* just let us play on */
-#else
- RETURN_UP(-EINVAL); /* play on, but say "error" */
-#endif
- }
- memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
- msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
- ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
- if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
- if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
- current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
- current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
- i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
- DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(-EIO);
- }
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
- tochdr.cdth_trk0=current_drive->n_first_track;
- tochdr.cdth_trk1=current_drive->n_last_track;
- memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
- RETURN_UP(0);
-
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
- memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
- i=tocentry.cdte_track;
- if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
- else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
- RETURN_UP(-EINVAL);
- tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
- tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
- tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
- if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
- {
- tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
- tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
- tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
- }
- else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
- tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
- else RETURN_UP(-EINVAL);
- memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
- RETURN_UP(0);
-
- case CDROMSTOP: /* Spin down the drive */
- msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- i=cc_Pause_Resume(1);
- current_drive->audio_state=0;
-#if 0
- cc_DriveReset();
-#endif
- RETURN_UP(i);
-
- case CDROMSTART: /* Spin up the drive */
- msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
- cc_SpinUp();
- current_drive->audio_state=0;
- RETURN_UP(0);
-
- case CDROMVOLCTRL: /* Volume control */
- msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
- memcpy(&volctrl,(char *) arg,sizeof(volctrl));
- current_drive->vol_chan0=0;
- current_drive->vol_ctrl0=volctrl.channel0;
- current_drive->vol_chan1=1;
- current_drive->vol_ctrl1=volctrl.channel1;
- i=cc_SetVolume();
- RETURN_UP(0);
-
- case CDROMVOLREAD: /* read Volume settings from drive */
- msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
- st=cc_GetVolume();
- if (st<0) RETURN_UP(st);
- volctrl.channel0=current_drive->vol_ctrl0;
- volctrl.channel1=current_drive->vol_ctrl1;
- volctrl.channel2=0;
- volctrl.channel2=0;
- memcpy((void *)arg,&volctrl,sizeof(volctrl));
- RETURN_UP(0);
-
- case CDROMSUBCHNL: /* Get subchannel info */
- msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
- /* Bogus, I can do better than this! --AJK
- if ((st_spinning)||(!subq_valid)) {
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- }
- */
- i=cc_ReadSubQ();
- if (i<0) {
- j=cc_ReadError(); /* clear out error status from drive */
- current_drive->audio_state=CDROM_AUDIO_NO_STATUS;
- /* get and set the disk state here,
- probably not the right place, but who cares!
- It makes it work properly! --AJK */
- if (current_drive->CD_changed==0xFF) {
- msg(DBG_000,"Disk changed detect\n");
- current_drive->diskstate_flags &= ~cd_size_bit;
- }
- RETURN_UP(-EIO);
- }
- if (current_drive->CD_changed==0xFF) {
- /* reread the TOC because the disk has changed! --AJK */
- msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
- i=DiskInfo();
- if(i==0) {
- current_drive->CD_changed=0x00; /* cd has changed, procede, */
- RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
- } else {
- RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
- }
- }
- memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
- /*
- This virtual crap is very bogus!
- It doesn't detect when the cd is done playing audio!
- Lets do this right with proper hardware register reading!
- */
- cc_ReadStatus();
- i=ResponseStatus();
- msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
- msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
- msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
- msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
- msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
- msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
- /* st_busy indicates if it's _ACTUALLY_ playing audio */
- switch (current_drive->audio_state)
- {
- case audio_playing:
- if(st_busy==0) {
- /* CD has stopped playing audio --AJK */
- current_drive->audio_state=audio_completed;
- SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
- } else {
- SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
- }
- break;
- case audio_pausing:
- SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
- break;
- case audio_completed:
- SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
- break;
- default:
- SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
- break;
- }
- SC.cdsc_adr=current_drive->SubQ_ctl_adr;
- SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4;
- SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk);
- SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx);
- if (SC.cdsc_format==CDROM_LBA)
- {
- SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot);
- SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk);
- }
- else /* not only if (SC.cdsc_format==CDROM_MSF) */
- {
- SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF;
- SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF;
- SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF;
- SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF;
- SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF;
- SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF;
- }
- memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
- msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
- SC.cdsc_format,SC.cdsc_audiostatus,
- SC.cdsc_adr,SC.cdsc_ctrl,
- SC.cdsc_trk,SC.cdsc_ind,
- SC.cdsc_absaddr,SC.cdsc_reladdr);
- RETURN_UP(0);
-
- default:
- msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
- RETURN_UP(-EINVAL);
- } /* end switch(cmd) */
-}
-/*==========================================================================*/
-/*
- * Take care of the different block sizes between cdrom and Linux.
- */
-static void sbp_transfer(struct request *req)
-{
- long offs;
-
- while ( (req->nr_sectors > 0) &&
- (req->sector/4 >= current_drive->sbp_first_frame) &&
- (req->sector/4 <= current_drive->sbp_last_frame) )
- {
- offs = (req->sector - current_drive->sbp_first_frame * 4) * 512;
- memcpy(req->buffer, current_drive->sbp_buf + offs, 512);
- req->nr_sectors--;
- req->sector++;
- req->buffer += 512;
- }
-}
-/*==========================================================================*/
-/*
- * special end_request for sbpcd to solve CURRENT==NULL bug. (GTL)
- * GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy>
- *
- * This is a kludge so we don't need to modify end_request.
- * We put the req we take out after INIT_REQUEST in the requests list,
- * so that end_request will discard it.
- *
- * The bug could be present in other block devices, perhaps we
- * should modify INIT_REQUEST and end_request instead, and
- * change every block device..
- *
- * Could be a race here?? Could e.g. a timer interrupt schedule() us?
- * If so, we should copy end_request here, and do it right.. (or
- * modify end_request and the block devices).
- *
- * In any case, the race here would be much small than it was, and
- * I couldn't reproduce..
- *
- * The race could be: suppose CURRENT==NULL. We put our req in the list,
- * and we are scheduled. Other process takes over, and gets into
- * do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so
- * proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in
- * end_request, but now CURRENT==NULL... oops!
- *
- */
-#undef DEBUG_GTL
-
-/*==========================================================================*/
-/*
- * I/O request routine, called from Linux kernel.
- */
-static void do_sbpcd_request(request_queue_t * q)
-{
- u_int block;
- u_int nsect;
- int status_tries, data_tries;
- struct request *req;
- struct sbpcd_drive *p;
-#ifdef DEBUG_GTL
- static int xx_nr=0;
- int xnr;
-#endif
-
- request_loop:
-#ifdef DEBUG_GTL
- xnr=++xx_nr;
-
- req = elv_next_request(q);
-
- if (!req)
- {
- printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
- xnr, current->pid, jiffies);
- printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n",
- xnr, jiffies);
- return;
- }
-
- printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
-#endif
-
- req = elv_next_request(q); /* take out our request so no other */
- if (!req)
- return;
-
- if (req -> sector == -1)
- end_request(req, 0);
- spin_unlock_irq(q->queue_lock);
-
- down(&ioctl_read_sem);
- if (rq_data_dir(elv_next_request(q)) != READ)
- {
- msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
- goto err_done;
- }
- p = req->rq_disk->private_data;
-#if OLD_BUSY
- while (busy_audio) sbp_sleep(HZ); /* wait a bit */
- busy_data=1;
-#endif /* OLD_BUSY */
-
- if (p->audio_state==audio_playing) goto err_done;
- if (p != current_drive)
- switch_drive(p);
-
- block = req->sector; /* always numbered as 512-byte-pieces */
- nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
-
- msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect);
-#if 0
- msg(DBG_MUL,"read LBA %d\n", block/4);
-#endif
-
- sbp_transfer(req);
- /* if we satisfied the request from the buffer, we're done. */
- if (req->nr_sectors == 0)
- {
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- spin_lock_irq(q->queue_lock);
- end_request(req, 1);
- goto request_loop;
- }
-
-#ifdef FUTURE
- i=prepare(0,0); /* at moment not really a hassle check, but ... */
- if (i!=0)
- msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
-#endif /* FUTURE */
-
- if (!st_spinning) cc_SpinUp();
-
- for (data_tries=n_retries; data_tries > 0; data_tries--)
- {
- for (status_tries=3; status_tries > 0; status_tries--)
- {
- flags_cmd_out |= f_respo3;
- cc_ReadStatus();
- if (sbp_status() != 0) break;
- if (st_check) cc_ReadError();
- sbp_sleep(1); /* wait a bit, try again */
- }
- if (status_tries == 0)
- {
- msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
- break;
- }
-
- sbp_read_cmd(req);
- sbp_sleep(0);
- if (sbp_data(req) != 0)
- {
-#ifdef SAFE_MIXED
- current_drive->has_data=2; /* is really a data disk */
-#endif /* SAFE_MIXED */
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- spin_lock_irq(q->queue_lock);
- end_request(req, 1);
- goto request_loop;
- }
- }
-
- err_done:
-#if OLD_BUSY
- busy_data=0;
-#endif /* OLD_BUSY */
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- sbp_sleep(0); /* wait a bit, try again */
- spin_lock_irq(q->queue_lock);
- end_request(req, 0);
- goto request_loop;
-}
-/*==========================================================================*/
-/*
- * build and send the READ command.
- */
-static void sbp_read_cmd(struct request *req)
-{
-#undef OLD
-
- int i;
- int block;
-
- current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
- current_drive->sbp_current = 0;
- block=req->sector/4;
- if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
- current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
- else
- {
- current_drive->sbp_read_frames=current_drive->CDsize_frm-block;
- /* avoid reading past end of data */
- if (current_drive->sbp_read_frames < 1)
- {
- msg(DBG_INF,"requested frame %d, CD size %d ???\n",
- block, current_drive->CDsize_frm);
- current_drive->sbp_read_frames=1;
- }
- }
-
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
- clr_cmdbuf();
- if (famV_drive)
- {
- drvcmd[0]=CMDV_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
- bin2bcdx(&drvcmd[1]);
- bin2bcdx(&drvcmd[2]);
- bin2bcdx(&drvcmd[3]);
- drvcmd[4]=current_drive->sbp_read_frames>>8;
- drvcmd[5]=current_drive->sbp_read_frames&0xff;
- drvcmd[6]=0x02; /* flag "msf-bcd" */
- }
- else if (fam0L_drive)
- {
- flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
- if (current_drive->xa_byte==0x20)
- {
- cmd_type=READ_M2;
- drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
- drvcmd[1]=(block>>16)&0x0ff;
- drvcmd[2]=(block>>8)&0x0ff;
- drvcmd[3]=block&0x0ff;
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- }
- else
- {
- drvcmd[0]=CMD0_READ; /* "read frames", old drives */
- if (current_drive->drv_type>=drv_201)
- {
- lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
- bin2bcdx(&drvcmd[1]);
- bin2bcdx(&drvcmd[2]);
- bin2bcdx(&drvcmd[3]);
- }
- else
- {
- drvcmd[1]=(block>>16)&0x0ff;
- drvcmd[2]=(block>>8)&0x0ff;
- drvcmd[3]=block&0x0ff;
- }
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
- }
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- drvcmd[6]=0x02;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_READ;
- drvcmd[2]=(block>>24)&0x0ff;
- drvcmd[3]=(block>>16)&0x0ff;
- drvcmd[4]=(block>>8)&0x0ff;
- drvcmd[5]=block&0x0ff;
- drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
- }
- flags_cmd_out=f_putcmd;
- response_count=0;
- i=cmd_out();
- if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i);
- return;
-}
-/*==========================================================================*/
-/*
- * Check the completion of the read-data command. On success, read
- * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
- */
-static int sbp_data(struct request *req)
-{
- int i=0, j=0, l, frame;
- u_int try=0;
- u_long timeout;
- u_char *p;
- u_int data_tries = 0;
- u_int data_waits = 0;
- u_int data_retrying = 0;
- int error_flag;
- int xa_count;
- int max_latency;
- int success;
- int wait;
- int duration;
-
- error_flag=0;
- success=0;
-#if LONG_TIMING
- max_latency=9*HZ;
-#else
- if (current_drive->f_multisession) max_latency=15*HZ;
- else max_latency=5*HZ;
-#endif
- duration=jiffies;
- for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
- {
- SBPCD_CLI;
-
- del_timer(&data_timer);
- data_timer.expires=jiffies+max_latency;
- timed_out_data=0;
- add_timer(&data_timer);
- while (!timed_out_data)
- {
- if (current_drive->f_multisession) try=maxtim_data*4;
- else try=maxtim_data;
- msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
- for ( ; try!=0;try--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (fam0LV_drive) if (j&s_attention) break;
- }
- if (!(j&s_not_data_ready)) goto data_ready;
- if (try==0)
- {
- if (data_retrying == 0) data_waits++;
- data_retrying = 1;
- msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n");
- sbp_sleep(1);
- try = 1;
- }
- }
- msg(DBG_INF,"sbp_data: CDi_status loop expired.\n");
- data_ready:
- del_timer(&data_timer);
-
- if (timed_out_data)
- {
- msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j);
- error_flag++;
- }
- if (try==0)
- {
- msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j);
- error_flag++;
- }
- if (!(j&s_not_result_ready))
- {
- msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j);
- response_count=20;
- j=ResponseInfo();
- j=inb(CDi_status);
- }
- if (j&s_not_data_ready)
- {
- if ((current_drive->ored_ctl_adr&0x40)==0)
- msg(DBG_INF, "CD contains no data tracks.\n");
- else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j);
- error_flag++;
- }
- SBPCD_STI;
- if (error_flag) break;
-
- msg(DBG_000, "sbp_data: beginning to read.\n");
- p = current_drive->sbp_buf + frame * CD_FRAMESIZE;
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (cmd_type==READ_M2) {
- if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
- else insb(CDi_data, xa_head_buf, CD_XA_HEAD);
- }
- if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1);
- else insb(CDi_data, p, CD_FRAMESIZE);
- if (cmd_type==READ_M2) {
- if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
- else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
- }
- current_drive->sbp_current++;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- if (cmd_type==READ_M2)
- {
- for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++)
- sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]);
- msgbuf[xa_count*3]=0;
- msg(DBG_XA1,"xa head:%s\n", msgbuf);
- }
- data_retrying = 0;
- data_tries++;
- if (data_tries >= 1000)
- {
- msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries);
- data_waits = data_tries = 0;
- }
- }
- duration=jiffies-duration;
- msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
- if (famT_drive)
- {
- wait=8;
- do
- {
- if (teac==2)
- {
- if ((i=CDi_stat_loop_T()) == -1) break;
- }
- else
- {
- sbp_sleep(1);
- OUT(CDo_sel_i_d,0);
- i=inb(CDi_status);
- }
- if (!(i&s_not_data_ready))
- {
- OUT(CDo_sel_i_d,1);
- j=0;
- do
- {
- if (do_16bit) i=inw(CDi_data);
- else i=inb(CDi_data);
- j++;
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j);
- }
- if (!(i&s_not_result_ready))
- {
- OUT(CDo_sel_i_d,0);
- l=0;
- do
- {
- infobuf[l++]=inb(CDi_info);
- i=inb(CDi_status);
- }
- while (!(i&s_not_result_ready));
- if (infobuf[0]==0x00) success=1;
-#if 1
- for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf);
-#endif
- if (infobuf[0]==0x02)
- {
- error_flag++;
- do
- {
- ++recursion;
- if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion);
- else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n");
- clr_cmdbuf();
- drvcmd[0]=CMDT_READ_ERR;
- j=cmd_out_T(); /* !!! recursive here !!! */
- --recursion;
- sbp_sleep(1);
- }
- while (j<0);
- current_drive->error_state=infobuf[2];
- current_drive->b3=infobuf[3];
- current_drive->b4=infobuf[4];
- }
- break;
- }
- else
- {
-#if 0
- msg(DBG_TEA, "============= waiting for result=================.\n");
- sbp_sleep(1);
-#endif
- }
- }
- while (wait--);
- }
-
- if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
- {
- msg(DBG_TEA, "================error flag: %d=================.\n", error_flag);
- msg(DBG_INF,"sbp_data: read aborted by drive.\n");
-#if 1
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
- i=cc_ReadError();
-#endif
- return (0);
- }
-
- if (fam0LV_drive)
- {
- SBPCD_CLI;
- i=maxtim_data;
- for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (j&s_attention) break;
- }
- if (i != 0 || time_after_eq(jiffies, timeout)) break;
- sbp_sleep(0);
- i = 1;
- }
- if (i==0) msg(DBG_INF,"status timeout after READ.\n");
- if (!(j&s_attention))
- {
- msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- SBPCD_STI;
- return (0);
- }
- SBPCD_STI;
- }
-
-#if 0
- if (!success)
-#endif
- do
- {
- if (fam0LV_drive) cc_ReadStatus();
-#if 1
- if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
-#endif
- i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-#if 1
- if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
-#endif
- if (i<0)
- {
- msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
- return (0);
- }
- }
- while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i);
- return (0);
- }
- if (fatal_err)
- {
- fatal_err=0;
- current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
- current_drive->sbp_current = 0;
- msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
- return (0);
- }
-
- current_drive->sbp_first_frame = req -> sector / 4;
- current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
- sbp_transfer(req);
- return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_block_open(struct inode *inode, struct file *file)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_open(p->sbpcd_infop, inode, file);
-}
-
-static int sbpcd_block_release(struct inode *inode, struct file *file)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_release(p->sbpcd_infop, file);
-}
-
-static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- struct cdrom_device_info *cdi = p->sbpcd_infop;
- int ret, i;
-
- ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg);
- if (ret != -ENOSYS)
- return ret;
-
- msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg);
- if (p->drv_id==-1) {
- msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
- return (-ENXIO); /* no such drive */
- }
- down(&ioctl_read_sem);
- if (p != current_drive)
- switch_drive(p);
-
- msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
- switch (cmd) /* Sun-compatible */
- {
- case DDIOCSDBG: /* DDI Debug */
- if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
- i=sbpcd_dbg_ioctl(arg,1);
- RETURN_UP(i);
- case CDROMRESET: /* hard reset the drive */
- msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
- i=DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(i);
-
- case CDROMREADMODE1:
- msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- cc_ModeSelect(CD_FRAMESIZE);
- cc_ModeSense();
- current_drive->mode=READ_M1;
- RETURN_UP(0);
-
- case CDROMREADMODE2: /* not usable at the moment */
- msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- cc_ModeSelect(CD_FRAMESIZE_RAW1);
- cc_ModeSense();
- current_drive->mode=READ_M2;
- RETURN_UP(0);
-
- case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
- msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
- if (current_drive->sbp_audsiz>0)
- vfree(current_drive->aud_buf);
- current_drive->aud_buf=NULL;
- current_drive->sbp_audsiz=arg;
-
- if (current_drive->sbp_audsiz>16)
- {
- current_drive->sbp_audsiz = 0;
- RETURN_UP(current_drive->sbp_audsiz);
- }
-
- if (current_drive->sbp_audsiz>0)
- {
- current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
- if (current_drive->aud_buf==NULL)
- {
- msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
- current_drive->sbp_audsiz=0;
- }
- else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
- }
- RETURN_UP(current_drive->sbp_audsiz);
-
- case CDROMREADAUDIO:
- { /* start of CDROMREADAUDIO */
- int i=0, j=0, frame, block=0;
- u_int try=0;
- u_long timeout;
- u_char *p;
- u_int data_tries = 0;
- u_int data_waits = 0;
- u_int data_retrying = 0;
- int status_tries;
- int error_flag;
-
- msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
- if (fam0_drive) RETURN_UP(-EINVAL);
- if (famL_drive) RETURN_UP(-EINVAL);
- if (famV_drive) RETURN_UP(-EINVAL);
- if (famT_drive) RETURN_UP(-EINVAL);
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL);
- if (copy_from_user(&read_audio, (void __user *)arg,
- sizeof(struct cdrom_read_audio)))
- RETURN_UP(-EFAULT);
- if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
- if (!access_ok(VERIFY_WRITE, read_audio.buf,
- read_audio.nframes*CD_FRAMESIZE_RAW))
- RETURN_UP(-EFAULT);
-
- if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
- block=msf2lba(&read_audio.addr.msf.minute);
- else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
- block=read_audio.addr.lba;
- else RETURN_UP(-EINVAL);
-#if 000
- i=cc_SetSpeed(speed_150,0,0);
- if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
-#endif
- msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
- block, blk2msf(block));
- msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
-#if OLD_BUSY
- while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
- busy_audio=1;
-#endif /* OLD_BUSY */
- error_flag=0;
- for (data_tries=5; data_tries>0; data_tries--)
- {
- msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
- current_drive->mode=READ_AU;
- cc_ModeSelect(CD_FRAMESIZE_RAW);
- cc_ModeSense();
- for (status_tries=3; status_tries > 0; status_tries--)
- {
- flags_cmd_out |= f_respo3;
- cc_ReadStatus();
- if (sbp_status() != 0) break;
- if (st_check) cc_ReadError();
- sbp_sleep(1); /* wait a bit, try again */
- }
- if (status_tries == 0)
- {
- msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
- continue;
- }
- msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
-
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
- if (fam0L_drive)
- {
- flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
- cmd_type=READ_M2;
- drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
- drvcmd[1]=(block>>16)&0x000000ff;
- drvcmd[2]=(block>>8)&0x000000ff;
- drvcmd[3]=block&0x000000ff;
- drvcmd[4]=0;
- drvcmd[5]=read_audio.nframes; /* # of frames */
- drvcmd[6]=0;
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ; /* "read frames", new drives */
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=0;
- drvcmd[5]=0;
- drvcmd[6]=read_audio.nframes; /* # of frames */
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ_XA2;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=0;
- drvcmd[5]=read_audio.nframes; /* # of frames */
- drvcmd[6]=0x11; /* raw mode */
- }
- else if (famT_drive) /* CD-55A: not tested yet */
- {
- }
- msg(DBG_AUD,"read_audio: before giving \"read\" command.\n");
- flags_cmd_out=f_putcmd;
- response_count=0;
- i=cmd_out();
- if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i);
- sbp_sleep(0);
- msg(DBG_AUD,"read_audio: after giving \"read\" command.\n");
- for (frame=1;frame<2 && !error_flag; frame++)
- {
- try=maxtim_data;
- for (timeout=jiffies+9*HZ; ; )
- {
- for ( ; try!=0;try--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (fam0L_drive) if (j&s_attention) break;
- }
- if (try != 0 || time_after_eq(jiffies, timeout)) break;
- if (data_retrying == 0) data_waits++;
- data_retrying = 1;
- sbp_sleep(1);
- try = 1;
- }
- if (try==0)
- {
- msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n");
- error_flag++;
- break;
- }
- msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n");
- if (j&s_not_data_ready)
- {
- msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n");
- error_flag++;
- break;
- }
- msg(DBG_AUD,"read_audio: before reading data.\n");
- error_flag=0;
- p = current_drive->aud_buf;
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (do_16bit)
- {
- u_short *p2 = (u_short *) p;
-
- for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
- {
- if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
- /* get one sample */
- *p2++ = inw_p(CDi_data);
- *p2++ = inw_p(CDi_data);
- }
- } else {
- for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
- {
- if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
- /* get one sample */
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- }
- }
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- data_retrying = 0;
- }
- msg(DBG_AUD,"read_audio: after reading data.\n");
- if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
- {
- msg(DBG_AUD,"read_audio: read aborted by drive\n");
-#if 0000
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
- i=cc_ReadError();
-#endif
- continue;
- }
- if (fam0L_drive)
- {
- i=maxtim_data;
- for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (j&s_attention) break;
- }
- if (i != 0 || time_after_eq(jiffies, timeout)) break;
- sbp_sleep(0);
- i = 1;
- }
- if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
- if (!(j&s_attention))
- {
- msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n");
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- continue;
- }
- }
- do
- {
- if (fam0L_drive) cc_ReadStatus();
- i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
- if (i<0) { msg(DBG_AUD,
- "read_audio: cc_ReadStatus error after read: %02X\n",
- current_drive->status_bits);
- continue; /* FIXME */
- }
- }
- while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
- continue;
- }
- if (copy_to_user(read_audio.buf,
- current_drive->aud_buf,
- read_audio.nframes * CD_FRAMESIZE_RAW))
- RETURN_UP(-EFAULT);
- msg(DBG_AUD,"read_audio: copy_to_user done.\n");
- break;
- }
- cc_ModeSelect(CD_FRAMESIZE);
- cc_ModeSense();
- current_drive->mode=READ_M1;
-#if OLD_BUSY
- busy_audio=0;
-#endif /* OLD_BUSY */
- if (data_tries == 0)
- {
- msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
- RETURN_UP(-EIO);
- }
- msg(DBG_AUD,"read_audio: successful return.\n");
- RETURN_UP(0);
- } /* end of CDROMREADAUDIO */
-
- default:
- msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
- RETURN_UP(-EINVAL);
- } /* end switch(cmd) */
-}
-
-static int sbpcd_block_media_changed(struct gendisk *disk)
-{
- struct sbpcd_drive *p = disk->private_data;
- return cdrom_media_changed(p->sbpcd_infop);
-}
-
-static struct block_device_operations sbpcd_bdops =
-{
- .owner = THIS_MODULE,
- .open = sbpcd_block_open,
- .release = sbpcd_block_release,
- .ioctl = sbpcd_block_ioctl,
- .media_changed = sbpcd_block_media_changed,
-};
-/*==========================================================================*/
-/*
- * Open the device special file. Check that a disk is in. Read TOC.
- */
-static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
-{
- struct sbpcd_drive *p = cdi->handle;
-
- down(&ioctl_read_sem);
- switch_drive(p);
-
- /*
- * try to keep an "open" counter here and lock the door if 0->1.
- */
- msg(DBG_LCK,"open_count: %d -> %d\n",
- current_drive->open_count,current_drive->open_count+1);
- if (++current_drive->open_count<=1)
- {
- int i;
- i=LockDoor();
- current_drive->open_count=1;
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n");
- i=DiskInfo();
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n");
- if ((current_drive->ored_ctl_adr&0x40)==0)
- {
- msg(DBG_INF,"CD contains no data tracks.\n");
-#ifdef SAFE_MIXED
- current_drive->has_data=0;
-#endif /* SAFE_MIXED */
- }
-#ifdef SAFE_MIXED
- else if (current_drive->has_data<1) current_drive->has_data=1;
-#endif /* SAFE_MIXED */
- }
- if (!st_spinning) cc_SpinUp();
- RETURN_UP(0);
-}
-/*==========================================================================*/
-/*
- * On close, we flush all sbp blocks from the buffer cache.
- */
-static void sbpcd_release(struct cdrom_device_info * cdi)
-{
- struct sbpcd_drive *p = cdi->handle;
-
- if (p->drv_id==-1) {
- msg(DBG_INF, "release: bad device: %s\n", cdi->name);
- return;
- }
- down(&ioctl_read_sem);
- switch_drive(p);
- /*
- * try to keep an "open" counter here and unlock the door if 1->0.
- */
- msg(DBG_LCK,"open_count: %d -> %d\n",
- p->open_count,p->open_count-1);
- if (p->open_count>-2) /* CDROMEJECT may have been done */
- {
- if (--p->open_count<=0)
- {
- p->sbp_first_frame=p->sbp_last_frame=-1;
- if (p->audio_state!=audio_playing)
- if (p->f_eject) cc_SpinDown();
- p->diskstate_flags &= ~cd_size_bit;
- p->open_count=0;
-#ifdef SAFE_MIXED
- p->has_data=0;
-#endif /* SAFE_MIXED */
- }
- }
- up(&ioctl_read_sem);
- return ;
-}
-/*==========================================================================*/
-/*
- *
- */
-static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
-static struct cdrom_device_ops sbpcd_dops = {
- .open = sbpcd_open,
- .release = sbpcd_release,
- .drive_status = sbpcd_drive_status,
- .media_changed = sbpcd_media_changed,
- .tray_move = sbpcd_tray_move,
- .lock_door = sbpcd_lock_door,
- .select_speed = sbpcd_select_speed,
- .get_last_session = sbpcd_get_last_session,
- .get_mcn = sbpcd_get_mcn,
- .reset = sbpcd_reset,
- .audio_ioctl = sbpcd_audio_ioctl,
- .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
- CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
- CDC_MCN | CDC_PLAY_AUDIO,
- .n_minors = 1,
-};
-
-/*==========================================================================*/
-/*
- * accept "kernel command line" parameters
- * (suggested by Peter MacDonald with SLS 1.03)
- *
- * This is only implemented for the first controller. Should be enough to
- * allow installing with a "strange" distribution kernel.
- *
- * use: tell LILO:
- * sbpcd=0x230,SoundBlaster
- * or
- * sbpcd=0x300,LaserMate
- * or
- * sbpcd=0x338,SoundScape
- * or
- * sbpcd=0x2C0,Teac16bit
- *
- * (upper/lower case sensitive here - but all-lowercase is ok!!!).
- *
- * the address value has to be the CDROM PORT ADDRESS -
- * not the soundcard base address.
- * For the SPEA/SoundScape setup, DO NOT specify the "configuration port"
- * address, but the address which is really used for the CDROM (usually 8
- * bytes above).
- *
- */
-
-int sbpcd_setup(char *s)
-{
-#ifndef MODULE
- int p[4];
- (void)get_options(s, ARRAY_SIZE(p), p);
- setup_done++;
- msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
- sbpro_type=0; /* default: "LaserMate" */
- if (p[0]>1) sbpro_type=p[2];
- else if (!strcmp(s,str_sb)) sbpro_type=1;
- else if (!strcmp(s,str_sb_l)) sbpro_type=1;
- else if (!strcmp(s,str_sp)) sbpro_type=2;
- else if (!strcmp(s,str_sp_l)) sbpro_type=2;
- else if (!strcmp(s,str_ss)) sbpro_type=2;
- else if (!strcmp(s,str_ss_l)) sbpro_type=2;
- else if (!strcmp(s,str_t16)) sbpro_type=3;
- else if (!strcmp(s,str_t16_l)) sbpro_type=3;
- if (p[0]>0) sbpcd_ioaddr=p[1];
- if (p[0]>2) max_drives=p[3];
-#else
- sbpcd_ioaddr = sbpcd[0];
- sbpro_type = sbpcd[1];
-#endif
-
- CDo_command=sbpcd_ioaddr;
- CDi_info=sbpcd_ioaddr;
- CDi_status=sbpcd_ioaddr+1;
- CDo_sel_i_d=sbpcd_ioaddr+1;
- CDo_reset=sbpcd_ioaddr+2;
- CDo_enable=sbpcd_ioaddr+3;
- f_16bit=0;
- if ((sbpro_type==1)||(sbpro_type==3))
- {
- CDi_data=sbpcd_ioaddr;
- if (sbpro_type==3)
- {
- f_16bit=1;
- sbpro_type=1;
- }
- }
- else CDi_data=sbpcd_ioaddr+2;
-
- return 1;
-}
-
-__setup("sbpcd=", sbpcd_setup);
-
-
-/*==========================================================================*/
-/*
- * Sequoia S-1000 CD-ROM Interface Configuration
- * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards
- * The soundcard has to get jumpered for the interface type "Panasonic"
- * (not Sony or Mitsumi) and to get soft-configured for
- * -> configuration port address
- * -> CDROM port offset (num_ports): has to be 8 here. Possibly this
- * offset value determines the interface type (none, Panasonic,
- * Mitsumi, Sony).
- * The interface uses a configuration port (0x320, 0x330, 0x340, 0x350)
- * some bytes below the real CDROM address.
- *
- * For the Panasonic style (LaserMate) interface and the configuration
- * port 0x330, we have to use an offset of 8; so, the real CDROM port
- * address is 0x338.
- */
-static int __init config_spea(void)
-{
- /*
- * base address offset between configuration port and CDROM port,
- * this probably defines the interface type
- * 2 (type=??): 0x00
- * 8 (type=LaserMate):0x10
- * 16 (type=??):0x20
- * 32 (type=??):0x30
- */
- int n_ports=0x10;
-
- int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */
- int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */
- int dack_polarity=0; /* L:0x00, H:0x80 */
- int drq_polarity=0x40; /* L:0x00, H:0x40 */
- int i;
-
-#define SPEA_REG_1 sbpcd_ioaddr-0x08+4
-#define SPEA_REG_2 sbpcd_ioaddr-0x08+5
-
- OUT(SPEA_REG_1,0xFF);
- i=inb(SPEA_REG_1);
- if (i!=0x0F)
- {
- msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr);
- return (-1); /* no interface found */
- }
- OUT(SPEA_REG_1,0x04);
- OUT(SPEA_REG_2,0xC0);
-
- OUT(SPEA_REG_1,0x05);
- OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity);
-
-#if 1
-#define SPEA_PATTERN 0x80
-#else
-#define SPEA_PATTERN 0x00
-#endif
- OUT(SPEA_REG_1,0x06);
- OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
- OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-
- OUT(SPEA_REG_1,0x09);
- i=(inb(SPEA_REG_2)&0xCF)|n_ports;
- OUT(SPEA_REG_2,i);
-
- sbpro_type = 0; /* acts like a LaserMate interface now */
- msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr);
- return (0);
-}
-
-/*==========================================================================*/
-/*
- * Test for presence of drive and initialize it.
- * Called once at boot or load time.
- */
-
-/* FIXME: cleanups after failed allocations are too ugly for words */
-#ifdef MODULE
-int __init __sbpcd_init(void)
-#else
-int __init sbpcd_init(void)
-#endif
-{
- int i=0, j=0;
- int addr[2]={1, CDROM_PORT};
- int port_index;
-
- sti();
-
- msg(DBG_INF,"sbpcd.c %s\n", VERSION);
-#ifndef MODULE
-#if DISTRIBUTION
- if (!setup_done)
- {
- msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drives\n");
- msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =\n");
- msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).\n");
- msg(DBG_INF,"If that happens, you have to reboot and use the\n");
- msg(DBG_INF,"LILO (kernel) command line feature like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x230,SoundBlaster\n");
- msg(DBG_INF,"or like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x300,LaserMate\n");
- msg(DBG_INF,"or like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x338,SoundScape\n");
- msg(DBG_INF,"with your REAL address.\n");
- msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n");
- }
-#endif /* DISTRIBUTION */
- sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
- sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */
-#endif /* MODULE */
-
- for (port_index=0;port_index<NUM_PROBE;port_index+=2)
- {
- addr[1]=sbpcd[port_index];
- if (addr[1]==0) break;
- if (check_region(addr[1],4))
- {
- msg(DBG_INF,"check_region: %03X is not free.\n",addr[1]);
- continue;
- }
- if (sbpcd[port_index+1]==2) type=str_sp;
- else if (sbpcd[port_index+1]==1) type=str_sb;
- else if (sbpcd[port_index+1]==3) type=str_t16;
- else type=str_lm;
- sbpcd_setup((char *)type);
-#if DISTRIBUTION
- msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
-#endif /* DISTRIBUTION */
- if (sbpcd[port_index+1]==2)
- {
- i=config_spea();
- if (i<0) continue;
- }
-#ifdef PATH_CHECK
- if (check_card(addr[1])) continue;
-#endif /* PATH_CHECK */
- i=check_drives();
- msg(DBG_INI,"check_drives done.\n");
- if (i>=0) break; /* drive found */
- } /* end of cycling through the set of possible I/O port addresses */
-
- if (ndrives==0)
- {
- msg(DBG_INF, "No drive found.\n");
-#ifdef MODULE
- return -EIO;
-#else
- goto init_done;
-#endif /* MODULE */
- }
-
- if (port_index>0)
- {
- msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n");
- msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n");
- }
- check_datarate();
- msg(DBG_INI,"check_datarate done.\n");
-
- for (j=0;j<NR_SBPCD;j++)
- {
- struct sbpcd_drive *p = D_S + j;
- if (p->drv_id==-1)
- continue;
- switch_drive(p);
-#if 1
- if (!famL_drive) cc_DriveReset();
-#endif
- if (!st_spinning) cc_SpinUp();
- p->sbp_first_frame = -1; /* First frame in buffer */
- p->sbp_last_frame = -1; /* Last frame in buffer */
- p->sbp_read_frames = 0; /* Number of frames being read to buffer */
- p->sbp_current = 0; /* Frame being currently read */
- p->CD_changed=1;
- p->frame_size=CD_FRAMESIZE;
- p->f_eject=0;
-#if EJECT
- if (!fam0_drive) p->f_eject=1;
-#endif /* EJECT */
- cc_ReadStatus();
- i=ResponseStatus(); /* returns orig. status or p_busy_new */
- if (famT_drive) i=ResponseStatus(); /* returns orig. status or p_busy_new */
- if (i<0)
- {
- if (i!=-402)
- msg(DBG_INF,"init: ResponseStatus returns %d.\n",i);
- }
- else
- {
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_INI,"init: cc_ReadError returns %d\n",i);
- }
- }
- msg(DBG_INI,"init: first GetStatus: %d\n",i);
- msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n",
- p->error_byte);
- if (p->error_byte==aud_12)
- {
- timeout=jiffies+2*HZ;
- do
- {
- i=GetStatus();
- msg(DBG_INI,"init: second GetStatus: %02X\n",i);
- msg(DBG_LCS,
- "init: second GetStatus: error_byte=%d\n",
- p->error_byte);
- if (i<0) break;
- if (!st_caddy_in) break;
- }
- while ((!st_diskok)||time_after(jiffies, timeout));
- }
- i=SetSpeed();
- if (i>=0) p->CD_changed=1;
- }
-
- if (!request_region(CDo_command,4,major_name))
- {
- printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command);
- return -EIO;
- }
-
- /*
- * Turn on the CD audio channels.
- * The addresses are obtained from SOUND_BASE (see sbpcd.h).
- */
-#if SOUND_BASE
- OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
- OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
-#endif /* SOUND_BASE */
-
- if (register_blkdev(MAJOR_NR, major_name)) {
-#ifdef MODULE
- return -EIO;
-#else
- goto init_done;
-#endif /* MODULE */
- }
-
- /*
- * init error handling is broken beyond belief in this driver...
- */
- sbpcd_queue = blk_init_queue(do_sbpcd_request, &sbpcd_lock);
- if (!sbpcd_queue) {
- release_region(CDo_command,4);
- unregister_blkdev(MAJOR_NR, major_name);
- return -ENOMEM;
- }
-
- for (j=0;j<NR_SBPCD;j++)
- {
- struct cdrom_device_info * sbpcd_infop;
- struct gendisk *disk;
- struct sbpcd_drive *p = D_S + j;
-
- if (p->drv_id==-1) continue;
- switch_drive(p);
-#ifdef SAFE_MIXED
- p->has_data=0;
-#endif /* SAFE_MIXED */
- /*
- * allocate memory for the frame buffers
- */
- p->aud_buf=NULL;
- p->sbp_audsiz=0;
- p->sbp_bufsiz=buffers;
- if (p->drv_type&drv_fam1)
- if (READ_AUDIO>0)
- p->sbp_audsiz = READ_AUDIO;
- p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE);
- if (!p->sbp_buf) {
- msg(DBG_INF,"data buffer (%d frames) not available.\n",
- buffers);
- if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- printk("Can't unregister %s\n", major_name);
- }
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- return -EIO;
- }
-#ifdef MODULE
- msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
-#endif /* MODULE */
- if (p->sbp_audsiz>0)
- {
- p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW);
- if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz);
- else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz);
- }
- sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
- if (sbpcd_infop == NULL)
- {
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- return -ENOMEM;
- }
- memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
- sbpcd_infop->ops = &sbpcd_dops;
- sbpcd_infop->speed = 2;
- sbpcd_infop->capacity = 1;
- sprintf(sbpcd_infop->name, "sbpcd%d", j);
- sbpcd_infop->handle = p;
- p->sbpcd_infop = sbpcd_infop;
- disk = alloc_disk(1);
- disk->major = MAJOR_NR;
- disk->first_minor = j;
- disk->fops = &sbpcd_bdops;
- strcpy(disk->disk_name, sbpcd_infop->name);
- disk->flags = GENHD_FL_CD;
- p->disk = disk;
- if (register_cdrom(sbpcd_infop))
- {
- printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
- }
- disk->private_data = p;
- disk->queue = sbpcd_queue;
- add_disk(disk);
- }
- blk_queue_hardsect_size(sbpcd_queue, CD_FRAMESIZE);
-
-#ifndef MODULE
- init_done:
-#endif
- return 0;
-}
-/*==========================================================================*/
-#ifdef MODULE
-static void sbpcd_exit(void)
-{
- int j;
-
- if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
- return;
- }
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- for (j=0;j<NR_SBPCD;j++)
- {
- if (D_S[j].drv_id==-1) continue;
- del_gendisk(D_S[j].disk);
- put_disk(D_S[j].disk);
- vfree(D_S[j].sbp_buf);
- if (D_S[j].sbp_audsiz>0)
- vfree(D_S[j].aud_buf);
- if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
- return;
- }
- vfree(D_S[j].sbpcd_infop);
- }
- msg(DBG_INF, "%s module released.\n", major_name);
-}
-
-
-module_init(__sbpcd_init) /*HACK!*/;
-module_exit(sbpcd_exit);
-
-
-#endif /* MODULE */
-static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- struct sbpcd_drive *p = cdi->handle;
- msg(DBG_CHK,"media_check (%s) called\n", cdi->name);
-
- if (p->CD_changed==0xFF)
- {
- p->CD_changed=0;
- msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
- current_drive->diskstate_flags &= ~toc_bit;
- /* we *don't* need invalidate here, it's done by caller */
- current_drive->diskstate_flags &= ~cd_size_bit;
-#ifdef SAFE_MIXED
- current_drive->has_data=0;
-#endif /* SAFE_MIXED */
-
- return (1);
- }
- else
- return (0);
-}
-
-MODULE_LICENSE("GPL");
-/* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but
- AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */
-MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR);
-
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
-
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
deleted file mode 100644
index 2f2225f13c6f..000000000000
--- a/drivers/cdrom/sbpcd.h
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * sbpcd.h Specify interface address and interface type here.
- */
-
-/*
- * Attention! This file contains user-serviceable parts!
- * I recommend to make use of it...
- * If you feel helpless, look into Documentation/cdrom/sbpcd
- * (good idea anyway, at least before mailing me).
- *
- * The definitions for the first controller can get overridden by
- * the kernel command line ("lilo boot option").
- * Examples:
- * sbpcd=0x300,LaserMate
- * or
- * sbpcd=0x230,SoundBlaster
- * or
- * sbpcd=0x338,SoundScape
- * or
- * sbpcd=0x2C0,Teac16bit
- *
- * If sbpcd gets used as a module, you can load it with
- * insmod sbpcd.o sbpcd=0x300,0
- * or
- * insmod sbpcd.o sbpcd=0x230,1
- * or
- * insmod sbpcd.o sbpcd=0x338,2
- * or
- * insmod sbpcd.o sbpcd=0x2C0,3
- * respective to override the configured address and type.
- */
-
-/*
- * define your CDROM port base address as CDROM_PORT
- * and specify the type of your interface card as SBPRO.
- *
- * address:
- * ========
- * SBPRO type addresses typically are 0x0230 (=0x220+0x10), 0x0250, ...
- * LASERMATE type (CI-101P, WDH-7001C) addresses typically are 0x0300, ...
- * SOUNDSCAPE addresses are from the LASERMATE type and range. You have to
- * specify the REAL address here, not the configuration port address. Look
- * at the CDROM driver's invoking line within your DOS CONFIG.SYS, or let
- * sbpcd auto-probe, if you are not firm with the address.
- * There are some soundcards on the market with 0x0630, 0x0650, ...; their
- * type is not obvious (both types are possible).
- *
- * example: if your SBPRO audio address is 0x220, specify 0x230 and SBPRO 1.
- * if your soundcard has its CDROM port above 0x300, specify
- * that address and try SBPRO 0 first.
- * if your SoundScape configuration port is at 0x330, specify
- * 0x338 and SBPRO 2.
- *
- * interface type:
- * ===============
- * set SBPRO to 1 for "true" SoundBlaster card
- * set SBPRO to 0 for "compatible" soundcards and
- * for "poor" (no sound) interface cards.
- * set SBPRO to 2 for Ensonic SoundScape or SPEA Media FX cards
- * set SBPRO to 3 for Teac 16bit interface cards
- *
- * Almost all "compatible" sound boards need to set SBPRO to 0.
- * If SBPRO is set wrong, the drives will get found - but any
- * data access will give errors (audio access will work).
- * The "OmniCD" no-sound interface card from CreativeLabs and most Teac
- * interface cards need SBPRO 1.
- *
- * sound base:
- * ===========
- * The SOUND_BASE definition tells if we should try to turn the CD sound
- * channels on. It will only be of use regarding soundcards with a SbPro
- * compatible mixer.
- *
- * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels
- * #define SOUND_BASE 0 leaves the soundcard untouched
- */
-#define CDROM_PORT 0x340 /* <-----------<< port address */
-#define SBPRO 0 /* <-----------<< interface type */
-#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */
-#define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0 */
-
-/*
- * some more or less user dependent definitions - service them!
- */
-
-/* Set this to 0 once you have configured your interface definitions right. */
-#define DISTRIBUTION 1
-
-/*
- * Time to wait after giving a message.
- * This gets important if you enable non-standard DBG_xxx flags.
- * You will see what happens if you omit the pause or make it
- * too short. Be warned!
- */
-#define KLOGD_PAUSE 1
-
-/* tray control: eject tray if no disk is in */
-#if DISTRIBUTION
-#define JUKEBOX 0
-#else
-#define JUKEBOX 1
-#endif /* DISTRIBUTION */
-
-/* tray control: eject tray after last use */
-#if DISTRIBUTION
-#define EJECT 0
-#else
-#define EJECT 1
-#endif /* DISTRIBUTION */
-
-/* max. number of audio frames to read with one */
-/* request (allocates n* 2352 bytes kernel memory!) */
-/* may be freely adjusted, f.e. 75 (= 1 sec.), at */
-/* runtime by use of the CDROMAUDIOBUFSIZ ioctl. */
-#define READ_AUDIO 0
-
-/* Optimizations for the Teac CD-55A drive read performance.
- * SBP_TEAC_SPEED can be changed here, or one can set the
- * variable "teac" when loading as a module.
- * Valid settings are:
- * 0 - very slow - the recommended "DISTRIBUTION 1" setup.
- * 1 - 2x performance with little overhead. No busy waiting.
- * 2 - 4x performance with 5ms overhead per read. Busy wait.
- *
- * Setting SBP_TEAC_SPEED or the variable 'teac' to anything
- * other than 0 may cause problems. If you run into them, first
- * change SBP_TEAC_SPEED back to 0 and see if your drive responds
- * normally. If yes, you are "allowed" to report your case - to help
- * me with the driver, not to solve your hassle. Don´t mail if you
- * simply are stuck into your own "tuning" experiments, you know?
- */
-#define SBP_TEAC_SPEED 1
-
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * nothing to change below here if you are not fully aware what you're doing
- */
-#ifndef _LINUX_SBPCD_H
-
-#define _LINUX_SBPCD_H
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * driver's own read_ahead, data mode
- */
-#define SBP_BUFFER_FRAMES 8
-
-#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
-#undef FUTURE
-#undef SAFE_MIXED
-
-#define TEST_UPC 0
-#define SPEA_TEST 0
-#define TEST_STI 0
-#define OLD_BUSY 0
-#undef PATH_CHECK
-#ifndef SOUND_BASE
-#define SOUND_BASE 0
-#endif
-#if DISTRIBUTION
-#undef SBP_TEAC_SPEED
-#define SBP_TEAC_SPEED 0
-#endif
-/*==========================================================================*/
-/*
- * DDI interface definitions
- * "invented" by Fred N. van Kempen..
- */
-#define DDIOCSDBG 0x9000
-
-/*==========================================================================*/
-/*
- * "private" IOCTL functions
- */
-#define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */
-
-/*==========================================================================*/
-/*
- * Debug output levels
- */
-#define DBG_INF 1 /* necessary information */
-#define DBG_BSZ 2 /* BLOCK_SIZE trace */
-#define DBG_REA 3 /* READ status trace */
-#define DBG_CHK 4 /* MEDIA CHECK trace */
-#define DBG_TIM 5 /* datarate timer test */
-#define DBG_INI 6 /* initialization trace */
-#define DBG_TOC 7 /* tell TocEntry values */
-#define DBG_IOC 8 /* ioctl trace */
-#define DBG_STA 9 /* ResponseStatus() trace */
-#define DBG_ERR 10 /* cc_ReadError() trace */
-#define DBG_CMD 11 /* cmd_out() trace */
-#define DBG_WRN 12 /* give explanation before auto-probing */
-#define DBG_MUL 13 /* multi session code test */
-#define DBG_IDX 14 /* test code for drive_id !=0 */
-#define DBG_IOX 15 /* some special information */
-#define DBG_DID 16 /* drive ID test */
-#define DBG_RES 17 /* drive reset info */
-#define DBG_SPI 18 /* SpinUp test */
-#define DBG_IOS 19 /* ioctl trace: subchannel functions */
-#define DBG_IO2 20 /* ioctl trace: general */
-#define DBG_UPC 21 /* show UPC information */
-#define DBG_XA1 22 /* XA mode debugging */
-#define DBG_LCK 23 /* door (un)lock info */
-#define DBG_SQ1 24 /* dump SubQ frame */
-#define DBG_AUD 25 /* READ AUDIO debugging */
-#define DBG_SEQ 26 /* Sequoia interface configuration trace */
-#define DBG_LCS 27 /* Longshine LCS-7260 debugging trace */
-#define DBG_CD2 28 /* MKE/Funai CD200 debugging trace */
-#define DBG_TEA 29 /* TEAC CD-55A debugging trace */
-#define DBG_ECS 30 /* ECS-AT (Vertos 100) debugging trace */
-#define DBG_000 31 /* unnecessary information */
-
-/*==========================================================================*/
-/*==========================================================================*/
-
-/*
- * bits of flags_cmd_out:
- */
-#define f_respo3 0x100
-#define f_putcmd 0x80
-#define f_respo2 0x40
-#define f_lopsta 0x20
-#define f_getsta 0x10
-#define f_ResponseStatus 0x08
-#define f_obey_p_check 0x04
-#define f_bit1 0x02
-#define f_wait_if_busy 0x01
-
-/*
- * diskstate_flags:
- */
-#define x80_bit 0x80
-#define upc_bit 0x40
-#define volume_bit 0x20
-#define toc_bit 0x10
-#define multisession_bit 0x08
-#define cd_size_bit 0x04
-#define subq_bit 0x02
-#define frame_size_bit 0x01
-
-/*
- * disk states (bits of diskstate_flags):
- */
-#define upc_valid (current_drive->diskstate_flags&upc_bit)
-#define volume_valid (current_drive->diskstate_flags&volume_bit)
-#define toc_valid (current_drive->diskstate_flags&toc_bit)
-#define cd_size_valid (current_drive->diskstate_flags&cd_size_bit)
-#define subq_valid (current_drive->diskstate_flags&subq_bit)
-#define frame_size_valid (current_drive->diskstate_flags&frame_size_bit)
-
-/*
- * the status_bits variable
- */
-#define p_success 0x100
-#define p_door_closed 0x80
-#define p_caddy_in 0x40
-#define p_spinning 0x20
-#define p_check 0x10
-#define p_busy_new 0x08
-#define p_door_locked 0x04
-#define p_disk_ok 0x01
-
-/*
- * LCS-7260 special status result bits:
- */
-#define p_lcs_door_locked 0x02
-#define p_lcs_door_closed 0x01 /* probably disk_in */
-
-/*
- * CR-52x special status result bits:
- */
-#define p_caddin_old 0x40
-#define p_success_old 0x08
-#define p_busy_old 0x04
-#define p_bit_1 0x02 /* hopefully unused now */
-
-/*
- * "generation specific" defs of the status result bits:
- */
-#define p0_door_closed 0x80
-#define p0_caddy_in 0x40
-#define p0_spinning 0x20
-#define p0_check 0x10
-#define p0_success 0x08 /* unused */
-#define p0_busy 0x04
-#define p0_bit_1 0x02 /* unused */
-#define p0_disk_ok 0x01
-
-#define pL_disk_in 0x40
-#define pL_spinning 0x20
-#define pL_check 0x10
-#define pL_success 0x08 /* unused ?? */
-#define pL_busy 0x04
-#define pL_door_locked 0x02
-#define pL_door_closed 0x01
-
-#define pV_door_closed 0x40
-#define pV_spinning 0x20
-#define pV_check 0x10
-#define pV_success 0x08
-#define pV_busy 0x04
-#define pV_door_locked 0x02
-#define pV_disk_ok 0x01
-
-#define p1_door_closed 0x80
-#define p1_disk_in 0x40
-#define p1_spinning 0x20
-#define p1_check 0x10
-#define p1_busy 0x08
-#define p1_door_locked 0x04
-#define p1_bit_1 0x02 /* unused */
-#define p1_disk_ok 0x01
-
-#define p2_disk_ok 0x80
-#define p2_door_locked 0x40
-#define p2_spinning 0x20
-#define p2_busy2 0x10
-#define p2_busy1 0x08
-#define p2_door_closed 0x04
-#define p2_disk_in 0x02
-#define p2_check 0x01
-
-/*
- * used drive states:
- */
-#define st_door_closed (current_drive->status_bits&p_door_closed)
-#define st_caddy_in (current_drive->status_bits&p_caddy_in)
-#define st_spinning (current_drive->status_bits&p_spinning)
-#define st_check (current_drive->status_bits&p_check)
-#define st_busy (current_drive->status_bits&p_busy_new)
-#define st_door_locked (current_drive->status_bits&p_door_locked)
-#define st_diskok (current_drive->status_bits&p_disk_ok)
-
-/*
- * bits of the CDi_status register:
- */
-#define s_not_result_ready 0x04 /* 0: "result ready" */
-#define s_not_data_ready 0x02 /* 0: "data ready" */
-#define s_attention 0x01 /* 1: "attention required" */
-/*
- * usable as:
- */
-#define DRV_ATTN ((inb(CDi_status)&s_attention)!=0)
-#define DATA_READY ((inb(CDi_status)&s_not_data_ready)==0)
-#define RESULT_READY ((inb(CDi_status)&s_not_result_ready)==0)
-
-/*
- * drive families and types (firmware versions):
- */
-#define drv_fam0 0x0100 /* CR-52x family */
-#define drv_199 (drv_fam0+0x01) /* <200 */
-#define drv_200 (drv_fam0+0x02) /* <201 */
-#define drv_201 (drv_fam0+0x03) /* <210 */
-#define drv_210 (drv_fam0+0x04) /* <211 */
-#define drv_211 (drv_fam0+0x05) /* <300 */
-#define drv_300 (drv_fam0+0x06) /* >=300 */
-
-#define drv_fam1 0x0200 /* CR-56x family */
-#define drv_099 (drv_fam1+0x01) /* <100 */
-#define drv_100 (drv_fam1+0x02) /* >=100, only 1.02 and 5.00 known */
-
-#define drv_fam2 0x0400 /* CD200 family */
-
-#define drv_famT 0x0800 /* TEAC CD-55A */
-
-#define drv_famL 0x1000 /* Longshine family */
-#define drv_260 (drv_famL+0x01) /* LCS-7260 */
-#define drv_e1 (drv_famL+0x01) /* LCS-7260, firmware "A E1" */
-#define drv_f4 (drv_famL+0x02) /* LCS-7260, firmware "A4F4" */
-
-#define drv_famV 0x2000 /* ECS-AT (vertos-100) family */
-#define drv_at (drv_famV+0x01) /* ECS-AT, firmware "1.00" */
-
-#define fam0_drive (current_drive->drv_type&drv_fam0)
-#define famL_drive (current_drive->drv_type&drv_famL)
-#define famV_drive (current_drive->drv_type&drv_famV)
-#define fam1_drive (current_drive->drv_type&drv_fam1)
-#define fam2_drive (current_drive->drv_type&drv_fam2)
-#define famT_drive (current_drive->drv_type&drv_famT)
-#define fam0L_drive (current_drive->drv_type&(drv_fam0|drv_famL))
-#define fam0V_drive (current_drive->drv_type&(drv_fam0|drv_famV))
-#define famLV_drive (current_drive->drv_type&(drv_famL|drv_famV))
-#define fam0LV_drive (current_drive->drv_type&(drv_fam0|drv_famL|drv_famV))
-#define fam1L_drive (current_drive->drv_type&(drv_fam1|drv_famL))
-#define fam1V_drive (current_drive->drv_type&(drv_fam1|drv_famV))
-#define fam1LV_drive (current_drive->drv_type&(drv_fam1|drv_famL|drv_famV))
-#define fam01_drive (current_drive->drv_type&(drv_fam0|drv_fam1))
-#define fam12_drive (current_drive->drv_type&(drv_fam1|drv_fam2))
-#define fam2T_drive (current_drive->drv_type&(drv_fam2|drv_famT))
-
-/*
- * audio states:
- */
-#define audio_completed 3 /* Forgot this one! --AJK */
-#define audio_playing 2
-#define audio_pausing 1
-
-/*
- * drv_pattern, drv_options:
- */
-#define speed_auto 0x80
-#define speed_300 0x40
-#define speed_150 0x20
-#define audio_mono 0x04
-
-/*
- * values of cmd_type (0 else):
- */
-#define READ_M1 0x01 /* "data mode 1": 2048 bytes per frame */
-#define READ_M2 0x02 /* "data mode 2": 12+2048+280 bytes per frame */
-#define READ_SC 0x04 /* "subchannel info": 96 bytes per frame */
-#define READ_AU 0x08 /* "audio frame": 2352 bytes per frame */
-
-/*
- * sense_byte:
- *
- * values: 00
- * 01
- * 81
- * 82 "raw audio" mode
- * xx from infobuf[0] after 85 00 00 00 00 00 00
- */
-
-/* audio status (bin) */
-#define aud_00 0x00 /* Audio status byte not supported or not valid */
-#define audx11 0x0b /* Audio play operation in progress */
-#define audx12 0x0c /* Audio play operation paused */
-#define audx13 0x0d /* Audio play operation successfully completed */
-#define audx14 0x0e /* Audio play operation stopped due to error */
-#define audx15 0x0f /* No current audio status to return */
-/* audio status (bcd) */
-#define aud_11 0x11 /* Audio play operation in progress */
-#define aud_12 0x12 /* Audio play operation paused */
-#define aud_13 0x13 /* Audio play operation successfully completed */
-#define aud_14 0x14 /* Audio play operation stopped due to error */
-#define aud_15 0x15 /* No current audio status to return */
-
-/*
- * highest allowed drive number (MINOR+1)
- */
-#define NR_SBPCD 4
-
-/*
- * we try to never disable interrupts - seems to work
- */
-#define SBPCD_DIS_IRQ 0
-
-/*
- * "write byte to port"
- */
-#define OUT(x,y) outb(y,x)
-
-/*==========================================================================*/
-
-#define MIXER_addr SOUND_BASE+4 /* sound card's address register */
-#define MIXER_data SOUND_BASE+5 /* sound card's data register */
-#define MIXER_CD_Volume 0x28 /* internal SB Pro register address */
-
-/*==========================================================================*/
-
-#define MAX_TRACKS 99
-
-#define ERR_DISKCHANGE 615
-
-/*==========================================================================*/
-/*
- * To make conversions easier (machine dependent!)
- */
-typedef union _msf
-{
- u_int n;
- u_char c[4];
-} MSF;
-
-typedef union _blk
-{
- u_int n;
- u_char c[4];
-} BLK;
-
-/*==========================================================================*/
-
-/*============================================================================
-==============================================================================
-
-COMMAND SET of "old" drives like CR-521, CR-522
- (the CR-562 family is different):
-
-No. Command Code
---------------------------------------------
-
-Drive Commands:
- 1 Seek 01
- 2 Read Data 02
- 3 Read XA-Data 03
- 4 Read Header 04
- 5 Spin Up 05
- 6 Spin Down 06
- 7 Diagnostic 07
- 8 Read UPC 08
- 9 Read ISRC 09
-10 Play Audio 0A
-11 Play Audio MSF 0B
-12 Play Audio Track/Index 0C
-
-Status Commands:
-13 Read Status 81
-14 Read Error 82
-15 Read Drive Version 83
-16 Mode Select 84
-17 Mode Sense 85
-18 Set XA Parameter 86
-19 Read XA Parameter 87
-20 Read Capacity 88
-21 Read SUB_Q 89
-22 Read Disc Code 8A
-23 Read Disc Information 8B
-24 Read TOC 8C
-25 Pause/Resume 8D
-26 Read Packet 8E
-27 Read Path Check 00
-
-
-all numbers (lba, msf-bin, msf-bcd, counts) to transfer high byte first
-
-mnemo 7-byte command #bytes response (r0...rn)
-________ ____________________ ____
-
-Read Status:
-status: 81. (1) one-byte command, gives the main
- status byte
-Read Error:
-check1: 82 00 00 00 00 00 00. (6) r1: audio status
-
-Read Packet:
-check2: 8e xx 00 00 00 00 00. (xx) gets xx bytes response, relating
- to commands 01 04 05 07 08 09
-
-Play Audio:
-play: 0a ll-bb-aa nn-nn-nn. (0) play audio, ll-bb-aa: starting block (lba),
- nn-nn-nn: #blocks
-Play Audio MSF:
- 0b mm-ss-ff mm-ss-ff (0) play audio from/to
-
-Play Audio Track/Index:
- 0c ...
-
-Pause/Resume:
-pause: 8d pr 00 00 00 00 00. (0) pause (pr=00)
- resume (pr=80) audio playing
-
-Mode Select:
- 84 00 nn-nn ??.?? 00 (0) nn-nn: 2048 or 2340
- possibly defines transfer size
-
-set_vol: 84 83 00 00 sw le 00. (0) sw(itch): lrxxxxxx (off=1)
- le(vel): min=0, max=FF, else half
- (firmware 2.11)
-
-Mode Sense:
-get_vol: 85 03 00 00 00 00 00. (2) tell current audio volume setting
-
-Read Disc Information:
-tocdesc: 8b 00 00 00 00 00 00. (6) read the toc descriptor ("msf-bin"-format)
-
-Read TOC:
-tocent: 8c fl nn 00 00 00 00. (8) read toc entry #nn
- (fl=0:"lba"-, =2:"msf-bin"-format)
-
-Read Capacity:
-capacit: 88 00 00 00 00 00 00. (5) "read CD-ROM capacity"
-
-
-Read Path Check:
-ping: 00 00 00 00 00 00 00. (2) r0=AA, r1=55
- ("ping" if the drive is connected)
-
-Read Drive Version:
-ident: 83 00 00 00 00 00 00. (12) gives "MATSHITAn.nn"
- (n.nn = 2.01, 2.11., 3.00, ...)
-
-Seek:
-seek: 01 00 ll-bb-aa 00 00. (0)
-seek: 01 02 mm-ss-ff 00 00. (0)
-
-Read Data:
-read: 02 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2048 bytes,
- starting at block xx-xx-xx
- fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read XA-Data:
-read: 03 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2340 bytes,
- starting at block xx-xx-xx
- fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read SUB_Q:
- 89 fl 00 00 00 00 00. (13) r0: audio status, r4-r7: lba/msf,
- fl=0: "lba", fl=2: "msf"
-
-Read Disc Code:
- 8a 00 00 00 00 00 00. (14) possibly extended "check condition"-info
-
-Read Header:
- 04 00 ll-bb-aa 00 00. (0) 4 bytes response with "check2"
- 04 02 mm-ss-ff 00 00. (0) 4 bytes response with "check2"
-
-Spin Up:
- 05 00 ll-bb-aa 00 00. (0) possibly implies a "seek"
-
-Spin Down:
- 06 ...
-
-Diagnostic:
- 07 00 ll-bb-aa 00 00. (2) 2 bytes response with "check2"
- 07 02 mm-ss-ff 00 00. (2) 2 bytes response with "check2"
-
-Read UPC:
- 08 00 ll-bb-aa 00 00. (16)
- 08 02 mm-ss-ff 00 00. (16)
-
-Read ISRC:
- 09 00 ll-bb-aa 00 00. (15) 15 bytes response with "check2"
- 09 02 mm-ss-ff 00 00. (15) 15 bytes response with "check2"
-
-Set XA Parameter:
- 86 ...
-
-Read XA Parameter:
- 87 ...
-
-==============================================================================
-============================================================================*/
-
-/*
- * commands
- *
- * CR-52x: CMD0_
- * CR-56x: CMD1_
- * CD200: CMD2_
- * LCS-7260: CMDL_
- * TEAC CD-55A: CMDT_
- * ECS-AT: CMDV_
- */
-#define CMD1_RESET 0x0a
-#define CMD2_RESET 0x01
-#define CMDT_RESET 0xc0
-
-#define CMD1_LOCK_CTL 0x0c
-#define CMD2_LOCK_CTL 0x1e
-#define CMDT_LOCK_CTL CMD2_LOCK_CTL
-#define CMDL_LOCK_CTL 0x0e
-#define CMDV_LOCK_CTL CMDL_LOCK_CTL
-
-#define CMD1_TRAY_CTL 0x07
-#define CMD2_TRAY_CTL 0x1b
-#define CMDT_TRAY_CTL CMD2_TRAY_CTL
-#define CMDL_TRAY_CTL 0x0d
-#define CMDV_TRAY_CTL CMDL_TRAY_CTL
-
-#define CMD1_MULTISESS 0x8d
-#define CMDL_MULTISESS 0x8c
-#define CMDV_MULTISESS CMDL_MULTISESS
-
-#define CMD1_SUBCHANINF 0x11
-#define CMD2_SUBCHANINF 0x??
-
-#define CMD1_ABORT 0x08
-#define CMD2_ABORT 0x08
-#define CMDT_ABORT 0x08
-
-#define CMD2_x02 0x02
-
-#define CMD2_SETSPEED 0xda
-
-#define CMD0_PATH_CHECK 0x00
-#define CMD1_PATH_CHECK 0x???
-#define CMD2_PATH_CHECK 0x???
-#define CMDT_PATH_CHECK 0x???
-#define CMDL_PATH_CHECK CMD0_PATH_CHECK
-#define CMDV_PATH_CHECK CMD0_PATH_CHECK
-
-#define CMD0_SEEK 0x01
-#define CMD1_SEEK CMD0_SEEK
-#define CMD2_SEEK 0x2b
-#define CMDT_SEEK CMD2_SEEK
-#define CMDL_SEEK CMD0_SEEK
-#define CMDV_SEEK CMD0_SEEK
-
-#define CMD0_READ 0x02
-#define CMD1_READ 0x10
-#define CMD2_READ 0x28
-#define CMDT_READ CMD2_READ
-#define CMDL_READ CMD0_READ
-#define CMDV_READ CMD0_READ
-
-#define CMD0_READ_XA 0x03
-#define CMD2_READ_XA 0xd4
-#define CMD2_READ_XA2 0xd5
-#define CMDL_READ_XA CMD0_READ_XA /* really ?? */
-#define CMDV_READ_XA CMD0_READ_XA
-
-#define CMD0_READ_HEAD 0x04
-
-#define CMD0_SPINUP 0x05
-#define CMD1_SPINUP 0x02
-#define CMD2_SPINUP CMD2_TRAY_CTL
-#define CMDL_SPINUP CMD0_SPINUP
-#define CMDV_SPINUP CMD0_SPINUP
-
-#define CMD0_SPINDOWN 0x06 /* really??? */
-#define CMD1_SPINDOWN 0x06
-#define CMD2_SPINDOWN CMD2_TRAY_CTL
-#define CMDL_SPINDOWN 0x0d
-#define CMDV_SPINDOWN CMD0_SPINDOWN
-
-#define CMD0_DIAG 0x07
-
-#define CMD0_READ_UPC 0x08
-#define CMD1_READ_UPC 0x88
-#define CMD2_READ_UPC 0x???
-#define CMDL_READ_UPC CMD0_READ_UPC
-#define CMDV_READ_UPC 0x8f
-
-#define CMD0_READ_ISRC 0x09
-
-#define CMD0_PLAY 0x0a
-#define CMD1_PLAY 0x???
-#define CMD2_PLAY 0x???
-#define CMDL_PLAY CMD0_PLAY
-#define CMDV_PLAY CMD0_PLAY
-
-#define CMD0_PLAY_MSF 0x0b
-#define CMD1_PLAY_MSF 0x0e
-#define CMD2_PLAY_MSF 0x47
-#define CMDT_PLAY_MSF CMD2_PLAY_MSF
-#define CMDL_PLAY_MSF 0x???
-
-#define CMD0_PLAY_TI 0x0c
-#define CMD1_PLAY_TI 0x0f
-
-#define CMD0_STATUS 0x81
-#define CMD1_STATUS 0x05
-#define CMD2_STATUS 0x00
-#define CMDT_STATUS CMD2_STATUS
-#define CMDL_STATUS CMD0_STATUS
-#define CMDV_STATUS CMD0_STATUS
-#define CMD2_SEEK_LEADIN 0x00
-
-#define CMD0_READ_ERR 0x82
-#define CMD1_READ_ERR CMD0_READ_ERR
-#define CMD2_READ_ERR 0x03
-#define CMDT_READ_ERR CMD2_READ_ERR /* get audio status */
-#define CMDL_READ_ERR CMD0_READ_ERR
-#define CMDV_READ_ERR CMD0_READ_ERR
-
-#define CMD0_READ_VER 0x83
-#define CMD1_READ_VER CMD0_READ_VER
-#define CMD2_READ_VER 0x12
-#define CMDT_READ_VER CMD2_READ_VER /* really ?? */
-#define CMDL_READ_VER CMD0_READ_VER
-#define CMDV_READ_VER CMD0_READ_VER
-
-#define CMD0_SETMODE 0x84
-#define CMD1_SETMODE 0x09
-#define CMD2_SETMODE 0x55
-#define CMDT_SETMODE CMD2_SETMODE
-#define CMDL_SETMODE CMD0_SETMODE
-
-#define CMD0_GETMODE 0x85
-#define CMD1_GETMODE 0x84
-#define CMD2_GETMODE 0x5a
-#define CMDT_GETMODE CMD2_GETMODE
-#define CMDL_GETMODE CMD0_GETMODE
-
-#define CMD0_SET_XA 0x86
-
-#define CMD0_GET_XA 0x87
-
-#define CMD0_CAPACITY 0x88
-#define CMD1_CAPACITY 0x85
-#define CMD2_CAPACITY 0x25
-#define CMDL_CAPACITY CMD0_CAPACITY /* missing in some firmware versions */
-
-#define CMD0_READSUBQ 0x89
-#define CMD1_READSUBQ 0x87
-#define CMD2_READSUBQ 0x42
-#define CMDT_READSUBQ CMD2_READSUBQ
-#define CMDL_READSUBQ CMD0_READSUBQ
-#define CMDV_READSUBQ CMD0_READSUBQ
-
-#define CMD0_DISKCODE 0x8a
-
-#define CMD0_DISKINFO 0x8b
-#define CMD1_DISKINFO CMD0_DISKINFO
-#define CMD2_DISKINFO 0x43
-#define CMDT_DISKINFO CMD2_DISKINFO
-#define CMDL_DISKINFO CMD0_DISKINFO
-#define CMDV_DISKINFO CMD0_DISKINFO
-
-#define CMD0_READTOC 0x8c
-#define CMD1_READTOC CMD0_READTOC
-#define CMD2_READTOC 0x???
-#define CMDL_READTOC CMD0_READTOC
-#define CMDV_READTOC CMD0_READTOC
-
-#define CMD0_PAU_RES 0x8d
-#define CMD1_PAU_RES 0x0d
-#define CMD2_PAU_RES 0x4b
-#define CMDT_PAUSE CMD2_PAU_RES
-#define CMDL_PAU_RES CMD0_PAU_RES
-#define CMDV_PAUSE CMD0_PAU_RES
-
-#define CMD0_PACKET 0x8e
-#define CMD1_PACKET CMD0_PACKET
-#define CMD2_PACKET 0x???
-#define CMDL_PACKET CMD0_PACKET
-#define CMDV_PACKET 0x???
-
-/*==========================================================================*/
-/*==========================================================================*/
-#endif /* _LINUX_SBPCD_H */
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
deleted file mode 100644
index 5409fca5bbfc..000000000000
--- a/drivers/cdrom/sjcd.c
+++ /dev/null
@@ -1,1815 +0,0 @@
-/* -- sjcd.c
- *
- * Sanyo CD-ROM device driver implementation, Version 1.6
- * Copyright (C) 1995 Vadim V. Model
- *
- * model@cecmow.enet.dec.com
- * vadim@rbrf.ru
- * vadim@ipsun.ras.ru
- *
- *
- * This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
- * it was developed under use of mcd.c from Martin Harriss, with help of
- * Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl).
- *
- * It is planned to include these routines into sbpcd.c later - to make
- * a "mixed use" on one cable possible for all kinds of drives which use
- * the SoundBlaster/Panasonic style CDROM interface. But today, the
- * ability to install directly from CDROM is more important than flexibility.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * History:
- * 1.1 First public release with kernel version 1.3.7.
- * Written by Vadim Model.
- * 1.2 Added detection and configuration of cdrom interface
- * on ISP16 soundcard.
- * Allow for command line options: sjcd=<io_base>,<irq>,<dma>
- * 1.3 Some minor changes to README.sjcd.
- * 1.4 MSS Sound support!! Listen to a CD through the speakers.
- * 1.5 Module support and bugfixes.
- * Tray locking.
- * 1.6 Removed ISP16 code from this driver.
- * Allow only to set io base address on command line: sjcd=<io_base>
- * Changes to Documentation/cdrom/sjcd
- * Added cleanup after any error in the initialisation.
- * 1.7 Added code to set the sector size tables to prevent the bug present in
- * the previous version of this driver. Coded added by Anthony Barbachan
- * from bugfix tip originally suggested by Alan Cox.
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- */
-
-#define SJCD_VERSION_MAJOR 1
-#define SJCD_VERSION_MINOR 7
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-#include "sjcd.h"
-
-static int sjcd_present = 0;
-static struct request_queue *sjcd_queue;
-
-#define MAJOR_NR SANYO_CDROM_MAJOR
-#define QUEUE (sjcd_queue)
-#define CURRENT elv_next_request(sjcd_queue)
-
-#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
-
-/*
- * buffer for block size conversion
- */
-static char sjcd_buf[2048 * SJCD_BUF_SIZ];
-static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn;
-static volatile int sjcd_buf_in, sjcd_buf_out = -1;
-
-/*
- * Status.
- */
-static unsigned short sjcd_status_valid = 0;
-static unsigned short sjcd_door_closed;
-static unsigned short sjcd_door_was_open;
-static unsigned short sjcd_media_is_available;
-static unsigned short sjcd_media_is_changed;
-static unsigned short sjcd_toc_uptodate = 0;
-static unsigned short sjcd_command_failed;
-static volatile unsigned char sjcd_completion_status = 0;
-static volatile unsigned char sjcd_completion_error = 0;
-static unsigned short sjcd_command_is_in_progress = 0;
-static unsigned short sjcd_error_reported = 0;
-static DEFINE_SPINLOCK(sjcd_lock);
-
-static int sjcd_open_count;
-
-static int sjcd_audio_status;
-static struct sjcd_play_msf sjcd_playing;
-
-static int sjcd_base = SJCD_BASE_ADDR;
-
-module_param(sjcd_base, int, 0);
-
-static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
-
-/*
- * Data transfer.
- */
-static volatile unsigned short sjcd_transfer_is_active = 0;
-
-enum sjcd_transfer_state {
- SJCD_S_IDLE = 0,
- SJCD_S_START = 1,
- SJCD_S_MODE = 2,
- SJCD_S_READ = 3,
- SJCD_S_DATA = 4,
- SJCD_S_STOP = 5,
- SJCD_S_STOPPING = 6
-};
-static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
-static long sjcd_transfer_timeout = 0;
-static int sjcd_read_count = 0;
-static unsigned char sjcd_mode = 0;
-
-#define SJCD_READ_TIMEOUT 5000
-
-#if defined( SJCD_GATHER_STAT )
-/*
- * Statistic.
- */
-static struct sjcd_stat statistic;
-#endif
-
-/*
- * Timer.
- */
-static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
-
-#define SJCD_SET_TIMER( func, tmout ) \
- ( sjcd_delay_timer.expires = jiffies+tmout, \
- sjcd_delay_timer.function = ( void * )func, \
- add_timer( &sjcd_delay_timer ) )
-
-#define CLEAR_TIMER del_timer( &sjcd_delay_timer )
-
-/*
- * Set up device, i.e., use command line data to set
- * base address.
- */
-#ifndef MODULE
-static int __init sjcd_setup(char *str)
-{
- int ints[2];
- (void) get_options(str, ARRAY_SIZE(ints), ints);
- if (ints[0] > 0)
- sjcd_base = ints[1];
-
- return 1;
-}
-
-__setup("sjcd=", sjcd_setup);
-
-#endif
-
-/*
- * Special converters.
- */
-static unsigned char bin2bcd(int bin)
-{
- int u, v;
-
- u = bin % 10;
- v = bin / 10;
- return (u | (v << 4));
-}
-
-static int bcd2bin(unsigned char bcd)
-{
- return ((bcd >> 4) * 10 + (bcd & 0x0F));
-}
-
-static long msf2hsg(struct msf *mp)
-{
- return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75
- + bcd2bin(mp->min) * 4500 - 150);
-}
-
-static void hsg2msf(long hsg, struct msf *msf)
-{
- hsg += 150;
- msf->min = hsg / 4500;
- hsg %= 4500;
- msf->sec = hsg / 75;
- msf->frame = hsg % 75;
- msf->min = bin2bcd(msf->min); /* convert to BCD */
- msf->sec = bin2bcd(msf->sec);
- msf->frame = bin2bcd(msf->frame);
-}
-
-/*
- * Send a command to cdrom. Invalidate status.
- */
-static void sjcd_send_cmd(unsigned char cmd)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with one arg to cdrom. Invalidate status.
- */
-static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(a, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with four args to cdrom. Invalidate status.
- */
-static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a,
- unsigned char b, unsigned char c,
- unsigned char d)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_4_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(a, SJCDPORT(0));
- outb(b, SJCDPORT(0));
- outb(c, SJCDPORT(0));
- outb(d, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a play or read command to cdrom. Invalidate Status.
- */
-static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_long_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(pms->start.min, SJCDPORT(0));
- outb(pms->start.sec, SJCDPORT(0));
- outb(pms->start.frame, SJCDPORT(0));
- outb(pms->end.min, SJCDPORT(0));
- outb(pms->end.sec, SJCDPORT(0));
- outb(pms->end.frame, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Get a value from the data port. Should not block, so we use a little
- * wait for a while. Returns 0 if OK.
- */
-static int sjcd_load_response(void *buf, int len)
-{
- unsigned char *resp = (unsigned char *) buf;
-
- for (; len; --len) {
- int i;
- for (i = 200;
- i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))););
- if (i > 0)
- *resp++ = (unsigned char) inb(SJCDPORT(0));
- else
- break;
- }
- return (len);
-}
-
-/*
- * Load and parse command completion status (drive info byte and maybe error).
- * Sorry, no error classification yet.
- */
-static void sjcd_load_status(void)
-{
- sjcd_media_is_changed = 0;
- sjcd_completion_error = 0;
- sjcd_completion_status = inb(SJCDPORT(0));
- if (sjcd_completion_status & SST_DOOR_OPENED) {
- sjcd_door_closed = sjcd_media_is_available = 0;
- } else {
- sjcd_door_closed = 1;
- if (sjcd_completion_status & SST_MEDIA_CHANGED)
- sjcd_media_is_available = sjcd_media_is_changed =
- 1;
- else if (sjcd_completion_status & 0x0F) {
- /*
- * OK, we seem to catch an error ...
- */
- while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))));
- sjcd_completion_error = inb(SJCDPORT(0));
- if ((sjcd_completion_status & 0x08) &&
- (sjcd_completion_error & 0x40))
- sjcd_media_is_available = 0;
- else
- sjcd_command_failed = 1;
- } else
- sjcd_media_is_available = 1;
- }
- /*
- * Ok, status loaded successfully.
- */
- sjcd_status_valid = 1, sjcd_error_reported = 0;
- sjcd_command_is_in_progress = 0;
-
- /*
- * If the disk is changed, the TOC is not valid.
- */
- if (sjcd_media_is_changed)
- sjcd_toc_uptodate = 0;
-#if defined( SJCD_TRACE )
- printk("SJCD: status %02x.%02x loaded.\n",
- (int) sjcd_completion_status, (int) sjcd_completion_error);
-#endif
-}
-
-/*
- * Read status from cdrom. Check to see if the status is available.
- */
-static int sjcd_check_status(void)
-{
- /*
- * Try to load the response from cdrom into buffer.
- */
- if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) {
- sjcd_load_status();
- return (1);
- } else {
- /*
- * No status is available.
- */
- return (0);
- }
-}
-
-/*
- * This is just timeout counter, and nothing more. Surprised ? :-)
- */
-static volatile long sjcd_status_timeout;
-
-/*
- * We need about 10 seconds to wait. The longest command takes about 5 seconds
- * to probe the disk (usually after tray closed or drive reset). Other values
- * should be thought of for other commands.
- */
-#define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
-
-static void sjcd_status_timer(void)
-{
- if (sjcd_check_status()) {
- /*
- * The command completed and status is loaded, stop waiting.
- */
- wake_up(&sjcd_waitq);
- } else if (--sjcd_status_timeout <= 0) {
- /*
- * We are timed out.
- */
- wake_up(&sjcd_waitq);
- } else {
- /*
- * We have still some time to wait. Try again.
- */
- SJCD_SET_TIMER(sjcd_status_timer, 1);
- }
-}
-
-/*
- * Wait for status for 10 sec approx. Returns non-positive when timed out.
- * Should not be used while reading data CDs.
- */
-static int sjcd_wait_for_status(void)
-{
- sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
- SJCD_SET_TIMER(sjcd_status_timer, 1);
- sleep_on(&sjcd_waitq);
-#if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
- if (sjcd_status_timeout <= 0)
- printk("SJCD: Error Wait For Status.\n");
-#endif
- return (sjcd_status_timeout);
-}
-
-static int sjcd_receive_status(void)
-{
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD: receive_status\n");
-#endif
- /*
- * Wait a bit for status available.
- */
- for (i = 200; i-- && (sjcd_check_status() == 0););
- if (i < 0) {
-#if defined( SJCD_TRACE )
- printk("SJCD: long wait for status\n");
-#endif
- if (sjcd_wait_for_status() <= 0)
- printk("SJCD: Timeout when read status.\n");
- else
- i = 0;
- }
- return (i);
-}
-
-/*
- * Load the status. Issue get status command and wait for status available.
- */
-static void sjcd_get_status(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: get_status\n");
-#endif
- sjcd_send_cmd(SCMD_GET_STATUS);
- sjcd_receive_status();
-}
-
-/*
- * Check the drive if the disk is changed. Should be revised.
- */
-static int sjcd_disk_change(struct gendisk *disk)
-{
-#if 0
- printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name);
-#endif
- if (!sjcd_command_is_in_progress)
- sjcd_get_status();
- return (sjcd_status_valid ? sjcd_media_is_changed : 0);
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary.
- * We assume that the drive contains no more than 99 toc entries.
- */
-static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS];
-static unsigned char sjcd_first_track_no, sjcd_last_track_no;
-#define sjcd_disk_length sjcd_table_of_contents[0].un.track_msf
-
-static int sjcd_update_toc(void)
-{
- struct sjcd_hw_disk_info info;
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD: update toc:\n");
-#endif
- /*
- * check to see if we need to do anything
- */
- if (sjcd_toc_uptodate)
- return (0);
-
- /*
- * Get the TOC start information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about TOC start.\n");
- return (-1);
- }
- sjcd_first_track_no = bcd2bin(info.un.track_no);
- } else {
- printk("SJCD: get first failed\n");
- return (-1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no);
-#endif
- /*
- * Get the TOC finish information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about TOC finish.\n");
- return (-1);
- }
- sjcd_last_track_no = bcd2bin(info.un.track_no);
- } else {
- printk("SJCD: get last failed\n");
- return (-1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no);
-#endif
- for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) {
- /*
- * Get the first track information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i));
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&sjcd_table_of_contents[i],
- sizeof(struct
- sjcd_hw_disk_info))
- != 0) {
- printk
- ("SJCD: cannot load info for %d track\n",
- i);
- return (-1);
- }
- } else {
- printk("SJCD: get info %d failed\n", i);
- return (-1);
- }
- }
-
- /*
- * Get the disk length info.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about disk size.\n");
- return (-1);
- }
- sjcd_disk_length.min = info.un.track_msf.min;
- sjcd_disk_length.sec = info.un.track_msf.sec;
- sjcd_disk_length.frame = info.un.track_msf.frame;
- } else {
- printk("SJCD: get size failed\n");
- return (1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,
- sjcd_disk_length.sec, sjcd_disk_length.frame);
-#endif
- return (0);
-}
-
-/*
- * Load subchannel information.
- */
-static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp)
-{
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: load sub q\n");
-#endif
- sjcd_send_cmd(SCMD_GET_QINFO);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {
- sjcd_send_cmd(0xF2);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
- return (-1);
- sjcd_send_cmd(SCMD_GET_QINFO);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
- return (-1);
- }
- if (sjcd_media_is_available)
- if (sjcd_load_response(qp, sizeof(*qp)) == 0)
- return (0);
- return (-1);
-}
-
-/*
- * Start playing from the specified position.
- */
-static int sjcd_play(struct sjcd_play_msf *mp)
-{
- struct sjcd_play_msf msf;
-
- /*
- * Turn the device to play mode.
- */
- sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);
- if (sjcd_receive_status() < 0)
- return (-1);
-
- /*
- * Seek to the starting point.
- */
- msf.start = mp->start;
- msf.end.min = msf.end.sec = msf.end.frame = 0x00;
- sjcd_send_6_cmd(SCMD_SEEK, &msf);
- if (sjcd_receive_status() < 0)
- return (-1);
-
- /*
- * Start playing.
- */
- sjcd_send_6_cmd(SCMD_PLAY, mp);
- return (sjcd_receive_status());
-}
-
-/*
- * Tray control functions.
- */
-static int sjcd_tray_close(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_close\n");
-#endif
- sjcd_send_cmd(SCMD_CLOSE_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_lock(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_lock\n");
-#endif
- sjcd_send_cmd(SCMD_LOCK_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_unlock(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_unlock\n");
-#endif
- sjcd_send_cmd(SCMD_UNLOCK_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_open(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_open\n");
-#endif
- sjcd_send_cmd(SCMD_EJECT_TRAY);
- return (sjcd_receive_status());
-}
-
-/*
- * Do some user commands.
- */
-static int sjcd_ioctl(struct inode *ip, struct file *fp,
- unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
-#if defined( SJCD_TRACE )
- printk("SJCD:ioctl\n");
-#endif
-
- sjcd_get_status();
- if (!sjcd_status_valid)
- return (-EIO);
- if (sjcd_update_toc() < 0)
- return (-EIO);
-
- switch (cmd) {
- case CDROMSTART:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: start\n");
-#endif
- return (0);
- }
-
- case CDROMSTOP:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: stop\n");
-#endif
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
- return (0);
- }
-
- case CDROMPAUSE:{
- struct sjcd_hw_qinfo q_info;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: pause\n");
-#endif
- if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- if (sjcd_get_q_info(&q_info) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_NO_STATUS;
- } else {
- sjcd_audio_status =
- CDROM_AUDIO_PAUSED;
- sjcd_playing.start = q_info.abs;
- }
- return (0);
- } else
- return (-EINVAL);
- }
-
- case CDROMRESUME:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: resume\n");
-#endif
- if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {
- /*
- * continue play starting at saved location
- */
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else {
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- return (0);
- }
- } else
- return (-EINVAL);
- }
-
- case CDROMPLAYTRKIND:{
- struct cdrom_ti ti;
- int s = -EFAULT;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: playtrkind\n");
-#endif
- if (!copy_from_user(&ti, argp, sizeof(ti))) {
- s = 0;
- if (ti.cdti_trk0 < sjcd_first_track_no)
- return (-EINVAL);
- if (ti.cdti_trk1 > sjcd_last_track_no)
- ti.cdti_trk1 = sjcd_last_track_no;
- if (ti.cdti_trk0 > ti.cdti_trk1)
- return (-EINVAL);
-
- sjcd_playing.start =
- sjcd_table_of_contents[ti.cdti_trk0].
- un.track_msf;
- sjcd_playing.end =
- (ti.cdti_trk1 <
- sjcd_last_track_no) ?
- sjcd_table_of_contents[ti.cdti_trk1 +
- 1].un.
- track_msf : sjcd_table_of_contents[0].
- un.track_msf;
-
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- }
- return (s);
- }
-
- case CDROMPLAYMSF:{
- struct cdrom_msf sjcd_msf;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: playmsf\n");
-#endif
- if ((s =
- access_ok(VERIFY_READ, argp, sizeof(sjcd_msf))
- ? 0 : -EFAULT) == 0) {
- if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- sjcd_audio_status =
- CDROM_AUDIO_NO_STATUS;
- }
-
- if (copy_from_user(&sjcd_msf, argp,
- sizeof(sjcd_msf)))
- return (-EFAULT);
-
- sjcd_playing.start.min =
- bin2bcd(sjcd_msf.cdmsf_min0);
- sjcd_playing.start.sec =
- bin2bcd(sjcd_msf.cdmsf_sec0);
- sjcd_playing.start.frame =
- bin2bcd(sjcd_msf.cdmsf_frame0);
- sjcd_playing.end.min =
- bin2bcd(sjcd_msf.cdmsf_min1);
- sjcd_playing.end.sec =
- bin2bcd(sjcd_msf.cdmsf_sec1);
- sjcd_playing.end.frame =
- bin2bcd(sjcd_msf.cdmsf_frame1);
-
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- }
- return (s);
- }
-
- case CDROMREADTOCHDR:{
- struct cdrom_tochdr toc_header;
-#if defined (SJCD_TRACE )
- printk("SJCD: ioctl: readtocheader\n");
-#endif
- toc_header.cdth_trk0 = sjcd_first_track_no;
- toc_header.cdth_trk1 = sjcd_last_track_no;
- if (copy_to_user(argp, &toc_header,
- sizeof(toc_header)))
- return -EFAULT;
- return 0;
- }
-
- case CDROMREADTOCENTRY:{
- struct cdrom_tocentry toc_entry;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: readtocentry\n");
-#endif
- if ((s =
- access_ok(VERIFY_WRITE, argp, sizeof(toc_entry))
- ? 0 : -EFAULT) == 0) {
- struct sjcd_hw_disk_info *tp;
-
- if (copy_from_user(&toc_entry, argp,
- sizeof(toc_entry)))
- return (-EFAULT);
- if (toc_entry.cdte_track == CDROM_LEADOUT)
- tp = &sjcd_table_of_contents[0];
- else if (toc_entry.cdte_track <
- sjcd_first_track_no)
- return (-EINVAL);
- else if (toc_entry.cdte_track >
- sjcd_last_track_no)
- return (-EINVAL);
- else
- tp = &sjcd_table_of_contents
- [toc_entry.cdte_track];
-
- toc_entry.cdte_adr =
- tp->track_control & 0x0F;
- toc_entry.cdte_ctrl =
- tp->track_control >> 4;
-
- switch (toc_entry.cdte_format) {
- case CDROM_LBA:
- toc_entry.cdte_addr.lba =
- msf2hsg(&(tp->un.track_msf));
- break;
- case CDROM_MSF:
- toc_entry.cdte_addr.msf.minute =
- bcd2bin(tp->un.track_msf.min);
- toc_entry.cdte_addr.msf.second =
- bcd2bin(tp->un.track_msf.sec);
- toc_entry.cdte_addr.msf.frame =
- bcd2bin(tp->un.track_msf.
- frame);
- break;
- default:
- return (-EINVAL);
- }
- if (copy_to_user(argp, &toc_entry,
- sizeof(toc_entry)))
- s = -EFAULT;
- }
- return (s);
- }
-
- case CDROMSUBCHNL:{
- struct cdrom_subchnl subchnl;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: subchnl\n");
-#endif
- if ((s =
- access_ok(VERIFY_WRITE, argp, sizeof(subchnl))
- ? 0 : -EFAULT) == 0) {
- struct sjcd_hw_qinfo q_info;
-
- if (copy_from_user(&subchnl, argp,
- sizeof(subchnl)))
- return (-EFAULT);
-
- if (sjcd_get_q_info(&q_info) < 0)
- return (-EIO);
-
- subchnl.cdsc_audiostatus =
- sjcd_audio_status;
- subchnl.cdsc_adr =
- q_info.track_control & 0x0F;
- subchnl.cdsc_ctrl =
- q_info.track_control >> 4;
- subchnl.cdsc_trk =
- bcd2bin(q_info.track_no);
- subchnl.cdsc_ind = bcd2bin(q_info.x);
-
- switch (subchnl.cdsc_format) {
- case CDROM_LBA:
- subchnl.cdsc_absaddr.lba =
- msf2hsg(&(q_info.abs));
- subchnl.cdsc_reladdr.lba =
- msf2hsg(&(q_info.rel));
- break;
- case CDROM_MSF:
- subchnl.cdsc_absaddr.msf.minute =
- bcd2bin(q_info.abs.min);
- subchnl.cdsc_absaddr.msf.second =
- bcd2bin(q_info.abs.sec);
- subchnl.cdsc_absaddr.msf.frame =
- bcd2bin(q_info.abs.frame);
- subchnl.cdsc_reladdr.msf.minute =
- bcd2bin(q_info.rel.min);
- subchnl.cdsc_reladdr.msf.second =
- bcd2bin(q_info.rel.sec);
- subchnl.cdsc_reladdr.msf.frame =
- bcd2bin(q_info.rel.frame);
- break;
- default:
- return (-EINVAL);
- }
- if (copy_to_user(argp, &subchnl,
- sizeof(subchnl)))
- s = -EFAULT;
- }
- return (s);
- }
-
- case CDROMVOLCTRL:{
- struct cdrom_volctrl vol_ctrl;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: volctrl\n");
-#endif
- if ((s =
- access_ok(VERIFY_READ, argp, sizeof(vol_ctrl))
- ? 0 : -EFAULT) == 0) {
- unsigned char dummy[4];
-
- if (copy_from_user(&vol_ctrl, argp,
- sizeof(vol_ctrl)))
- return (-EFAULT);
- sjcd_send_4_cmd(SCMD_SET_VOLUME,
- vol_ctrl.channel0, 0xFF,
- vol_ctrl.channel1, 0xFF);
- if (sjcd_receive_status() < 0)
- return (-EIO);
- (void) sjcd_load_response(dummy, 4);
- }
- return (s);
- }
-
- case CDROMEJECT:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: eject\n");
-#endif
- if (!sjcd_command_is_in_progress) {
- sjcd_tray_unlock();
- sjcd_send_cmd(SCMD_EJECT_TRAY);
- (void) sjcd_receive_status();
- }
- return (0);
- }
-
-#if defined( SJCD_GATHER_STAT )
- case 0xABCD:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: statistic\n");
-#endif
- if (copy_to_user(argp, &statistic, sizeof(statistic)))
- return -EFAULT;
- return 0;
- }
-#endif
-
- default:
- return (-EINVAL);
- }
-}
-
-/*
- * Invalidate internal buffers of the driver.
- */
-static void sjcd_invalidate_buffers(void)
-{
- int i;
- for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);
- sjcd_buf_out = -1;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-static void sjcd_transfer(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: transfer:\n");
-#endif
- if (current_valid()) {
- while (CURRENT->nr_sectors) {
- int i, bn = CURRENT->sector / 4;
- for (i = 0;
- i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;
- i++);
- if (i < SJCD_BUF_SIZ) {
- int offs =
- (i * 4 + (CURRENT->sector & 3)) * 512;
- int nr_sectors = 4 - (CURRENT->sector & 3);
- if (sjcd_buf_out != i) {
- sjcd_buf_out = i;
- if (sjcd_buf_bn[i] != bn) {
- sjcd_buf_out = -1;
- continue;
- }
- }
- if (nr_sectors > CURRENT->nr_sectors)
- nr_sectors = CURRENT->nr_sectors;
-#if defined( SJCD_TRACE )
- printk("SJCD: copy out\n");
-#endif
- memcpy(CURRENT->buffer, sjcd_buf + offs,
- nr_sectors * 512);
- CURRENT->nr_sectors -= nr_sectors;
- CURRENT->sector += nr_sectors;
- CURRENT->buffer += nr_sectors * 512;
- } else {
- sjcd_buf_out = -1;
- break;
- }
- }
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: transfer: done\n");
-#endif
-}
-
-static void sjcd_poll(void)
-{
-#if defined( SJCD_GATHER_STAT )
- /*
- * Update total number of ticks.
- */
- statistic.ticks++;
- statistic.tticks[sjcd_transfer_state]++;
-#endif
-
- ReSwitch:switch (sjcd_transfer_state) {
-
- case SJCD_S_IDLE:{
-#if defined( SJCD_GATHER_STAT )
- statistic.idle_ticks++;
-#endif
-#if defined( SJCD_TRACE )
- printk("SJCD_S_IDLE\n");
-#endif
- return;
- }
-
- case SJCD_S_START:{
-#if defined( SJCD_GATHER_STAT )
- statistic.start_ticks++;
-#endif
- sjcd_send_cmd(SCMD_GET_STATUS);
- sjcd_transfer_state =
- sjcd_mode ==
- SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
- printk("SJCD_S_START: goto SJCD_S_%s mode\n",
- sjcd_transfer_state ==
- SJCD_S_READ ? "READ" : "MODE");
-#endif
- break;
- }
-
- case SJCD_S_MODE:{
- if (sjcd_check_status()) {
- /*
- * Previous command is completed.
- */
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- sjcd_mode = 0; /* unknown mode; should not be valid when failed */
- sjcd_send_1_cmd(SCMD_SET_MODE,
- SCMD_MODE_COOKED);
- sjcd_transfer_state = SJCD_S_READ;
- sjcd_transfer_timeout = 1000;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_MODE: goto SJCD_S_READ mode\n");
-#endif
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.mode_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_READ:{
- if (sjcd_status_valid ? 1 : sjcd_check_status()) {
- /*
- * Previous command is completed.
- */
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- if (!sjcd_media_is_available) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- if (sjcd_mode != SCMD_MODE_COOKED) {
- /*
- * We seem to come from set mode. So discard one byte of result.
- */
- if (sjcd_load_response
- (&sjcd_mode, 1) != 0) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- if (sjcd_mode != SCMD_MODE_COOKED) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- }
-
- if (current_valid()) {
- struct sjcd_play_msf msf;
-
- sjcd_next_bn = CURRENT->sector / 4;
- hsg2msf(sjcd_next_bn, &msf.start);
- msf.end.min = 0;
- msf.end.sec = 0;
- msf.end.frame = sjcd_read_count =
- SJCD_BUF_SIZ;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n",
- msf.start.min, msf.start.sec,
- msf.start.frame, msf.end.min,
- msf.end.sec, msf.end.frame);
- printk
- ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n",
- sjcd_next_bn, sjcd_buf_in,
- sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
-#endif
- sjcd_send_6_cmd(SCMD_DATA_READ,
- &msf);
- sjcd_transfer_state = SJCD_S_DATA;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: go to SJCD_S_DATA mode\n");
-#endif
- } else {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.read_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_DATA:{
- unsigned char stat;
-
- sjcd_s_data:stat =
- inb(SJCDPORT
- (1));
-#if defined( SJCD_TRACE )
- printk("SJCD_S_DATA: status = 0x%02x\n", stat);
-#endif
- if (SJCD_STATUS_AVAILABLE(stat)) {
- /*
- * No data is waiting for us in the drive buffer. Status of operation
- * completion is available. Read and parse it.
- */
- sjcd_load_status();
-
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: read block %d failed, maybe audio disk? Giving up\n",
- sjcd_next_bn);
-#endif
- if (current_valid())
- end_request(CURRENT, 0);
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- if (!sjcd_media_is_available) {
- printk
- ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n");
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- sjcd_transfer_state = SJCD_S_READ;
- goto ReSwitch;
- } else if (SJCD_DATA_AVAILABLE(stat)) {
- /*
- * One frame is read into device buffer. We must copy it to our memory.
- * Otherwise cdrom hangs up. Check to see if we have something to copy
- * to.
- */
- if (!current_valid()
- && sjcd_buf_in == sjcd_buf_out) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n");
- printk
- (" ... all the date would be discarded\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- /*
- * Everything seems to be OK. Just read the frame and recalculate
- * indices.
- */
- sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */
- insb(SJCDPORT(2),
- sjcd_buf + 2048 * sjcd_buf_in, 2048);
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
- sjcd_next_bn, sjcd_buf_in,
- sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
-#endif
- sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;
- if (sjcd_buf_out == -1)
- sjcd_buf_out = sjcd_buf_in;
- if (++sjcd_buf_in == SJCD_BUF_SIZ)
- sjcd_buf_in = 0;
-
- /*
- * Only one frame is ready at time. So we should turn over to wait for
- * another frame. If we need that, of course.
- */
- if (--sjcd_read_count == 0) {
- /*
- * OK, request seems to be precessed. Continue transferring...
- */
- if (!sjcd_transfer_is_active) {
- while (current_valid()) {
- /*
- * Continue transferring.
- */
- sjcd_transfer();
- if (CURRENT->
- nr_sectors ==
- 0)
- end_request
- (CURRENT, 1);
- else
- break;
- }
- }
- if (current_valid() &&
- (CURRENT->sector / 4 <
- sjcd_next_bn
- || CURRENT->sector / 4 >
- sjcd_next_bn +
- SJCD_BUF_SIZ)) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- }
- /*
- * Now we should turn around rather than wait for while.
- */
- goto sjcd_s_data;
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.data_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_STOP:{
- sjcd_read_count = 0;
- sjcd_send_cmd(SCMD_STOP);
- sjcd_transfer_state = SJCD_S_STOPPING;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_GATHER_STAT )
- statistic.stop_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_STOPPING:{
- unsigned char stat;
-
- stat = inb(SJCDPORT(1));
-#if defined( SJCD_TRACE )
- printk("SJCD_S_STOP: status = 0x%02x\n", stat);
-#endif
- if (SJCD_DATA_AVAILABLE(stat)) {
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD_S_STOP: discard data\n");
-#endif
- /*
- * Discard all the data from the pipe. Foolish method.
- */
- for (i = 2048; i--;
- (void) inb(SJCDPORT(2)));
- sjcd_transfer_timeout = 500;
- } else if (SJCD_STATUS_AVAILABLE(stat)) {
- sjcd_load_status();
- if (sjcd_status_valid
- && sjcd_media_is_changed) {
- sjcd_toc_uptodate = 0;
- sjcd_invalidate_buffers();
- }
- if (current_valid()) {
- if (sjcd_status_valid)
- sjcd_transfer_state =
- SJCD_S_READ;
- else
- sjcd_transfer_state =
- SJCD_S_START;
- } else
- sjcd_transfer_state = SJCD_S_IDLE;
- goto ReSwitch;
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.stopping_ticks++;
-#endif
- break;
- }
-
- default:
- printk("SJCD: poll: invalid state %d\n",
- sjcd_transfer_state);
- return;
- }
-
- if (--sjcd_transfer_timeout == 0) {
- printk("SJCD: timeout in state %d\n", sjcd_transfer_state);
- while (current_valid())
- end_request(CURRENT, 0);
- sjcd_send_cmd(SCMD_STOP);
- sjcd_transfer_state = SJCD_S_IDLE;
- goto ReSwitch;
- }
-
- /*
- * Get back in some time. 1 should be replaced with count variable to
- * avoid unnecessary testings.
- */
- SJCD_SET_TIMER(sjcd_poll, 1);
-}
-
-static void do_sjcd_request(request_queue_t * q)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: do_sjcd_request(%ld+%ld)\n",
- CURRENT->sector, CURRENT->nr_sectors);
-#endif
- sjcd_transfer_is_active = 1;
- while (current_valid()) {
- sjcd_transfer();
- if (CURRENT->nr_sectors == 0)
- end_request(CURRENT, 1);
- else {
- sjcd_buf_out = -1; /* Want to read a block not in buffer */
- if (sjcd_transfer_state == SJCD_S_IDLE) {
- if (!sjcd_toc_uptodate) {
- if (sjcd_update_toc() < 0) {
- printk
- ("SJCD: transfer: discard\n");
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- }
- sjcd_transfer_state = SJCD_S_START;
- SJCD_SET_TIMER(sjcd_poll, HZ / 100);
- }
- break;
- }
- }
- sjcd_transfer_is_active = 0;
-#if defined( SJCD_TRACE )
- printk
- ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
- sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
- printk("do_sjcd_request ends\n");
-#endif
-}
-
-/*
- * Open the device special file. Check disk is in.
- */
-static int sjcd_open(struct inode *ip, struct file *fp)
-{
- /*
- * Check the presence of device.
- */
- if (!sjcd_present)
- return (-ENXIO);
-
- /*
- * Only read operations are allowed. Really? (:-)
- */
- if (fp->f_mode & 2)
- return (-EROFS);
-
- if (sjcd_open_count == 0) {
- int s, sjcd_open_tries;
-/* We don't know that, do we? */
-/*
- sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-*/
- sjcd_mode = 0;
- sjcd_door_was_open = 0;
- sjcd_transfer_state = SJCD_S_IDLE;
- sjcd_invalidate_buffers();
- sjcd_status_valid = 0;
-
- /*
- * Strict status checking.
- */
- for (sjcd_open_tries = 4; --sjcd_open_tries;) {
- if (!sjcd_status_valid)
- sjcd_get_status();
- if (!sjcd_status_valid) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: open: timed out when check status.\n");
-#endif
- goto err_out;
- } else if (!sjcd_media_is_available) {
-#if defined( SJCD_DIAGNOSTIC )
- printk("SJCD: open: no disk in drive\n");
-#endif
- if (!sjcd_door_closed) {
- sjcd_door_was_open = 1;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: open: close the tray\n");
-#endif
- s = sjcd_tray_close();
- if (s < 0 || !sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: open: tray close attempt failed\n");
-#endif
- goto err_out;
- }
- continue;
- } else
- goto err_out;
- }
- break;
- }
- s = sjcd_tray_lock();
- if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk("SJCD: open: tray lock attempt failed\n");
-#endif
- goto err_out;
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: open: done\n");
-#endif
- }
-
- ++sjcd_open_count;
- return (0);
-
- err_out:
- return (-EIO);
-}
-
-/*
- * On close, we flush all sjcd blocks from the buffer cache.
- */
-static int sjcd_release(struct inode *inode, struct file *file)
-{
- int s;
-
-#if defined( SJCD_TRACE )
- printk("SJCD: release\n");
-#endif
- if (--sjcd_open_count == 0) {
- sjcd_invalidate_buffers();
- s = sjcd_tray_unlock();
- if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: release: tray unlock attempt failed.\n");
-#endif
- }
- if (sjcd_door_was_open) {
- s = sjcd_tray_open();
- if (s < 0 || !sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: release: tray unload attempt failed.\n");
-#endif
- }
- }
- }
- return 0;
-}
-
-/*
- * A list of file operations allowed for this cdrom.
- */
-static struct block_device_operations sjcd_fops = {
- .owner = THIS_MODULE,
- .open = sjcd_open,
- .release = sjcd_release,
- .ioctl = sjcd_ioctl,
- .media_changed = sjcd_disk_change,
-};
-
-/*
- * Following stuff is intended for initialization of the cdrom. It
- * first looks for presence of device. If the device is present, it
- * will be reset. Then read the version of the drive and load status.
- * The version is two BCD-coded bytes.
- */
-static struct {
- unsigned char major, minor;
-} sjcd_version;
-
-static struct gendisk *sjcd_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- * Probe cdrom, find out version and status.
- */
-static int __init sjcd_init(void)
-{
- int i;
-
- printk(KERN_INFO
- "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n",
- SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);
-
-#if defined( SJCD_TRACE )
- printk("SJCD: sjcd=0x%x: ", sjcd_base);
-#endif
-
- if (register_blkdev(MAJOR_NR, "sjcd"))
- return -EIO;
-
- sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock);
- if (!sjcd_queue)
- goto out0;
-
- blk_queue_hardsect_size(sjcd_queue, 2048);
-
- sjcd_disk = alloc_disk(1);
- if (!sjcd_disk) {
- printk(KERN_ERR "SJCD: can't allocate disk");
- goto out1;
- }
- sjcd_disk->major = MAJOR_NR,
- sjcd_disk->first_minor = 0,
- sjcd_disk->fops = &sjcd_fops,
- sprintf(sjcd_disk->disk_name, "sjcd");
-
- if (!request_region(sjcd_base, 4,"sjcd")) {
- printk
- ("SJCD: Init failed, I/O port (%X) is already in use\n",
- sjcd_base);
- goto out2;
- }
-
- /*
- * Check for card. Since we are booting now, we can't use standard
- * wait algorithm.
- */
- printk(KERN_INFO "SJCD: Resetting: ");
- sjcd_send_cmd(SCMD_RESET);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies; time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" reset failed, no drive found.\n");
- goto out3;
- } else
- printk("\n");
-
- /*
- * Get and print out cdrom version.
- */
- printk(KERN_INFO "SJCD: Getting version: ");
- sjcd_send_cmd(SCMD_GET_VERSION);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies; time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" get version failed, no drive found.\n");
- goto out3;
- }
-
- if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
- printk(" %1x.%02x\n", (int) sjcd_version.major,
- (int) sjcd_version.minor);
- } else {
- printk(" read version failed, no drive found.\n");
- goto out3;
- }
-
- /*
- * Check and print out the tray state. (if it is needed?).
- */
- if (!sjcd_status_valid) {
- printk(KERN_INFO "SJCD: Getting status: ");
- sjcd_send_cmd(SCMD_GET_STATUS);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies;
- time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" get status failed, no drive found.\n");
- goto out3;
- } else
- printk("\n");
- }
-
- printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
- sjcd_disk->queue = sjcd_queue;
- add_disk(sjcd_disk);
-
- sjcd_present++;
- return (0);
-out3:
- release_region(sjcd_base, 4);
-out2:
- put_disk(sjcd_disk);
-out1:
- blk_cleanup_queue(sjcd_queue);
-out0:
- if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
- printk("SJCD: cannot unregister device.\n");
- return (-EIO);
-}
-
-static void __exit sjcd_exit(void)
-{
- del_gendisk(sjcd_disk);
- put_disk(sjcd_disk);
- release_region(sjcd_base, 4);
- blk_cleanup_queue(sjcd_queue);
- if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
- printk("SJCD: cannot unregister device.\n");
- printk(KERN_INFO "SJCD: module: removed.\n");
-}
-
-module_init(sjcd_init);
-module_exit(sjcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR);
diff --git a/drivers/cdrom/sjcd.h b/drivers/cdrom/sjcd.h
deleted file mode 100644
index 0aa5e714659d..000000000000
--- a/drivers/cdrom/sjcd.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Definitions for a Sanyo CD-ROM interface.
- *
- * Copyright (C) 1995 Vadim V. Model
- * model@cecmow.enet.dec.com
- * vadim@rbrf.msk.su
- * vadim@ipsun.ras.ru
- * Eric van der Maarel
- * H.T.M.v.d.Maarel@marin.nl
- *
- * This information is based on mcd.c from M. Harriss and sjcd102.lst from
- * E. Moenkeberg.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __SJCD_H__
-#define __SJCD_H__
-
-/*
- * Change this to set the I/O port address as default. More flexibility
- * come with setup implementation.
- */
-#define SJCD_BASE_ADDR 0x340
-
-/*
- * Change this to set the irq as default. Really SANYO do not use interrupts
- * at all.
- */
-#define SJCD_INTR_NR 0
-
-/*
- * Change this to set the dma as default value. really SANYO does not use
- * direct memory access at all.
- */
-#define SJCD_DMA_NR 0
-
-/*
- * Macros which allow us to find out the status of the drive.
- */
-#define SJCD_STATUS_AVAILABLE( x ) (((x)&0x02)==0)
-#define SJCD_DATA_AVAILABLE( x ) (((x)&0x01)==0)
-
-/*
- * Port access macro. Three ports are available: S-data port (command port),
- * status port (read only) and D-data port (read only).
- */
-#define SJCDPORT( x ) ( sjcd_base + ( x ) )
-#define SJCD_STATUS_PORT SJCDPORT( 1 )
-#define SJCD_S_DATA_PORT SJCDPORT( 0 )
-#define SJCD_COMMAND_PORT SJCDPORT( 0 )
-#define SJCD_D_DATA_PORT SJCDPORT( 2 )
-
-/*
- * Drive info bits. Drive info available as first (mandatory) byte of
- * command completion status.
- */
-#define SST_NOT_READY 0x10 /* no disk in the drive (???) */
-#define SST_MEDIA_CHANGED 0x20 /* disk is changed */
-#define SST_DOOR_OPENED 0x40 /* door is open */
-
-/* commands */
-
-#define SCMD_EJECT_TRAY 0xD0 /* eject tray if not locked */
-#define SCMD_LOCK_TRAY 0xD2 /* lock tray when in */
-#define SCMD_UNLOCK_TRAY 0xD4 /* unlock tray when in */
-#define SCMD_CLOSE_TRAY 0xD6 /* load tray in */
-
-#define SCMD_RESET 0xFA /* soft reset */
-#define SCMD_GET_STATUS 0x80
-#define SCMD_GET_VERSION 0xCC
-
-#define SCMD_DATA_READ 0xA0 /* are the same, depend on mode&args */
-#define SCMD_SEEK 0xA0
-#define SCMD_PLAY 0xA0
-
-#define SCMD_GET_QINFO 0xA8
-
-#define SCMD_SET_MODE 0xC4
-#define SCMD_MODE_PLAY 0xE0
-#define SCMD_MODE_COOKED (0xF8 & ~0x20)
-#define SCMD_MODE_RAW 0xF9
-#define SCMD_MODE_x20_BIT 0x20 /* What is it for ? */
-
-#define SCMD_SET_VOLUME 0xAE
-#define SCMD_PAUSE 0xE0
-#define SCMD_STOP 0xE0
-
-#define SCMD_GET_DISK_INFO 0xAA
-
-/*
- * Some standard arguments for SCMD_GET_DISK_INFO.
- */
-#define SCMD_GET_1_TRACK 0xA0 /* get the first track information */
-#define SCMD_GET_L_TRACK 0xA1 /* get the last track information */
-#define SCMD_GET_D_SIZE 0xA2 /* get the whole disk information */
-
-/*
- * Borrowed from hd.c. Allows to optimize multiple port read commands.
- */
-#define S_READ_DATA( port, buf, nr ) insb( port, buf, nr )
-
-/*
- * We assume that there are no audio disks with TOC length more than this
- * number (I personally have never seen disks with more than 20 fragments).
- */
-#define SJCD_MAX_TRACKS 100
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct sjcd_hw_disk_info {
- unsigned char track_control;
- unsigned char track_no;
- unsigned char x, y, z;
- union {
- unsigned char track_no;
- struct msf track_msf;
- } un;
-};
-
-struct sjcd_hw_qinfo {
- unsigned char track_control;
- unsigned char track_no;
- unsigned char x;
- struct msf rel;
- struct msf abs;
-};
-
-struct sjcd_play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct sjcd_disk_info {
- unsigned char first;
- unsigned char last;
- struct msf disk_length;
- struct msf first_track;
-};
-
-struct sjcd_toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char point_index;
- struct msf track_time;
- struct msf disk_time;
-};
-
-#if defined( SJCD_GATHER_STAT )
-
-struct sjcd_stat {
- int ticks;
- int tticks[ 8 ];
- int idle_ticks;
- int start_ticks;
- int mode_ticks;
- int read_ticks;
- int data_ticks;
- int stop_ticks;
- int stopping_ticks;
-};
-
-#endif
-
-#endif
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
deleted file mode 100644
index f77ada933ea0..000000000000
--- a/drivers/cdrom/sonycd535.c
+++ /dev/null
@@ -1,1689 +0,0 @@
-/*
- * Sony CDU-535 interface device driver
- *
- * This is a modified version of the CDU-31A device driver (see below).
- * Changes were made using documentation for the CDU-531 (which Sony
- * assures me is very similar to the 535) and partial disassembly of the
- * DOS driver. I used Minyard's driver and replaced the CDU-31A
- * commands with the CDU-531 commands. This was complicated by a different
- * interface protocol with the drive. The driver is still polled.
- *
- * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec.
- * I tried polling without the sony_sleep during the data transfers but
- * it did not speed things up any.
- *
- * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict
- * with CDU-31A driver. This is the also the number from the Linux
- * Device Driver Registry for the Sony Drive. Hope nobody else is using it.
- *
- * 1993-08-29 (rgj) remove the configuring of the interface board address
- * from the top level configuration, you have to modify it in this file.
- *
- * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>)
- *
- * 1995-05-20
- * Modified to support CDU-510/515 series
- * (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- * Fixed to report verify_area() failures
- * (Heiko Eissfeldt <heiko@colossus.escape.de>)
- *
- * 1995-06-01
- * More changes to support CDU-510/515 series
- * (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * September 2003 - Fix SMP support by removing cli/sti calls.
- * Using spinlocks with a wait_queue instead.
- * Felipe Damasio <felipewd@terra.com.br>
- *
- * Things to do:
- * - handle errors and status better, put everything into a single word
- * - use interrupts (code mostly there, but a big hole still missing)
- * - handle multi-session CDs?
- * - use DMA?
- *
- * Known Bugs:
- * -
- *
- * Ken Pizzini (ken@halcyon.com)
- *
- * Original by:
- * Ron Jeppesen (ronj.an@site007.saic.com)
- *
- *
- *------------------------------------------------------------------------
- * Sony CDROM interface device driver.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above)
- *
- * Colossians 3:17
- *
- * The Sony interface device driver handles Sony interface CDROM
- * drives and provides a complete block-level interface as well as an
- * ioctl() interface compatible with the Sun (as specified in
- * include/linux/cdrom.h). With this interface, CDROMs can be
- * accessed and standard audio CDs can be played back normally.
- *
- * This interface is (unfortunately) a polled interface. This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables. Some (like mine) do not even have the capability to
- * handle interrupts or DMA. For this reason you will see a bit of
- * the following:
- *
- * snap = jiffies;
- * while (jiffies-snap < SONY_JIFFIES_TIMEOUT)
- * {
- * if (some_condition())
- * break;
- * sony_sleep();
- * }
- * if (some_condition not met)
- * {
- * return an_error;
- * }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try. (The conditional is written so that jiffies
- * wrap-around is handled properly.)
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk. The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal. A lot of conversion goes on.
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-# include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#define REALLY_SLOW_IO
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/cdrom.h>
-
-#define MAJOR_NR CDU535_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
-#include "sonycd535.h"
-
-/*
- * this is the base address of the interface card for the Sony CDU-535
- * CDROM drive. If your jumpers are set for an address other than
- * this one (the default), change the following line to the
- * proper address.
- */
-#ifndef CDU535_ADDRESS
-# define CDU535_ADDRESS 0x340
-#endif
-#ifndef CDU535_INTERRUPT
-# define CDU535_INTERRUPT 0
-#endif
-#ifndef CDU535_HANDLE
-# define CDU535_HANDLE "cdu535"
-#endif
-#ifndef CDU535_MESSAGE_NAME
-# define CDU535_MESSAGE_NAME "Sony CDU-535"
-#endif
-
-#define CDU535_BLOCK_SIZE 2048
-
-#ifndef MAX_SPINUP_RETRY
-# define MAX_SPINUP_RETRY 3 /* 1 is sufficient for most drives... */
-#endif
-#ifndef RETRY_FOR_BAD_STATUS
-# define RETRY_FOR_BAD_STATUS 100 /* in 10th of second */
-#endif
-
-#ifndef DEBUG
-# define DEBUG 1
-#endif
-
-/*
- * SONY535_BUFFER_SIZE determines the size of internal buffer used
- * by the drive. It must be at least 2K and the larger the buffer
- * the better the transfer rate. It does however take system memory.
- * On my system I get the following transfer rates using dd to read
- * 10 Mb off /dev/cdrom.
- *
- * 8K buffer 43 Kb/sec
- * 16K buffer 66 Kb/sec
- * 32K buffer 91 Kb/sec
- * 64K buffer 111 Kb/sec
- * 128K buffer 123 Kb/sec
- * 512K buffer 123 Kb/sec
- */
-#define SONY535_BUFFER_SIZE (64*1024)
-
-/*
- * if LOCK_DOORS is defined then the eject button is disabled while
- * the device is open.
- */
-#ifndef NO_LOCK_DOORS
-# define LOCK_DOORS
-#endif
-
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int cdu_open(struct inode *inode, struct file *filp);
-static inline unsigned int int_to_bcd(unsigned int val);
-static unsigned int bcd_to_int(unsigned int bcd);
-static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
- Byte * response, int n_response, int ignoreStatusBit7);
-
-/* The base I/O address of the Sony Interface. This is a variable (not a
- #define) so it can be easily changed via some future ioctl() */
-static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
-module_param(sony535_cd_base_io, int, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive. The
- * comment for the base address also applies here.
- */
-static unsigned short select_unit_reg;
-static unsigned short result_reg;
-static unsigned short command_reg;
-static unsigned short read_status_reg;
-static unsigned short data_reg;
-
-static DEFINE_SPINLOCK(sonycd535_lock); /* queue lock */
-static struct request_queue *sonycd535_queue;
-
-static int initialized; /* Has the drive been initialized? */
-static int sony_disc_changed = 1; /* Has the disk been changed
- since the last check? */
-static int sony_toc_read; /* Has the table of contents been
- read? */
-static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead
- buffer. */
-static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of
- the read-ahead buffer. */
-static unsigned int sony_usage; /* How many processes have the
- drive open. */
-
-static int sony_first_block = -1; /* First OS block (512 byte) in
- the read-ahead buffer */
-static int sony_last_block = -1; /* Last OS block (512 byte) in
- the read-ahead buffer */
-
-static struct s535_sony_toc *sony_toc; /* Points to the table of
- contents. */
-
-static struct s535_sony_subcode *last_sony_subcode; /* Points to the last
- subcode address read */
-static Byte **sony_buffer; /* Points to the pointers
- to the sector buffers */
-
-static int sony_inuse; /* is the drive in use? Only one
- open at a time allowed */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play. The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over. This holds the
- * position during a pause so a resume can restart it. It uses the
- * audio status variable above to tell if it is paused.
- * I just kept the CDU-31A driver behavior rather than using the PAUSE
- * command on the CDU-535.
- */
-static Byte cur_pos_msf[3];
-static Byte final_pos_msf[3];
-
-/* What IRQ is the drive using? 0 if none. */
-static int sony535_irq_used = CDU535_INTERRUPT;
-
-/* The interrupt handler will wake this queue up when it gets an interrupt. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
-
-
-/*
- * This routine returns 1 if the disk has been changed since the last
- * check or 0 if it hasn't. Setting flag to 0 resets the changed flag.
- */
-static int
-cdu535_check_media_change(struct gendisk *disk)
-{
- /* if driver is not initialized, always return 0 */
- int retval = initialized ? sony_disc_changed : 0;
- sony_disc_changed = 0;
- return retval;
-}
-
-static inline void
-enable_interrupts(void)
-{
-#ifdef USE_IRQ
- /*
- * This code was taken from cdu31a.c; it will not
- * directly work for the cdu535 as written...
- */
- curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static inline void
-disable_interrupts(void)
-{
-#ifdef USE_IRQ
- /*
- * This code was taken from cdu31a.c; it will not
- * directly work for the cdu535 as written...
- */
- curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static irqreturn_t
-cdu535_interrupt(int irq, void *dev_id)
-{
- disable_interrupts();
- if (waitqueue_active(&cdu535_irq_wait)) {
- wake_up(&cdu535_irq_wait);
- return IRQ_HANDLED;
- }
- printk(CDU535_MESSAGE_NAME
- ": Got an interrupt but nothing was waiting\n");
- return IRQ_NONE;
-}
-
-
-/*
- * Wait a little while.
- */
-static inline void
-sony_sleep(void)
-{
- if (sony535_irq_used <= 0) { /* poll */
- yield();
- } else { /* Interrupt driven */
- DEFINE_WAIT(wait);
-
- spin_lock_irq(&sonycd535_lock);
- enable_interrupts();
- prepare_to_wait(&cdu535_irq_wait, &wait, TASK_INTERRUPTIBLE);
- spin_unlock_irq(&sonycd535_lock);
- schedule();
- finish_wait(&cdu535_irq_wait, &wait);
- }
-}
-
-/*------------------start of SONY CDU535 very specific ---------------------*/
-
-/****************************************************************************
- * void select_unit( int unit_no )
- *
- * Select the specified unit (0-3) so that subsequent commands reference it
- ****************************************************************************/
-static void
-select_unit(int unit_no)
-{
- unsigned int select_mask = ~(1 << unit_no);
- outb(select_mask, select_unit_reg);
-}
-
-/***************************************************************************
- * int read_result_reg( Byte *data_ptr )
- *
- * Read a result byte from the Sony CDU controller, store in location pointed
- * to by data_ptr. Return zero on success, TIME_OUT if we did not receive
- * data.
- ***************************************************************************/
-static int
-read_result_reg(Byte *data_ptr)
-{
- unsigned long snap;
- int read_status;
-
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- read_status = inb(read_status_reg);
- if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME
- ": read_result_reg(): readStatReg = 0x%x\n", read_status);
-#endif
- *data_ptr = inb(result_reg);
- return 0;
- } else {
- sony_sleep();
- }
- }
- printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
- return TIME_OUT;
-}
-
-/****************************************************************************
- * int read_exec_status( Byte status[2] )
- *
- * Read the execution status of the last command and put into status.
- * Handles reading second status word if available. Returns 0 on success,
- * TIME_OUT on failure.
- ****************************************************************************/
-static int
-read_exec_status(Byte status[2])
-{
- status[1] = 0;
- if (read_result_reg(&(status[0])) != 0)
- return TIME_OUT;
- if ((status[0] & 0x80) != 0) { /* byte two follows */
- if (read_result_reg(&(status[1])) != 0)
- return TIME_OUT;
- }
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
- status[0], status[1]);
-#endif
- return 0;
-}
-
-/****************************************************************************
- * int check_drive_status( void )
- *
- * Check the current drive status. Using this before executing a command
- * takes care of the problem of unsolicited drive status-2 messages.
- * Add a check of the audio status if we think the disk is playing.
- ****************************************************************************/
-static int
-check_drive_status(void)
-{
- Byte status, e_status[2];
- int CDD, ATN;
- Byte cmd;
-
- select_unit(0);
- if (sony_audio_status == CDROM_AUDIO_PLAY) { /* check status */
- outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
- if (read_result_reg(&status) == 0) {
- switch (status) {
- case 0x0:
- break; /* play in progress */
- case 0x1:
- break; /* paused */
- case 0x3: /* audio play completed */
- case 0x5: /* play not requested */
- sony_audio_status = CDROM_AUDIO_COMPLETED;
- read_subcode();
- break;
- case 0x4: /* error during play */
- sony_audio_status = CDROM_AUDIO_ERROR;
- break;
- }
- }
- }
- /* now check drive status */
- outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
- if (read_result_reg(&status) != 0)
- return TIME_OUT;
-
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
-#endif
-
- if (status == 0)
- return 0;
-
- ATN = status & 0xf;
- CDD = (status >> 4) & 0xf;
-
- switch (ATN) {
- case 0x0:
- break; /* go on to CDD stuff */
- case SONY535_ATN_BUSY:
- if (initialized)
- printk(CDU535_MESSAGE_NAME " error: drive busy\n");
- return CD_BUSY;
- case SONY535_ATN_EJECT_IN_PROGRESS:
- printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
- sony_audio_status = CDROM_AUDIO_INVALID;
- return CD_BUSY;
- case SONY535_ATN_RESET_OCCURRED:
- case SONY535_ATN_DISC_CHANGED:
- case SONY535_ATN_RESET_AND_DISC_CHANGED:
-#if DEBUG > 0
- printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
-#endif
- sony_disc_changed = 1;
- sony_toc_read = 0;
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- sony_first_block = -1;
- sony_last_block = -1;
- if (initialized) {
- cmd = SONY535_SPIN_UP;
- do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
- sony_get_toc();
- }
- return 0;
- default:
- printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
- return CD_BUSY;
- }
- switch (CDD) { /* the 531 docs are not helpful in decoding this */
- case 0x0: /* just use the values from the DOS driver */
- case 0x2:
- case 0xa:
- break; /* no error */
- case 0xc:
- printk(CDU535_MESSAGE_NAME
- ": check_drive_status(): CDD = 0xc! Not properly handled!\n");
- return CD_BUSY; /* ? */
- default:
- return CD_BUSY;
- }
- return 0;
-} /* check_drive_status() */
-
-/*****************************************************************************
- * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
- * Byte *response, int n_response, int ignore_status_bit7 )
- *
- * Generic routine for executing commands. The command and its parameters
- * should be placed in the cmd[] array, number of bytes in the command is
- * stored in nCmd. The response from the command will be stored in the
- * response array. The number of bytes you expect back (excluding status)
- * should be passed in n_response. Finally, some
- * commands set bit 7 of the return status even when there is no second
- * status byte, on these commands set ignoreStatusBit7 TRUE.
- * If the command was sent and data received back, then we return 0,
- * else we return TIME_OUT. You still have to check the status yourself.
- * You should call check_drive_status() before calling this routine
- * so that you do not lose notifications of disk changes, etc.
- ****************************************************************************/
-static int
-do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
- Byte * response, int n_response, int ignore_status_bit7)
-{
- int i;
-
- /* write out the command */
- for (i = 0; i < n_cmd; i++)
- outb(cmd[i], command_reg);
-
- /* read back the status */
- if (read_result_reg(status) != 0)
- return TIME_OUT;
- if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
- /* get second status byte */
- if (read_result_reg(status + 1) != 0)
- return TIME_OUT;
- } else {
- status[1] = 0;
- }
-#if DEBUG > 2
- printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
- *cmd, status[0], status[1]);
-#endif
-
- /* do not know about when I should read set of data and when not to */
- if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
- return 0;
-
- /* else, read in rest of data */
- for (i = 0; 0 < n_response; n_response--, i++)
- if (read_result_reg(response + i) != 0)
- return TIME_OUT;
- return 0;
-} /* do_sony_cmd() */
-
-/**************************************************************************
- * int set_drive_mode( int mode, Byte status[2] )
- *
- * Set the drive mode to the specified value (mode=0 is audio, mode=e0
- * is mode-1 CDROM
- **************************************************************************/
-static int
-set_drive_mode(int mode, Byte status[2])
-{
- Byte cmd_buff[2];
- Byte ret_buff[1];
-
- cmd_buff[0] = SONY535_SET_DRIVE_MODE;
- cmd_buff[1] = mode;
- return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
-}
-
-/***************************************************************************
- * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
- * Byte *data_buff, int buff_size )
- *
- * Read n_blocks of data from the CDROM starting at position params[0:2],
- * number of blocks in stored in params[3:5] -- both these are already
- * int bcd format.
- * Transfer the data into the buffer pointed at by data_buff. buff_size
- * gives the number of bytes available in the buffer.
- * The routine returns number of bytes read in if successful, otherwise
- * it returns one of the standard error returns.
- ***************************************************************************/
-static int
-seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
- Byte **buff, int buf_size)
-{
- Byte cmd_buff[7];
- int i;
- int read_status;
- unsigned long snap;
- Byte *data_buff;
- int sector_count = 0;
-
- if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
- return NO_ROOM;
-
- set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
-
- /* send command to read the data */
- cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
- for (i = 0; i < 6; i++)
- cmd_buff[i + 1] = params[i];
- for (i = 0; i < 7; i++)
- outb(cmd_buff[i], command_reg);
-
- /* read back the data one block at a time */
- while (0 < n_blocks--) {
- /* wait for data to be ready */
- int data_valid = 0;
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- read_status = inb(read_status_reg);
- if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
- read_exec_status(status);
- return BAD_STATUS;
- }
- if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
- /* data is ready, read it */
- data_buff = buff[sector_count++];
- for (i = 0; i < CDU535_BLOCK_SIZE; i++)
- *data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */
- data_valid = 1;
- break; /* exit the timeout loop */
- }
- sony_sleep(); /* data not ready, sleep a while */
- }
- if (!data_valid)
- return TIME_OUT; /* if we reach this stage */
- }
-
- /* read all the data, now read the status */
- if ((i = read_exec_status(status)) != 0)
- return i;
- return CDU535_BLOCK_SIZE * sector_count;
-} /* seek_and_read_N_blocks() */
-
-/****************************************************************************
- * int request_toc_data( Byte status[2], struct s535_sony_toc *toc )
- *
- * Read in the table of contents data. Converts all the bcd data
- * into integers in the toc structure.
- ****************************************************************************/
-static int
-request_toc_data(Byte status[2], struct s535_sony_toc *toc)
-{
- int to_status;
- int i, j, n_tracks, track_no;
- int first_track_num, last_track_num;
- Byte cmd_no = 0xb2;
- Byte track_address_buffer[5];
-
- /* read the fixed portion of the table of contents */
- if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
- return to_status;
-
- /* convert the data into integers so we can use them */
- first_track_num = bcd_to_int(toc->first_track_num);
- last_track_num = bcd_to_int(toc->last_track_num);
- n_tracks = last_track_num - first_track_num + 1;
-
- /* read each of the track address descriptors */
- for (i = 0; i < n_tracks; i++) {
- /* read the descriptor into a temporary buffer */
- for (j = 0; j < 5; j++) {
- if (read_result_reg(track_address_buffer + j) != 0)
- return TIME_OUT;
- if (j == 1) /* need to convert from bcd */
- track_no = bcd_to_int(track_address_buffer[j]);
- }
- /* copy the descriptor to proper location - sonycd.c just fills */
- memcpy(toc->tracks + i, track_address_buffer, 5);
- }
- return 0;
-} /* request_toc_data() */
-
-/***************************************************************************
- * int spin_up_drive( Byte status[2] )
- *
- * Spin up the drive (unless it is already spinning).
- ***************************************************************************/
-static int
-spin_up_drive(Byte status[2])
-{
- Byte cmd;
-
- /* first see if the drive is already spinning */
- cmd = SONY535_REQUEST_DRIVE_STATUS_1;
- if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
- return TIME_OUT;
- if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
- return 0; /* it's already spinning */
-
- /* otherwise, give the spin-up command */
- cmd = SONY535_SPIN_UP;
- return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
-}
-
-/*--------------------end of SONY CDU535 very specific ---------------------*/
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int
-int_to_bcd(unsigned int val)
-{
- int retval;
-
- retval = (val / 10) << 4;
- retval = retval | val % 10;
- return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int
-bcd_to_int(unsigned int bcd)
-{
- return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void
-log_to_msf(unsigned int log, Byte *msf)
-{
- log = log + LOG_START_OFFSET;
- msf[0] = int_to_bcd(log / 4500);
- log = log % 4500;
- msf[1] = int_to_bcd(log / 75);
- msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int
-msf_to_log(Byte *msf)
-{
- unsigned int log;
-
-
- log = bcd_to_int(msf[2]);
- log += bcd_to_int(msf[1]) * 75;
- log += bcd_to_int(msf[0]) * 4500;
- log = log - LOG_START_OFFSET;
-
- return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void
-size_to_buf(unsigned int size, Byte *buf)
-{
- buf[0] = size / 65536;
- size = size % 65536;
- buf[1] = size / 256;
- buf[2] = size % 256;
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail. Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations. This especially helps since the OS
- * may use 1024 byte blocks and the drive uses 2048 byte blocks. Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void
-do_cdu535_request(request_queue_t * q)
-{
- struct request *req;
- unsigned int read_size;
- int block;
- int nsect;
- int copyoff;
- int spin_up_retry;
- Byte params[10];
- Byte status[2];
- Byte cmd[2];
-
- while (1) {
- req = elv_next_request(q);
- if (!req)
- return;
-
- block = req->sector;
- nsect = req->nr_sectors;
- if (!blk_fs_request(req)) {
- end_request(req, 0);
- continue;
- }
- if (rq_data_dir(req) == WRITE) {
- end_request(req, 0);
- continue;
- }
- /*
- * If the block address is invalid or the request goes beyond
- * the end of the media, return an error.
- */
- if (sony_toc->lead_out_start_lba <= (block/4)) {
- end_request(req, 0);
- return;
- }
- if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
- end_request(req, 0);
- return;
- }
- while (0 < nsect) {
- /*
- * If the requested sector is not currently in
- * the read-ahead buffer, it must be read in.
- */
- if ((block < sony_first_block) || (sony_last_block < block)) {
- sony_first_block = (block / 4) * 4;
- log_to_msf(block / 4, params);
-
- /*
- * If the full read-ahead would go beyond the end of the media, trim
- * it back to read just till the end of the media.
- */
- if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
- sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
- read_size = sony_toc->lead_out_start_lba - (block / 4);
- } else {
- sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
- read_size = sony_buffer_sectors;
- }
- size_to_buf(read_size, &params[3]);
-
- /*
- * Read the data. If the drive was not spinning,
- * spin it up and try some more.
- */
- for (spin_up_retry=0 ;; ++spin_up_retry) {
- /* This loop has been modified to support the Sony
- * CDU-510/515 series, thanks to Claudio Porfiri
- * <C.Porfiri@nisms.tei.ericsson.se>.
- */
- /*
- * This part is to deal with very slow hardware. We
- * try at most MAX_SPINUP_RETRY times to read the same
- * block. A check for seek_and_read_N_blocks' result is
- * performed; if the result is wrong, the CDROM's engine
- * is restarted and the operation is tried again.
- */
- /*
- * 1995-06-01: The system got problems when downloading
- * from Slackware CDROM, the problem seems to be:
- * seek_and_read_N_blocks returns BAD_STATUS and we
- * should wait for a while before retrying, so a new
- * part was added to discriminate the return value from
- * seek_and_read_N_blocks for the various cases.
- */
- int readStatus = seek_and_read_N_blocks(params, read_size,
- status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
- if (0 <= readStatus) /* Good data; common case, placed first */
- break;
- if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
- /* give up */
- if (readStatus == NO_ROOM)
- printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
- else
- printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
- status[0]);
- sony_first_block = -1;
- sony_last_block = -1;
- end_request(req, 0);
- return;
- }
- if (readStatus == BAD_STATUS) {
- /* Sleep for a while, then retry */
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&sonycd535_lock);
- schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
- spin_lock_irq(&sonycd535_lock);
- }
-#if DEBUG > 0
- printk(CDU535_MESSAGE_NAME
- " debug: calling spin up when reading data!\n");
-#endif
- cmd[0] = SONY535_SPIN_UP;
- do_sony_cmd(cmd, 1, status, NULL, 0, 0);
- }
- }
- /*
- * The data is in memory now, copy it to the buffer and advance to the
- * next block to read.
- */
- copyoff = block - sony_first_block;
- memcpy(req->buffer,
- sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-
- block += 1;
- nsect -= 1;
- req->buffer += 512;
- }
-
- end_request(req, 1);
- }
-}
-
-/*
- * Read the table of contents from the drive and set sony_toc_read if
- * successful.
- */
-static void
-sony_get_toc(void)
-{
- Byte status[2];
- if (!sony_toc_read) {
- /* do not call check_drive_status() from here since it can call this routine */
- if (request_toc_data(status, sony_toc) < 0)
- return;
- sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
- sony_toc_read = 1;
- }
-}
-
-
-/*
- * Search for a specific track in the table of contents. track is
- * passed in bcd format
- */
-static int
-find_track(int track)
-{
- int i;
- int num_tracks;
-
-
- num_tracks = bcd_to_int(sony_toc->last_track_num) -
- bcd_to_int(sony_toc->first_track_num) + 1;
- for (i = 0; i < num_tracks; i++) {
- if (sony_toc->tracks[i].track == track) {
- return i;
- }
- }
-
- return -1;
-}
-
-/*
- * Read the subcode and put it int last_sony_subcode for future use.
- */
-static int
-read_subcode(void)
-{
- Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
- Byte status[2];
- int dsc_status;
-
- if (check_drive_status() != 0)
- return -EIO;
-
- if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
- sizeof(struct s535_sony_subcode), 1)) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
- status[0], dsc_status);
- return -EIO;
- }
- return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing). If the drive is paused or completed, the subcode information has
- * already been stored, just use that. The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int
-sony_get_subchnl_info(void __user *arg)
-{
- struct cdrom_subchnl schi;
-
- /* Get attention stuff */
- if (check_drive_status() != 0)
- return -EIO;
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
- if (copy_from_user(&schi, arg, sizeof schi))
- return -EFAULT;
-
- switch (sony_audio_status) {
- case CDROM_AUDIO_PLAY:
- if (read_subcode() < 0) {
- return -EIO;
- }
- break;
-
- case CDROM_AUDIO_PAUSED:
- case CDROM_AUDIO_COMPLETED:
- break;
-
- case CDROM_AUDIO_NO_STATUS:
- schi.cdsc_audiostatus = sony_audio_status;
- if (copy_to_user(arg, &schi, sizeof schi))
- return -EFAULT;
- return 0;
- break;
-
- case CDROM_AUDIO_INVALID:
- case CDROM_AUDIO_ERROR:
- default:
- return -EIO;
- }
-
- schi.cdsc_audiostatus = sony_audio_status;
- schi.cdsc_adr = last_sony_subcode->address;
- schi.cdsc_ctrl = last_sony_subcode->control;
- schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
- schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
- if (schi.cdsc_format == CDROM_MSF) {
- schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
- schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
- schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
-
- schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
- schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
- schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
- } else if (schi.cdsc_format == CDROM_LBA) {
- schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
- schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
- }
- return copy_to_user(arg, &schi, sizeof schi) ? -EFAULT : 0;
-}
-
-
-/*
- * The big ugly ioctl handler.
- */
-static int
-cdu_ioctl(struct inode *inode,
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
-{
- Byte status[2];
- Byte cmd_buff[10], params[10];
- int i;
- int dsc_status;
- void __user *argp = (void __user *)arg;
-
- if (check_drive_status() != 0)
- return -EIO;
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- if (spin_up_drive(status) < 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- case CDROMSTOP: /* Spin down the drive */
- cmd_buff[0] = SONY535_HOLD;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
- /*
- * Spin the drive down, ignoring the error if the disk was
- * already not spinning.
- */
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- cmd_buff[0] = SONY535_SPIN_DOWN;
- dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
- ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- case CDROMPAUSE: /* Pause the drive */
- cmd_buff[0] = SONY535_HOLD; /* CDU-31 driver uses AUDIO_STOP, not pause */
- if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
- status[0]);
- return -EIO;
- }
- /* Get the current position and save it for resuming */
- if (read_subcode() < 0) {
- return -EIO;
- }
- cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
- cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
- cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
- sony_audio_status = CDROM_AUDIO_PAUSED;
- return 0;
- break;
-
- case CDROMRESUME: /* Start the drive after being paused */
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- if (sony_audio_status != CDROM_AUDIO_PAUSED) {
- return -EINVAL;
- }
- spin_up_drive(status);
-
- /* Start the drive at the saved position. */
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- cmd_buff[2] = cur_pos_msf[0];
- cmd_buff[3] = cur_pos_msf[1];
- cmd_buff[4] = cur_pos_msf[2];
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- cmd_buff[7] = final_pos_msf[0];
- cmd_buff[8] = final_pos_msf[1];
- cmd_buff[9] = final_pos_msf[2];
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
- status[0]);
- return -EIO;
- }
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- break;
-
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
- if (copy_from_user(params, argp, 6))
- return -EFAULT;
- spin_up_drive(status);
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- /* The parameters are given in int, must be converted */
- for (i = 0; i < 3; i++) {
- cmd_buff[2 + i] = int_to_bcd(params[i]);
- cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
- }
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- /* cmd_buff[2-4] are filled in for loop above */
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- /* cmd_buff[7-9] are filled in for loop above */
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
- status[0]);
- return -EIO;
- }
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = cmd_buff[7];
- final_pos_msf[1] = cmd_buff[8];
- final_pos_msf[2] = cmd_buff[9];
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- {
- struct cdrom_tochdr __user *hdr = argp;
- struct cdrom_tochdr loc_hdr;
-
- sony_get_toc();
- if (!sony_toc_read)
- return -EIO;
- loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
- loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
- if (copy_to_user(hdr, &loc_hdr, sizeof *hdr))
- return -EFAULT;
- }
- return 0;
- break;
-
- case CDROMREADTOCENTRY: /* Read a given table of contents entry */
- {
- struct cdrom_tocentry __user *entry = argp;
- struct cdrom_tocentry loc_entry;
- int track_idx;
- Byte *msf_val = NULL;
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
-
- if (copy_from_user(&loc_entry, entry, sizeof loc_entry))
- return -EFAULT;
-
- /* Lead out is handled separately since it is special. */
- if (loc_entry.cdte_track == CDROM_LEADOUT) {
- loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;
- loc_entry.cdte_ctrl = sony_toc->control2;
- msf_val = sony_toc->lead_out_start_msf;
- } else {
- track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
- if (track_idx < 0)
- return -EINVAL;
- loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;
- loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
- msf_val = sony_toc->tracks[track_idx].track_start_msf;
- }
-
- /* Logical buffer address or MSF format requested? */
- if (loc_entry.cdte_format == CDROM_LBA) {
- loc_entry.cdte_addr.lba = msf_to_log(msf_val);
- } else if (loc_entry.cdte_format == CDROM_MSF) {
- loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
- loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
- loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
- }
- if (copy_to_user(entry, &loc_entry, sizeof *entry))
- return -EFAULT;
- }
- return 0;
- break;
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- {
- struct cdrom_ti ti;
- int track_idx;
-
- sony_get_toc();
- if (!sony_toc_read)
- return -EIO;
-
- if (copy_from_user(&ti, argp, sizeof ti))
- return -EFAULT;
- if ((ti.cdti_trk0 < sony_toc->first_track_num)
- || (sony_toc->last_track_num < ti.cdti_trk0)
- || (ti.cdti_trk1 < ti.cdti_trk0)) {
- return -EINVAL;
- }
- track_idx = find_track(int_to_bcd(ti.cdti_trk0));
- if (track_idx < 0)
- return -EINVAL;
- params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
- params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
- params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
- /*
- * If we want to stop after the last track, use the lead-out
- * MSF to do that.
- */
- if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
- log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
- &(params[4]));
- } else {
- track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
- if (track_idx < 0)
- return -EINVAL;
- log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
- &(params[4]));
- }
- params[0] = 0x03;
-
- spin_up_drive(status);
-
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- /* Start the drive at the saved position. */
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- cmd_buff[2] = params[1];
- cmd_buff[3] = params[2];
- cmd_buff[4] = params[3];
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- cmd_buff[7] = params[4];
- cmd_buff[8] = params[5];
- cmd_buff[9] = params[6];
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
- status[0]);
- printk("... Params: %x %x %x %x %x %x %x\n",
- params[0], params[1], params[2],
- params[3], params[4], params[5], params[6]);
- return -EIO;
- }
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = params[4];
- final_pos_msf[1] = params[5];
- final_pos_msf[2] = params[6];
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- }
-
- case CDROMSUBCHNL: /* Get subchannel info */
- return sony_get_subchnl_info(argp);
-
- case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
- {
- struct cdrom_volctrl volctrl;
-
- if (copy_from_user(&volctrl, argp, sizeof volctrl))
- return -EFAULT;
- cmd_buff[0] = SONY535_SET_VOLUME;
- cmd_buff[1] = volctrl.channel0;
- cmd_buff[2] = volctrl.channel1;
- if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
- status[0]);
- return -EIO;
- }
- }
- return 0;
-
- case CDROMEJECT: /* Eject the drive */
- cmd_buff[0] = SONY535_STOP;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- cmd_buff[0] = SONY535_SPIN_DOWN;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
- sony_audio_status = CDROM_AUDIO_INVALID;
- cmd_buff[0] = SONY535_EJECT_CADDY;
- if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- default:
- return -EINVAL;
- }
-}
-
-
-/*
- * Open the drive for operations. Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int
-cdu_open(struct inode *inode,
- struct file *filp)
-{
- Byte status[2], cmd_buff[2];
-
- if (sony_inuse)
- return -EBUSY;
- if (check_drive_status() != 0)
- return -EIO;
- sony_inuse = 1;
-
- if (spin_up_drive(status) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
- status[0]);
- sony_inuse = 0;
- return -EIO;
- }
- sony_get_toc();
- if (!sony_toc_read) {
- cmd_buff[0] = SONY535_SPIN_DOWN;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- sony_inuse = 0;
- return -EIO;
- }
- check_disk_change(inode->i_bdev);
- sony_usage++;
-
-#ifdef LOCK_DOORS
- /* disable the eject button while mounted */
- cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-#endif
-
- return 0;
-}
-
-
-/*
- * Close the drive. Spin it down if no task is using it. The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static int
-cdu_release(struct inode *inode,
- struct file *filp)
-{
- Byte status[2], cmd_no;
-
- sony_inuse = 0;
-
- if (0 < sony_usage) {
- sony_usage--;
- }
- if (sony_usage == 0) {
- check_drive_status();
-
- if (sony_audio_status != CDROM_AUDIO_PLAY) {
- cmd_no = SONY535_SPIN_DOWN;
- do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
- }
-#ifdef LOCK_DOORS
- /* enable the eject button after umount */
- cmd_no = SONY535_ENABLE_EJECT_BUTTON;
- do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-#endif
- }
- return 0;
-}
-
-static struct block_device_operations cdu_fops =
-{
- .owner = THIS_MODULE,
- .open = cdu_open,
- .release = cdu_release,
- .ioctl = cdu_ioctl,
- .media_changed = cdu535_check_media_change,
-};
-
-static struct gendisk *cdu_disk;
-
-/*
- * Initialize the driver.
- */
-static int __init sony535_init(void)
-{
- struct s535_sony_drive_config drive_config;
- Byte cmd_buff[3];
- Byte ret_buff[2];
- Byte status[2];
- unsigned long snap;
- int got_result = 0;
- int tmp_irq;
- int i;
- int err;
-
- /* Setting the base I/O address to 0 will disable it. */
- if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
- return 0;
-
- /* Set up all the register locations */
- result_reg = sony535_cd_base_io;
- command_reg = sony535_cd_base_io;
- data_reg = sony535_cd_base_io + 1;
- read_status_reg = sony535_cd_base_io + 2;
- select_unit_reg = sony535_cd_base_io + 3;
-
-#ifndef USE_IRQ
- sony535_irq_used = 0; /* polling only until this is ready... */
-#endif
- /* we need to poll until things get initialized */
- tmp_irq = sony535_irq_used;
- sony535_irq_used = 0;
-
-#if DEBUG > 0
- printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n",
- sony535_cd_base_io);
-#endif
- /* look for the CD-ROM, follows the procedure in the DOS driver */
- inb(select_unit_reg);
- /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
- schedule_timeout_interruptible((HZ+17)*40/18);
- inb(result_reg);
-
- outb(0, read_status_reg); /* does a reset? */
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- select_unit(0);
- if (inb(result_reg) != 0xff) {
- got_result = 1;
- break;
- }
- sony_sleep();
- }
-
- if (!got_result || check_drive_status() == TIME_OUT)
- goto Enodev;
-
- /* CD-ROM drive responded -- get the drive configuration */
- cmd_buff[0] = SONY535_INQUIRY;
- if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0)
- goto Enodev;
-
- /* was able to get the configuration,
- * set drive mode as rest of init
- */
-#if DEBUG > 0
- /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
- if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
- printk(CDU535_MESSAGE_NAME
- "Inquiry command returned status = 0x%x\n", status[0]);
-#endif
- /* now ready to use interrupts, if available */
- sony535_irq_used = tmp_irq;
-
- /* A negative sony535_irq_used will attempt an autoirq. */
- if (sony535_irq_used < 0) {
- unsigned long irq_mask, delay;
-
- irq_mask = probe_irq_on();
- enable_interrupts();
- outb(0, read_status_reg); /* does a reset? */
- delay = jiffies + HZ/10;
- while (time_before(jiffies, delay)) ;
-
- sony535_irq_used = probe_irq_off(irq_mask);
- disable_interrupts();
- }
- if (sony535_irq_used > 0) {
- if (request_irq(sony535_irq_used, cdu535_interrupt,
- IRQF_DISABLED, CDU535_HANDLE, NULL)) {
- printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
- " driver; polling instead.\n", sony535_irq_used);
- sony535_irq_used = 0;
- }
- }
- cmd_buff[0] = SONY535_SET_DRIVE_MODE;
- cmd_buff[1] = 0x0; /* default audio */
- if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0)
- goto Enodev_irq;
-
- /* set the drive mode successful, we are set! */
- sony_buffer_size = SONY535_BUFFER_SIZE;
- sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
-
- printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
- drive_config.vendor_id,
- drive_config.product_id,
- drive_config.product_rev_level);
- printk(" base address %03X, ", sony535_cd_base_io);
- if (tmp_irq > 0)
- printk("IRQ%d, ", tmp_irq);
- printk("using %d byte buffer\n", sony_buffer_size);
-
- if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
- err = -EIO;
- goto out1;
- }
- sonycd535_queue = blk_init_queue(do_cdu535_request, &sonycd535_lock);
- if (!sonycd535_queue) {
- err = -ENOMEM;
- goto out1a;
- }
-
- blk_queue_hardsect_size(sonycd535_queue, CDU535_BLOCK_SIZE);
- sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
- err = -ENOMEM;
- if (!sony_toc)
- goto out2;
- last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL);
- if (!last_sony_subcode)
- goto out3;
- sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL);
- if (!sony_buffer)
- goto out4;
- for (i = 0; i < sony_buffer_sectors; i++) {
- sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
- if (!sony_buffer[i]) {
- while (--i>=0)
- kfree(sony_buffer[i]);
- goto out5;
- }
- }
- initialized = 1;
-
- cdu_disk = alloc_disk(1);
- if (!cdu_disk)
- goto out6;
- cdu_disk->major = MAJOR_NR;
- cdu_disk->first_minor = 0;
- cdu_disk->fops = &cdu_fops;
- sprintf(cdu_disk->disk_name, "cdu");
-
- if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) {
- printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n",
- sony535_cd_base_io);
- goto out7;
- }
- cdu_disk->queue = sonycd535_queue;
- add_disk(cdu_disk);
- return 0;
-
-out7:
- put_disk(cdu_disk);
-out6:
- for (i = 0; i < sony_buffer_sectors; i++)
- kfree(sony_buffer[i]);
-out5:
- kfree(sony_buffer);
-out4:
- kfree(last_sony_subcode);
-out3:
- kfree(sony_toc);
-out2:
- blk_cleanup_queue(sonycd535_queue);
-out1a:
- unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
-out1:
- if (sony535_irq_used)
- free_irq(sony535_irq_used, NULL);
- return err;
-Enodev_irq:
- if (sony535_irq_used)
- free_irq(sony535_irq_used, NULL);
-Enodev:
- printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
- return -EIO;
-}
-
-#ifndef MODULE
-
-/*
- * accept "kernel command line" parameters
- * (added by emoenke@gwdg.de)
- *
- * use: tell LILO:
- * sonycd535=0x320
- *
- * the address value has to be the existing CDROM port address.
- */
-static int __init
-sonycd535_setup(char *strings)
-{
- int ints[3];
- (void)get_options(strings, ARRAY_SIZE(ints), ints);
- /* if IRQ change and default io base desired,
- * then call with io base of 0
- */
- if (ints[0] > 0)
- if (ints[1] != 0)
- sony535_cd_base_io = ints[1];
- if (ints[0] > 1)
- sony535_irq_used = ints[2];
- if ((strings != NULL) && (*strings != '\0'))
- printk(CDU535_MESSAGE_NAME
- ": Warning: Unknown interface type: %s\n", strings);
-
- return 1;
-}
-
-__setup("sonycd535=", sonycd535_setup);
-
-#endif /* MODULE */
-
-static void __exit
-sony535_exit(void)
-{
- int i;
-
- release_region(sony535_cd_base_io, 4);
- for (i = 0; i < sony_buffer_sectors; i++)
- kfree(sony_buffer[i]);
- kfree(sony_buffer);
- kfree(last_sony_subcode);
- kfree(sony_toc);
- del_gendisk(cdu_disk);
- put_disk(cdu_disk);
- blk_cleanup_queue(sonycd535_queue);
- if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
- printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
- else
- printk(KERN_INFO CDU535_HANDLE " module released\n");
-}
-
-module_init(sony535_init);
-module_exit(sony535_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU535_CDROM_MAJOR);
diff --git a/drivers/cdrom/sonycd535.h b/drivers/cdrom/sonycd535.h
deleted file mode 100644
index 5dea1ef168d6..000000000000
--- a/drivers/cdrom/sonycd535.h
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef SONYCD535_H
-#define SONYCD535_H
-
-/*
- * define all the commands recognized by the CDU-531/5
- */
-#define SONY535_REQUEST_DRIVE_STATUS_1 (0x80)
-#define SONY535_REQUEST_SENSE (0x82)
-#define SONY535_REQUEST_DRIVE_STATUS_2 (0x84)
-#define SONY535_REQUEST_ERROR_STATUS (0x86)
-#define SONY535_REQUEST_AUDIO_STATUS (0x88)
-#define SONY535_INQUIRY (0x8a)
-
-#define SONY535_SET_INACTIVITY_TIME (0x90)
-
-#define SONY535_SEEK_AND_READ_N_BLOCKS_1 (0xa0)
-#define SONY535_SEEK_AND_READ_N_BLOCKS_2 (0xa4)
-#define SONY535_PLAY_AUDIO (0xa6)
-
-#define SONY535_REQUEST_DISC_CAPACITY (0xb0)
-#define SONY535_REQUEST_TOC_DATA (0xb2)
-#define SONY535_REQUEST_SUB_Q_DATA (0xb4)
-#define SONY535_REQUEST_ISRC (0xb6)
-#define SONY535_REQUEST_UPC_EAN (0xb8)
-
-#define SONY535_SET_DRIVE_MODE (0xc0)
-#define SONY535_REQUEST_DRIVE_MODE (0xc2)
-#define SONY535_SET_RETRY_COUNT (0xc4)
-
-#define SONY535_DIAGNOSTIC_1 (0xc6)
-#define SONY535_DIAGNOSTIC_4 (0xcc)
-#define SONY535_DIAGNOSTIC_5 (0xce)
-
-#define SONY535_EJECT_CADDY (0xd0)
-#define SONY535_DISABLE_EJECT_BUTTON (0xd2)
-#define SONY535_ENABLE_EJECT_BUTTON (0xd4)
-
-#define SONY535_HOLD (0xe0)
-#define SONY535_AUDIO_PAUSE_ON_OFF (0xe2)
-#define SONY535_SET_VOLUME (0xe8)
-
-#define SONY535_STOP (0xf0)
-#define SONY535_SPIN_UP (0xf2)
-#define SONY535_SPIN_DOWN (0xf4)
-
-#define SONY535_CLEAR_PARAMETERS (0xf6)
-#define SONY535_CLEAR_ENDING_ADDRESS (0xf8)
-
-/*
- * define some masks
- */
-#define SONY535_DATA_NOT_READY_BIT (0x1)
-#define SONY535_RESULT_NOT_READY_BIT (0x2)
-
-/*
- * drive status 1
- */
-#define SONY535_STATUS1_COMMAND_ERROR (0x1)
-#define SONY535_STATUS1_DATA_ERROR (0x2)
-#define SONY535_STATUS1_SEEK_ERROR (0x4)
-#define SONY535_STATUS1_DISC_TYPE_ERROR (0x8)
-#define SONY535_STATUS1_NOT_SPINNING (0x10)
-#define SONY535_STATUS1_EJECT_BUTTON_PRESSED (0x20)
-#define SONY535_STATUS1_CADDY_NOT_INSERTED (0x40)
-#define SONY535_STATUS1_BYTE_TWO_FOLLOWS (0x80)
-
-/*
- * drive status 2
- */
-#define SONY535_CDD_LOADING_ERROR (0x7)
-#define SONY535_CDD_NO_DISC (0x8)
-#define SONY535_CDD_UNLOADING_ERROR (0x9)
-#define SONY535_CDD_CADDY_NOT_INSERTED (0xd)
-#define SONY535_ATN_RESET_OCCURRED (0x2)
-#define SONY535_ATN_DISC_CHANGED (0x4)
-#define SONY535_ATN_RESET_AND_DISC_CHANGED (0x6)
-#define SONY535_ATN_EJECT_IN_PROGRESS (0xe)
-#define SONY535_ATN_BUSY (0xf)
-
-/*
- * define some parameters
- */
-#define SONY535_AUDIO_DRIVE_MODE (0)
-#define SONY535_CDROM_DRIVE_MODE (0xe0)
-
-#define SONY535_PLAY_OP_PLAYBACK (0)
-#define SONY535_PLAY_OP_ENTER_HOLD (1)
-#define SONY535_PLAY_OP_SET_AUDIO_ENDING_ADDR (2)
-#define SONY535_PLAY_OP_SCAN_FORWARD (3)
-#define SONY535_PLAY_OP_SCAN_BACKWARD (4)
-
-/*
- * convert from msf format to block number
- */
-#define SONY_BLOCK_NUMBER(m,s,f) (((m)*60L+(s))*75L+(f))
-#define SONY_BLOCK_NUMBER_MSF(x) (((x)[0]*60L+(x)[1])*75L+(x)[2])
-
-/*
- * error return values from the doSonyCmd() routines
- */
-#define TIME_OUT (-1)
-#define NO_CDROM (-2)
-#define BAD_STATUS (-3)
-#define CD_BUSY (-4)
-#define NOT_DATA_CD (-5)
-#define NO_ROOM (-6)
-
-#define LOG_START_OFFSET 150 /* Offset of first logical sector */
-
-#define SONY_JIFFIES_TIMEOUT (5*HZ) /* Maximum time
- the drive will wait/try for an
- operation */
-#define SONY_READY_RETRIES (50000) /* How many times to retry a
- spin waiting for a register
- to come ready */
-#define SONY535_FAST_POLLS (10000) /* how many times recheck
- status waiting for a data
- to become ready */
-
-typedef unsigned char Byte;
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s535_sony_drive_config
-{
- char vendor_id[8];
- char product_id[16];
- char product_rev_level[4];
-};
-
-/* The following is returned from the request sub-q data command */
-struct s535_sony_subcode
-{
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track_num;
- unsigned char index_num;
- unsigned char rel_msf[3];
- unsigned char abs_msf[3];
-};
-
-struct s535_sony_disc_capacity
-{
- Byte mFirstTrack, sFirstTrack, fFirstTrack;
- Byte mLeadOut, sLeadOut, fLeadOut;
-};
-
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s535_sony_toc
-{
- unsigned char reserved0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char reserved0a;
- unsigned char reserved0b;
- unsigned char reserved1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char reserved2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char reserved :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[100];
-
- unsigned int lead_out_start_lba;
-};
-
-#endif /* SONYCD535_H */
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 1b094509b1d2..90965b4def5c 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1005,8 +1005,8 @@ static const unsigned short x86_keycodes[256] =
284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
- 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
- 291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
+ 103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
+ 291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index cc9a9d0df979..bbee97ff355f 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -24,7 +24,7 @@
#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
#include <linux/bootmem.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
#include <linux/pfn.h>
#include <asm/uaccess.h>
@@ -75,6 +75,13 @@ static inline int uncached_access(struct file *file, unsigned long addr)
* On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
*/
return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
+#elif defined(CONFIG_MIPS)
+ {
+ extern int __uncached_access(struct file *file,
+ unsigned long addr);
+
+ return __uncached_access(file, addr);
+ }
#else
/*
* Accessing memory above the top the kernel knows about or through a file pointer
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 9eb1edacd825..0aeab3218bb6 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -336,8 +336,11 @@ fw_card_bm_work(struct work_struct *work)
}
pick_me:
- /* Now figure out what gap count to set. */
- if (card->topology_type == FW_TOPOLOGY_A &&
+ /*
+ * Pick a gap count from 1394a table E-1. The table doesn't cover
+ * the typically much larger 1394b beta repeater delays though.
+ */
+ if (!card->beta_repeaters_present &&
card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
gap_count = gap_count_table[card->root_node->max_hops];
else
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index dbb76427d529..75388641a7d3 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -397,7 +397,7 @@ static int ioctl_send_request(struct client *client, void *buffer)
request->tcode & 0x1f,
device->node->node_id,
request->generation,
- device->node->max_speed,
+ device->max_speed,
request->offset,
response->response.data, request->length,
complete_transaction, response);
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index c1ce465d9710..2b6586341635 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -401,8 +401,7 @@ static int read_rom(struct fw_device *device, int index, u32 * data)
offset = 0xfffff0000400ULL + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
- device->node_id,
- device->generation, SCODE_100,
+ device->node_id, device->generation, device->max_speed,
offset, NULL, 4, complete_transaction, &callback_data);
wait_for_completion(&callback_data.done);
@@ -418,6 +417,8 @@ static int read_bus_info_block(struct fw_device *device)
u32 stack[16], sp, key;
int i, end, length;
+ device->max_speed = SCODE_100;
+
/* First read the bus info block. */
for (i = 0; i < 5; i++) {
if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
@@ -434,6 +435,33 @@ static int read_bus_info_block(struct fw_device *device)
return -1;
}
+ device->max_speed = device->node->max_speed;
+
+ /*
+ * Determine the speed of
+ * - devices with link speed less than PHY speed,
+ * - devices with 1394b PHY (unless only connected to 1394a PHYs),
+ * - all devices if there are 1394b repeaters.
+ * Note, we cannot use the bus info block's link_spd as starting point
+ * because some buggy firmwares set it lower than necessary and because
+ * 1394-1995 nodes do not have the field.
+ */
+ if ((rom[2] & 0x7) < device->max_speed ||
+ device->max_speed == SCODE_BETA ||
+ device->card->beta_repeaters_present) {
+ u32 dummy;
+
+ /* for S1600 and S3200 */
+ if (device->max_speed == SCODE_BETA)
+ device->max_speed = device->card->link_speed;
+
+ while (device->max_speed > SCODE_100) {
+ if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
+ break;
+ device->max_speed--;
+ }
+ }
+
/*
* Now parse the config rom. The config rom is a recursive
* directory structure so we parse it using a stack of
@@ -680,8 +708,10 @@ static void fw_device_init(struct work_struct *work)
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
fw_device_shutdown(&device->work.work);
else
- fw_notify("created new fw device %s (%d config rom retries)\n",
- device->device.bus_id, device->config_rom_retries);
+ fw_notify("created new fw device %s "
+ "(%d config rom retries, S%d00)\n",
+ device->device.bus_id, device->config_rom_retries,
+ 1 << device->max_speed);
/*
* Reschedule the IRM work if we just finished reading the
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index af1723eae4ba..d13e6a69707f 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -40,6 +40,7 @@ struct fw_device {
struct fw_node *node;
int node_id;
int generation;
+ unsigned max_speed;
struct fw_card *card;
struct device device;
struct list_head link;
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 96c8ac5b86cc..41476abc0693 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -1934,12 +1934,12 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
free_irq(pdev->irq, ohci);
err = pci_save_state(pdev);
if (err) {
- fw_error("pci_save_state failed with %d", err);
+ fw_error("pci_save_state failed\n");
return err;
}
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
if (err) {
- fw_error("pci_set_power_state failed with %d", err);
+ fw_error("pci_set_power_state failed\n");
return err;
}
@@ -1955,7 +1955,7 @@ static int pci_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
err = pci_enable_device(pdev);
if (err) {
- fw_error("pci_enable_device failed with %d", err);
+ fw_error("pci_enable_device failed\n");
return err;
}
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index a98d3915e26f..7c53be0387fb 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -30,10 +30,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/mod_devicetable.h>
#include <linux/device.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
+#include <linux/string.h>
#include <linux/timer.h>
#include <scsi/scsi.h>
@@ -46,6 +49,18 @@
#include "fw-topology.h"
#include "fw-device.h"
+/*
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
+ *
+ * Concurrent logins are useful together with cluster filesystems.
+ */
+static int sbp2_param_exclusive_login = 1;
+module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
+MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
+ "(default = Y, use N for concurrent initiators)");
+
/* I don't know why the SCSI stack doesn't define something like this... */
typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
@@ -154,7 +169,7 @@ struct sbp2_orb {
#define MANAGEMENT_ORB_LUN(v) ((v))
#define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16)
#define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20)
-#define MANAGEMENT_ORB_EXCLUSIVE ((1) << 28)
+#define MANAGEMENT_ORB_EXCLUSIVE(v) ((v) ? 1 << 28 : 0)
#define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29)
#define MANAGEMENT_ORB_NOTIFY ((1) << 31)
@@ -205,9 +220,8 @@ struct sbp2_command_orb {
scsi_done_fn_t done;
struct fw_unit *unit;
- struct sbp2_pointer page_table[SG_ALL];
+ struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
dma_addr_t page_table_bus;
- dma_addr_t request_buffer_bus;
};
/*
@@ -347,8 +361,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
spin_unlock_irqrestore(&device->card->lock, flags);
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
- node_id, generation,
- device->node->max_speed, offset,
+ node_id, generation, device->max_speed, offset,
&orb->pointer, sizeof(orb->pointer),
complete_transaction, orb);
}
@@ -383,7 +396,7 @@ static void
complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{
struct sbp2_management_orb *orb =
- (struct sbp2_management_orb *)base_orb;
+ container_of(base_orb, struct sbp2_management_orb, base);
if (status)
memcpy(&orb->status, status, sizeof(*status));
@@ -403,21 +416,11 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
if (orb == NULL)
return -ENOMEM;
- /*
- * The sbp2 device is going to send a block read request to
- * read out the request from host memory, so map it for dma.
- */
- orb->base.request_bus =
- dma_map_single(device->card->device, &orb->request,
- sizeof(orb->request), DMA_TO_DEVICE);
- if (dma_mapping_error(orb->base.request_bus))
- goto out;
-
orb->response_bus =
dma_map_single(device->card->device, &orb->response,
sizeof(orb->response), DMA_FROM_DEVICE);
if (dma_mapping_error(orb->response_bus))
- goto out;
+ goto fail_mapping_response;
orb->request.response.high = 0;
orb->request.response.low = orb->response_bus;
@@ -432,14 +435,9 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
orb->request.status_fifo.high = sd->address_handler.offset >> 32;
orb->request.status_fifo.low = sd->address_handler.offset;
- /*
- * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive
- * login and 1 second reconnect time. The reconnect setting
- * is probably fine, but the exclusive login should be an option.
- */
if (function == SBP2_LOGIN_REQUEST) {
orb->request.misc |=
- MANAGEMENT_ORB_EXCLUSIVE |
+ MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
MANAGEMENT_ORB_RECONNECT(0);
}
@@ -448,6 +446,12 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
init_completion(&orb->done);
orb->base.callback = complete_management_orb;
+ orb->base.request_bus =
+ dma_map_single(device->card->device, &orb->request,
+ sizeof(orb->request), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->base.request_bus))
+ goto fail_mapping_request;
+
sbp2_send_orb(&orb->base, unit,
node_id, generation, sd->management_agent_address);
@@ -479,9 +483,10 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
out:
dma_unmap_single(device->card->device, orb->base.request_bus,
sizeof(orb->request), DMA_TO_DEVICE);
+ fail_mapping_request:
dma_unmap_single(device->card->device, orb->response_bus,
sizeof(orb->response), DMA_FROM_DEVICE);
-
+ fail_mapping_response:
if (response)
fw_memcpy_from_be32(response,
orb->response, sizeof(orb->response));
@@ -511,7 +516,7 @@ static int sbp2_agent_reset(struct fw_unit *unit)
return -ENOMEM;
fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
- sd->node_id, sd->generation, SCODE_400,
+ sd->node_id, sd->generation, device->max_speed,
sd->command_block_agent_address + SBP2_AGENT_RESET,
&zero, sizeof(zero), complete_agent_reset_write, t);
@@ -521,17 +526,15 @@ static int sbp2_agent_reset(struct fw_unit *unit)
static void sbp2_reconnect(struct work_struct *work);
static struct scsi_host_template scsi_driver_template;
-static void
-release_sbp2_device(struct kref *kref)
+static void release_sbp2_device(struct kref *kref)
{
struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
struct Scsi_Host *host =
container_of((void *)sd, struct Scsi_Host, hostdata[0]);
+ scsi_remove_host(host);
sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
-
- scsi_remove_host(host);
fw_core_remove_address_handler(&sd->address_handler);
fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
put_device(&sd->unit->device);
@@ -833,7 +836,8 @@ sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
static void
complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{
- struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb;
+ struct sbp2_command_orb *orb =
+ container_of(base_orb, struct sbp2_command_orb, base);
struct fw_unit *unit = orb->unit;
struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg;
@@ -880,12 +884,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
if (orb->page_table_bus != 0)
dma_unmap_single(device->card->device, orb->page_table_bus,
- sizeof(orb->page_table_bus), DMA_TO_DEVICE);
-
- if (orb->request_buffer_bus != 0)
- dma_unmap_single(device->card->device, orb->request_buffer_bus,
- sizeof(orb->request_buffer_bus),
- DMA_FROM_DEVICE);
+ sizeof(orb->page_table), DMA_TO_DEVICE);
orb->cmd->result = result;
orb->done(orb->cmd);
@@ -900,7 +899,6 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg;
int sg_len, l, i, j, count;
- size_t size;
dma_addr_t sg_addr;
sg = (struct scatterlist *)orb->cmd->request_buffer;
@@ -935,6 +933,11 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
sg_len = sg_dma_len(sg + i);
sg_addr = sg_dma_address(sg + i);
while (sg_len) {
+ /* FIXME: This won't get us out of the pinch. */
+ if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
+ fw_error("page table overflow\n");
+ goto fail_page_table;
+ }
l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
orb->page_table[j].low = sg_addr;
orb->page_table[j].high = (l << 16);
@@ -944,7 +947,13 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
}
}
- size = sizeof(orb->page_table[0]) * j;
+ fw_memcpy_to_be32(orb->page_table, orb->page_table,
+ sizeof(orb->page_table[0]) * j);
+ orb->page_table_bus =
+ dma_map_single(device->card->device, orb->page_table,
+ sizeof(orb->page_table), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->page_table_bus))
+ goto fail_page_table;
/*
* The data_descriptor pointer is the one case where we need
@@ -953,20 +962,12 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
* initiator (i.e. us), but data_descriptor can refer to data
* on other nodes so we need to put our ID in descriptor.high.
*/
-
- orb->page_table_bus =
- dma_map_single(device->card->device, orb->page_table,
- size, DMA_TO_DEVICE);
- if (dma_mapping_error(orb->page_table_bus))
- goto fail_page_table;
orb->request.data_descriptor.high = sd->address_high;
orb->request.data_descriptor.low = orb->page_table_bus;
orb->request.misc |=
COMMAND_ORB_PAGE_TABLE_PRESENT |
COMMAND_ORB_DATA_SIZE(j);
- fw_memcpy_to_be32(orb->page_table, orb->page_table, size);
-
return 0;
fail_page_table:
@@ -991,7 +992,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
* transfer direction not handled.
*/
if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
- fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+ fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
cmd->result = DID_ERROR << 16;
done(cmd);
return 0;
@@ -1005,11 +1006,6 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
/* Initialize rcode to something not RCODE_COMPLETE. */
orb->base.rcode = -1;
- orb->base.request_bus =
- dma_map_single(device->card->device, &orb->request,
- sizeof(orb->request), DMA_TO_DEVICE);
- if (dma_mapping_error(orb->base.request_bus))
- goto fail_mapping;
orb->unit = unit;
orb->done = done;
@@ -1024,8 +1020,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
* if we set this to max_speed + 7, we get the right value.
*/
orb->request.misc =
- COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) |
- COMMAND_ORB_SPEED(device->node->max_speed) |
+ COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
+ COMMAND_ORB_SPEED(device->max_speed) |
COMMAND_ORB_NOTIFY;
if (cmd->sc_data_direction == DMA_FROM_DEVICE)
@@ -1036,7 +1032,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
- goto fail_map_payload;
+ goto fail_mapping;
fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
@@ -1045,15 +1041,17 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
orb->base.callback = complete_command_orb;
+ orb->base.request_bus =
+ dma_map_single(device->card->device, &orb->request,
+ sizeof(orb->request), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->base.request_bus))
+ goto fail_mapping;
sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
sd->command_block_agent_address + SBP2_ORB_POINTER);
return 0;
- fail_map_payload:
- dma_unmap_single(device->card->device, orb->base.request_bus,
- sizeof(orb->request), DMA_TO_DEVICE);
fail_mapping:
kfree(orb);
fail_alloc:
@@ -1087,7 +1085,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
sdev->fix_capacity = 1;
}
-
+ if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+ blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
return 0;
}
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 7aebb8ae0efa..39e5cd12aa52 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -135,17 +135,17 @@ static void update_hop_count(struct fw_node *node)
int i;
for (i = 0; i < node->port_count; i++) {
- if (node->ports[i].node == NULL)
+ if (node->ports[i] == NULL)
continue;
- if (node->ports[i].node->max_hops > max_child_hops)
- max_child_hops = node->ports[i].node->max_hops;
+ if (node->ports[i]->max_hops > max_child_hops)
+ max_child_hops = node->ports[i]->max_hops;
- if (node->ports[i].node->max_depth > depths[0]) {
+ if (node->ports[i]->max_depth > depths[0]) {
depths[1] = depths[0];
- depths[0] = node->ports[i].node->max_depth;
- } else if (node->ports[i].node->max_depth > depths[1])
- depths[1] = node->ports[i].node->max_depth;
+ depths[0] = node->ports[i]->max_depth;
+ } else if (node->ports[i]->max_depth > depths[1])
+ depths[1] = node->ports[i]->max_depth;
}
node->max_depth = depths[0] + 1;
@@ -172,7 +172,8 @@ static struct fw_node *build_tree(struct fw_card *card,
struct list_head stack, *h;
u32 *next_sid, *end, q;
int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
- int gap_count, topology_type;
+ int gap_count;
+ bool beta_repeaters_present;
local_node = NULL;
node = NULL;
@@ -182,7 +183,7 @@ static struct fw_node *build_tree(struct fw_card *card,
phy_id = 0;
irm_node = NULL;
gap_count = SELF_ID_GAP_COUNT(*sid);
- topology_type = 0;
+ beta_repeaters_present = false;
while (sid < end) {
next_sid = count_ports(sid, &port_count, &child_port_count);
@@ -214,7 +215,7 @@ static struct fw_node *build_tree(struct fw_card *card,
node = fw_node_create(q, port_count, card->color);
if (node == NULL) {
- fw_error("Out of memory while building topology.");
+ fw_error("Out of memory while building topology.\n");
return NULL;
}
@@ -224,11 +225,6 @@ static struct fw_node *build_tree(struct fw_card *card,
if (SELF_ID_CONTENDER(q))
irm_node = node;
- if (node->phy_speed == SCODE_BETA)
- topology_type |= FW_TOPOLOGY_B;
- else
- topology_type |= FW_TOPOLOGY_A;
-
parent_count = 0;
for (i = 0; i < port_count; i++) {
@@ -249,12 +245,12 @@ static struct fw_node *build_tree(struct fw_card *card,
break;
case SELFID_PORT_CHILD:
- node->ports[i].node = child;
+ node->ports[i] = child;
/*
* Fix up parent reference for this
* child node.
*/
- child->ports[child->color].node = node;
+ child->ports[child->color] = node;
child->color = card->color;
child = fw_node(child->link.next);
break;
@@ -278,6 +274,10 @@ static struct fw_node *build_tree(struct fw_card *card,
list_add_tail(&node->link, &stack);
stack_depth += 1 - child_port_count;
+ if (node->phy_speed == SCODE_BETA &&
+ parent_count + child_port_count > 1)
+ beta_repeaters_present = true;
+
/*
* If all PHYs does not report the same gap count
* setting, we fall back to 63 which will force a gap
@@ -295,7 +295,7 @@ static struct fw_node *build_tree(struct fw_card *card,
card->root_node = node;
card->irm_node = irm_node;
card->gap_count = gap_count;
- card->topology_type = topology_type;
+ card->beta_repeaters_present = beta_repeaters_present;
return local_node;
}
@@ -321,7 +321,7 @@ for_each_fw_node(struct fw_card *card, struct fw_node *root,
node->color = card->color;
for (i = 0; i < node->port_count; i++) {
- child = node->ports[i].node;
+ child = node->ports[i];
if (!child)
continue;
if (child->color == card->color)
@@ -382,11 +382,11 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
struct fw_node *tree;
int i;
- tree = node1->ports[port].node;
- node0->ports[port].node = tree;
+ tree = node1->ports[port];
+ node0->ports[port] = tree;
for (i = 0; i < tree->port_count; i++) {
- if (tree->ports[i].node == node1) {
- tree->ports[i].node = node0;
+ if (tree->ports[i] == node1) {
+ tree->ports[i] = node0;
break;
}
}
@@ -437,19 +437,17 @@ update_tree(struct fw_card *card, struct fw_node *root)
card->irm_node = node0;
for (i = 0; i < node0->port_count; i++) {
- if (node0->ports[i].node && node1->ports[i].node) {
+ if (node0->ports[i] && node1->ports[i]) {
/*
* This port didn't change, queue the
* connected node for further
* investigation.
*/
- if (node0->ports[i].node->color == card->color)
+ if (node0->ports[i]->color == card->color)
continue;
- list_add_tail(&node0->ports[i].node->link,
- &list0);
- list_add_tail(&node1->ports[i].node->link,
- &list1);
- } else if (node0->ports[i].node) {
+ list_add_tail(&node0->ports[i]->link, &list0);
+ list_add_tail(&node1->ports[i]->link, &list1);
+ } else if (node0->ports[i]) {
/*
* The nodes connected here were
* unplugged; unref the lost nodes and
@@ -457,10 +455,10 @@ update_tree(struct fw_card *card, struct fw_node *root)
* them.
*/
- for_each_fw_node(card, node0->ports[i].node,
+ for_each_fw_node(card, node0->ports[i],
report_lost_node);
- node0->ports[i].node = NULL;
- } else if (node1->ports[i].node) {
+ node0->ports[i] = NULL;
+ } else if (node1->ports[i]) {
/*
* One or more node were connected to
* this port. Move the new nodes into
@@ -468,7 +466,7 @@ update_tree(struct fw_card *card, struct fw_node *root)
* callbacks for them.
*/
move_tree(node0, node1, i);
- for_each_fw_node(card, node0->ports[i].node,
+ for_each_fw_node(card, node0->ports[i],
report_found_node);
}
}
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index 363b6cbcd0b3..1b56b4ac7fb2 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -20,12 +20,6 @@
#define __fw_topology_h
enum {
- FW_TOPOLOGY_A = 0x01,
- FW_TOPOLOGY_B = 0x02,
- FW_TOPOLOGY_MIXED = 0x03,
-};
-
-enum {
FW_NODE_CREATED = 0x00,
FW_NODE_UPDATED = 0x01,
FW_NODE_DESTROYED = 0x02,
@@ -33,21 +27,16 @@ enum {
FW_NODE_LINK_OFF = 0x04,
};
-struct fw_port {
- struct fw_node *node;
- unsigned speed : 3; /* S100, S200, ... S3200 */
-};
-
struct fw_node {
u16 node_id;
u8 color;
u8 port_count;
- unsigned link_on : 1;
- unsigned initiated_reset : 1;
- unsigned b_path : 1;
- u8 phy_speed : 3; /* As in the self ID packet. */
- u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on
- * the path from the local node to this node. */
+ u8 link_on : 1;
+ u8 initiated_reset : 1;
+ u8 b_path : 1;
+ u8 phy_speed : 2; /* As in the self ID packet. */
+ u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
+ * local node to this node. */
u8 max_depth : 4; /* Maximum depth to any leaf node */
u8 max_hops : 4; /* Max hops in this sub tree */
atomic_t ref_count;
@@ -58,7 +47,7 @@ struct fw_node {
/* Upper layer specific data. */
void *data;
- struct fw_port ports[0];
+ struct fw_node *ports[0];
};
static inline struct fw_node *
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index acdc3be38c61..5abed193f4a6 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -81,7 +81,6 @@
#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
static inline void
fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
@@ -246,7 +245,7 @@ struct fw_card {
struct fw_node *irm_node;
int color;
int gap_count;
- int topology_type;
+ bool beta_repeaters_present;
int index;
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8fbe9fdac128..3b63b0b78122 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1,8 +1,12 @@
#
# HID driver configuration
#
-menu "HID Devices"
+menuconfig HID_SUPPORT
+ bool "HID Devices"
depends on INPUT
+ default y
+
+if HID_SUPPORT
config HID
tristate "Generic HID support"
@@ -24,6 +28,7 @@ config HID
config HID_DEBUG
bool "HID debugging support"
+ default y if !EMBEDDED
depends on HID
---help---
This option lets the HID layer output diagnostics about its internal
@@ -38,5 +43,4 @@ config HID_DEBUG
source "drivers/hid/usbhid/Kconfig"
-endmenu
-
+endif # HID_SUPPORT
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6ec04e79f685..317cf8a7b63c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -40,6 +40,13 @@
#define DRIVER_DESC "HID core driver"
#define DRIVER_LICENSE "GPL"
+#ifdef CONFIG_HID_DEBUG
+int hid_debug = 0;
+module_param_named(debug, hid_debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Turn HID debugging mode on and off");
+EXPORT_SYMBOL_GPL(hid_debug);
+#endif
+
/*
* Register a new report for a device.
*/
@@ -78,7 +85,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
struct hid_field *field;
if (report->maxfield == HID_MAX_FIELDS) {
- dbg("too many fields in report");
+ dbg_hid("too many fields in report\n");
return NULL;
}
@@ -106,7 +113,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
usage = parser->local.usage[0];
if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
- dbg("collection stack overflow");
+ dbg_hid("collection stack overflow\n");
return -1;
}
@@ -114,7 +121,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
collection = kmalloc(sizeof(struct hid_collection) *
parser->device->collection_size * 2, GFP_KERNEL);
if (collection == NULL) {
- dbg("failed to reallocate collection array");
+ dbg_hid("failed to reallocate collection array\n");
return -1;
}
memcpy(collection, parser->device->collection,
@@ -150,7 +157,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
static int close_collection(struct hid_parser *parser)
{
if (!parser->collection_stack_ptr) {
- dbg("collection stack underflow");
+ dbg_hid("collection stack underflow\n");
return -1;
}
parser->collection_stack_ptr--;
@@ -178,7 +185,7 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
static int hid_add_usage(struct hid_parser *parser, unsigned usage)
{
if (parser->local.usage_index >= HID_MAX_USAGES) {
- dbg("usage index exceeded");
+ dbg_hid("usage index exceeded\n");
return -1;
}
parser->local.usage[parser->local.usage_index] = usage;
@@ -202,12 +209,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
int i;
if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
- dbg("hid_register_report failed");
+ dbg_hid("hid_register_report failed\n");
return -1;
}
if (parser->global.logical_maximum < parser->global.logical_minimum) {
- dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+ dbg_hid("logical range invalid %d %d\n", parser->global.logical_minimum, parser->global.logical_maximum);
return -1;
}
@@ -287,7 +294,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_PUSH:
if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
- dbg("global enviroment stack overflow");
+ dbg_hid("global enviroment stack overflow\n");
return -1;
}
@@ -298,7 +305,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_POP:
if (!parser->global_stack_ptr) {
- dbg("global enviroment stack underflow");
+ dbg_hid("global enviroment stack underflow\n");
return -1;
}
@@ -342,27 +349,27 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
if ((parser->global.report_size = item_udata(item)) > 32) {
- dbg("invalid report_size %d", parser->global.report_size);
+ dbg_hid("invalid report_size %d\n", parser->global.report_size);
return -1;
}
return 0;
case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
- dbg("invalid report_count %d", parser->global.report_count);
+ dbg_hid("invalid report_count %d\n", parser->global.report_count);
return -1;
}
return 0;
case HID_GLOBAL_ITEM_TAG_REPORT_ID:
if ((parser->global.report_id = item_udata(item)) == 0) {
- dbg("report_id 0 is invalid");
+ dbg_hid("report_id 0 is invalid\n");
return -1;
}
return 0;
default:
- dbg("unknown global tag 0x%x", item->tag);
+ dbg_hid("unknown global tag 0x%x\n", item->tag);
return -1;
}
}
@@ -377,7 +384,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
unsigned n;
if (item->size == 0) {
- dbg("item data expected for local item");
+ dbg_hid("item data expected for local item\n");
return -1;
}
@@ -395,14 +402,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
* items and the first delimiter set.
*/
if (parser->local.delimiter_depth != 0) {
- dbg("nested delimiters");
+ dbg_hid("nested delimiters\n");
return -1;
}
parser->local.delimiter_depth++;
parser->local.delimiter_branch++;
} else {
if (parser->local.delimiter_depth < 1) {
- dbg("bogus close delimiter");
+ dbg_hid("bogus close delimiter\n");
return -1;
}
parser->local.delimiter_depth--;
@@ -412,7 +419,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -424,7 +431,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -437,7 +444,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -446,14 +453,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
for (n = parser->local.usage_minimum; n <= data; n++)
if (hid_add_usage(parser, n)) {
- dbg("hid_add_usage failed\n");
+ dbg_hid("hid_add_usage failed\n");
return -1;
}
return 0;
default:
- dbg("unknown local item tag 0x%x", item->tag);
+ dbg_hid("unknown local item tag 0x%x\n", item->tag);
return 0;
}
return 0;
@@ -487,7 +494,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
break;
default:
- dbg("unknown main item tag 0x%x", item->tag);
+ dbg_hid("unknown main item tag 0x%x\n", item->tag);
ret = 0;
}
@@ -502,7 +509,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
{
- dbg("reserved item type, tag 0x%x", item->tag);
+ dbg_hid("reserved item type, tag 0x%x\n", item->tag);
return 0;
}
@@ -667,14 +674,14 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
while ((start = fetch_item(start, end, &item)) != NULL) {
if (item.format != HID_ITEM_FORMAT_SHORT) {
- dbg("unexpected long global item");
+ dbg_hid("unexpected long global item\n");
hid_free_device(device);
vfree(parser);
return NULL;
}
if (dispatch_type[item.type](parser, &item)) {
- dbg("item %u %u %u %u parsing failed\n",
+ dbg_hid("item %u %u %u %u parsing failed\n",
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
hid_free_device(device);
vfree(parser);
@@ -683,13 +690,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
if (start == end) {
if (parser->collection_stack_ptr) {
- dbg("unbalanced collection at end of report description");
+ dbg_hid("unbalanced collection at end of report description\n");
hid_free_device(device);
vfree(parser);
return NULL;
}
if (parser->local.delimiter_depth) {
- dbg("unbalanced delimiter at end of report description");
+ dbg_hid("unbalanced delimiter at end of report description\n");
hid_free_device(device);
vfree(parser);
return NULL;
@@ -699,7 +706,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
}
}
- dbg("item fetching failed at offset %d\n", (int)(end - start));
+ dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
hid_free_device(device);
vfree(parser);
return NULL;
@@ -915,13 +922,13 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
hid_dump_input(field->usage + offset, value);
if (offset >= field->report_count) {
- dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
+ dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count);
hid_dump_field(field, 8);
return -1;
}
if (field->logical_minimum < 0) {
if (value != snto32(s32ton(value, size), size)) {
- dbg("value %d is out of range", value);
+ dbg_hid("value %d is out of range\n", value);
return -1;
}
}
@@ -934,19 +941,17 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
{
struct hid_report_enum *report_enum = hid->report_enum + type;
struct hid_report *report;
- int n, rsize;
+ int n, rsize, i;
if (!hid)
return -ENODEV;
if (!size) {
- dbg("empty report");
+ dbg_hid("empty report\n");
return -1;
}
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
-#endif
+ dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
n = 0; /* Normally report number is 0 */
if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
@@ -954,25 +959,21 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
size--;
}
-#ifdef CONFIG_HID_DEBUG
- {
- int i;
- printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
- for (i = 0; i < size; i++)
- printk(" %02x", data[i]);
- printk("\n");
- }
-#endif
+ /* dump the report descriptor */
+ dbg_hid("report %d (size %u) = ", n, size);
+ for (i = 0; i < size; i++)
+ dbg_hid_line(" %02x", data[i]);
+ dbg_hid_line("\n");
if (!(report = report_enum->report_id_hash[n])) {
- dbg("undefined report_id %d received", n);
+ dbg_hid("undefined report_id %d received\n", n);
return -1;
}
rsize = ((report->size - 1) >> 3) + 1;
if (size < rsize) {
- dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
+ dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
memset(data + size, 0, rsize - size);
}
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 83c4126b37c3..a13757b78980 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -347,6 +347,9 @@ static void resolv_usage_page(unsigned page) {
void hid_resolv_usage(unsigned usage) {
const struct hid_usage_entry *p;
+ if (!hid_debug)
+ return;
+
resolv_usage_page(usage >> 16);
printk(".");
for (p = hid_usage_table; p->description; p++)
@@ -369,6 +372,9 @@ __inline__ static void tab(int n) {
void hid_dump_field(struct hid_field *field, int n) {
int j;
+ if (!hid_debug)
+ return;
+
if (field->physical) {
tab(n);
printk("Physical(");
@@ -466,6 +472,9 @@ void hid_dump_device(struct hid_device *device) {
unsigned i,k;
static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
+ if (!hid_debug)
+ return;
+
for (i = 0; i < HID_REPORT_TYPES; i++) {
report_enum = device->report_enum + i;
list = report_enum->report_list.next;
@@ -489,6 +498,9 @@ void hid_dump_device(struct hid_device *device) {
EXPORT_SYMBOL_GPL(hid_dump_device);
void hid_dump_input(struct hid_usage *usage, __s32 value) {
+ if (!hid_debug)
+ return;
+
printk("hid-debug: input ");
hid_resolv_usage(usage->hid);
printk(" = %d\n", value);
@@ -758,6 +770,9 @@ static char **names[EV_MAX + 1] = {
void hid_resolv_event(__u8 type, __u16 code) {
+ if (!hid_debug)
+ return;
+
printk("%s.%s", events[type] ? events[type] : "?",
names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
}
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7f817897b178..8edbd30cf795 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -60,6 +60,19 @@ static const unsigned char hid_keyboard[256] = {
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};
+/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
+#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
+static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
+ 0,216, 0,213,175,156, 0, 0, 0, 0,
+ 144, 0, 0, 0, 0, 0, 0, 0, 0,212,
+ 174,167,152,161,112, 0, 0, 0,154, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,183,184,185,186,187,
+ 188,189,190,191,192,193,194, 0, 0, 0
+};
+
static const struct {
__s32 x;
__s32 y;
@@ -308,9 +321,7 @@ static int hidinput_setkeycode(struct input_dev *dev, int scancode,
clear_bit(old_keycode, dev->keybit);
set_bit(usage->code, dev->keybit);
-#ifdef CONFIG_HID_DEBUG
- printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
-#endif
+ dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
/* Set the keybit for the old keycode if the old keycode is used
* by another key */
if (hidinput_find_key (hid, 0, old_keycode))
@@ -333,11 +344,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
field->hidinput = hidinput;
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG "Mapping: ");
+ dbg_hid("Mapping: ");
hid_resolv_usage(usage->hid);
- printk(" ---> ");
-#endif
+ dbg_hid_line(" ---> ");
if (field->flags & HID_MAIN_ITEM_CONSTANT)
goto ignore;
@@ -378,6 +387,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
}
+ /* Special handling for Logitech Cordless Desktop */
+ if (field->application != HID_GD_MOUSE) {
+ if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
+ int hid = usage->hid & HID_USAGE;
+ if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
+ code = logitech_expanded_keymap[hid];
+ }
+ } else {
+ if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
+ int hid = usage->hid & HID_USAGE;
+ if (hid == 7 || hid == 8)
+ goto ignore;
+ }
+ }
+
map_key(code);
break;
@@ -566,6 +590,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
+
+ /* reserved in HUT 1.12. Reported on Petalynx remote */
+ case 0x0f6: map_key_clear(KEY_NEXT); break;
+ case 0x0fa: map_key_clear(KEY_BACK); break;
+
case 0x183: map_key_clear(KEY_CONFIG); break;
case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
case 0x185: map_key_clear(KEY_EDITOR); break;
@@ -598,7 +627,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x21b: map_key_clear(KEY_COPY); break;
case 0x21c: map_key_clear(KEY_CUT); break;
case 0x21d: map_key_clear(KEY_PASTE); break;
- case 0x221: map_key_clear(KEY_FIND); break;
+ case 0x21f: map_key_clear(KEY_FIND); break;
+ case 0x221: map_key_clear(KEY_SEARCH); break;
+ case 0x222: map_key_clear(KEY_GOTO); break;
case 0x223: map_key_clear(KEY_HOMEPAGE); break;
case 0x224: map_key_clear(KEY_BACK); break;
case 0x225: map_key_clear(KEY_FORWARD); break;
@@ -688,7 +719,28 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break;
case HID_UP_MSVENDOR:
- goto ignore;
+
+ /* special case - Chicony Chicony KU-0418 tactical pad */
+ if (device->vendor == 0x04f2 && device->product == 0x0418) {
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ case 0xff01: map_key_clear(BTN_1); break;
+ case 0xff02: map_key_clear(BTN_2); break;
+ case 0xff03: map_key_clear(BTN_3); break;
+ case 0xff04: map_key_clear(BTN_4); break;
+ case 0xff05: map_key_clear(BTN_5); break;
+ case 0xff06: map_key_clear(BTN_6); break;
+ case 0xff07: map_key_clear(BTN_7); break;
+ case 0xff08: map_key_clear(BTN_8); break;
+ case 0xff09: map_key_clear(BTN_9); break;
+ case 0xff0a: map_key_clear(BTN_A); break;
+ case 0xff0b: map_key_clear(BTN_B); break;
+ default: goto ignore;
+ }
+ } else {
+ goto ignore;
+ }
+ break;
case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
@@ -704,10 +756,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
break;
- case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
-
+ case HID_UP_LOGIVENDOR:
set_bit(EV_REP, input->evbit);
switch(usage->hid & HID_USAGE) {
+ /* Reported on Logitech Ultra X Media Remote */
case 0x004: map_key_clear(KEY_AGAIN); break;
case 0x00d: map_key_clear(KEY_HOME); break;
case 0x024: map_key_clear(KEY_SHUFFLE); break;
@@ -725,6 +777,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x04d: map_key_clear(KEY_SUBTITLE); break;
case 0x051: map_key_clear(KEY_RED); break;
case 0x052: map_key_clear(KEY_CLOSE); break;
+
+ /* Reported on Petalynx Maxter remote */
+ case 0x05a: map_key_clear(KEY_TEXT); break;
+ case 0x05b: map_key_clear(KEY_RED); break;
+ case 0x05c: map_key_clear(KEY_GREEN); break;
+ case 0x05d: map_key_clear(KEY_YELLOW); break;
+ case 0x05e: map_key_clear(KEY_BLUE); break;
+
default: goto ignore;
}
break;
@@ -818,16 +878,24 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
field->dpad = usage->code;
}
+ /* for those devices which produce Consumer volume usage as relative,
+ * we emulate pressing volumeup/volumedown appropriate number of times
+ * in hidinput_hid_event()
+ */
+ if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+ (usage->code == ABS_VOLUME)) {
+ set_bit(KEY_VOLUMEUP, input->keybit);
+ set_bit(KEY_VOLUMEDOWN, input->keybit);
+ }
+
hid_resolv_event(usage->type, usage->code);
-#ifdef CONFIG_HID_DEBUG
- printk("\n");
-#endif
+
+ dbg_hid_line("\n");
+
return;
ignore:
-#ifdef CONFIG_HID_DEBUG
- printk("IGNORED\n");
-#endif
+ dbg_hid_line("IGNORED\n");
return;
}
@@ -896,18 +964,33 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
}
if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
- dbg("Maximum Effects - %d",value);
+ dbg_hid("Maximum Effects - %d\n",value);
return;
}
if (usage->hid == (HID_UP_PID | 0x7fUL)) {
- dbg("PID Pool Report\n");
+ dbg_hid("PID Pool Report\n");
return;
}
if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
return;
+ if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+ (usage->code == ABS_VOLUME)) {
+ int count = abs(value);
+ int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ input_event(input, EV_KEY, direction, 1);
+ input_sync(input);
+ input_event(input, EV_KEY, direction, 0);
+ input_sync(input);
+ }
+ return;
+ }
+
input_event(input, usage->type, usage->code, value);
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
@@ -976,7 +1059,7 @@ int hidinput_connect(struct hid_device *hid)
if (IS_INPUT_APPLICATION(hid->collection[i].usage))
break;
- if (i == hid->maxcollection)
+ if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
return -1;
if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
@@ -994,7 +1077,7 @@ int hidinput_connect(struct hid_device *hid)
if (!hidinput || !input_dev) {
kfree(hidinput);
input_free_device(input_dev);
- err("Out of memory during hid input probe");
+ err_hid("Out of memory during hid input probe");
return -1;
}
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index d91b9dac6dff..3afa4a5035b7 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -60,6 +60,12 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
" quirks=vendorID:productID:quirks"
" where vendorID, productID, and quirks are all in"
" 0x-prefixed hex");
+static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
+module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
+MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
+ " rdesc_quirks=vendorID:productID:rdesc_quirks"
+ " where vendorID, productID, and rdesc_quirks are all in"
+ " 0x-prefixed hex");
/*
* Input submission and I/O error handler.
*/
@@ -127,7 +133,7 @@ static void hid_reset(struct work_struct *work)
hid_io_error(hid);
break;
default:
- err("can't reset device, %s-%s/input%d, status %d",
+ err_hid("can't reset device, %s-%s/input%d, status %d",
hid_to_usb_dev(hid)->bus->bus_name,
hid_to_usb_dev(hid)->devpath,
usbhid->ifnum, rc);
@@ -220,7 +226,7 @@ static void hid_irq_in(struct urb *urb)
if (status) {
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
if (status != -EPERM) {
- err("can't resubmit intr, %s-%s/input%d, status %d",
+ err_hid("can't resubmit intr, %s-%s/input%d, status %d",
hid_to_usb_dev(hid)->bus->bus_name,
hid_to_usb_dev(hid)->devpath,
usbhid->ifnum, status);
@@ -240,10 +246,10 @@ static int hid_submit_out(struct hid_device *hid)
usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
usbhid->urbout->dev = hid_to_usb_dev(hid);
- dbg("submitting out urb");
+ dbg_hid("submitting out urb\n");
if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
- err("usb_submit_urb(out) failed");
+ err_hid("usb_submit_urb(out) failed");
return -1;
}
@@ -287,12 +293,12 @@ static int hid_submit_ctrl(struct hid_device *hid)
usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
usbhid->cr->wLength = cpu_to_le16(len);
- dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
+ dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n",
usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
- err("usb_submit_urb(ctrl) failed");
+ err_hid("usb_submit_urb(ctrl) failed");
return -1;
}
@@ -474,7 +480,7 @@ int usbhid_wait_io(struct hid_device *hid)
if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
10*HZ)) {
- dbg("timeout waiting for ctrl or out queue to clear");
+ dbg_hid("timeout waiting for ctrl or out queue to clear\n");
return -1;
}
@@ -633,20 +639,6 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
}
/*
- * Cherry Cymotion keyboard have an invalid HID report descriptor,
- * that needs fixing before we can parse it.
- */
-
-static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
-{
- if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
- info("Fixing up Cherry Cymotion report descriptor");
- rdesc[11] = rdesc[16] = 0xff;
- rdesc[12] = rdesc[17] = 0x03;
- }
-}
-
-/*
* Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
* to "operational". Without this, the ps3 controller will not report any
* events.
@@ -667,51 +659,11 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
USB_CTRL_GET_TIMEOUT);
if (result < 0)
- err("%s failed: %d\n", __func__, result);
+ err_hid("%s failed: %d\n", __func__, result);
kfree(buf);
}
-/*
- * Certain Logitech keyboards send in report #3 keys which are far
- * above the logical maximum described in descriptor. This extends
- * the original value of 0x28c of logical maximum to 0x104d
- */
-static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
-{
- if (rsize >= 90 && rdesc[83] == 0x26
- && rdesc[84] == 0x8c
- && rdesc[85] == 0x02) {
- info("Fixing up Logitech keyboard report descriptor");
- rdesc[84] = rdesc[89] = 0x4d;
- rdesc[85] = rdesc[90] = 0x10;
- }
-}
-
-/*
- * Some USB barcode readers from cypress have usage min and usage max in
- * the wrong order
- */
-static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
-{
- short fixed = 0;
- int i;
-
- for (i = 0; i < rsize - 4; i++) {
- if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
- unsigned char tmp;
-
- rdesc[i] = 0x19; rdesc[i+2] = 0x29;
- tmp = rdesc[i+3];
- rdesc[i+3] = rdesc[i+1];
- rdesc[i+1] = tmp;
- }
- }
-
- if (fixed)
- info("Fixing up Cypress report descriptor");
-}
-
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
struct usb_host_interface *interface = intf->cur_altsetting;
@@ -746,7 +698,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
(!interface->desc.bNumEndpoints ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
- dbg("class descriptor not present\n");
+ dbg_hid("class descriptor not present\n");
return NULL;
}
@@ -755,41 +707,34 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
- dbg("weird size of report descriptor (%u)", rsize);
+ dbg_hid("weird size of report descriptor (%u)\n", rsize);
return NULL;
}
if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
- dbg("couldn't allocate rdesc memory");
+ dbg_hid("couldn't allocate rdesc memory\n");
return NULL;
}
hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
- dbg("reading report descriptor failed");
+ dbg_hid("reading report descriptor failed\n");
kfree(rdesc);
return NULL;
}
- if ((quirks & HID_QUIRK_CYMOTION))
- hid_fixup_cymotion_descriptor(rdesc, rsize);
+ usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct), rdesc,
+ rsize, rdesc_quirks_param);
- if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
- hid_fixup_logitech_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
- hid_fixup_cypress_descriptor(rdesc, rsize);
-
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
+ dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
- printk(" %02x", (unsigned char) rdesc[n]);
- printk("\n");
-#endif
+ dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
+ dbg_hid_line("\n");
if (!(hid = hid_parse_report(rdesc, n))) {
- dbg("parsing report descriptor failed");
+ dbg_hid("parsing report descriptor failed\n");
kfree(rdesc);
return NULL;
}
@@ -861,7 +806,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
}
if (!usbhid->urbin) {
- err("couldn't find an input interrupt endpoint");
+ err_hid("couldn't find an input interrupt endpoint");
goto fail;
}
@@ -956,7 +901,7 @@ static void hid_disconnect(struct usb_interface *intf)
usb_kill_urb(usbhid->urbctrl);
del_timer_sync(&usbhid->io_retry);
- flush_scheduled_work();
+ cancel_work_sync(&usbhid->reset_work);
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(hid);
@@ -978,7 +923,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
int i;
char *c;
- dbg("HID probe called for ifnum %d",
+ dbg_hid("HID probe called for ifnum %d\n",
intf->altsetting->desc.bInterfaceNumber);
if (!(hid = usb_hid_configure(intf)))
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c
index c5cd4107d6af..4b7ab6a46d93 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/usbhid/hid-lgff.c
@@ -78,7 +78,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[1] = 0x08;
report->field[0]->value[2] = x;
report->field[0]->value[3] = y;
- dbg("(x, y)=(%04x, %04x)", x, y);
+ dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
@@ -93,7 +93,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[1] = 0x00;
report->field[0]->value[2] = left;
report->field[0]->value[3] = right;
- dbg("(left, right)=(%04x, %04x)", left, right);
+ dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
}
@@ -113,20 +113,20 @@ int hid_lgff_init(struct hid_device* hid)
/* Find the report to use */
if (list_empty(report_list)) {
- err("No output report found");
+ err_hid("No output report found");
return -1;
}
/* Check that the report looks ok */
report = list_entry(report_list->next, struct hid_report, list);
if (!report) {
- err("NULL output report");
+ err_hid("NULL output report");
return -1;
}
field = report->field[0];
if (!field) {
- err("NULL field");
+ err_hid("NULL field");
return -1;
}
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index f5a90e950e6b..011326178c06 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -738,6 +738,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
+ pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
pidff->set_effect[PID_START_DELAY].value[0] = 0;
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index f6c4145dc202..775b9f3b8ce3 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -105,6 +105,9 @@
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+#define USB_VENDOR_ID_GAMERON 0x0810
+#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
+
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@@ -196,8 +199,10 @@
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
+#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
+#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
@@ -209,6 +214,13 @@
#define USB_DEVICE_ID_MGE_UPS 0xffff
#define USB_DEVICE_ID_MGE_UPS1 0x0001
+#define USB_VENDOR_ID_MICROSOFT 0x045e
+#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
+
+#define USB_VENDOR_ID_NCR 0x0404
+#define USB_DEVICE_ID_NCR_FIRST 0x0300
+#define USB_DEVICE_ID_NCR_LAST 0x03ff
+
#define USB_VENDOR_ID_NEC 0x073e
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
@@ -220,6 +232,9 @@
#define USB_VENDOR_ID_PANTHERLORD 0x0810
#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
+#define USB_VENDOR_ID_PETALYNX 0x18b1
+#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
+
#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
@@ -278,6 +293,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
+ { USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -285,11 +301,10 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
- { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
-
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
{ USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
@@ -409,9 +424,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
@@ -426,6 +439,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -448,9 +462,28 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
+ { 0, 0 }
+};
+
+/* Quirks for devices which require report descriptor fixup go here */
+static const struct hid_rdesc_blacklist {
+ __u16 idVendor;
+ __u16 idProduct;
+ __u32 quirks;
+} hid_rdesc_blacklist[] = {
+
+ { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
+
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
+
+ { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
+
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
{ 0, 0 }
};
@@ -493,7 +526,7 @@ static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor,
}
if (bl_entry != NULL)
- dbg("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+ dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
bl_entry->quirks, bl_entry->idVendor,
bl_entry->idProduct);
@@ -521,13 +554,13 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
int list_edited = 0;
if (!idVendor) {
- dbg("Cannot add a quirk with idVendor = 0");
+ dbg_hid("Cannot add a quirk with idVendor = 0\n");
return -EINVAL;
}
q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);
if (!q_new) {
- dbg("Could not allocate quirks_list_struct");
+ dbg_hid("Could not allocate quirks_list_struct\n");
return -ENOMEM;
}
@@ -559,7 +592,6 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
return 0;
}
-
/**
* usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
*
@@ -643,7 +675,7 @@ static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor,
bl_entry = &hid_blacklist[n];
if (bl_entry != NULL)
- dbg("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+ dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
bl_entry->quirks, bl_entry->idVendor,
bl_entry->idProduct);
return bl_entry;
@@ -675,6 +707,12 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
return HID_QUIRK_IGNORE;
+ /* NCR devices must not be queried for reports */
+ if (idVendor == USB_VENDOR_ID_NCR &&
+ idProduct >= USB_DEVICE_ID_NCR_FIRST &&
+ idProduct <= USB_DEVICE_ID_NCR_LAST)
+ return HID_QUIRK_NOGET;
+
down_read(&dquirks_rwsem);
bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
if (!bl_entry)
@@ -686,3 +724,126 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
return quirks;
}
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
+{
+ if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+ printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
+ rdesc[11] = rdesc[16] = 0xff;
+ rdesc[12] = rdesc[17] = 0x03;
+ }
+}
+
+
+/*
+ * Certain Logitech keyboards send in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
+{
+ if (rsize >= 90 && rdesc[83] == 0x26
+ && rdesc[84] == 0x8c
+ && rdesc[85] == 0x02) {
+ printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
+ rdesc[84] = rdesc[89] = 0x4d;
+ rdesc[85] = rdesc[90] = 0x10;
+ }
+}
+
+/* Petalynx Maxter Remote has maximum for consumer page set too low */
+static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
+{
+ if (rsize >= 60 && rdesc[39] == 0x2a
+ && rdesc[40] == 0xf5
+ && rdesc[41] == 0x00
+ && rdesc[59] == 0x26
+ && rdesc[60] == 0xf9
+ && rdesc[61] == 0x00) {
+ printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
+ rdesc[60] = 0xfa;
+ rdesc[40] = 0xfa;
+ }
+}
+
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
+{
+ short fixed = 0;
+ int i;
+
+ for (i = 0; i < rsize - 4; i++) {
+ if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
+ unsigned char tmp;
+
+ rdesc[i] = 0x19; rdesc[i+2] = 0x29;
+ tmp = rdesc[i+3];
+ rdesc[i+3] = rdesc[i+1];
+ rdesc[i+1] = tmp;
+ }
+ }
+
+ if (fixed)
+ printk(KERN_INFO "Fixing up Cypress report descriptor\n");
+}
+
+
+static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+{
+ if ((quirks & HID_QUIRK_RDESC_CYMOTION))
+ usbhid_fixup_cymotion_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_LOGITECH)
+ usbhid_fixup_logitech_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
+ usbhid_fixup_cypress_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_PETALYNX)
+ usbhid_fixup_petalynx_descriptor(rdesc, rsize);
+}
+
+/**
+ * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
+ *
+ * Description:
+ * Walks the hid_rdesc_blacklist[] array and checks whether the device
+ * is known to have broken report descriptor that needs to be fixed up
+ * prior to entering the HID parser
+ *
+ * Returns: nothing
+ */
+void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
+ char *rdesc, unsigned rsize, char **quirks_param)
+{
+ int n, m;
+ u16 paramVendor, paramProduct;
+ u32 quirks;
+
+ /* static rdesc quirk entries */
+ for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
+ if (hid_rdesc_blacklist[n].idVendor == idVendor &&
+ hid_rdesc_blacklist[n].idProduct == idProduct)
+ __usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
+ rdesc, rsize);
+
+ /* runtime rdesc quirk entries handling */
+ for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
+ m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
+ &paramVendor, &paramProduct, &quirks);
+
+ if (m != 3)
+ printk(KERN_WARNING
+ "Could not parse HID quirk module param %s\n",
+ quirks_param[n]);
+ else if (paramVendor == idVendor && paramProduct == idProduct)
+ __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
+ }
+
+}
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
index ab5ba6ef891c..555bb48b4295 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/usbhid/hid-tmff.c
@@ -70,7 +70,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
tmff->rumble->value[0] = left;
tmff->rumble->value[1] = right;
- dbg("(left,right)=(%08x, %08x)", left, right);
+ dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
return 0;
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c
index a7fbffcdaf36..5a688274f6a3 100644
--- a/drivers/hid/usbhid/hid-zpff.c
+++ b/drivers/hid/usbhid/hid-zpff.c
@@ -21,10 +21,6 @@
*/
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg)
-
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h>
@@ -49,14 +45,14 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
left = effect->u.rumble.strong_magnitude;
right = effect->u.rumble.weak_magnitude;
- debug("called with 0x%04x 0x%04x", left, right);
+ dbg_hid("called with 0x%04x 0x%04x\n", left, right);
left = left * 0x7f / 0xffff;
right = right * 0x7f / 0xffff;
zpff->report->field[2]->value[0] = left;
zpff->report->field[3]->value[0] = right;
- debug("running with 0x%02x 0x%02x", left, right);
+ dbg_hid("running with 0x%02x 0x%02x\n", left, right);
usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
return 0;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 488d61bdbf2c..e793127f971e 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -779,7 +779,7 @@ int hiddev_connect(struct hid_device *hid)
retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) {
- err("Not able to get a minor for this device.");
+ err_hid("Not able to get a minor for this device.");
kfree(hiddev);
return -1;
}
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 130978780713..b76b02f7b52d 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -125,7 +125,7 @@ static void usb_kbd_irq(struct urb *urb)
resubmit:
i = usb_submit_urb (urb, GFP_ATOMIC);
if (i)
- err ("can't resubmit intr, %s-%s/input0, status %d",
+ err_hid ("can't resubmit intr, %s-%s/input0, status %d",
kbd->usbdev->bus->bus_name,
kbd->usbdev->devpath, i);
}
@@ -151,7 +151,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type,
*(kbd->leds) = kbd->newleds;
kbd->led->dev = kbd->usbdev;
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
- err("usb_submit_urb(leds) failed");
+ err_hid("usb_submit_urb(leds) failed");
return 0;
}
@@ -169,7 +169,7 @@ static void usb_kbd_led(struct urb *urb)
*(kbd->leds) = kbd->newleds;
kbd->led->dev = kbd->usbdev;
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
- err("usb_submit_urb(leds) failed");
+ err_hid("usb_submit_urb(leds) failed");
}
static int usb_kbd_open(struct input_dev *dev)
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 66f826252aee..444a0b84f5bd 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -448,23 +448,21 @@ static int icside_dma_test_irq(ide_drive_t *drive)
ICS_ARCIN_V6_INTRSTAT_1)) & 1;
}
-static int icside_dma_timeout(ide_drive_t *drive)
+static void icside_dma_timeout(ide_drive_t *drive)
{
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
if (icside_dma_test_irq(drive))
- return 0;
+ return;
- ide_dump_status(drive, "DMA timeout",
- HWIF(drive)->INB(IDE_STATUS_REG));
+ ide_dump_status(drive, "DMA timeout", HWIF(drive)->INB(IDE_STATUS_REG));
- return icside_dma_end(drive);
+ icside_dma_end(drive);
}
-static int icside_dma_lostirq(ide_drive_t *drive)
+static void icside_dma_lost_irq(ide_drive_t *drive)
{
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
- return 1;
}
static void icside_dma_init(ide_hwif_t *hwif)
@@ -490,8 +488,8 @@ static void icside_dma_init(ide_hwif_t *hwif)
hwif->dma_start = icside_dma_start;
hwif->ide_dma_end = icside_dma_end;
hwif->ide_dma_test_irq = icside_dma_test_irq;
- hwif->ide_dma_timeout = icside_dma_timeout;
- hwif->ide_dma_lostirq = icside_dma_lostirq;
+ hwif->dma_timeout = icside_dma_timeout;
+ hwif->dma_lost_irq = icside_dma_lost_irq;
hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index ca0341c05e55..886091bc7db0 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -819,7 +819,7 @@ init_e100_ide (void)
hwif->dma_host_off = &cris_dma_off;
hwif->dma_host_on = &cris_dma_on;
hwif->dma_off_quietly = &cris_dma_off;
- hwif->udma_four = 0;
+ hwif->cbl = ATA_CBL_PATA40;
hwif->ultra_mask = cris_ultra_mask;
hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
hwif->autodma = 1;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 252ab8295edf..1486eb212ccc 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -481,7 +481,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
else
printk(" Unknown Error Type: ");
- if (sense->sense_key < ARY_LEN(sense_key_texts))
+ if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
s = sense_key_texts[sense->sense_key];
printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
@@ -491,7 +491,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
sense->ascq);
s = buf;
} else {
- int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
+ int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
unsigned long key = (sense->sense_key << 16);
key |= (sense->asc << 8);
if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
@@ -524,7 +524,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
if (failed_command != NULL) {
- int lo=0, mid, hi= ARY_LEN (packet_command_texts);
+ int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
s = NULL;
while (hi > lo) {
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index ad1f2ed14a37..228b29c5d2e4 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -498,8 +498,6 @@ struct cdrom_info {
* Descriptions of ATAPI error codes.
*/
-#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
-
/* This stuff should be in cdrom.h, since it is now generic... */
/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index dc2175c81f5e..b1304a7f3e0a 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1190,11 +1190,11 @@ static int idedisk_ioctl(struct inode *inode, struct file *file,
return generic_ide_ioctl(drive, file, bdev, cmd, arg);
read_val:
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
err = *val;
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
set_val:
@@ -1204,9 +1204,9 @@ set_val:
if (!capable(CAP_SYS_ADMIN))
err = -EACCES;
else {
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
err = setfunc(drive, arg);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
}
return err;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index ead141e2db9e..5fe1d72ab451 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -91,45 +91,45 @@
static const struct drive_list_entry drive_whitelist [] = {
- { "Micropolis 2112A" , "ALL" },
- { "CONNER CTMA 4000" , "ALL" },
- { "CONNER CTT8000-A" , "ALL" },
- { "ST34342A" , "ALL" },
+ { "Micropolis 2112A" , NULL },
+ { "CONNER CTMA 4000" , NULL },
+ { "CONNER CTT8000-A" , NULL },
+ { "ST34342A" , NULL },
{ NULL , NULL }
};
static const struct drive_list_entry drive_blacklist [] = {
- { "WDC AC11000H" , "ALL" },
- { "WDC AC22100H" , "ALL" },
- { "WDC AC32500H" , "ALL" },
- { "WDC AC33100H" , "ALL" },
- { "WDC AC31600H" , "ALL" },
+ { "WDC AC11000H" , NULL },
+ { "WDC AC22100H" , NULL },
+ { "WDC AC32500H" , NULL },
+ { "WDC AC33100H" , NULL },
+ { "WDC AC31600H" , NULL },
{ "WDC AC32100H" , "24.09P07" },
{ "WDC AC23200L" , "21.10N21" },
- { "Compaq CRD-8241B" , "ALL" },
- { "CRD-8400B" , "ALL" },
- { "CRD-8480B", "ALL" },
- { "CRD-8482B", "ALL" },
- { "CRD-84" , "ALL" },
- { "SanDisk SDP3B" , "ALL" },
- { "SanDisk SDP3B-64" , "ALL" },
- { "SANYO CD-ROM CRD" , "ALL" },
- { "HITACHI CDR-8" , "ALL" },
- { "HITACHI CDR-8335" , "ALL" },
- { "HITACHI CDR-8435" , "ALL" },
- { "Toshiba CD-ROM XM-6202B" , "ALL" },
- { "TOSHIBA CD-ROM XM-1702BC", "ALL" },
- { "CD-532E-A" , "ALL" },
- { "E-IDE CD-ROM CR-840", "ALL" },
- { "CD-ROM Drive/F5A", "ALL" },
- { "WPI CDD-820", "ALL" },
- { "SAMSUNG CD-ROM SC-148C", "ALL" },
- { "SAMSUNG CD-ROM SC", "ALL" },
- { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
- { "_NEC DV5800A", "ALL" },
+ { "Compaq CRD-8241B" , NULL },
+ { "CRD-8400B" , NULL },
+ { "CRD-8480B", NULL },
+ { "CRD-8482B", NULL },
+ { "CRD-84" , NULL },
+ { "SanDisk SDP3B" , NULL },
+ { "SanDisk SDP3B-64" , NULL },
+ { "SANYO CD-ROM CRD" , NULL },
+ { "HITACHI CDR-8" , NULL },
+ { "HITACHI CDR-8335" , NULL },
+ { "HITACHI CDR-8435" , NULL },
+ { "Toshiba CD-ROM XM-6202B" , NULL },
+ { "TOSHIBA CD-ROM XM-1702BC", NULL },
+ { "CD-532E-A" , NULL },
+ { "E-IDE CD-ROM CR-840", NULL },
+ { "CD-ROM Drive/F5A", NULL },
+ { "WPI CDD-820", NULL },
+ { "SAMSUNG CD-ROM SC-148C", NULL },
+ { "SAMSUNG CD-ROM SC", NULL },
+ { "ATAPI CD-ROM DRIVE 40X MAXIMUM", NULL },
+ { "_NEC DV5800A", NULL },
{ "SAMSUNG CD-ROM SN-124", "N001" },
- { "Seagate STT20000A", "ALL" },
+ { "Seagate STT20000A", NULL },
{ NULL , NULL }
};
@@ -147,8 +147,8 @@ int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *driv
{
for ( ; drive_table->id_model ; drive_table++)
if ((!strcmp(drive_table->id_model, id->model)) &&
- ((strstr(id->fw_rev, drive_table->id_firmware)) ||
- (!strcmp(drive_table->id_firmware, "ALL"))))
+ (!drive_table->id_firmware ||
+ strstr(id->fw_rev, drive_table->id_firmware)))
return 1;
return 0;
}
@@ -702,8 +702,22 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
mask = id->dma_mword & hwif->mwdma_mask;
break;
case XFER_SW_DMA_0:
- if (id->field_valid & 2)
+ if (id->field_valid & 2) {
mask = id->dma_1word & hwif->swdma_mask;
+ } else if (id->tDMA) {
+ /*
+ * ide_fix_driveid() doesn't convert ->tDMA to the
+ * CPU endianness so we need to do it here
+ */
+ u8 mode = le16_to_cpu(id->tDMA);
+
+ /*
+ * if the mode is valid convert it to the mask
+ * (the maximum allowed mode is XFER_SW_DMA_2)
+ */
+ if (mode <= 2)
+ mask = ((2 << mode) - 1) & hwif->swdma_mask;
+ }
break;
default:
BUG();
@@ -847,27 +861,27 @@ int ide_set_dma(ide_drive_t *drive)
return rc;
}
-EXPORT_SYMBOL_GPL(ide_set_dma);
-
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-int __ide_dma_lostirq (ide_drive_t *drive)
+void ide_dma_lost_irq (ide_drive_t *drive)
{
printk("%s: DMA interrupt recovery\n", drive->name);
- return 1;
}
-EXPORT_SYMBOL(__ide_dma_lostirq);
+EXPORT_SYMBOL(ide_dma_lost_irq);
-int __ide_dma_timeout (ide_drive_t *drive)
+void ide_dma_timeout (ide_drive_t *drive)
{
+ ide_hwif_t *hwif = HWIF(drive);
+
printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
- if (HWIF(drive)->ide_dma_test_irq(drive))
- return 0;
- return HWIF(drive)->ide_dma_end(drive);
+ if (hwif->ide_dma_test_irq(drive))
+ return;
+
+ hwif->ide_dma_end(drive);
}
-EXPORT_SYMBOL(__ide_dma_timeout);
+EXPORT_SYMBOL(ide_dma_timeout);
/*
* Needed for allowing full modular support of ide-driver
@@ -1018,10 +1032,10 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
hwif->ide_dma_end = &__ide_dma_end;
if (!hwif->ide_dma_test_irq)
hwif->ide_dma_test_irq = &__ide_dma_test_irq;
- if (!hwif->ide_dma_timeout)
- hwif->ide_dma_timeout = &__ide_dma_timeout;
- if (!hwif->ide_dma_lostirq)
- hwif->ide_dma_lostirq = &__ide_dma_lostirq;
+ if (!hwif->dma_timeout)
+ hwif->dma_timeout = &ide_dma_timeout;
+ if (!hwif->dma_lost_irq)
+ hwif->dma_lost_irq = &ide_dma_lost_irq;
if (hwif->chipset != ide_trm290) {
u8 dma_stat = hwif->INB(hwif->dma_status);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index bfe8f1b712ba..c5b5011da56e 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -1350,7 +1350,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
hwif->INB(IDE_STATUS_REG));
} else {
printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
- (void) hwif->ide_dma_timeout(drive);
+ hwif->dma_timeout(drive);
}
/*
@@ -1466,7 +1466,7 @@ void ide_timer_expiry (unsigned long data)
startstop = handler(drive);
} else if (drive_is_ready(drive)) {
if (drive->waiting_for_dma)
- (void) hwgroup->hwif->ide_dma_lostirq(drive);
+ hwgroup->hwif->dma_lost_irq(drive);
(void)ide_ack_intr(hwif);
printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
startstop = handler(drive);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index f0be5f665a0e..92578b6832e9 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -574,7 +574,10 @@ u8 eighty_ninty_three (ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id = drive->id;
- if (hwif->udma_four == 0)
+ if (hwif->cbl == ATA_CBL_PATA40_SHORT)
+ return 1;
+
+ if (hwif->cbl != ATA_CBL_PATA80)
goto no_80w;
/* Check for SATA but only if we are ATA5 or higher */
@@ -600,7 +603,8 @@ no_80w:
printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
"limiting max speed to UDMA33\n",
- drive->name, hwif->udma_four ? "drive" : "host");
+ drive->name,
+ hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
drive->udma33_warned = 1;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index f5ce22c38f82..cc5801399467 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -144,7 +144,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
local_irq_enable();
ide_fix_driveid(id);
-#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
+#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
/*
* EATA SCSI controllers do a hardware ATA emulation:
* Ignore them if there is a driver for them available.
@@ -154,7 +154,7 @@ static inline void do_identify (ide_drive_t *drive, u8 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 /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */
/*
* WIN_IDENTIFY returns little-endian info,
@@ -1025,7 +1025,7 @@ static int init_irq (ide_hwif_t *hwif)
BUG_ON(irqs_disabled());
BUG_ON(hwif == NULL);
- down(&ide_cfg_sem);
+ mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL;
#if MAX_HWIFS > 1
/*
@@ -1154,7 +1154,7 @@ static int init_irq (ide_hwif_t *hwif)
printk(" (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name);
printk("\n");
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
return 0;
out_unlink:
spin_lock_irq(&ide_lock);
@@ -1177,7 +1177,7 @@ out_unlink:
}
spin_unlock_irq(&ide_lock);
out_up:
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
return 1;
}
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index ea94c9aa1220..fc1d8ae6a803 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -156,7 +156,7 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int d
{
ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
while ((*p) && strcmp((*p)->name, name) < 0)
p = &((*p)->next);
if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
@@ -177,10 +177,10 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int d
if (auto_remove)
setting->auto_remove = 1;
*p = setting;
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return 0;
abort:
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
kfree(setting);
return -1;
}
@@ -224,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
*
* Automatically remove all the driver specific settings for this
* drive. This function may not be called from IRQ context. The
- * caller must hold ide_setting_sem.
+ * caller must hold ide_setting_mtx.
*/
static void auto_remove_settings (ide_drive_t *drive)
@@ -269,7 +269,7 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
* @setting: drive setting
*
* Read a drive setting and return the value. The caller
- * must hold the ide_setting_sem when making this call.
+ * must hold the ide_setting_mtx when making this call.
*
* BUGS: the data return and error are the same return value
* so an error -EINVAL and true return of the same value cannot
@@ -306,7 +306,7 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
* @val: value
*
* Write a drive setting if it is possible. The caller
- * must hold the ide_setting_sem when making this call.
+ * must hold the ide_setting_mtx when making this call.
*
* BUGS: the data return and error are the same return value
* so an error -EINVAL and true return of the same value cannot
@@ -367,7 +367,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
* @drive: drive being configured
*
* Add the generic parts of the system settings to the /proc files.
- * The caller must not be holding the ide_setting_sem.
+ * The caller must not be holding the ide_setting_mtx.
*/
void ide_add_generic_settings (ide_drive_t *drive)
@@ -408,7 +408,7 @@ static int proc_ide_read_settings
proc_ide_settings_warn();
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
while(setting) {
@@ -428,7 +428,7 @@ static int proc_ide_read_settings
setting = setting->next;
}
len = out - page;
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
@@ -508,16 +508,16 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
++p;
}
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
setting = ide_find_setting_by_name(drive, name);
if (!setting)
{
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
goto parse_error;
}
if (for_real)
ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
} while (!for_real++);
free_page((unsigned long)buf);
@@ -705,7 +705,7 @@ EXPORT_SYMBOL(ide_proc_register_driver);
* Clean up the driver specific /proc files and IDE settings
* for a given drive.
*
- * Takes ide_setting_sem and ide_lock.
+ * Takes ide_setting_mtx and ide_lock.
* Caller must hold none of the locks.
*/
@@ -715,10 +715,10 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
ide_remove_proc_entries(drive->proc, driver->proc);
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
/*
- * ide_setting_sem protects the settings list
+ * ide_setting_mtx protects the settings list
* ide_lock protects the use of settings
*
* so we need to hold both, ide_settings_sem because we want to
@@ -726,11 +726,11 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
* a setting out that is being used.
*
* OTOH both ide_{read,write}_setting are only ever used under
- * ide_setting_sem.
+ * ide_setting_mtx.
*/
auto_remove_settings(drive);
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
EXPORT_SYMBOL(ide_proc_unregister_driver);
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index c0864b1e9228..e6cb8593b5ba 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -102,66 +102,16 @@ static struct ide_timing ide_timing[] = {
#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
#define XFER_MODE 0xf0
-#define XFER_UDMA_133 0x48
-#define XFER_UDMA_100 0x44
-#define XFER_UDMA_66 0x42
-#define XFER_UDMA 0x40
#define XFER_MWDMA 0x20
-#define XFER_SWDMA 0x10
#define XFER_EPIO 0x01
#define XFER_PIO 0x00
-static short ide_find_best_mode(ide_drive_t *drive, int map)
+static short ide_find_best_pio_mode(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
short best = 0;
- if (!id)
- return XFER_PIO_SLOW;
-
- if ((map & XFER_UDMA) && (id->field_valid & 4)) { /* Want UDMA and UDMA bitmap valid */
-
- if ((map & XFER_UDMA_133) == XFER_UDMA_133)
- if ((best = (id->dma_ultra & 0x0040) ? XFER_UDMA_6 : 0)) return best;
-
- if ((map & XFER_UDMA_100) == XFER_UDMA_100)
- if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
-
- if ((map & XFER_UDMA_66) == XFER_UDMA_66)
- if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 :
- (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
-
- if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
- (id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
- (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : 0)) return best;
- }
-
- if ((map & XFER_MWDMA) && (id->field_valid & 2)) { /* Want MWDMA and drive has EIDE fields */
-
- if ((best = (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
- (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
- (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : 0)) return best;
- }
-
- if (map & XFER_SWDMA) { /* Want SWDMA */
-
- if (id->field_valid & 2) { /* EIDE SWDMA */
-
- if ((best = (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
- (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
- (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0)) return best;
- }
-
- if (id->capability & 1) { /* Pre-EIDE style SWDMA */
-
- if ((best = (id->tDMA == 2) ? XFER_SW_DMA_2 :
- (id->tDMA == 1) ? XFER_SW_DMA_1 :
- (id->tDMA == 0) ? XFER_SW_DMA_0 : 0)) return best;
- }
- }
-
-
- if ((map & XFER_EPIO) && (id->field_valid & 2)) { /* EIDE PIO modes */
+ if (id->field_valid & 2) { /* EIDE PIO modes */
if ((best = (drive->id->eide_pio_modes & 4) ? XFER_PIO_5 :
(drive->id->eide_pio_modes & 2) ? XFER_PIO_4 :
@@ -262,7 +212,7 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
*/
if ((speed & XFER_MODE) != XFER_PIO) {
- ide_timing_compute(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO), &p, T, UT);
+ ide_timing_compute(drive, ide_find_best_pio_mode(drive), &p, T, UT);
ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 0cd76bf66833..c948a5c17a5d 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -169,7 +169,7 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
static int idebus_parameter; /* holds the "idebus=" parameter */
static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
-DECLARE_MUTEX(ide_cfg_sem);
+DEFINE_MUTEX(ide_cfg_mtx);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
@@ -460,6 +460,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->mwdma_mask = tmp_hwif->mwdma_mask;
hwif->swdma_mask = tmp_hwif->swdma_mask;
+ hwif->cbl = tmp_hwif->cbl;
+
hwif->chipset = tmp_hwif->chipset;
hwif->hold = tmp_hwif->hold;
@@ -496,8 +498,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq;
hwif->dma_host_on = tmp_hwif->dma_host_on;
hwif->dma_host_off = tmp_hwif->dma_host_off;
- hwif->ide_dma_lostirq = tmp_hwif->ide_dma_lostirq;
- hwif->ide_dma_timeout = tmp_hwif->ide_dma_timeout;
+ hwif->dma_lost_irq = tmp_hwif->dma_lost_irq;
+ hwif->dma_timeout = tmp_hwif->dma_timeout;
hwif->OUTB = tmp_hwif->OUTB;
hwif->OUTBSYNC = tmp_hwif->OUTBSYNC;
@@ -533,7 +535,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->extra_base = tmp_hwif->extra_base;
hwif->extra_ports = tmp_hwif->extra_ports;
hwif->autodma = tmp_hwif->autodma;
- hwif->udma_four = tmp_hwif->udma_four;
hwif->hwif_data = tmp_hwif->hwif_data;
}
@@ -564,7 +565,7 @@ void ide_unregister(unsigned int index)
{
ide_drive_t *drive;
ide_hwif_t *hwif, *g;
- static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
+ static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
ide_hwgroup_t *hwgroup;
int irq_count = 0, unit;
@@ -572,7 +573,7 @@ void ide_unregister(unsigned int index)
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
- down(&ide_cfg_sem);
+ mutex_lock(&ide_cfg_mtx);
spin_lock_irq(&ide_lock);
hwif = &ide_hwifs[index];
if (!hwif->present)
@@ -679,7 +680,7 @@ void ide_unregister(unsigned int index)
abort:
spin_unlock_irq(&ide_lock);
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
}
EXPORT_SYMBOL(ide_unregister);
@@ -817,9 +818,9 @@ EXPORT_SYMBOL(ide_register_hw);
* Locks for IDE setting functionality
*/
-DECLARE_MUTEX(ide_setting_sem);
+DEFINE_MUTEX(ide_setting_mtx);
-EXPORT_SYMBOL_GPL(ide_setting_sem);
+EXPORT_SYMBOL_GPL(ide_setting_mtx);
/**
* ide_spin_wait_hwgroup - wait for group
@@ -1192,11 +1193,11 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
}
read_val:
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
err = *val;
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
set_val:
@@ -1206,9 +1207,9 @@ set_val:
if (!capable(CAP_SYS_ADMIN))
err = -EACCES;
else {
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
err = setfunc(drive, arg);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
}
return err;
@@ -1548,7 +1549,11 @@ static int __init ide_setup(char *s)
goto bad_option;
case -7: /* ata66 */
#ifdef CONFIG_BLK_DEV_IDEPCI
- hwif->udma_four = 1;
+ /*
+ * Use ATA_CBL_PATA40_SHORT so drive side
+ * cable detection is also overriden.
+ */
+ hwif->cbl = ATA_CBL_PATA40_SHORT;
goto obsolete_option;
#else
goto bad_hwif;
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 45ed03591cd8..7f4c0a5050a1 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -130,7 +130,7 @@ struct hd_i_struct {
#ifdef HD_TYPE
static struct hd_i_struct hd_info[] = { HD_TYPE };
-static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
+static int NR_HD = ARRAY_SIZE(hd_info);
#else
static struct hd_i_struct hd_info[MAX_HD];
static int NR_HD;
@@ -623,7 +623,8 @@ repeat:
cyl = track / disk->head;
#ifdef DEBUG
printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
- req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
+ req->rq_disk->disk_name,
+ req_data_dir(req) == READ ? "read" : "writ",
cyl, head, sec, nsect, req->buffer);
#endif
if (blk_fs_request(req)) {
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index c211fc78345d..b557c45a5a9d 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -77,15 +77,6 @@ int macide_ack_intr(ide_hwif_t* hwif)
return 0;
}
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
-static void macide_mediabay_interrupt(int irq, void *dev_id)
-{
- int state = baboon->mb_status & 0x04;
-
- printk(KERN_INFO "macide: media bay %s detected\n", state? "removal":"insertion");
-}
-#endif
-
/*
* Probe for a Macintosh IDE interface
*/
@@ -128,11 +119,6 @@ void macide_init(void)
ide_drive_t *drive = &ide_hwifs[index].drives[0];
drive->capacity64 = drive->cyl*drive->head*drive->sect;
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
- request_irq(IRQ_BABOON_2, macide_mediabay_interrupt,
- IRQ_FLG_FAST, "mediabay",
- macide_mediabay_interrupt);
-#endif
}
break;
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index ca95e990862e..2e7013a2a7f6 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -381,9 +381,7 @@ static int auide_dma_setup(ide_drive_t *drive)
static int auide_dma_check(ide_drive_t *drive)
{
- u8 speed;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ u8 speed = ide_max_dma_mode(drive);
if( dbdma_init_done == 0 ){
auide_hwif.white_list = ide_in_drive_list(drive->id,
@@ -394,7 +392,6 @@ static int auide_dma_check(ide_drive_t *drive)
auide_ddma_init(&auide_hwif);
dbdma_init_done = 1;
}
-#endif
/* Is the drive in our DMA black list? */
@@ -409,8 +406,6 @@ static int auide_dma_check(ide_drive_t *drive)
else
drive->using_dma = 1;
- speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA);
-
if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
return 0;
@@ -456,10 +451,9 @@ static void auide_dma_off_quietly(ide_drive_t *drive)
drive->using_dma = 0;
}
-static int auide_dma_lostirq(ide_drive_t *drive)
+static void auide_dma_lost_irq(ide_drive_t *drive)
{
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
- return 0;
}
static void auide_ddma_tx_callback(int irq, void *param)
@@ -489,16 +483,16 @@ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 de
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
-static int auide_dma_timeout(ide_drive_t *drive)
+static void auide_dma_timeout(ide_drive_t *drive)
{
-// printk("%s\n", __FUNCTION__);
+ ide_hwif_t *hwif = HWIF(drive);
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
- if (HWIF(drive)->ide_dma_test_irq(drive))
- return 0;
+ if (hwif->ide_dma_test_irq(drive))
+ return;
- return HWIF(drive)->ide_dma_end(drive);
+ hwif->ide_dma_end(drive);
}
@@ -721,7 +715,7 @@ static int au_ide_probe(struct device *dev)
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
hwif->dma_off_quietly = &auide_dma_off_quietly;
- hwif->ide_dma_timeout = &auide_dma_timeout;
+ hwif->dma_timeout = &auide_dma_timeout;
hwif->ide_dma_check = &auide_dma_check;
hwif->dma_exec_cmd = &auide_dma_exec_cmd;
@@ -731,7 +725,7 @@ static int au_ide_probe(struct device *dev)
hwif->ide_dma_test_irq = &auide_dma_test_irq;
hwif->dma_host_off = &auide_dma_host_off;
hwif->dma_host_on = &auide_dma_host_on;
- hwif->ide_dma_lostirq = &auide_dma_lostirq;
+ hwif->dma_lost_irq = &auide_dma_lost_irq;
hwif->ide_dma_on = &auide_dma_on;
hwif->autodma = 1;
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index b173bc66ce1e..e5d09367627e 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/aec62xx.c Version 0.21 Apr 21, 2007
+ * linux/drivers/ide/pci/aec62xx.c Version 0.24 May 24, 2007
*
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
@@ -140,25 +140,10 @@ static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed)
return(ide_config_drive_speed(drive, speed));
}
-static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed)
-{
- switch (HWIF(drive)->pci_dev->device) {
- case PCI_DEVICE_ID_ARTOP_ATP865:
- case PCI_DEVICE_ID_ARTOP_ATP865R:
- case PCI_DEVICE_ID_ARTOP_ATP860:
- case PCI_DEVICE_ID_ARTOP_ATP860R:
- return ((int) aec6260_tune_chipset(drive, speed));
- case PCI_DEVICE_ID_ARTOP_ATP850UF:
- return ((int) aec6210_tune_chipset(drive, speed));
- default:
- return -1;
- }
-}
-
static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
{
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
- (void) aec62xx_tune_chipset(drive, pio + XFER_PIO_0);
+ (void) HWIF(drive)->speedproc(drive, pio + XFER_PIO_0);
}
static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
@@ -172,12 +157,9 @@ static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
return -1;
}
-static int aec62xx_irq_timeout (ide_drive_t *drive)
+static void aec62xx_dma_lost_irq (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
-
- switch(dev->device) {
+ switch (HWIF(drive)->pci_dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP860:
case PCI_DEVICE_ID_ARTOP_ATP860R:
case PCI_DEVICE_ID_ARTOP_ATP865:
@@ -186,7 +168,6 @@ static int aec62xx_irq_timeout (ide_drive_t *drive)
default:
break;
}
- return 0;
}
static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
@@ -224,64 +205,46 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch
static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = hwif->pci_dev;
+ u8 reg54 = 0, mask = hwif->channel ? 0xf0 : 0x0f;
+ unsigned long flags;
- hwif->autodma = 0;
hwif->tuneproc = &aec62xx_tune_drive;
- hwif->speedproc = &aec62xx_tune_chipset;
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
- hwif->serialized = hwif->channel;
-
- if (hwif->mate)
- hwif->mate->serialized = hwif->serialized;
+ if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+ if(hwif->mate)
+ hwif->mate->serialized = hwif->serialized = 1;
+ hwif->speedproc = &aec6210_tune_chipset;
+ } else
+ hwif->speedproc = &aec6260_tune_chipset;
if (!hwif->dma_base) {
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
+ hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
return;
}
hwif->ultra_mask = hwif->cds->udma_mask;
-
- /* atp865 and atp865r */
- if (hwif->ultra_mask == 0x3f) {
- /* check bit 0x10 of DMA status register */
- if (inb(pci_resource_start(dev, 4) + 2) & 0x10)
- hwif->ultra_mask = 0x7f; /* udma0-6 */
- }
-
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate;
- hwif->ide_dma_lostirq = &aec62xx_irq_timeout;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
-}
-
-static void __devinit init_dma_aec62xx(ide_hwif_t *hwif, unsigned long dmabase)
-{
- struct pci_dev *dev = hwif->pci_dev;
+ hwif->dma_lost_irq = &aec62xx_dma_lost_irq;
if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
- u8 reg54h = 0;
- unsigned long flags;
-
spin_lock_irqsave(&ide_lock, flags);
- pci_read_config_byte(dev, 0x54, &reg54h);
- pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
+ pci_read_config_byte (dev, 0x54, &reg54);
+ pci_write_config_byte(dev, 0x54, (reg54 & ~mask));
spin_unlock_irqrestore(&ide_lock, flags);
- } else {
- u8 ata66 = 0;
+ } else if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+ u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
+
pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
- if (!(hwif->udma_four))
- hwif->udma_four = (ata66&(hwif->channel?0x02:0x01))?0:1;
+
+ hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
- ide_setup_dma(hwif, dmabase, 8);
+ if (!noautodma)
+ hwif->autodma = 1;
+ hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d)
@@ -291,16 +254,12 @@ static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d
static int __devinit init_setup_aec6x80(struct pci_dev *dev, ide_pci_device_t *d)
{
- unsigned long bar4reg = pci_resource_start(dev, 4);
-
- if (inb(bar4reg+2) & 0x10) {
- strcpy(d->name, "AEC6880");
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
- strcpy(d->name, "AEC6880R");
- } else {
- strcpy(d->name, "AEC6280");
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
- strcpy(d->name, "AEC6280R");
+ unsigned long dma_base = pci_resource_start(dev, 4);
+
+ if (inb(dma_base + 2) & 0x10) {
+ d->name = (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) ?
+ "AEC6880R" : "AEC6880";
+ d->udma_mask = 0x7f; /* udma0-6 */
}
return ide_setup_pci_device(dev, d);
@@ -312,7 +271,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -323,7 +281,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = OFF_BOARD,
@@ -333,28 +290,25 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.bootable = NEVER_BOARD,
.udma_mask = 0x1f, /* udma0-4 */
},{ /* 3 */
- .name = "AEC6X80",
+ .name = "AEC6280",
.init_setup = init_setup_aec6x80,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.bootable = OFF_BOARD,
.udma_mask = 0x3f, /* udma0-5 */
},{ /* 4 */
- .name = "AEC6X80R",
+ .name = "AEC6280R",
.init_setup = init_setup_aec6x80,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -370,13 +324,16 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
*
* Called when the PCI registration layer (or the IDE initialization)
* finds a device matching our IDE device tables.
+ *
+ * NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
+ * chips, pass a local copy of 'struct pci_device_id' down the call chain.
*/
static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &aec62xx_chipsets[id->driver_data];
+ ide_pci_device_t d = aec62xx_chipsets[id->driver_data];
- return d->init_setup(dev, d);
+ return d.init_setup(dev, &d);
}
static struct pci_device_id aec62xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 27525ec2e19a..8a6b27b3bcc3 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/alim15x3.c Version 0.21 2007/02/03
+ * linux/drivers/ide/pci/alim15x3.c Version 0.25 Jun 9 2007
*
* Copyright (C) 1998-2000 Michel Aubry, Maintainer
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
@@ -10,6 +10,7 @@
* Copyright (C) 2002 Alan Cox <alan@redhat.com>
* ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
*
* (U)DMA capable version of ali 1533/1543(C), 1535(D)
*
@@ -36,6 +37,7 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
+#include <linux/dmi.h>
#include <asm/io.h>
@@ -583,6 +585,35 @@ out:
return 0;
}
+/*
+ * Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+ {
+ .ident = "HP Pavilion N5430",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"),
+ },
+ },
+ { }
+};
+
+static int ali_cable_override(struct pci_dev *pdev)
+{
+ /* Fujitsu P2000 */
+ if (pdev->subsystem_vendor == 0x10CF &&
+ pdev->subsystem_device == 0x10AF)
+ return 1;
+
+ /* Systems by DMI */
+ if (dmi_check_system(cable_dmi_table))
+ return 1;
+
+ return 0;
+}
+
/**
* ata66_ali15x3 - check for UDMA 66 support
* @hwif: IDE interface
@@ -594,37 +625,31 @@ out:
* FIXME: frobs bits that are not defined on newer ALi devicea
*/
-static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
+static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- unsigned int ata66 = 0;
- u8 cable_80_pin[2] = { 0, 0 };
-
unsigned long flags;
- u8 tmpbyte;
+ u8 cbl = ATA_CBL_PATA40, tmpbyte;
local_irq_save(flags);
if (m5229_revision >= 0xC2) {
/*
- * Ultra66 cable detection (from Host View)
- * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
- */
- pci_read_config_byte(dev, 0x4a, &tmpbyte);
- /*
- * 0x4a, bit0 is 0 => primary channel
- * has 80-pin (from host view)
- */
- if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1;
- /*
- * 0x4a, bit1 is 0 => secondary channel
- * has 80-pin (from host view)
- */
- if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1;
- /*
- * Allow ata66 if cable of current channel has 80 pins
+ * m5229 80-pin cable detection (from Host View)
+ *
+ * 0x4a bit0 is 0 => primary channel has 80-pin
+ * 0x4a bit1 is 0 => secondary channel has 80-pin
+ *
+ * Certain laptops use short but suitable cables
+ * and don't implement the detect logic.
*/
- ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
+ if (ali_cable_override(dev))
+ cbl = ATA_CBL_PATA40_SHORT;
+ else {
+ pci_read_config_byte(dev, 0x4a, &tmpbyte);
+ if ((tmpbyte & (1 << hwif->channel)) == 0)
+ cbl = ATA_CBL_PATA80;
+ }
} else {
/*
* check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
@@ -657,7 +682,7 @@ static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
local_irq_restore(flags);
- return(ata66);
+ return cbl;
}
/**
@@ -708,8 +733,9 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
hwif->dma_setup = &ali15x3_dma_setup;
if (!noautodma)
hwif->autodma = 1;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_ali15x3(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_ali15x3(hwif);
}
hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index a2be65fcf89c..84ed30cdb324 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,10 +1,11 @@
/*
- * Version 2.16
+ * Version 2.20
*
* AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
* IDE driver for Linux.
*
* Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
*
* Based on the work of:
* Andre Hedrick
@@ -37,11 +38,6 @@
#define AMD_ADDRESS_SETUP (0x0c + amd_config->base)
#define AMD_UDMA_TIMING (0x10 + amd_config->base)
-#define AMD_UDMA 0x07
-#define AMD_UDMA_33 0x01
-#define AMD_UDMA_66 0x02
-#define AMD_UDMA_100 0x03
-#define AMD_UDMA_133 0x04
#define AMD_CHECK_SWDMA 0x08
#define AMD_BAD_SWDMA 0x10
#define AMD_BAD_FIFO 0x20
@@ -53,32 +49,33 @@
static struct amd_ide_chip {
unsigned short id;
- unsigned long base;
- unsigned char flags;
+ u8 base;
+ u8 udma_mask;
+ u8 flags;
} amd_ide_chips[] = {
- { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },
- { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },
- { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO },
- { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, AMD_UDMA_100 },
- { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, AMD_UDMA_133 | AMD_CHECK_SERENADE },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, AMD_UDMA_100 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 },
+ { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, ATA_UDMA2, AMD_BAD_SWDMA },
+ { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, ATA_UDMA4, AMD_CHECK_SWDMA },
+ { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, ATA_UDMA5, AMD_BAD_FIFO },
+ { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, ATA_UDMA5, },
+ { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, ATA_UDMA6, AMD_CHECK_SERENADE },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, ATA_UDMA5, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, ATA_UDMA5, },
{ 0 }
};
@@ -87,7 +84,7 @@ static ide_pci_device_t *amd_chipset;
static unsigned int amd_80w;
static unsigned int amd_clock;
-static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
/*
@@ -128,7 +125,7 @@ static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count)
pci_read_config_byte(dev, PCI_REVISION_ID, &t);
amd_print("Revision: IDE %#x", t);
- amd_print("Highest DMA rate: %s", amd_dma[amd_config->flags & AMD_UDMA]);
+ amd_print("Highest DMA rate: UDMA%s", amd_dma[fls(amd_config->udma_mask) - 1]);
amd_print("BM-DMA base: %#lx", amd_base);
amd_print("PCI clock: %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10);
@@ -221,12 +218,12 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
- switch (amd_config->flags & AMD_UDMA) {
- case AMD_UDMA_33: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
- case AMD_UDMA_66: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
- case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
- case AMD_UDMA_133: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
- default: return;
+ switch (amd_config->udma_mask) {
+ case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+ case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
+ case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
+ case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
+ default: return;
}
pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
@@ -248,7 +245,7 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed)
ide_config_drive_speed(drive, speed);
T = 1000000000 / amd_clock;
- UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2);
+ UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
ide_timing_compute(drive, speed, &t, T, UT);
@@ -277,29 +274,19 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed)
static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio)
{
if (pio == 255) {
- amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+ amd_set_drive(drive, ide_find_best_pio_mode(drive));
return;
}
amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
}
-/*
- * amd74xx_dmaproc() is a callback from upper layers that can do
- * a lot, but we use it for DMA/PIO tuning only, delegating everything
- * else to the default ide_dmaproc().
- */
-
static int amd74xx_ide_dma_check(ide_drive_t *drive)
{
- int w80 = HWIF(drive)->udma_four;
+ u8 speed = ide_max_dma_mode(drive);
- u8 speed = ide_find_best_mode(drive,
- XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
- ((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0));
+ if (speed == 0)
+ speed = ide_find_best_pio_mode(drive);
amd_set_drive(drive, speed);
@@ -334,10 +321,10 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
* Check 80-wire cable presence.
*/
- switch (amd_config->flags & AMD_UDMA) {
+ switch (amd_config->udma_mask) {
- case AMD_UDMA_133:
- case AMD_UDMA_100:
+ case ATA_UDMA6:
+ case ATA_UDMA5:
pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
@@ -349,7 +336,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
}
break;
- case AMD_UDMA_66:
+ case ATA_UDMA4:
/* no host side cable detection */
amd_80w = 0x03;
break;
@@ -370,7 +357,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
if ((amd_config->flags & AMD_CHECK_SERENADE) &&
dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
- amd_config->flags = AMD_UDMA_100;
+ amd_config->udma_mask = ATA_UDMA5;
/*
* Determine the system bus clock.
@@ -395,8 +382,9 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
*/
pci_read_config_byte(dev, PCI_REVISION_ID, &t);
- printk(KERN_INFO "%s: %s (rev %02x) %s controller\n",
- amd_chipset->name, pci_name(dev), t, amd_dma[amd_config->flags & AMD_UDMA]);
+ printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
+ amd_chipset->name, pci_name(dev), t,
+ amd_dma[fls(amd_config->udma_mask) - 1]);
/*
* Register /proc/ide/amd74xx entry
@@ -437,12 +425,19 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
return;
hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
- if (!hwif->udma_four)
- hwif->udma_four = (amd_80w >> hwif->channel) & 1;
+ hwif->ultra_mask = amd_config->udma_mask;
+ hwif->mwdma_mask = 0x07;
+ if ((amd_config->flags & AMD_BAD_SWDMA) == 0)
+ hwif->swdma_mask = 0x07;
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+ if ((amd_80w >> hwif->channel) & 1)
+ hwif->cbl = ATA_CBL_PATA80;
+ else
+ hwif->cbl = ATA_CBL_PATA40;
+ }
+
hwif->ide_dma_check = &amd74xx_ide_dma_check;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 8ab33faf6f76..2761510309b3 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -264,10 +264,11 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+
if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
- hwif->udma_four = 1;
+ hwif->cbl = ATA_CBL_PATA80;
else
- hwif->udma_four = 0;
+ hwif->cbl = ATA_CBL_PATA40;
hwif->dma_host_on = &atiixp_dma_host_on;
hwif->dma_host_off = &atiixp_dma_host_off;
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 7c57dc696f52..8631b6c8aa15 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/cmd64x.c Version 1.47 Mar 19, 2007
+ * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007
*
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported
@@ -52,9 +52,6 @@
#define ARTTIM23_DIS_RA2 0x04
#define ARTTIM23_DIS_RA3 0x08
#define ARTTIM23_INTR_CH1 0x10
-#define ARTTIM2 0x57
-#define ARTTIM3 0x57
-#define DRWTIM23 0x58
#define DRWTIM2 0x58
#define BRST 0x59
#define DRWTIM3 0x5b
@@ -469,71 +466,43 @@ static int cmd646_1_ide_dma_end (ide_drive_t *drive)
static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
{
- u32 class_rev = 0;
u8 mrdmode = 0;
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
+ if (dev->device == PCI_DEVICE_ID_CMD_646) {
+ u8 rev = 0;
- switch(dev->device) {
- case PCI_DEVICE_ID_CMD_643:
- break;
- case PCI_DEVICE_ID_CMD_646:
- printk(KERN_INFO "%s: chipset revision 0x%02X, ", name, class_rev);
- switch(class_rev) {
- case 0x07:
- case 0x05:
- printk("UltraDMA Capable");
- break;
- case 0x03:
- printk("MultiWord DMA Force Limited");
- break;
- case 0x01:
- default:
- printk("MultiWord DMA Limited, IRQ workaround enabled");
- break;
- }
- printk("\n");
- break;
- case PCI_DEVICE_ID_CMD_648:
- case PCI_DEVICE_ID_CMD_649:
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+
+ switch (rev) {
+ case 0x07:
+ case 0x05:
+ printk("%s: UltraDMA capable", name);
break;
+ case 0x03:
default:
+ printk("%s: MultiWord DMA force limited", name);
+ break;
+ case 0x01:
+ printk("%s: MultiWord DMA limited, "
+ "IRQ workaround enabled\n", name);
break;
+ }
}
/* Set a good latency timer and cache line size value. */
(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
/* FIXME: pci_set_master() to ensure a good latency timer value */
- /* Setup interrupts. */
- (void) pci_read_config_byte(dev, MRDMODE, &mrdmode);
- mrdmode &= ~(0x30);
- (void) pci_write_config_byte(dev, MRDMODE, mrdmode);
-
- /* Use MEMORY READ LINE for reads.
- * NOTE: Although not mentioned in the PCI0646U specs,
- * these bits are write only and won't be read
- * back as set or not. The PCI0646U2 specs clarify
- * this point.
+ /*
+ * Enable interrupts, select MEMORY READ LINE for reads.
+ *
+ * NOTE: although not mentioned in the PCI0646U specs,
+ * bits 0-1 are write only and won't be read back as
+ * set or not -- PCI0646U2 specs clarify this point.
*/
- (void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02);
-
- /* Set reasonable active/recovery/address-setup values. */
- (void) pci_write_config_byte(dev, ARTTIM0, 0x40);
- (void) pci_write_config_byte(dev, DRWTIM0, 0x3f);
- (void) pci_write_config_byte(dev, ARTTIM1, 0x40);
- (void) pci_write_config_byte(dev, DRWTIM1, 0x3f);
-#ifdef __i386__
- (void) pci_write_config_byte(dev, ARTTIM23, 0x1c);
-#else
- (void) pci_write_config_byte(dev, ARTTIM23, 0x5c);
-#endif
- (void) pci_write_config_byte(dev, DRWTIM23, 0x3f);
- (void) pci_write_config_byte(dev, DRWTIM3, 0x3f);
-#ifdef CONFIG_PPC
- (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);
-#endif /* CONFIG_PPC */
+ (void) pci_read_config_byte (dev, MRDMODE, &mrdmode);
+ mrdmode &= ~0x30;
+ (void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
@@ -548,29 +517,27 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
return 0;
}
-static unsigned int __devinit ata66_cmd64x(ide_hwif_t *hwif)
+static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
{
- u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01;
+ struct pci_dev *dev = hwif->pci_dev;
+ u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01;
- switch(hwif->pci_dev->device) {
- case PCI_DEVICE_ID_CMD_643:
- case PCI_DEVICE_ID_CMD_646:
- return ata66;
- default:
- break;
+ switch (dev->device) {
+ case PCI_DEVICE_ID_CMD_648:
+ case PCI_DEVICE_ID_CMD_649:
+ pci_read_config_byte(dev, BMIDECSR, &bmidecsr);
+ return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ default:
+ return ATA_CBL_PATA40;
}
- pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);
- return (ata66 & mask) ? 1 : 0;
}
static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- unsigned int class_rev;
+ u8 rev = 0;
- hwif->autodma = 0;
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
hwif->tuneproc = &cmd64x_tune_drive;
hwif->speedproc = &cmd64x_tune_chipset;
@@ -580,8 +547,8 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
if (!hwif->dma_base)
return;
- hwif->atapi_dma = 1;
-
+ hwif->atapi_dma = 1;
+ hwif->mwdma_mask = 0x07;
hwif->ultra_mask = hwif->cds->udma_mask;
/*
@@ -596,16 +563,15 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
*
* So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
*/
- if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5)
+ if (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 5)
hwif->ultra_mask = 0x00;
- hwif->mwdma_mask = 0x07;
-
hwif->ide_dma_check = &cmd64x_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_cmd64x(hwif);
- switch(dev->device) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_cmd64x(hwif);
+
+ switch (dev->device) {
case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_649:
alt_irq_bits:
@@ -614,10 +580,10 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
break;
case PCI_DEVICE_ID_CMD_646:
hwif->chipset = ide_cmd646;
- if (class_rev == 0x01) {
+ if (rev == 0x01) {
hwif->ide_dma_end = &cmd646_1_ide_dma_end;
break;
- } else if (class_rev >= 0x03)
+ } else if (rev >= 0x03)
goto alt_irq_bits;
/* fall thru */
default:
@@ -626,11 +592,9 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
break;
}
-
if (!noautodma)
hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
+ hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 41925c47ef05..10f61f38243c 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -187,7 +187,8 @@ static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
/* if a 80 wire cable was detected */
pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
- return (bit & 1);
+
+ return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/****
@@ -212,8 +213,7 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
hwif->ultra_mask = 0x1F;
hwif->mwdma_mask = 0x07;
-
- hwif->udma_four = cs5535_cable_detect(hwif->pci_dev);
+ hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index c33d0b0f11c9..4b6bae8eee82 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.06 Jun 27, 2007
+ * linux/drivers/ide/pci/hpt366.c Version 1.10 Jun 29, 2007
*
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
@@ -77,7 +77,7 @@
* since they may tamper with its fields
* - prefix the driver startup messages with the real chip name
* - claim the extra 240 bytes of I/O space for all chips
- * - optimize the rate masking/filtering and the drive list lookup code
+ * - optimize the UltraDMA filtering and the drive list lookup code
* - use pci_get_slot() to get to the function 1 of HPT36x/374
* - cache offset of the channel's misc. control registers (MCRs) being used
* throughout the driver
@@ -99,9 +99,9 @@
* stop duplicating it for each channel by storing the pointer in the pci_dev
* structure: first, at the init_setup stage, point it to a static "template"
* with only the chip type and its specific base DPLL frequency, the highest
- * supported DMA mode, and the chip settings table pointer filled, then, at
- * the init_chipset stage, allocate per-chip instance and fill it with the
- * rest of the necessary information
+ * UltraDMA mode, and the chip settings table pointer filled, then, at the
+ * init_chipset stage, allocate per-chip instance and fill it with the rest
+ * of the necessary information
* - get rid of the constant thresholds in the HPT37x PCI clock detection code,
* switch to calculating PCI clock frequency based on the chip's base DPLL
* frequency
@@ -112,6 +112,7 @@
* also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
* unify HPT36x/37x timing setup code and the speedproc handlers by joining
* the register setting lists into the table indexed by the clock selected
+ * - set the correct hwif->ultra_mask for each individual chip
* Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
*/
@@ -391,7 +392,7 @@ enum ata_clock {
struct hpt_info {
u8 chip_type; /* Chip type */
- u8 max_mode; /* Speeds allowed */
+ u8 max_ultra; /* Max. UltraDMA mode allowed */
u8 dpll_clk; /* DPLL clock in MHz */
u8 pci_clk; /* PCI clock in MHz */
u32 **settings; /* Chipset settings table */
@@ -430,77 +431,77 @@ static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
static struct hpt_info hpt36x __devinitdata = {
.chip_type = HPT36x,
- .max_mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1,
+ .max_ultra = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? 4 : 3) : 2,
.dpll_clk = 0, /* no DPLL */
.settings = hpt36x_settings
};
static struct hpt_info hpt370 __devinitdata = {
.chip_type = HPT370,
- .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2,
+ .max_ultra = HPT370_ALLOW_ATA100_5 ? 5 : 4,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt370a __devinitdata = {
.chip_type = HPT370A,
- .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2,
+ .max_ultra = HPT370_ALLOW_ATA100_5 ? 5 : 4,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt374 __devinitdata = {
.chip_type = HPT374,
- .max_mode = 3,
+ .max_ultra = 5,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt372 __devinitdata = {
.chip_type = HPT372,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 55,
.settings = hpt37x_settings
};
static struct hpt_info hpt372a __devinitdata = {
.chip_type = HPT372A,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt302 __devinitdata = {
.chip_type = HPT302,
- .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt371 __devinitdata = {
.chip_type = HPT371,
- .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT371_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt372n __devinitdata = {
.chip_type = HPT372N,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
static struct hpt_info hpt302n __devinitdata = {
.chip_type = HPT302N,
- .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT302_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
static struct hpt_info hpt371n __devinitdata = {
.chip_type = HPT371N,
- .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT371_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
@@ -523,53 +524,38 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list)
static u8 hpt3xx_udma_filter(ide_drive_t *drive)
{
struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev);
- u8 chip_type = info->chip_type;
- u8 mode = info->max_mode;
u8 mask;
- switch (mode) {
- case 0x04:
- mask = 0x7f;
- break;
- case 0x03:
+ switch (info->chip_type) {
+ case HPT370A:
+ if (!HPT370_ALLOW_ATA100_5 ||
+ check_in_drive_list(drive, bad_ata100_5))
+ return 0x1f;
+ else
+ return 0x3f;
+ case HPT370:
+ if (!HPT370_ALLOW_ATA100_5 ||
+ check_in_drive_list(drive, bad_ata100_5))
+ mask = 0x1f;
+ else
mask = 0x3f;
- if (chip_type >= HPT374)
- break;
- if (!check_in_drive_list(drive, bad_ata100_5))
- goto check_bad_ata33;
- /* fall thru */
- case 0x02:
+ break;
+ case HPT36x:
+ if (!HPT366_ALLOW_ATA66_4 ||
+ check_in_drive_list(drive, bad_ata66_4))
+ mask = 0x0f;
+ else
mask = 0x1f;
- /*
- * CHECK ME, Does this need to be changed to HPT374 ??
- */
- if (chip_type >= HPT370)
- goto check_bad_ata33;
- if (HPT366_ALLOW_ATA66_4 &&
- !check_in_drive_list(drive, bad_ata66_4))
- goto check_bad_ata33;
-
- mask = 0x0f;
- if (HPT366_ALLOW_ATA66_3 &&
- !check_in_drive_list(drive, bad_ata66_3))
- goto check_bad_ata33;
- /* fall thru */
- case 0x01:
+ if (!HPT366_ALLOW_ATA66_3 ||
+ check_in_drive_list(drive, bad_ata66_3))
mask = 0x07;
-
- check_bad_ata33:
- if (chip_type >= HPT370A)
- break;
- if (!check_in_drive_list(drive, bad_ata33))
- break;
- /* fall thru */
- case 0x00:
- default:
- mask = 0x00;
- break;
+ break;
+ default:
+ return 0x7f;
}
- return mask;
+
+ return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
}
static u32 get_speed_setting(u8 speed, struct hpt_info *info)
@@ -737,7 +723,7 @@ static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
* This is specific to the HPT366 UDMA chipset
* by HighPoint|Triones Technologies, Inc.
*/
-static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
+static void hpt366_dma_lost_irq(ide_drive_t *drive)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
@@ -749,7 +735,7 @@ static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
drive->name, __FUNCTION__, mcr1, mcr3, scr1);
if (scr1 & 0x10)
pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
- return __ide_dma_lostirq(drive);
+ ide_dma_lost_irq(drive);
}
static void hpt370_clear_engine(ide_drive_t *drive)
@@ -799,10 +785,10 @@ static int hpt370_ide_dma_end(ide_drive_t *drive)
return __ide_dma_end(drive);
}
-static int hpt370_ide_dma_timeout(ide_drive_t *drive)
+static void hpt370_dma_timeout(ide_drive_t *drive)
{
hpt370_irq_timeout(drive);
- return __ide_dma_timeout(drive);
+ ide_dma_timeout(drive);
}
/* returns 1 if DMA IRQ issued, 0 otherwise */
@@ -1150,7 +1136,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
* Select 66 MHz DPLL clock only if UltraATA/133 mode is
* supported/enabled, use 50 MHz DPLL clock otherwise...
*/
- if (info->max_mode == 0x04) {
+ if (info->max_ultra == 6) {
dpll_clk = 66;
clock = ATA_CLOCK_66MHZ;
} else if (dpll_clk) { /* HPT36x chips don't have DPLL */
@@ -1243,7 +1229,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = pci_get_drvdata(dev);
int serialize = HPT_SERIALIZE_IO;
- u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02;
+ u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02;
u8 chip_type = info->chip_type;
u8 new_mcr, old_mcr = 0;
@@ -1256,7 +1242,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
hwif->busproc = &hpt3xx_busproc;
- hwif->udma_filter = &hpt3xx_udma_filter;
+
+ if (chip_type <= HPT370A)
+ hwif->udma_filter = &hpt3xx_udma_filter;
/*
* HPT3xxN chips have some complications:
@@ -1305,7 +1293,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
return;
}
- hwif->ultra_mask = 0x7f;
+ hwif->ultra_mask = hwif->cds->udma_mask;
hwif->mwdma_mask = 0x07;
/*
@@ -1342,8 +1330,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
} else
pci_read_config_byte (dev, 0x5a, &scr1);
- if (!hwif->udma_four)
- hwif->udma_four = (scr1 & ata66) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
@@ -1353,9 +1341,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
} else if (chip_type >= HPT370) {
hwif->dma_start = &hpt370_ide_dma_start;
hwif->ide_dma_end = &hpt370_ide_dma_end;
- hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
+ hwif->dma_timeout = &hpt370_dma_timeout;
} else
- hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
+ hwif->dma_lost_irq = &hpt366_dma_lost_irq;
if (!noautodma)
hwif->autodma = 1;
@@ -1503,9 +1491,35 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
- if (rev > 6)
+ switch (rev) {
+ case 0:
+ case 1:
+ case 2:
+ /*
+ * HPT36x chips have one channel per function and have
+ * both channel enable bits located differently and visible
+ * to both functions -- really stupid design decision... :-(
+ * Bit 4 is for the primary channel, bit 5 for the secondary.
+ */
+ d->channels = 1;
+ d->enablebits[0].mask = d->enablebits[0].val = 0x10;
+
+ d->udma_mask = HPT366_ALLOW_ATA66_3 ?
+ (HPT366_ALLOW_ATA66_4 ? 0x1f : 0x0f) : 0x07;
+ break;
+ case 3:
+ case 4:
+ d->udma_mask = HPT370_ALLOW_ATA100_5 ? 0x3f : 0x1f;
+ break;
+ default:
rev = 6;
-
+ /* fall thru */
+ case 5:
+ case 6:
+ d->udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f;
+ break;
+ }
+
d->name = chipset_names[rev];
pci_set_drvdata(dev, info[rev]);
@@ -1513,15 +1527,6 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
if (rev > 2)
goto init_single;
- /*
- * HPT36x chips have one channel per function and have
- * both channel enable bits located differently and visible
- * to both functions -- really stupid design decision... :-(
- * Bit 4 is for the primary channel, bit 5 for the secondary.
- */
- d->channels = 1;
- d->enablebits[0].mask = d->enablebits[0].val = 0x10;
-
if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
u8 mcr1 = 0, pin1 = 0, pin2 = 0;
int ret;
@@ -1573,6 +1578,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 2 */
@@ -1584,6 +1590,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT302_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 3 */
@@ -1595,6 +1602,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT371_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 4 */
@@ -1606,6 +1614,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2, /* 4 */
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 5 */
@@ -1617,6 +1626,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2, /* 4 */
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
}
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index c04a02687b95..ff48c23e571e 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -231,7 +231,7 @@ static int it8213_config_drive_for_dma (ide_drive_t *drive)
static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
{
- u8 reg42h = 0, ata66 = 0;
+ u8 reg42h = 0;
hwif->speedproc = &it8213_tune_chipset;
hwif->tuneproc = &it8213_tuneproc;
@@ -250,11 +250,11 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
- ata66 = (reg42h & 0x02) ? 0 : 1;
hwif->ide_dma_check = &it8213_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66;
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
/*
* The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 3aeb7f1b7916..8197b653ba1e 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -491,10 +491,10 @@ static int it821x_config_drive_for_dma (ide_drive_t *drive)
* the needed logic onboard.
*/
-static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif)
+static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
{
/* The reference driver also only does disk side */
- return 1;
+ return ATA_CBL_PATA80;
}
/**
@@ -662,8 +662,9 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &it821x_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_it821x(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_it821x(hwif);
/*
* The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 76ed25147229..a6008f63e71e 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -25,10 +25,10 @@ typedef enum {
* ata66_jmicron - Cable check
* @hwif: IDE port
*
- * Return 1 if the cable is 80pin
+ * Returns the cable type.
*/
-static int __devinit ata66_jmicron(ide_hwif_t *hwif)
+static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
{
struct pci_dev *pdev = hwif->pci_dev;
@@ -70,16 +70,17 @@ static int __devinit ata66_jmicron(ide_hwif_t *hwif)
{
case PORT_PATA0:
if (control & (1 << 3)) /* 40/80 pin primary */
- return 0;
- return 1;
+ return ATA_CBL_PATA40;
+ return ATA_CBL_PATA80;
case PORT_PATA1:
if (control5 & (1 << 19)) /* 40/80 pin secondary */
- return 0;
- return 1;
+ return ATA_CBL_PATA40;
+ return ATA_CBL_PATA80;
case PORT_SATA:
break;
}
- return 1; /* Avoid bogus "control reaches end of non-void function" */
+ /* Avoid bogus "control reaches end of non-void function" */
+ return ATA_CBL_PATA80;
}
static void jmicron_tuneproc (ide_drive_t *drive, byte mode_wanted)
@@ -159,8 +160,9 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &jmicron_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_jmicron(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_jmicron(hwif);
hwif->autodma = 1;
hwif->drives[0].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 0765dce6948e..ee5020df005d 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -225,7 +225,10 @@ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio)
static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
{
- return get_indexed_reg(hwif, 0x0b) & 0x04;
+ if (get_indexed_reg(hwif, 0x0b) & 0x04)
+ return ATA_CBL_PATA40;
+ else
+ return ATA_CBL_PATA80;
}
static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
@@ -509,8 +512,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
- if (!hwif->udma_four)
- hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = pdcnew_cable_detect(hwif);
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 23844687deea..41ac4a94959f 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -152,8 +152,10 @@ static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
{
u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
+
pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
- return (CIS & mask) ? 1 : 0;
+
+ return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
/*
@@ -267,18 +269,24 @@ somebody_else:
return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
}
-static int pdc202xx_ide_dma_lostirq(ide_drive_t *drive)
+static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
{
- if (HWIF(drive)->resetproc != NULL)
- HWIF(drive)->resetproc(drive);
- return __ide_dma_lostirq(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+
+ if (hwif->resetproc != NULL)
+ hwif->resetproc(drive);
+
+ ide_dma_lost_irq(drive);
}
-static int pdc202xx_ide_dma_timeout(ide_drive_t *drive)
+static void pdc202xx_dma_timeout(ide_drive_t *drive)
{
- if (HWIF(drive)->resetproc != NULL)
- HWIF(drive)->resetproc(drive);
- return __ide_dma_timeout(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+
+ if (hwif->resetproc != NULL)
+ hwif->resetproc(drive);
+
+ ide_dma_timeout(drive);
}
static void pdc202xx_reset_host (ide_hwif_t *hwif)
@@ -347,12 +355,13 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
hwif->err_stops_fifo = 1;
hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate;
- hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq;
- hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout;
+ hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
+ hwif->dma_timeout = &pdc202xx_dma_timeout;
if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
- if (!(hwif->udma_four))
- hwif->udma_four = (pdc202xx_old_cable_detect(hwif)) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = pdc202xx_old_cable_detect(hwif);
+
hwif->dma_start = &pdc202xx_old_ide_dma_start;
hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
}
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 8b219dd63024..2e0b29ef596a 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/piix.c Version 0.47 February 8, 2007
+ * linux/drivers/ide/pci/piix.c Version 0.50 Jun 10, 2007
*
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -394,14 +394,45 @@ static void piix_dma_clear_irq(ide_drive_t *drive)
hwif->OUTB(dma_stat, hwif->dma_status);
}
-static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+struct ich_laptop {
+ u16 device;
+ u16 subvendor;
+ u16 subdevice;
+};
+
+/*
+ * List of laptops that use short cables rather than 80 wire
+ */
+
+static const struct ich_laptop ich_laptop[] = {
+ /* devid, subvendor, subdev */
+ { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
+ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
+ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
+ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
+ /* end marker */
+ { 0, }
+};
+
+static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *pdev = hwif->pci_dev;
+ const struct ich_laptop *lap = &ich_laptop[0];
u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
- pci_read_config_byte(dev, 0x54, &reg54h);
+ /* check for specials */
+ while (lap->device) {
+ if (lap->device == pdev->device &&
+ lap->subvendor == pdev->subsystem_vendor &&
+ lap->subdevice == pdev->subsystem_device) {
+ return ATA_CBL_PATA40_SHORT;
+ }
+ lap++;
+ }
+
+ pci_read_config_byte(pdev, 0x54, &reg54h);
- return (reg54h & mask) ? 1 : 0;
+ return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/**
@@ -444,8 +475,8 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
if (hwif->ultra_mask & 0x78) {
- if (!hwif->udma_four)
- hwif->udma_four = piix_cable_detect(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = piix_cable_detect(hwif);
}
if (no_piix_dma)
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 55bc0a32e34f..7b87488e3daa 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -716,7 +716,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
hwif->atapi_dma = 1;
/* we support 80c cable only. */
- hwif->udma_four = 1;
+ hwif->cbl = ATA_CBL_PATA80;
hwif->autodma = 0;
if (!noautodma)
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index d9c4fd1ae996..1371b5bf6bf0 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/serverworks.c Version 0.11 Jun 2 2007
+ * linux/drivers/ide/pci/serverworks.c Version 0.20 Jun 3 2007
*
* Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -151,84 +151,11 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 &&
drive->media == ide_disk && speed >= XFER_UDMA_0)
BUG();
-
- pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing);
- pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing);
+
pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
pci_read_config_word(dev, 0x4A, &csb5_pio);
pci_read_config_byte(dev, 0x54, &ultra_enable);
- /* If we are in RAID mode (eg AMI MegaIDE) then we can't it
- turns out trust the firmware configuration */
-
- if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
- goto oem_setup_failed;
-
- /* Per Specified Design by OEM, and ASIC Architect */
- if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
- (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
- if (!drive->init_speed) {
- u8 dma_stat = inb(hwif->dma_status);
-
- if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
- ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
- drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
- return 0;
- } else if ((dma_timing) &&
- ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
- u8 dmaspeed;
-
- switch (dma_timing & 0x77) {
- case 0x20:
- dmaspeed = XFER_MW_DMA_2;
- break;
- case 0x21:
- dmaspeed = XFER_MW_DMA_1;
- break;
- case 0x77:
- dmaspeed = XFER_MW_DMA_0;
- break;
- default:
- goto dma_pio;
- }
-
- drive->current_speed = drive->init_speed = dmaspeed;
- return 0;
- }
-dma_pio:
- if (pio_timing) {
- u8 piospeed;
-
- switch (pio_timing & 0x7f) {
- case 0x20:
- piospeed = XFER_PIO_4;
- break;
- case 0x22:
- piospeed = XFER_PIO_3;
- break;
- case 0x34:
- piospeed = XFER_PIO_2;
- break;
- case 0x47:
- piospeed = XFER_PIO_1;
- break;
- case 0x5d:
- piospeed = XFER_PIO_0;
- break;
- default:
- goto oem_setup_failed;
- }
-
- drive->current_speed = drive->init_speed = piospeed;
- return 0;
- }
- }
- }
-
-oem_setup_failed:
-
- pio_timing = 0;
- dma_timing = 0;
ultra_timing &= ~(0x0F << (4*unit));
ultra_enable &= ~(0x01 << drive->dn);
csb5_pio &= ~(0x0F << (4*drive->dn));
@@ -402,9 +329,9 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
return dev->irq;
}
-static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
{
- return 1;
+ return ATA_CBL_PATA80;
}
/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits
@@ -414,7 +341,7 @@ static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
* Bit 14 clear = primary IDE channel does not have 80-pin cable.
* Bit 14 set = primary IDE channel has 80-pin cable.
*/
-static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
@@ -422,8 +349,8 @@ static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE))
return ((1 << (hwif->channel + 14)) &
- dev->subsystem_device) ? 1 : 0;
- return 0;
+ dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ return ATA_CBL_PATA40;
}
/* Sun Cobalt Alpine hardware avoids the 80-pin cable
@@ -432,18 +359,18 @@ static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
*
* WARNING: this only works on Alpine hardware!
*/
-static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
return ((1 << (hwif->channel + 14)) &
- dev->subsystem_device) ? 1 : 0;
- return 0;
+ dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ return ATA_CBL_PATA40;
}
-static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
@@ -462,9 +389,9 @@ static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
/* Per Specified Design by OEM, and ASIC Architect */
if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
- return 1;
+ return ATA_CBL_PATA80;
- return 0;
+ return ATA_CBL_PATA40;
}
static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
@@ -495,8 +422,8 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
- if (!hwif->udma_four)
- hwif->udma_four = ata66_svwks(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_svwks(hwif);
}
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index d3185e29a38e..d396b2929ed8 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -316,14 +316,6 @@ static void sgiioc4_dma_host_off(ide_drive_t * drive)
sgiioc4_clearirq(drive);
}
-static int
-sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
-{
- HWIF(drive)->resetproc(drive);
-
- return __ide_dma_lostirq(drive);
-}
-
static void
sgiioc4_resetproc(ide_drive_t * drive)
{
@@ -331,6 +323,14 @@ sgiioc4_resetproc(ide_drive_t * drive)
sgiioc4_clearirq(drive);
}
+static void
+sgiioc4_dma_lost_irq(ide_drive_t * drive)
+{
+ sgiioc4_resetproc(drive);
+
+ ide_dma_lost_irq(drive);
+}
+
static u8
sgiioc4_INB(unsigned long port)
{
@@ -607,8 +607,8 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
hwif->dma_host_on = &sgiioc4_dma_host_on;
hwif->dma_host_off = &sgiioc4_dma_host_off;
- hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
- hwif->ide_dma_timeout = &__ide_dma_timeout;
+ hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
+ hwif->dma_timeout = &ide_dma_timeout;
hwif->INB = &sgiioc4_INB;
}
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 1a4444e7226a..1c3e35487893 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -933,16 +933,17 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
* interface.
*/
-static unsigned int __devinit ata66_siimage(ide_hwif_t *hwif)
+static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
{
unsigned long addr = siimage_selreg(hwif, 0);
- if (pci_get_drvdata(hwif->pci_dev) == NULL) {
- u8 ata66 = 0;
+ u8 ata66 = 0;
+
+ if (pci_get_drvdata(hwif->pci_dev) == NULL)
pci_read_config_byte(hwif->pci_dev, addr, &ata66);
- return (ata66 & 0x01) ? 1 : 0;
- }
+ else
+ ata66 = hwif->INB(addr);
- return (hwif->INB(addr) & 0x01) ? 1 : 0;
+ return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/**
@@ -988,8 +989,9 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
hwif->atapi_dma = 1;
hwif->ide_dma_check = &siimage_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_siimage(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_siimage(hwif);
if (hwif->mmio) {
hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index ec0adad9ef61..f875183ac8d9 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/sis5513.c Version 0.20 Mar 4, 2007
+ * linux/drivers/ide/pci/sis5513.c Version 0.25 Jun 10, 2007
*
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
@@ -796,10 +796,33 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
return 0;
}
-static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
+struct sis_laptop {
+ u16 device;
+ u16 subvendor;
+ u16 subdevice;
+};
+
+static const struct sis_laptop sis_laptop[] = {
+ /* devid, subvendor, subdev */
+ { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */
+ /* end marker */
+ { 0, }
+};
+
+static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
{
+ struct pci_dev *pdev = hwif->pci_dev;
+ const struct sis_laptop *lap = &sis_laptop[0];
u8 ata66 = 0;
+ while (lap->device) {
+ if (lap->device == pdev->device &&
+ lap->subvendor == pdev->subsystem_vendor &&
+ lap->subdevice == pdev->subsystem_device)
+ return ATA_CBL_PATA40_SHORT;
+ lap++;
+ }
+
if (chipset_family >= ATA_133) {
u16 regw = 0;
u16 reg_addr = hwif->channel ? 0x52: 0x50;
@@ -811,7 +834,8 @@ static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
ata66 = (reg48h & mask) ? 0 : 1;
}
- return ata66;
+
+ return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
@@ -841,8 +865,8 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
if (!chipset_family)
return;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_sis5513(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_sis5513(hwif);
if (chipset_family > ATA_16) {
hwif->ide_dma_check = &sis5513_config_xfer_rate;
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 7c383d9cc472..487879842af4 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -195,7 +195,7 @@ static inline void sl82c105_reset_host(struct pci_dev *dev)
* This function is called when the IDE timer expires, the drive
* indicates that it is READY, and we were waiting for DMA to complete.
*/
-static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
+static void sl82c105_dma_lost_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
@@ -222,9 +222,6 @@ static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
}
sl82c105_reset_host(dev);
-
- /* __ide_dma_lostirq would return 1, so we do as well */
- return 1;
}
/*
@@ -244,15 +241,12 @@ static void sl82c105_dma_start(ide_drive_t *drive)
ide_dma_start(drive);
}
-static int sl82c105_ide_dma_timeout(ide_drive_t *drive)
+static void sl82c105_dma_timeout(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
- DBG(("sl82c105_ide_dma_timeout(drive:%s)\n", drive->name));
-
- sl82c105_reset_host(dev);
- return __ide_dma_timeout(drive);
+ sl82c105_reset_host(HWIF(drive)->pci_dev);
+ ide_dma_timeout(drive);
}
static int sl82c105_ide_dma_on(ide_drive_t *drive)
@@ -441,9 +435,9 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
hwif->ide_dma_check = &sl82c105_ide_dma_check;
hwif->ide_dma_on = &sl82c105_ide_dma_on;
hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
- hwif->ide_dma_lostirq = &sl82c105_ide_dma_lostirq;
+ hwif->dma_lost_irq = &sl82c105_dma_lost_irq;
hwif->dma_start = &sl82c105_dma_start;
- hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout;
+ hwif->dma_timeout = &sl82c105_dma_timeout;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index c40f291f91e0..575dbbd8b482 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -199,10 +199,9 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
hwif->mwdma_mask = 0x06;
hwif->swdma_mask = 0x04;
- if (!hwif->udma_four) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
/* bit[0(1)]: 0:80, 1:40 */
- hwif->udma_four = (reg47 & mask) ? 0 : 1;
- }
+ hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate;
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index cee619bb2eaf..8de1f8e22494 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -220,13 +220,13 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate;
hwif->dma_start = &tc86c001_dma_start;
- if (!hwif->udma_four) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
/*
* System Control 1 Register bit 13 (PDIAGN):
* 0=80-pin cable, 1=40-pin cable
*/
scr1 = hwif->INW(sc_base + 0x00);
- hwif->udma_four = (scr1 & 0x2000) ? 0 : 1;
+ hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
if (!noautodma)
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index a508550c4095..d21dd2e7eeb3 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -1,6 +1,6 @@
/*
*
- * Version 3.38
+ * Version 3.45
*
* VIA IDE driver for Linux. Supported southbridges:
*
@@ -9,6 +9,7 @@
* vt8235, vt8237, vt8237a
*
* Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
*
* Based on the work of:
* Michel Aubry
@@ -33,6 +34,8 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/dmi.h>
+
#include <asm/io.h>
#ifdef CONFIG_PPC_CHRP
@@ -41,8 +44,6 @@
#include "ide-timing.h"
-#define DISPLAY_VIA_TIMINGS
-
#define VIA_IDE_ENABLE 0x40
#define VIA_IDE_CONFIG 0x41
#define VIA_FIFO_CONFIG 0x43
@@ -54,18 +55,12 @@
#define VIA_ADDRESS_SETUP 0x4c
#define VIA_UDMA_TIMING 0x50
-#define VIA_UDMA 0x007
-#define VIA_UDMA_NONE 0x000
-#define VIA_UDMA_33 0x001
-#define VIA_UDMA_66 0x002
-#define VIA_UDMA_100 0x003
-#define VIA_UDMA_133 0x004
-#define VIA_BAD_PREQ 0x010 /* Crashes if PREQ# till DDACK# set */
-#define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */
-#define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */
-#define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */
-#define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */
-#define VIA_BAD_AST 0x200 /* Don't touch Address Setup Timing */
+#define VIA_BAD_PREQ 0x01 /* Crashes if PREQ# till DDACK# set */
+#define VIA_BAD_CLK66 0x02 /* 66 MHz clock doesn't work correctly */
+#define VIA_SET_FIFO 0x04 /* Needs to have FIFO split set */
+#define VIA_NO_UNMASK 0x08 /* Doesn't work with IRQ unmasking on */
+#define VIA_BAD_ID 0x10 /* Has wrong vendor ID (0x1107) */
+#define VIA_BAD_AST 0x20 /* Don't touch Address Setup Timing */
/*
* VIA SouthBridge chips.
@@ -76,36 +71,37 @@ static struct via_isa_bridge {
u16 id;
u8 rev_min;
u8 rev_max;
- u16 flags;
+ u8 udma_mask;
+ u8 flags;
} via_isa_bridges[] = {
- { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 },
- { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 },
- { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
- { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 },
- { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
- { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },
- { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+ { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, ATA_UDMA5, },
+ { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, ATA_UDMA4, },
+ { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+ { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, ATA_UDMA4, },
+ { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, 0x00, VIA_SET_FIFO },
+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK },
+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
{ NULL }
};
static unsigned int via_clock;
-static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
struct via82cxxx_dev
{
@@ -140,12 +136,12 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
- case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
- case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
- case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
- default: return;
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA2: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+ case ATA_UDMA4: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
+ case ATA_UDMA5: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+ case ATA_UDMA6: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+ default: return;
}
pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
@@ -173,12 +169,12 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
T = 1000000000 / via_clock;
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_33: UT = T; break;
- case VIA_UDMA_66: UT = T/2; break;
- case VIA_UDMA_100: UT = T/3; break;
- case VIA_UDMA_133: UT = T/4; break;
- default: UT = T;
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA2: UT = T; break;
+ case ATA_UDMA4: UT = T/2; break;
+ case ATA_UDMA5: UT = T/3; break;
+ case ATA_UDMA6: UT = T/4; break;
+ default: UT = T;
}
ide_timing_compute(drive, speed, &t, T, UT);
@@ -208,8 +204,7 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
{
if (pio == 255) {
- via_set_drive(drive,
- ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+ via_set_drive(drive, ide_find_best_pio_mode(drive));
return;
}
@@ -226,16 +221,10 @@ static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
static int via82cxxx_ide_dma_check (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
- u16 w80 = hwif->udma_four;
+ u8 speed = ide_max_dma_mode(drive);
- u16 speed = ide_find_best_mode(drive,
- XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
- (vdev->via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
+ if (speed == 0)
+ speed = ide_find_best_pio_mode(drive);
via_set_drive(drive, speed);
@@ -272,8 +261,8 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
{
int i;
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_66:
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA4:
for (i = 24; i >= 0; i -= 8)
if (((u >> (i & 16)) & 8) &&
((u >> i) & 0x20) &&
@@ -286,7 +275,7 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
}
break;
- case VIA_UDMA_100:
+ case ATA_UDMA5:
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
@@ -298,7 +287,7 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
}
break;
- case VIA_UDMA_133:
+ case ATA_UDMA6:
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
@@ -353,7 +342,7 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
via_cable_detect(vdev, u);
- if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) {
+ if (via_config->udma_mask == ATA_UDMA4) {
/* Enable Clk66 */
pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
} else if (via_config->flags & VIA_BAD_CLK66) {
@@ -416,16 +405,54 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
*/
pci_read_config_byte(isa, PCI_REVISION_ID, &t);
- printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s "
+ printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
"controller on pci%s\n",
via_config->name, t,
- via_dma[via_config->flags & VIA_UDMA],
+ via_config->udma_mask ? "U" : "MW",
+ via_dma[via_config->udma_mask ?
+ (fls(via_config->udma_mask) - 1) : 0],
pci_name(dev));
pci_dev_put(isa);
return 0;
}
+/*
+ * Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+ {
+ .ident = "Acer Ferrari 3400",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),
+ DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),
+ },
+ },
+ { }
+};
+
+static int via_cable_override(void)
+{
+ /* Systems by DMI */
+ if (dmi_check_system(cable_dmi_table))
+ return 1;
+ return 0;
+}
+
+static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
+{
+ struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
+
+ if (via_cable_override())
+ return ATA_CBL_PATA40_SHORT;
+
+ if ((vdev->via_80w >> hwif->channel) & 1)
+ return ATA_CBL_PATA80;
+ else
+ return ATA_CBL_PATA40;
+}
+
static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
{
struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
@@ -454,12 +481,14 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
return;
hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
+
+ hwif->ultra_mask = vdev->via_config->udma_mask;
hwif->mwdma_mask = 0x07;
hwif->swdma_mask = 0x07;
- if (!hwif->udma_four)
- hwif->udma_four = (vdev->via_80w >> hwif->channel) & 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = via82cxxx_cable_detect(hwif);
+
hwif->ide_dma_check = &via82cxxx_ide_dma_check;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 45fc36f0f219..e46f47206542 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -942,8 +942,8 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
return 1;
case XFER_UDMA_4:
case XFER_UDMA_3:
- if (HWIF(drive)->udma_four == 0)
- return 1;
+ if (drive->hwif->cbl != ATA_CBL_PATA80)
+ return 1;
case XFER_UDMA_2:
case XFER_UDMA_1:
case XFER_UDMA_0:
@@ -1244,7 +1244,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->chipset = ide_pmac;
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
hwif->hold = pmif->mediabay;
- hwif->udma_four = pmif->cable_80;
+ hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
hwif->drives[0].unmask = 1;
hwif->drives[1].unmask = 1;
hwif->tuneproc = pmac_ide_tuneproc;
@@ -1821,28 +1821,11 @@ pmac_ide_dma_check(ide_drive_t *drive)
enable = 0;
if (enable) {
- short mode;
-
- map = XFER_MWDMA;
- if (pmif->kind == controller_kl_ata4
- || pmif->kind == controller_un_ata6
- || pmif->kind == controller_k2_ata6
- || pmif->kind == controller_sh_ata6) {
- map |= XFER_UDMA;
- if (pmif->cable_80) {
- map |= XFER_UDMA_66;
- if (pmif->kind == controller_un_ata6 ||
- pmif->kind == controller_k2_ata6 ||
- pmif->kind == controller_sh_ata6)
- map |= XFER_UDMA_100;
- if (pmif->kind == controller_sh_ata6)
- map |= XFER_UDMA_133;
- }
- }
- mode = ide_find_best_mode(drive, map);
- if (mode & XFER_UDMA)
+ u8 mode = ide_max_dma_mode(drive);
+
+ if (mode >= XFER_UDMA_0)
drive->using_dma = pmac_ide_udma_enable(drive, mode);
- else if (mode & XFER_MWDMA)
+ else if (mode >= XFER_MW_DMA_0)
drive->using_dma = pmac_ide_mdma_enable(drive, mode);
hwif->OUTB(0, IDE_CONTROL_REG);
/* Apply settings to controller */
@@ -2004,20 +1987,19 @@ static void pmac_ide_dma_host_on(ide_drive_t *drive)
{
}
-static int
-pmac_ide_dma_lostirq (ide_drive_t *drive)
+static void
+pmac_ide_dma_lost_irq (ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
volatile struct dbdma_regs __iomem *dma;
unsigned long status;
if (pmif == NULL)
- return 0;
+ return;
dma = pmif->dma_regs;
status = readl(&dma->status);
printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
- return 0;
}
/*
@@ -2057,8 +2039,8 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
hwif->dma_host_off = &pmac_ide_dma_host_off;
hwif->dma_host_on = &pmac_ide_dma_host_on;
- hwif->ide_dma_timeout = &__ide_dma_timeout;
- hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
+ hwif->dma_timeout = &ide_dma_timeout;
+ hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
hwif->atapi_dma = 1;
switch(pmif->kind) {
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 208141377612..65722117ab6e 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2280,7 +2280,7 @@ static void dv1394_remove_host(struct hpsb_host *host)
} while (video);
if (found_ohci_card)
- class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+ device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
}
@@ -2295,9 +2295,9 @@ static void dv1394_add_host(struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
- NULL, "dv1394-%d", id);
+ device_create(hpsb_protocol_class, NULL, MKDEV(
+ IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+ "dv1394-%d", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 7c13fb3c167b..93362eed94ed 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -599,9 +599,7 @@ static void ether1394_add_host(struct hpsb_host *host)
}
SET_MODULE_OWNER(dev);
-
- /* This used to be &host->device in Linux 2.6.20 and before. */
- SET_NETDEV_DEV(dev, host->device.parent);
+ SET_NETDEV_DEV(dev, &host->device);
priv = netdev_priv(dev);
INIT_LIST_HEAD(&priv->ip_node_list);
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 83a493312751..b6425469b6ee 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -483,37 +483,6 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval;
}
-/**
- * hpsb_listen_channel - enable receving a certain isochronous channel
- *
- * Reception is handled through the @hl's iso_receive op.
- */
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel)
-{
- if (channel > 63) {
- HPSB_ERR("%s called with invalid channel", __FUNCTION__);
- return -EINVAL;
- }
- if (host->iso_listen_count[channel]++ == 0)
- return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
- return 0;
-}
-
-/**
- * hpsb_unlisten_channel - disable receving a certain isochronous channel
- */
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel)
-{
- if (channel > 63) {
- HPSB_ERR("%s called with invalid channel", __FUNCTION__);
- return;
- }
- if (--host->iso_listen_count[channel] == 0)
- host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
-}
-
static void init_hpsb_highlevel(struct hpsb_host *host)
{
INIT_LIST_HEAD(&dummy_zero_addr.host_list);
@@ -570,20 +539,6 @@ void highlevel_host_reset(struct hpsb_host *host)
read_unlock_irqrestore(&hl_irqs_lock, flags);
}
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
-{
- unsigned long flags;
- struct hpsb_highlevel *hl;
- int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
-
- read_lock_irqsave(&hl_irqs_lock, flags);
- list_for_each_entry(hl, &hl_irqs, irq_list) {
- if (hl->iso_receive)
- hl->iso_receive(host, channel, data, length);
- }
- read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length)
{
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
index 63474f7ee69d..eb9fe321e09a 100644
--- a/drivers/ieee1394/highlevel.h
+++ b/drivers/ieee1394/highlevel.h
@@ -26,9 +26,7 @@ struct hpsb_address_serve {
struct hpsb_highlevel {
const char *name;
- /* Any of the following pointers can legally be NULL, except for
- * iso_receive which can only be NULL when you don't request
- * channels. */
+ /* Any of the following pointers can legally be NULL. */
/* New host initialized. Will also be called during
* hpsb_register_highlevel for all hosts already installed. */
@@ -43,13 +41,6 @@ struct hpsb_highlevel {
* You can not expect to be able to do stock hpsb_reads. */
void (*host_reset)(struct hpsb_host *host);
- /* An isochronous packet was received. Channel contains the channel
- * number for your convenience, it is also contained in the included
- * packet header (first quadlet, CRCs are missing). You may get called
- * for channel/host combinations you did not request. */
- void (*iso_receive)(struct hpsb_host *host, int channel,
- quadlet_t *data, size_t length);
-
/* A write request was received on either the FCP_COMMAND (direction =
* 0) or the FCP_RESPONSE (direction = 1) register. The cts arg
* contains the cts field (first byte of data). */
@@ -109,7 +100,6 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags);
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length);
@@ -125,10 +115,6 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start);
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel);
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel);
void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index bd0755c789c5..8dd09d850419 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -154,15 +154,16 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev;
+ set_dev_node(&h->device, dev_to_node(dev));
snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
- h->class_dev.dev = &h->device;
- h->class_dev.class = &hpsb_host_class;
- snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
+ h->host_dev.parent = &h->device;
+ h->host_dev.class = &hpsb_host_class;
+ snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
if (device_register(&h->device))
goto fail;
- if (class_device_register(&h->class_dev)) {
+ if (device_register(&h->host_dev)) {
device_unregister(&h->device);
goto fail;
}
@@ -202,7 +203,7 @@ void hpsb_remove_host(struct hpsb_host *host)
host->driver = &dummy_driver;
highlevel_remove_host(host);
- class_device_unregister(&host->class_dev);
+ device_unregister(&host->host_dev);
device_unregister(&host->device);
}
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index feb55d032294..e4e8aeb4d778 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -28,8 +28,6 @@ struct hpsb_host {
struct timer_list timeout;
unsigned long timeout_interval;
- unsigned char iso_listen_count[64];
-
int node_count; /* number of identified nodes on this bus */
int selfid_count; /* total number of SelfIDs received */
int nodes_active; /* number of nodes with active link layer */
@@ -57,7 +55,7 @@ struct hpsb_host {
struct hpsb_host_driver *driver;
struct pci_dev *pdev;
struct device device;
- struct class_device class_dev;
+ struct device host_dev;
struct delayed_work delayed_reset;
unsigned config_roms:31;
@@ -99,12 +97,6 @@ enum devctl_cmd {
/* Cancel all outstanding async requests without resetting the bus.
* Return void. */
CANCEL_REQUESTS,
-
- /* Start or stop receiving isochronous channel in arg. Return void.
- * This acts as an optimization hint, hosts are not required not to
- * listen on unrequested channels. */
- ISO_LISTEN_CHANNEL,
- ISO_UNLISTEN_CHANNEL
};
enum isoctl_cmd {
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 8f71b6a06aa0..0fc8c6e559e4 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -1028,11 +1028,6 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
handle_incoming_packet(host, tcode, data, size, write_acked);
break;
-
- case TCODE_ISO_DATA:
- highlevel_iso_receive(host, data, size);
- break;
-
case TCODE_CYCLE_START:
/* simply ignore this packet if it is passed on */
break;
@@ -1316,7 +1311,6 @@ EXPORT_SYMBOL(hpsb_make_streampacket);
EXPORT_SYMBOL(hpsb_make_lockpacket);
EXPORT_SYMBOL(hpsb_make_lock64packet);
EXPORT_SYMBOL(hpsb_make_phypacket);
-EXPORT_SYMBOL(hpsb_make_isopacket);
EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_packet_success);
@@ -1327,8 +1321,6 @@ EXPORT_SYMBOL(hpsb_unregister_highlevel);
EXPORT_SYMBOL(hpsb_register_addrspace);
EXPORT_SYMBOL(hpsb_unregister_addrspace);
EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
-EXPORT_SYMBOL(hpsb_listen_channel);
-EXPORT_SYMBOL(hpsb_unlisten_channel);
EXPORT_SYMBOL(hpsb_get_hostinfo);
EXPORT_SYMBOL(hpsb_create_hostinfo);
EXPORT_SYMBOL(hpsb_destroy_hostinfo);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index ad526523d0ef..21d50f73a210 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -24,9 +24,8 @@ struct hpsb_packet {
nodeid_t node_id;
- /* Async and Iso types should be clear, raw means send-as-is, do not
- * CRC! Byte swapping shall still be done in this case. */
- enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+ /* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
+ enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
/* Okay, this is core internal and a no care for hosts.
* queued = queued for sending
@@ -37,7 +36,7 @@ struct hpsb_packet {
hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
} __attribute__((packed)) state;
- /* These are core internal. */
+ /* These are core-internal. */
signed char tlabel;
signed char ack_code;
unsigned char tcode;
@@ -62,11 +61,15 @@ struct hpsb_packet {
/* Store jiffies for implementing bus timeouts. */
unsigned long sendtime;
- /* Sizes are in bytes. *data can be DMA-mapped. */
+ /* Core-internal. */
size_t allocated_data_size; /* as allocated */
+
+ /* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
size_t data_size; /* as filled in */
size_t header_size; /* as filled in, not counting the CRC */
- quadlet_t *data;
+
+ /* Buffers */
+ quadlet_t *data; /* can be DMA-mapped */
quadlet_t header[5];
quadlet_t embedded_data[0]; /* keep as last member */
};
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 40078ce930c8..c39c70a8aa9f 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -89,18 +89,6 @@ static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
packet->expect_response = 1;
}
-static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
- int tag, int sync)
-{
- packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
- | (TCODE_ISO_DATA << 4) | sync;
-
- packet->header_size = 4;
- packet->data_size = length;
- packet->type = hpsb_iso;
- packet->tcode = TCODE_ISO_DATA;
-}
-
static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
{
packet->header[0] = data;
@@ -491,24 +479,6 @@ struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
return p;
}
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
- int length, int channel,
- int tag, int sync)
-{
- struct hpsb_packet *p;
-
- p = hpsb_alloc_packet(length);
- if (!p)
- return NULL;
-
- p->host = host;
- fill_iso_packet(p, length, channel, tag, sync);
-
- p->generation = get_hpsb_generation(host);
-
- return p;
-}
-
/*
* FIXME - these functions should probably read from / write to user space to
* avoid in kernel buffers for user space callers
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 86b8ee692ea7..d2d5bc3546d7 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -19,8 +19,6 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
nodeid_t node, u64 addr, int extcode,
octlet_t *data, octlet_t arg);
struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length,
- int channel, int tag, int sync);
struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
nodeid_t node, u64 addr,
quadlet_t *buffer, size_t length);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 81b3864d2ba7..c4d3d4131f01 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,6 +19,7 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <asm/atomic.h>
+#include <asm/semaphore.h>
#include "csr.h"
#include "highlevel.h"
@@ -145,8 +146,6 @@ static struct csr1212_bus_ops nodemgr_csr_ops = {
* but now we are much simpler because of the LDM.
*/
-static DEFINE_MUTEX(nodemgr_serialize);
-
struct host_info {
struct hpsb_host *host;
struct list_head list;
@@ -154,7 +153,7 @@ struct host_info {
};
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size);
static void nodemgr_resume_ne(struct node_entry *ne);
static void nodemgr_remove_ne(struct node_entry *ne);
@@ -165,37 +164,38 @@ struct bus_type ieee1394_bus_type = {
.match = nodemgr_bus_match,
};
-static void host_cls_release(struct class_device *class_dev)
+static void host_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device);
+ put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
}
struct class hpsb_host_class = {
.name = "ieee1394_host",
- .release = host_cls_release,
+ .dev_release = host_cls_release,
};
-static void ne_cls_release(struct class_device *class_dev)
+static void ne_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
+ put_device(&container_of((dev), struct node_entry, node_dev)->device);
}
static struct class nodemgr_ne_class = {
.name = "ieee1394_node",
- .release = ne_cls_release,
+ .dev_release = ne_cls_release,
};
-static void ud_cls_release(struct class_device *class_dev)
+static void ud_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct unit_directory, class_dev)->device);
+ put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
}
/* The name here is only so that unit directory hotplug works with old
- * style hotplug, which only ever did unit directories anyway. */
+ * style hotplug, which only ever did unit directories anyway.
+ */
static struct class nodemgr_ud_class = {
.name = "ieee1394",
- .release = ud_cls_release,
- .uevent = nodemgr_uevent,
+ .dev_release = ud_cls_release,
+ .dev_uevent = nodemgr_uevent,
};
static struct hpsb_highlevel nodemgr_highlevel;
@@ -730,11 +730,11 @@ static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
static void nodemgr_remove_uds(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *tmp, *ud;
- /* Iteration over nodemgr_ud_class.children has to be protected by
- * nodemgr_ud_class.sem, but class_device_unregister() will eventually
+ /* Iteration over nodemgr_ud_class.devices has to be protected by
+ * nodemgr_ud_class.sem, but device_unregister() will eventually
* take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
* release the semaphore, and then unregister the ud. Since this code
* may be called from other contexts besides the knodemgrds, protect the
@@ -744,9 +744,9 @@ static void nodemgr_remove_uds(struct node_entry *ne)
for (;;) {
ud = NULL;
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- tmp = container_of(cdev, struct unit_directory,
- class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ tmp = container_of(dev, struct unit_directory,
+ unit_dev);
if (tmp->ne == ne) {
ud = tmp;
break;
@@ -755,7 +755,7 @@ static void nodemgr_remove_uds(struct node_entry *ne)
up(&nodemgr_ud_class.sem);
if (ud == NULL)
break;
- class_device_unregister(&ud->class_dev);
+ device_unregister(&ud->unit_dev);
device_unregister(&ud->device);
}
mutex_unlock(&nodemgr_serialize_remove_uds);
@@ -772,10 +772,9 @@ static void nodemgr_remove_ne(struct node_entry *ne)
HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-
nodemgr_remove_uds(ne);
- class_device_unregister(&ne->class_dev);
+ device_unregister(&ne->node_dev);
device_unregister(dev);
put_device(dev);
@@ -783,7 +782,9 @@ static void nodemgr_remove_ne(struct node_entry *ne)
static int __nodemgr_remove_host_dev(struct device *dev, void *data)
{
- nodemgr_remove_ne(container_of(dev, struct node_entry, device));
+ if (dev->bus == &ieee1394_bus_type)
+ nodemgr_remove_ne(container_of(dev, struct node_entry,
+ device));
return 0;
}
@@ -850,14 +851,14 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
(unsigned long long)(ne->guid));
- ne->class_dev.dev = &ne->device;
- ne->class_dev.class = &nodemgr_ne_class;
- snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
- (unsigned long long)(ne->guid));
+ ne->node_dev.parent = &ne->device;
+ ne->node_dev.class = &nodemgr_ne_class;
+ snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
+ (unsigned long long)(ne->guid));
if (device_register(&ne->device))
goto fail_devreg;
- if (class_device_register(&ne->class_dev))
+ if (device_register(&ne->node_dev))
goto fail_classdevreg;
get_device(&ne->device);
@@ -885,12 +886,12 @@ fail_alloc:
static struct node_entry *find_entry_by_guid(u64 guid)
{
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne, *ret_ne = NULL;
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->guid == guid) {
ret_ne = ne;
@@ -906,12 +907,12 @@ static struct node_entry *find_entry_by_guid(u64 guid)
static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
nodeid_t nodeid)
{
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne, *ret_ne = NULL;
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->host == host && ne->nodeid == nodeid) {
ret_ne = ne;
@@ -935,14 +936,14 @@ static void nodemgr_register_device(struct node_entry *ne,
snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id);
- ud->class_dev.dev = &ud->device;
- ud->class_dev.class = &nodemgr_ud_class;
- snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
+ ud->unit_dev.parent = &ud->device;
+ ud->unit_dev.class = &nodemgr_ud_class;
+ snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id);
if (device_register(&ud->device))
goto fail_devreg;
- if (class_device_register(&ud->class_dev))
+ if (device_register(&ud->unit_dev))
goto fail_classdevreg;
get_device(&ud->device);
@@ -1159,7 +1160,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
#ifdef CONFIG_HOTPLUG
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct unit_directory *ud;
@@ -1169,10 +1170,10 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
/* ieee1394:venNmoNspNverN */
char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
- if (!cdev)
+ if (!dev)
return -ENODEV;
- ud = container_of(cdev, struct unit_directory, class_dev);
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne->in_limbo || ud->ignore_driver)
return -ENODEV;
@@ -1207,7 +1208,7 @@ do { \
#else
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
return -ENODEV;
@@ -1378,8 +1379,10 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
static void nodemgr_suspend_ne(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
+ int error;
HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
@@ -1388,15 +1391,24 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver &&
- (!ud->device.driver->suspend ||
- ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ error = 1; /* release if suspend is not implemented */
+ if (drv->suspend) {
+ down(&ud->device.sem);
+ error = drv->suspend(&ud->device, PMSG_SUSPEND);
+ up(&ud->device.sem);
+ }
+ if (error)
device_release_driver(&ud->device);
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
}
@@ -1404,20 +1416,29 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
static void nodemgr_resume_ne(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
ne->in_limbo = 0;
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver && ud->device.driver->resume)
- ud->device.driver->resume(&ud->device);
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ if (drv->resume) {
+ down(&ud->device.sem);
+ drv->resume(&ud->device);
+ up(&ud->device.sem);
+ }
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
@@ -1428,23 +1449,32 @@ static void nodemgr_resume_ne(struct node_entry *ne)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
struct hpsb_protocol_driver *pdrv;
- struct class_device *cdev;
+ int error;
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver) {
- pdrv = container_of(ud->device.driver,
- struct hpsb_protocol_driver,
- driver);
- if (pdrv->update && pdrv->update(ud))
- device_release_driver(&ud->device);
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ error = 0;
+ pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
+ if (pdrv->update) {
+ down(&ud->device.sem);
+ error = pdrv->update(ud);
+ up(&ud->device.sem);
}
+ if (error)
+ device_release_driver(&ud->device);
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
}
@@ -1509,7 +1539,7 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
static void nodemgr_node_probe(struct host_info *hi, int generation)
{
struct hpsb_host *host = hi->host;
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne;
/* Do some processing of the nodes we've probed. This pulls them
@@ -1522,13 +1552,13 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
* improvement...) */
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (!ne->needs_probe)
nodemgr_probe_ne(hi, ne, generation);
}
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->needs_probe)
nodemgr_probe_ne(hi, ne, generation);
}
@@ -1686,18 +1716,12 @@ static int nodemgr_host_thread(void *__hi)
if (kthread_should_stop())
goto exit;
- if (mutex_lock_interruptible(&nodemgr_serialize)) {
- if (try_to_freeze())
- continue;
- goto exit;
- }
-
/* Pause for 1/4 second in 1/16 second intervals,
* to make sure things settle down. */
g = get_hpsb_generation(host);
for (i = 0; i < 4 ; i++) {
if (msleep_interruptible(63) || kthread_should_stop())
- goto unlock_exit;
+ goto exit;
/* Now get the generation in which the node ID's we collect
* are valid. During the bus scan we will use this generation
@@ -1715,7 +1739,6 @@ static int nodemgr_host_thread(void *__hi)
if (!nodemgr_check_irm_capability(host, reset_cycles) ||
!nodemgr_do_irm_duties(host, reset_cycles)) {
reset_cycles++;
- mutex_unlock(&nodemgr_serialize);
continue;
}
reset_cycles = 0;
@@ -1732,11 +1755,7 @@ static int nodemgr_host_thread(void *__hi)
/* Update some of our sysfs symlinks */
nodemgr_update_host_dev_links(host);
-
- mutex_unlock(&nodemgr_serialize);
}
-unlock_exit:
- mutex_unlock(&nodemgr_serialize);
exit:
HPSB_VERBOSE("NodeMgr: Exiting thread");
return 0;
@@ -1756,13 +1775,13 @@ exit:
*/
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
{
- struct class_device *cdev;
+ struct device *dev;
struct hpsb_host *host;
int error = 0;
down(&hpsb_host_class.sem);
- list_for_each_entry(cdev, &hpsb_host_class.children, node) {
- host = container_of(cdev, struct hpsb_host, class_dev);
+ list_for_each_entry(dev, &hpsb_host_class.devices, node) {
+ host = container_of(dev, struct hpsb_host, host_dev);
if ((error = cb(host, data)))
break;
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 4530b29d941c..919e92e2a955 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -84,7 +84,7 @@ struct unit_directory {
int length; /* Number of quadlets */
struct device device;
- struct class_device class_dev;
+ struct device unit_dev;
struct csr1212_keyval *ud_kv;
u32 lun; /* logical unit number immediate value */
@@ -107,7 +107,7 @@ struct node_entry {
u32 capabilities;
struct device device;
- struct class_device class_dev;
+ struct device node_dev;
/* Means this node is not attached anymore */
int in_limbo;
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 5dadfd296f79..5667c8102efc 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -138,19 +138,6 @@ printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->
#define DBGMSG(fmt, args...) do {} while (0)
#endif
-#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
-#define OHCI_DMA_ALLOC(fmt, args...) \
- HPSB_ERR("%s(%s)alloc(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
- ++global_outstanding_dmas, ## args)
-#define OHCI_DMA_FREE(fmt, args...) \
- HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
- --global_outstanding_dmas, ## args)
-static int global_outstanding_dmas = 0;
-#else
-#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0)
-#define OHCI_DMA_FREE(fmt, args...) do {} while (0)
-#endif
-
/* print general (card independent) information */
#define PRINT_G(level, fmt, args...) \
printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
@@ -170,7 +157,6 @@ static void dma_trm_reset(struct dma_trm_ctx *d);
static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
enum context_type type, int ctx, int num_desc,
int buf_size, int split_buf_size, int context_base);
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
@@ -533,9 +519,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
initialize_dma_trm_ctx(&ohci->at_req_context);
initialize_dma_trm_ctx(&ohci->at_resp_context);
- /* Initialize IR Legacy DMA channel mask */
- ohci->ir_legacy_channels = 0;
-
/* Accept AR requests from all nodes */
reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
@@ -733,7 +716,6 @@ static void insert_packet(struct ti_ohci *ohci,
pci_map_single(ohci->dev, packet->data,
packet->data_size,
PCI_DMA_TODEVICE));
- OHCI_DMA_ALLOC("single, block transmit packet");
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
@@ -783,7 +765,6 @@ static void insert_packet(struct ti_ohci *ohci,
d->prg_cpu[idx]->end.address = cpu_to_le32(
pci_map_single(ohci->dev, packet->data,
packet->data_size, PCI_DMA_TODEVICE));
- OHCI_DMA_ALLOC("single, iso transmit packet");
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
@@ -884,36 +865,9 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
return -EOVERFLOW;
}
- /* Decide whether we have an iso, a request, or a response packet */
if (packet->type == hpsb_raw)
d = &ohci->at_req_context;
- else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
- /* The legacy IT DMA context is initialized on first
- * use. However, the alloc cannot be run from
- * interrupt context, so we bail out if that is the
- * case. I don't see anyone sending ISO packets from
- * interrupt context anyway... */
-
- if (ohci->it_legacy_context.ohci == NULL) {
- if (in_interrupt()) {
- PRINT(KERN_ERR,
- "legacy IT context cannot be initialized during interrupt");
- return -EINVAL;
- }
-
- if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
- DMA_CTX_ISO, 0, IT_NUM_DESC,
- OHCI1394_IsoXmitContextBase) < 0) {
- PRINT(KERN_ERR,
- "error initializing legacy IT context");
- return -ENOMEM;
- }
-
- initialize_dma_trm_ctx(&ohci->it_legacy_context);
- }
-
- d = &ohci->it_legacy_context;
- } else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
+ else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
d = &ohci->at_resp_context;
else
d = &ohci->at_req_context;
@@ -932,9 +886,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
{
struct ti_ohci *ohci = host->hostdata;
- int retval = 0;
- unsigned long flags;
- int phy_reg;
+ int retval = 0, phy_reg;
switch (cmd) {
case RESET_BUS:
@@ -1027,117 +979,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
dma_trm_reset(&ohci->at_resp_context);
break;
- case ISO_LISTEN_CHANNEL:
- {
- u64 mask;
- struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
- int ir_legacy_active;
-
- if (arg<0 || arg>63) {
- PRINT(KERN_ERR,
- "%s: IS0 listen channel %d is out of range",
- __FUNCTION__, arg);
- return -EFAULT;
- }
-
- mask = (u64)0x1<<arg;
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (ohci->ISO_channel_usage & mask) {
- PRINT(KERN_ERR,
- "%s: IS0 listen channel %d is already used",
- __FUNCTION__, arg);
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- return -EFAULT;
- }
-
- ir_legacy_active = ohci->ir_legacy_channels;
-
- ohci->ISO_channel_usage |= mask;
- ohci->ir_legacy_channels |= mask;
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-
- if (!ir_legacy_active) {
- if (ohci1394_register_iso_tasklet(ohci,
- &ohci->ir_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, "No IR DMA context available");
- return -EBUSY;
- }
-
- /* the IR context can be assigned to any DMA context
- * by ohci1394_register_iso_tasklet */
- d->ctx = ohci->ir_legacy_tasklet.context;
- d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
- 32*d->ctx;
- d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
- 32*d->ctx;
- d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
- d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
-
- initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
- if (printk_ratelimit())
- DBGMSG("IR legacy activated");
- }
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (arg>31)
- reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
- 1<<(arg-32));
- else
- reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
- 1<<arg);
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- DBGMSG("Listening enabled on channel %d", arg);
- break;
- }
- case ISO_UNLISTEN_CHANNEL:
- {
- u64 mask;
-
- if (arg<0 || arg>63) {
- PRINT(KERN_ERR,
- "%s: IS0 unlisten channel %d is out of range",
- __FUNCTION__, arg);
- return -EFAULT;
- }
-
- mask = (u64)0x1<<arg;
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (!(ohci->ISO_channel_usage & mask)) {
- PRINT(KERN_ERR,
- "%s: IS0 unlisten channel %d is not used",
- __FUNCTION__, arg);
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- return -EFAULT;
- }
-
- ohci->ISO_channel_usage &= ~mask;
- ohci->ir_legacy_channels &= ~mask;
-
- if (arg>31)
- reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear,
- 1<<(arg-32));
- else
- reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear,
- 1<<arg);
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- DBGMSG("Listening disabled on channel %d", arg);
-
- if (ohci->ir_legacy_channels == 0) {
- stop_dma_rcv_ctx(&ohci->ir_legacy_context);
- DBGMSG("ISO legacy receive context stopped");
- }
-
- break;
- }
default:
PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
cmd);
@@ -2869,12 +2710,10 @@ static void dma_trm_tasklet (unsigned long data)
list_del_init(&packet->driver_list);
hpsb_packet_sent(ohci->host, packet, ack);
- if (datasize) {
+ if (datasize)
pci_unmap_single(ohci->dev,
cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
datasize, PCI_DMA_TODEVICE);
- OHCI_DMA_FREE("single Xmit data packet");
- }
d->sent_ind = (d->sent_ind+1)%d->num_desc;
d->free_prgs++;
@@ -2885,22 +2724,6 @@ static void dma_trm_tasklet (unsigned long data)
spin_unlock_irqrestore(&d->lock, flags);
}
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d)
-{
- if (d->ctrlClear) {
- ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
-
- if (d->type == DMA_CTX_ISO) {
- /* disable interrupts */
- reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx);
- ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet);
- } else {
- tasklet_kill(&d->task);
- }
- }
-}
-
-
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
{
int i;
@@ -2913,23 +2736,19 @@ static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
if (d->buf_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->buf_cpu[i] && d->buf_bus[i]) {
+ if (d->buf_cpu[i] && d->buf_bus[i])
pci_free_consistent(
ohci->dev, d->buf_size,
d->buf_cpu[i], d->buf_bus[i]);
- OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i);
- }
kfree(d->buf_cpu);
kfree(d->buf_bus);
}
if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->prg_cpu[i] && d->prg_bus[i]) {
- pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
- OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i);
- }
+ if (d->prg_cpu[i] && d->prg_bus[i])
+ pci_pool_free(d->prg_pool, d->prg_cpu[i],
+ d->prg_bus[i]);
pci_pool_destroy(d->prg_pool);
- OHCI_DMA_FREE("dma_rcv prg pool");
kfree(d->prg_cpu);
kfree(d->prg_bus);
}
@@ -2998,13 +2817,10 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
}
num_allocs++;
- OHCI_DMA_ALLOC("dma_rcv prg pool");
-
for (i=0; i<d->num_desc; i++) {
d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
d->buf_size,
d->buf_bus+i);
- OHCI_DMA_ALLOC("consistent dma_rcv buf[%d]", i);
if (d->buf_cpu[i] != NULL) {
memset(d->buf_cpu[i], 0, d->buf_size);
@@ -3016,7 +2832,6 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
}
d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
- OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
@@ -3030,18 +2845,11 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
spin_lock_init(&d->lock);
- if (type == DMA_CTX_ISO) {
- ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
- OHCI_ISO_MULTICHANNEL_RECEIVE,
- dma_rcv_tasklet, (unsigned long) d);
- } else {
- d->ctrlSet = context_base + OHCI1394_ContextControlSet;
- d->ctrlClear = context_base + OHCI1394_ContextControlClear;
- d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-
- tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d);
- }
+ d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+ d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+ d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+ tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
return 0;
}
@@ -3057,12 +2865,10 @@ static void free_dma_trm_ctx(struct dma_trm_ctx *d)
if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->prg_cpu[i] && d->prg_bus[i]) {
- pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
- OHCI_DMA_FREE("pool dma_trm prg[%d]", i);
- }
+ if (d->prg_cpu[i] && d->prg_bus[i])
+ pci_pool_free(d->prg_pool, d->prg_cpu[i],
+ d->prg_bus[i]);
pci_pool_destroy(d->prg_pool);
- OHCI_DMA_FREE("dma_trm prg pool");
kfree(d->prg_cpu);
kfree(d->prg_bus);
}
@@ -3108,11 +2914,8 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
}
num_allocs++;
- OHCI_DMA_ALLOC("dma_rcv prg pool");
-
for (i = 0; i < d->num_desc; i++) {
d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
- OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
@@ -3127,28 +2930,10 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
spin_lock_init(&d->lock);
/* initialize tasklet */
- if (type == DMA_CTX_ISO) {
- ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT,
- dma_trm_tasklet, (unsigned long) d);
- if (ohci1394_register_iso_tasklet(ohci,
- &ohci->it_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, "No IT DMA context available");
- free_dma_trm_ctx(d);
- return -EBUSY;
- }
-
- /* IT can be assigned to any context by register_iso_tasklet */
- d->ctx = ohci->it_legacy_tasklet.context;
- d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx;
- d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx;
- d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx;
- } else {
- d->ctrlSet = context_base + OHCI1394_ContextControlSet;
- d->ctrlClear = context_base + OHCI1394_ContextControlClear;
- d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
- tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d);
- }
-
+ d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+ d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+ d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+ tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
return 0;
}
@@ -3294,7 +3079,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->csr_config_rom_cpu =
pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
&ohci->csr_config_rom_bus);
- OHCI_DMA_ALLOC("consistent csr_config_rom");
if (ohci->csr_config_rom_cpu == NULL)
FAIL(-ENOMEM, "Failed to allocate buffer config rom");
ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
@@ -3303,8 +3087,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->selfid_buf_cpu =
pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
&ohci->selfid_buf_bus);
- OHCI_DMA_ALLOC("consistent selfid_buf");
-
if (ohci->selfid_buf_cpu == NULL)
FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
@@ -3377,20 +3159,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->ISO_channel_usage = 0;
spin_lock_init(&ohci->IR_channel_lock);
- /* Allocate the IR DMA context right here so we don't have
- * to do it in interrupt path - note that this doesn't
- * waste much memory and avoids the jugglery required to
- * allocate it in IRQ path. */
- if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
- DMA_CTX_ISO, 0, IR_NUM_DESC,
- IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
- OHCI1394_IsoRcvContextBase) < 0) {
- FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
- }
-
- /* We hopefully don't have to pre-allocate IT DMA like we did
- * for IR DMA above. Allocate it on-demand and mark inactive. */
- ohci->it_legacy_context.ohci = NULL;
spin_lock_init(&ohci->event_lock);
/*
@@ -3483,20 +3251,16 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
free_dma_rcv_ctx(&ohci->ar_resp_context);
free_dma_trm_ctx(&ohci->at_req_context);
free_dma_trm_ctx(&ohci->at_resp_context);
- free_dma_rcv_ctx(&ohci->ir_legacy_context);
- free_dma_trm_ctx(&ohci->it_legacy_context);
case OHCI_INIT_HAVE_SELFID_BUFFER:
pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
ohci->selfid_buf_cpu,
ohci->selfid_buf_bus);
- OHCI_DMA_FREE("consistent selfid_buf");
case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
ohci->csr_config_rom_cpu,
ohci->csr_config_rom_bus);
- OHCI_DMA_FREE("consistent csr_config_rom");
case OHCI_INIT_HAVE_IOMAPPING:
iounmap(ohci->registers);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index f1ad539e7c1b..4320bf010495 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -190,23 +190,10 @@ struct ti_ohci {
unsigned long ir_multichannel_used; /* ditto */
spinlock_t IR_channel_lock;
- /* iso receive (legacy API) */
- u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
- it only accounts for channels listened to
- by the legacy API, so that we can know when
- it is safe to free the legacy API context */
-
- struct dma_rcv_ctx ir_legacy_context;
- struct ohci1394_iso_tasklet ir_legacy_tasklet;
-
/* iso transmit */
int nb_iso_xmit_ctx;
unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
- /* iso transmit (legacy API) */
- struct dma_trm_ctx it_legacy_context;
- struct ohci1394_iso_tasklet it_legacy_tasklet;
-
u64 ISO_channel_usage;
/* IEEE-1394 part follows */
@@ -221,7 +208,6 @@ struct ti_ohci {
/* Tasklets for iso receive and transmit, used by video1394
* and dv1394 */
-
struct list_head iso_tasklet_list;
spinlock_t iso_tasklet_list_lock;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 0742befe9227..d1a5bcdb5e0b 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -477,7 +477,11 @@ static void send_next(struct ti_lynx *lynx, int what)
struct lynx_send_data *d;
struct hpsb_packet *packet;
+#if 0 /* has been removed from ieee1394 core */
d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
+#else
+ d = &lynx->async;
+#endif
if (!list_empty(&d->pcl_queue)) {
PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
BUG();
@@ -511,9 +515,11 @@ static void send_next(struct ti_lynx *lynx, int what)
case hpsb_async:
pcl.buffer[0].control |= PCL_CMD_XMT;
break;
+#if 0 /* has been removed from ieee1394 core */
case hpsb_iso:
pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
break;
+#endif
case hpsb_raw:
pcl.buffer[0].control |= PCL_CMD_UNFXMT;
break;
@@ -542,9 +548,11 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
case hpsb_raw:
d = &lynx->async;
break;
+#if 0 /* has been removed from ieee1394 core */
case hpsb_iso:
d = &lynx->iso_send;
break;
+#endif
default:
PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
packet->type);
@@ -797,7 +805,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
}
break;
-
+#if 0 /* has been removed from ieee1394 core */
case ISO_LISTEN_CHANNEL:
spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
@@ -819,7 +827,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
break;
-
+#endif
default:
PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
retval = -1;
@@ -1009,11 +1017,11 @@ static irqreturn_t lynx_irq_handler(int irq, void *dev_id)
pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
packet->data_size, PCI_DMA_TODEVICE);
}
-
+#if 0 /* has been removed from ieee1394 core */
if (!list_empty(&lynx->iso_send.queue)) {
send_next(lynx, hpsb_iso);
}
-
+#endif
spin_unlock(&lynx->iso_send.queue_lock);
if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
index 50daabf6e5fa..a06aaad5b448 100644
--- a/drivers/ieee1394/raw1394-private.h
+++ b/drivers/ieee1394/raw1394-private.h
@@ -36,11 +36,6 @@ struct file_info {
u8 __user *fcp_buffer;
- /* old ISO API */
- u64 listen_channels;
- quadlet_t __user *iso_buffer;
- size_t iso_buffer_length;
-
u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
/* new rawiso API */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index f1d05eeb9f51..336e5ff4cfcf 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -98,21 +98,6 @@ static struct hpsb_address_ops arm_ops = {
static void queue_complete_cb(struct pending_request *req);
-#include <asm/current.h>
-static void print_old_iso_deprecation(void)
-{
- static pid_t p;
-
- if (p == current->pid)
- return;
- p = current->pid;
- printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
- " isochronous request types which will be removed in a next"
- " kernel release\n", current->comm);
- printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
- " newer interface\n");
-}
-
static struct pending_request *__alloc_pending_request(gfp_t flags)
{
struct pending_request *req;
@@ -297,67 +282,6 @@ static void host_reset(struct hpsb_host *host)
spin_unlock_irqrestore(&host_info_lock, flags);
}
-static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
- size_t length)
-{
- unsigned long flags;
- struct host_info *hi;
- struct file_info *fi;
- struct pending_request *req, *req_next;
- struct iso_block_store *ibs = NULL;
- LIST_HEAD(reqs);
-
- if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
- HPSB_INFO("dropped iso packet");
- return;
- }
-
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(host);
-
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- if (!(fi->listen_channels & (1ULL << channel)))
- continue;
-
- req = __alloc_pending_request(GFP_ATOMIC);
- if (!req)
- break;
-
- if (!ibs) {
- ibs = kmalloc(sizeof(*ibs) + length,
- GFP_ATOMIC);
- if (!ibs) {
- kfree(req);
- break;
- }
-
- atomic_add(length, &iso_buffer_size);
- atomic_set(&ibs->refcount, 0);
- ibs->data_size = length;
- memcpy(ibs->data, data, length);
- }
-
- atomic_inc(&ibs->refcount);
-
- req->file_info = fi;
- req->ibs = ibs;
- req->data = ibs->data;
- req->req.type = RAW1394_REQ_ISO_RECEIVE;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = 0;
- req->req.recvb = ptr2int(fi->iso_buffer);
- req->req.length = min(length, fi->iso_buffer_length);
-
- list_add_tail(&req->list, &reqs);
- }
- }
- spin_unlock_irqrestore(&host_info_lock, flags);
-
- list_for_each_entry_safe(req, req_next, &reqs, list)
- queue_complete_req(req);
-}
-
static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
int cts, u8 * data, size_t length)
{
@@ -434,7 +358,11 @@ struct compat_raw1394_req {
__u64 sendb;
__u64 recvb;
-} __attribute__((packed));
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
static const char __user *raw1394_compat_write(const char __user *buf)
{
@@ -459,7 +387,7 @@ static const char __user *raw1394_compat_write(const char __user *buf)
static int
raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
{
- struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+ struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
P(type) ||
P(error) ||
@@ -587,7 +515,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req)
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
static int state_initialized(struct file_info *fi, struct pending_request *req)
@@ -601,7 +529,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
req->req.generation = atomic_read(&internal_generation);
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
switch (req->req.type) {
@@ -673,44 +601,7 @@ out_set_card:
}
queue_complete_req(req);
- return sizeof(struct raw1394_request);
-}
-
-static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
-{
- int channel = req->req.misc;
-
- if ((channel > 63) || (channel < -64)) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- } else if (channel >= 0) {
- /* allocate channel req.misc */
- if (fi->listen_channels & (1ULL << channel)) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- if (hpsb_listen_channel
- (&raw1394_highlevel, fi->host, channel)) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- fi->listen_channels |= 1ULL << channel;
- fi->iso_buffer = int2ptr(req->req.recvb);
- fi->iso_buffer_length = req->req.length;
- }
- }
- } else {
- /* deallocate channel (one's complement neg) req.misc */
- channel = ~channel;
-
- if (fi->listen_channels & (1ULL << channel)) {
- hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
- channel);
- fi->listen_channels &= ~(1ULL << channel);
- } else {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- }
- }
-
- req->req.length = 0;
- queue_complete_req(req);
+ return 0;
}
static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
@@ -865,7 +756,7 @@ static int handle_async_request(struct file_info *fi,
if (req->req.error) {
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
hpsb_set_packet_complete_task(packet,
@@ -883,51 +774,7 @@ static int handle_async_request(struct file_info *fi,
hpsb_free_tlabel(packet);
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
-}
-
-static int handle_iso_send(struct file_info *fi, struct pending_request *req,
- int channel)
-{
- unsigned long flags;
- struct hpsb_packet *packet;
-
- packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
- (req->req.misc >> 16) & 0x3,
- req->req.misc & 0xf);
- if (!packet)
- return -ENOMEM;
-
- packet->speed_code = req->req.address & 0x3;
-
- req->packet = packet;
-
- if (copy_from_user(packet->data, int2ptr(req->req.sendb),
- req->req.length)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- req->req.length = 0;
- hpsb_set_packet_complete_task(packet,
- (void (*)(void *))queue_complete_req,
- req);
-
- spin_lock_irqsave(&fi->reqlists_lock, flags);
- list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
- /* Update the generation of the packet just before sending. */
- packet->generation = req->req.generation;
-
- if (hpsb_send_packet(packet) < 0) {
- req->req.error = RAW1394_ERROR_SEND_ERROR;
- queue_complete_req(req);
- }
-
- return sizeof(struct raw1394_request);
+ return 0;
}
static int handle_async_send(struct file_info *fi, struct pending_request *req)
@@ -943,7 +790,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_INVALID_ARG;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
data_size = req->req.length - header_length;
@@ -957,7 +804,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
if (copy_from_user
@@ -966,7 +813,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
packet->type = hpsb_async;
@@ -994,7 +841,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
+ return 0;
}
static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
@@ -1869,7 +1716,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
spin_lock_irqsave(&host_info_lock, flags);
list_add_tail(&addr->addr_list, &fi->addr_list);
spin_unlock_irqrestore(&host_info_lock, flags);
- return sizeof(struct raw1394_request);
+ return 0;
}
retval =
hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
@@ -1887,7 +1734,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
return (-EALREADY);
}
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
static int arm_unregister(struct file_info *fi, struct pending_request *req)
@@ -1955,7 +1802,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
vfree(addr->addr_space_buffer);
kfree(addr);
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
retval =
hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
@@ -1971,7 +1818,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
vfree(addr->addr_space_buffer);
kfree(addr);
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* Copy data from ARM buffer(s) to user buffer. */
@@ -2013,7 +1860,7 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req)
* queue no response, and therefore nobody
* will free it. */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
DBGMSG("arm_get_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2065,7 +1912,7 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req)
* queue no response, and therefore nobody
* will free it. */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
DBGMSG("arm_set_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2086,7 +1933,7 @@ static int reset_notification(struct file_info *fi, struct pending_request *req)
(req->req.misc == RAW1394_NOTIFY_ON)) {
fi->notification = (u8) req->req.misc;
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* error EINVAL (22) invalid argument */
return (-EINVAL);
@@ -2119,12 +1966,12 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
req->req.length = 0;
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
+ return 0;
}
static int get_config_rom(struct file_info *fi, struct pending_request *req)
{
- int ret = sizeof(struct raw1394_request);
+ int ret = 0;
quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
int status;
@@ -2154,7 +2001,7 @@ static int get_config_rom(struct file_info *fi, struct pending_request *req)
static int update_config_rom(struct file_info *fi, struct pending_request *req)
{
- int ret = sizeof(struct raw1394_request);
+ int ret = 0;
quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -2221,7 +2068,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
hpsb_update_config_rom_image(fi->host);
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
}
@@ -2286,7 +2133,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
/* we have to free the request, because we queue no response,
* and therefore nobody will free it */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
for (dentry =
fi->csr1212_dirs[dr]->value.directory.dentries_head;
@@ -2311,11 +2158,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_ECHO:
queue_complete_req(req);
- return sizeof(struct raw1394_request);
-
- case RAW1394_REQ_ISO_SEND:
- print_old_iso_deprecation();
- return handle_iso_send(fi, req, node);
+ return 0;
case RAW1394_REQ_ARM_REGISTER:
return arm_register(fi, req);
@@ -2332,27 +2175,30 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_RESET_NOTIFY:
return reset_notification(fi, req);
+ case RAW1394_REQ_ISO_SEND:
case RAW1394_REQ_ISO_LISTEN:
- print_old_iso_deprecation();
- handle_iso_listen(fi, req);
- return sizeof(struct raw1394_request);
+ printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
+ req->req.error = RAW1394_ERROR_COMPAT;
+ req->req.misc = RAW1394_KERNELAPI_VERSION;
+ queue_complete_req(req);
+ return 0;
case RAW1394_REQ_FCP_LISTEN:
handle_fcp_listen(fi, req);
- return sizeof(struct raw1394_request);
+ return 0;
case RAW1394_REQ_RESET_BUS:
if (req->req.misc == RAW1394_LONG_RESET) {
DBGMSG("busreset called (type: LONG)");
hpsb_reset_bus(fi->host, LONG_RESET);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
if (req->req.misc == RAW1394_SHORT_RESET) {
DBGMSG("busreset called (type: SHORT)");
hpsb_reset_bus(fi->host, SHORT_RESET);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* error EINVAL (22) invalid argument */
return (-EINVAL);
@@ -2371,7 +2217,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
req->req.generation = get_hpsb_generation(fi->host);
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
switch (req->req.type) {
@@ -2384,7 +2230,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
if (req->req.length == 0) {
req->req.error = RAW1394_ERROR_INVALID_ARG;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
return handle_async_request(fi, req, node);
@@ -2395,7 +2241,7 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
{
struct file_info *fi = (struct file_info *)file->private_data;
struct pending_request *req;
- ssize_t retval = 0;
+ ssize_t retval = -EBADFD;
#ifdef CONFIG_COMPAT
if (count == sizeof(struct compat_raw1394_req) &&
@@ -2437,6 +2283,9 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
if (retval < 0) {
free_pending_request(req);
+ } else {
+ BUG_ON(retval);
+ retval = count;
}
return retval;
@@ -2802,6 +2651,103 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
+#ifdef CONFIG_COMPAT
+struct raw1394_iso_packets32 {
+ __u32 n_packets;
+ compat_uptr_t infos;
+} __attribute__((packed));
+
+struct raw1394_cycle_timer32 {
+ __u32 cycle_timer;
+ __u64 local_time;
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
+
+#define RAW1394_IOC_ISO_RECV_PACKETS32 \
+ _IOW ('#', 0x25, struct raw1394_iso_packets32)
+#define RAW1394_IOC_ISO_XMIT_PACKETS32 \
+ _IOW ('#', 0x27, struct raw1394_iso_packets32)
+#define RAW1394_IOC_GET_CYCLE_TIMER32 \
+ _IOR ('#', 0x30, struct raw1394_cycle_timer32)
+
+static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
+ struct raw1394_iso_packets32 __user *arg)
+{
+ compat_uptr_t infos32;
+ void *infos;
+ long err = -EFAULT;
+ struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
+
+ if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
+ !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
+ infos = compat_ptr(infos32);
+ if (!copy_to_user(&dst->infos, &infos, sizeof infos))
+ err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst);
+ }
+ return err;
+}
+
+static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
+{
+ struct raw1394_cycle_timer32 ct;
+ int err;
+
+ err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+ if (!err)
+ if (copy_to_user(uaddr, &ct, sizeof(ct)))
+ err = -EFAULT;
+ return err;
+}
+
+static long raw1394_compat_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct file_info *fi = file->private_data;
+ void __user *argp = (void __user *)arg;
+ long err;
+
+ lock_kernel();
+ switch (cmd) {
+ /* These requests have same format as long as 'int' has same size. */
+ case RAW1394_IOC_ISO_RECV_INIT:
+ case RAW1394_IOC_ISO_RECV_START:
+ case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+ case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+ case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
+ case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
+ case RAW1394_IOC_ISO_RECV_FLUSH:
+ case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+ case RAW1394_IOC_ISO_XMIT_INIT:
+ case RAW1394_IOC_ISO_XMIT_START:
+ case RAW1394_IOC_ISO_XMIT_SYNC:
+ case RAW1394_IOC_ISO_GET_STATUS:
+ case RAW1394_IOC_ISO_SHUTDOWN:
+ case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+ err = raw1394_ioctl(NULL, file, cmd, arg);
+ break;
+ /* These request have different format. */
+ case RAW1394_IOC_ISO_RECV_PACKETS32:
+ err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
+ break;
+ case RAW1394_IOC_ISO_XMIT_PACKETS32:
+ err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
+ break;
+ case RAW1394_IOC_GET_CYCLE_TIMER32:
+ err = raw1394_read_cycle_timer32(fi, argp);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+
+ return err;
+}
+#endif
+
static unsigned int raw1394_poll(struct file *file, poll_table * pt)
{
struct file_info *fi = file->private_data;
@@ -2861,14 +2807,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
if (fi->iso_state != RAW1394_ISO_INACTIVE)
raw1394_iso_shutdown(fi);
- for (i = 0; i < 64; i++) {
- if (fi->listen_channels & (1ULL << i)) {
- hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
- }
- }
-
spin_lock_irqsave(&host_info_lock, flags);
- fi->listen_channels = 0;
fail = 0;
/* set address-entries invalid */
@@ -3030,7 +2969,6 @@ static struct hpsb_highlevel raw1394_highlevel = {
.add_host = add_host,
.remove_host = remove_host,
.host_reset = host_reset,
- .iso_receive = iso_receive,
.fcp_request = fcp_request,
};
@@ -3041,7 +2979,9 @@ static const struct file_operations raw1394_fops = {
.write = raw1394_write,
.mmap = raw1394_mmap,
.ioctl = raw1394_ioctl,
- // .compat_ioctl = ... someone needs to do this
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = raw1394_compat_ioctl,
+#endif
.poll = raw1394_poll,
.open = raw1394_open,
.release = raw1394_release,
@@ -3054,9 +2994,9 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
if (IS_ERR
- (class_device_create
- (hpsb_protocol_class, NULL,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+ (device_create(
+ hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
@@ -3083,9 +3023,9 @@ static int __init init_raw1394(void)
goto out;
out_dev:
- class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
out_unreg:
hpsb_unregister_highlevel(&raw1394_highlevel);
out:
@@ -3094,9 +3034,9 @@ static int __init init_raw1394(void)
static void __exit cleanup_raw1394(void)
{
- class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
hpsb_unregister_highlevel(&raw1394_highlevel);
hpsb_unregister_protocol(&raw1394_driver);
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 7bd22ee1afbb..963ac20373d2 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -17,11 +17,11 @@
#define RAW1394_REQ_ASYNC_WRITE 101
#define RAW1394_REQ_LOCK 102
#define RAW1394_REQ_LOCK64 103
-#define RAW1394_REQ_ISO_SEND 104
+#define RAW1394_REQ_ISO_SEND 104 /* removed ABI, now a no-op */
#define RAW1394_REQ_ASYNC_SEND 105
#define RAW1394_REQ_ASYNC_STREAM 106
-#define RAW1394_REQ_ISO_LISTEN 200
+#define RAW1394_REQ_ISO_LISTEN 200 /* removed ABI, now a no-op */
#define RAW1394_REQ_FCP_LISTEN 201
#define RAW1394_REQ_RESET_BUS 202
#define RAW1394_REQ_GET_ROM 203
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 3f873cc7e247..e0c385a3b450 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -118,14 +118,13 @@ MODULE_PARM_DESC(max_speed, "Force max speed "
"(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
/*
- * Set serialize_io to 1 if you'd like only one scsi command sent
- * down to us at a time (debugging). This might be necessary for very
- * badly behaved sbp2 devices.
+ * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
+ * This is and always has been buggy in multiple subtle ways. See above TODOs.
*/
static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
- "(default = 1, faster = 0)");
+module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
+MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
+ "(default = Y, faster but buggy = N)");
/*
* Bump up max_sectors if you'd like to support very large sized
@@ -154,9 +153,9 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
* are possible on OXFW911 and newer Oxsemi bridges.
*/
static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
+module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
- "(default = 1)");
+ "(default = Y, use N for concurrent initiators)");
/*
* If any of the following workarounds is required for your device to work,
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 44402b9d82a8..333a4bb76743 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -67,7 +67,7 @@ struct sbp2_command_orb {
#define ORB_SET_LUN(v) ((v) & 0xffff)
#define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16)
#define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(v) (((v) & 0x1) << 28)
+#define ORB_SET_EXCLUSIVE(v) ((v) ? 1 << 28 : 0)
#define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff)
#define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16)
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 87ebd0846c34..bd28adfd7afc 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1340,9 +1340,9 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
- class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, minor),
- NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+ device_create(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, minor),
+ "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
@@ -1351,8 +1351,8 @@ static void video1394_remove_host (struct hpsb_host *host)
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
if (ohci)
- class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
+ device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
return;
}
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index be6b93c20f60..ab4b2d9b5327 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -30,6 +30,7 @@ struct evdev {
wait_queue_head_t wait;
struct evdev_client *grab;
struct list_head client_list;
+ struct device dev;
};
struct evdev_client {
@@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id)
return input_flush_device(&evdev->handle, file);
}
-static void evdev_free(struct evdev *evdev)
+static void evdev_free(struct device *dev)
{
+ struct evdev *evdev = container_of(dev, struct evdev, dev);
+
evdev_table[evdev->minor] = NULL;
kfree(evdev);
}
@@ -114,12 +117,10 @@ static int evdev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--evdev->open) {
- if (evdev->exist)
- input_close_device(&evdev->handle);
- else
- evdev_free(evdev);
- }
+ if (!--evdev->open && evdev->exist)
+ input_close_device(&evdev->handle);
+
+ put_device(&evdev->dev);
return 0;
}
@@ -139,24 +140,32 @@ static int evdev_open(struct inode *inode, struct file *file)
if (!evdev || !evdev->exist)
return -ENODEV;
+ get_device(&evdev->dev);
+
client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_evdev;
+ }
client->evdev = evdev;
list_add_tail(&client->node, &evdev->client_list);
if (!evdev->open++ && evdev->exist) {
error = input_open_device(&evdev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_evdev:
+ put_device(&evdev->dev);
+ return error;
}
#ifdef CONFIG_COMPAT
@@ -625,8 +634,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
- struct class_device *cdev;
- dev_t devt;
int minor;
int error;
@@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
evdev->handle.name = evdev->name;
evdev->handle.handler = handler;
evdev->handle.private = evdev;
- sprintf(evdev->name, "event%d", minor);
-
- evdev_table[minor] = evdev;
+ snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
- devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+ snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
+ "event%d", minor);
+ evdev->dev.class = &input_class;
+ evdev->dev.parent = &dev->dev;
+ evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
+ evdev->dev.release = evdev_free;
+ device_initialize(&evdev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, evdev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_evdev;
- }
+ evdev_table[minor] = evdev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, evdev->name);
+ error = device_add(&evdev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_evdev;
error = input_register_handle(&evdev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_evdev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_evdev:
+ device_del(&evdev->dev);
err_free_evdev:
- kfree(evdev);
- evdev_table[minor] = NULL;
+ put_device(&evdev->dev);
return error;
}
@@ -690,10 +691,8 @@ static void evdev_disconnect(struct input_handle *handle)
struct evdev_client *client;
input_unregister_handle(handle);
+ device_del(&evdev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
evdev->exist = 0;
if (evdev->open) {
@@ -702,8 +701,9 @@ static void evdev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &evdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&evdev->wait);
- } else
- evdev_free(evdev);
+ }
+
+ put_device(&evdev->dev);
}
static const struct input_device_id evdev_ids[] = {
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccd8abafcb70..75b4d2a83dd9 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -442,7 +442,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
printk(KERN_ERR
"input: failed to attach handler %s to device %s, "
"error: %d\n",
- handler->name, kobject_name(&dev->cdev.kobj), error);
+ handler->name, kobject_name(&dev->dev.kobj), error);
return error;
}
@@ -527,7 +527,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
static int input_devices_seq_show(struct seq_file *seq, void *v)
{
struct input_dev *dev = container_of(v, struct input_dev, node);
- const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
struct input_handle *handle;
seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
@@ -682,15 +682,17 @@ static inline int input_proc_init(void) { return 0; }
static inline void input_proc_exit(void) { }
#endif
-#define INPUT_DEV_STRING_ATTR_SHOW(name) \
-static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- \
- return scnprintf(buf, PAGE_SIZE, "%s\n", \
- input_dev->name ? input_dev->name : ""); \
-} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+#define INPUT_DEV_STRING_ATTR_SHOW(name) \
+static ssize_t input_dev_show_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ \
+ return scnprintf(buf, PAGE_SIZE, "%s\n", \
+ input_dev->name ? input_dev->name : ""); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys);
@@ -744,7 +746,9 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
return len;
}
-static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+static ssize_t input_dev_show_modalias(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct input_dev *id = to_input_dev(dev);
ssize_t len;
@@ -753,13 +757,13 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
return min_t(int, len, PAGE_SIZE);
}
-static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
static struct attribute *input_dev_attrs[] = {
- &class_device_attr_name.attr,
- &class_device_attr_phys.attr,
- &class_device_attr_uniq.attr,
- &class_device_attr_modalias.attr,
+ &dev_attr_name.attr,
+ &dev_attr_phys.attr,
+ &dev_attr_uniq.attr,
+ &dev_attr_modalias.attr,
NULL
};
@@ -767,13 +771,15 @@ static struct attribute_group input_dev_attr_group = {
.attrs = input_dev_attrs,
};
-#define INPUT_DEV_ID_ATTR(name) \
-static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
-} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+#define INPUT_DEV_ID_ATTR(name) \
+static ssize_t input_dev_show_id_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
INPUT_DEV_ID_ATTR(bustype);
INPUT_DEV_ID_ATTR(vendor);
@@ -781,10 +787,10 @@ INPUT_DEV_ID_ATTR(product);
INPUT_DEV_ID_ATTR(version);
static struct attribute *input_dev_id_attrs[] = {
- &class_device_attr_bustype.attr,
- &class_device_attr_vendor.attr,
- &class_device_attr_product.attr,
- &class_device_attr_version.attr,
+ &dev_attr_bustype.attr,
+ &dev_attr_vendor.attr,
+ &dev_attr_product.attr,
+ &dev_attr_version.attr,
NULL
};
@@ -813,15 +819,17 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
return len;
}
-#define INPUT_DEV_CAP_ATTR(ev, bm) \
-static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- int len = input_print_bitmap(buf, PAGE_SIZE, \
- input_dev->bm##bit, ev##_MAX, 1); \
- return min_t(int, len, PAGE_SIZE); \
-} \
-static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+#define INPUT_DEV_CAP_ATTR(ev, bm) \
+static ssize_t input_dev_show_cap_##bm(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ int len = input_print_bitmap(buf, PAGE_SIZE, \
+ input_dev->bm##bit, ev##_MAX, 1); \
+ return min_t(int, len, PAGE_SIZE); \
+} \
+static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
INPUT_DEV_CAP_ATTR(EV, ev);
INPUT_DEV_CAP_ATTR(KEY, key);
@@ -834,15 +842,15 @@ INPUT_DEV_CAP_ATTR(FF, ff);
INPUT_DEV_CAP_ATTR(SW, sw);
static struct attribute *input_dev_caps_attrs[] = {
- &class_device_attr_ev.attr,
- &class_device_attr_key.attr,
- &class_device_attr_rel.attr,
- &class_device_attr_abs.attr,
- &class_device_attr_msc.attr,
- &class_device_attr_led.attr,
- &class_device_attr_snd.attr,
- &class_device_attr_ff.attr,
- &class_device_attr_sw.attr,
+ &dev_attr_ev.attr,
+ &dev_attr_key.attr,
+ &dev_attr_rel.attr,
+ &dev_attr_abs.attr,
+ &dev_attr_msc.attr,
+ &dev_attr_led.attr,
+ &dev_attr_snd.attr,
+ &dev_attr_ff.attr,
+ &dev_attr_sw.attr,
NULL
};
@@ -858,9 +866,9 @@ static struct attribute_group *input_dev_attr_groups[] = {
NULL
};
-static void input_dev_release(struct class_device *class_dev)
+static void input_dev_release(struct device *device)
{
- struct input_dev *dev = to_input_dev(class_dev);
+ struct input_dev *dev = to_input_dev(device);
input_ff_destroy(dev);
kfree(dev);
@@ -947,10 +955,10 @@ static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_ind
return err; \
} while (0)
-static int input_dev_uevent(struct class_device *cdev, char **envp,
+static int input_dev_uevent(struct device *device, char **envp,
int num_envp, char *buffer, int buffer_size)
{
- struct input_dev *dev = to_input_dev(cdev);
+ struct input_dev *dev = to_input_dev(device);
int i = 0;
int len = 0;
@@ -988,10 +996,14 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
return 0;
}
+static struct device_type input_dev_type = {
+ .groups = input_dev_attr_groups,
+ .release = input_dev_release,
+ .uevent = input_dev_uevent,
+};
+
struct class input_class = {
- .name = "input",
- .release = input_dev_release,
- .uevent = input_dev_uevent,
+ .name = "input",
};
EXPORT_SYMBOL_GPL(input_class);
@@ -1010,9 +1022,9 @@ struct input_dev *input_allocate_device(void)
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) {
- dev->cdev.class = &input_class;
- dev->cdev.groups = input_dev_attr_groups;
- class_device_initialize(&dev->cdev);
+ dev->dev.type = &input_dev_type;
+ dev->dev.class = &input_class;
+ device_initialize(&dev->dev);
mutex_init(&dev->mutex);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
@@ -1131,17 +1143,17 @@ int input_register_device(struct input_dev *dev)
list_add_tail(&dev->node, &input_dev_list);
- snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+ snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
- if (!dev->cdev.dev)
- dev->cdev.dev = dev->dev.parent;
+ if (dev->cdev.dev)
+ dev->dev.parent = dev->cdev.dev;
- error = class_device_add(&dev->cdev);
+ error = device_add(&dev->dev);
if (error)
return error;
- path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s as %s\n",
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
kfree(path);
@@ -1173,7 +1185,7 @@ void input_unregister_device(struct input_dev *dev)
list_del_init(&dev->node);
- class_device_unregister(&dev->cdev);
+ device_unregister(&dev->dev);
input_wakeup_procfs_readers();
}
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 10e3b7bc925f..a9a0180bfd46 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,6 +43,8 @@ struct joydev {
struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
+ struct device dev;
+
struct js_corr corr[ABS_MAX + 1];
struct JS_DATA_SAVE_TYPE glue;
int nabs;
@@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
return retval < 0 ? retval : 0;
}
-static void joydev_free(struct joydev *joydev)
+static void joydev_free(struct device *dev)
{
+ struct joydev *joydev = container_of(dev, struct joydev, dev);
+
joydev_table[joydev->minor] = NULL;
kfree(joydev);
}
@@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--joydev->open) {
- if (joydev->exist)
- input_close_device(&joydev->handle);
- else
- joydev_free(joydev);
- }
+ if (!--joydev->open && joydev->exist)
+ input_close_device(&joydev->handle);
+
+ put_device(&joydev->dev);
return 0;
}
@@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file)
if (!joydev || !joydev->exist)
return -ENODEV;
+ get_device(&joydev->dev);
+
client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_joydev;
+ }
client->joydev = joydev;
list_add_tail(&client->node, &joydev->client_list);
if (!joydev->open++ && joydev->exist) {
error = input_open_device(&joydev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_joydev:
+ put_device(&joydev->dev);
+ return error;
}
static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct joydev *joydev;
- struct class_device *cdev;
- dev_t devt;
int i, j, t, minor;
int error;
@@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->handle.name = joydev->name;
joydev->handle.handler = handler;
joydev->handle.private = joydev;
- sprintf(joydev->name, "js%d", minor);
+ snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
for (i = 0; i < ABS_MAX + 1; i++)
if (test_bit(i, dev->absbit)) {
@@ -547,36 +555,30 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
}
- joydev_table[minor] = joydev;
-
- devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+ snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
+ "js%d", minor);
+ joydev->dev.class = &input_class;
+ joydev->dev.parent = &dev->dev;
+ joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
+ joydev->dev.release = joydev_free;
+ device_initialize(&joydev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, joydev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_joydev;
- }
+ joydev_table[minor] = joydev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, joydev->name);
+ error = device_add(&joydev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_joydev;
error = input_register_handle(&joydev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_joydev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_joydev:
+ device_del(&joydev->dev);
err_free_joydev:
- joydev_table[minor] = NULL;
- kfree(joydev);
+ put_device(&joydev->dev);
return error;
}
@@ -587,9 +589,8 @@ static void joydev_disconnect(struct input_handle *handle)
struct joydev_client *client;
input_unregister_handle(handle);
+ device_del(&joydev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
joydev->exist = 0;
if (joydev->open) {
@@ -597,8 +598,9 @@ static void joydev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &joydev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&joydev->wait);
- } else
- joydev_free(joydev);
+ }
+
+ put_device(&joydev->dev);
}
static const struct input_device_id joydev_blacklist[] = {
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index b0023452ec90..12db72d83ea0 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -268,4 +268,11 @@ config JOYSTICK_XPAD
To compile this driver as a module, choose M here: the
module will be called xpad.
+config JOYSTICK_XPAD_FF
+ bool "X-Box gamepad rumble support"
+ depends on JOYSTICK_XPAD && INPUT
+ select INPUT_FF_MEMLESS
+ ---help---
+ Say Y here if you want to take advantage of xbox 360 rumble features.
+
endif
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 555319e6378c..4ed3a3eadf19 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -320,10 +320,10 @@ static int multiport_io(struct gameport* gameport, int sendflags, int sendcode,
static int dig_mode_start(struct gameport *gameport, u32 *packet)
{
- int i, seq_len = sizeof(init_seq)/sizeof(int);
+ int i;
int flags, tries = 0, bads = 0;
- for (i = 0; i < seq_len; i++) { /* Send magic sequence */
+ for (i = 0; i < ARRAY_SIZE(init_seq); i++) { /* Send magic sequence */
if (init_seq[i])
gameport_trigger(gameport);
udelay(GRIP_INIT_DELAY);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 8c8cd95a6989..244089c52650 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -8,6 +8,7 @@
* Ivan Hawkes <blackhawk@ivanhawkes.com>
* 2005 Dominic Cerquetti <binary1230@yahoo.com>
* 2006 Adam Buchbinder <adam.buchbinder@gmail.com>
+ * 2007 Jan Kratochvil <honza@jikos.cz>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -28,6 +29,7 @@
* - information from http://euc.jp/periphs/xbox-controller.ja.html
* - the iForce driver drivers/char/joystick/iforce.c
* - the skeleton-driver drivers/usb/usb-skeleton.c
+ * - Xbox 360 information http://www.free60.org/wiki/Gamepad
*
* Thanks to:
* - ITO Takayuki for providing essential xpad information on his website
@@ -88,6 +90,9 @@
#define MAP_DPAD_TO_AXES 1
#define MAP_DPAD_UNKNOWN -1
+#define XTYPE_XBOX 0
+#define XTYPE_XBOX360 1
+
static int dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
@@ -97,40 +102,42 @@ static const struct xpad_device {
u16 idProduct;
char *name;
u8 dpad_mapping;
+ u8 xtype;
} xpad_device[] = {
- { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS },
- { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES },
- { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES },
- { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES },
- { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES },
- { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS },
- { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS },
- { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES },
- { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES },
- { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES},
- { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES },
- { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES },
- { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES },
- { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES },
- { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS },
- { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS },
- { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN }
+ { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
};
static const signed short xpad_btn[] = {
@@ -146,6 +153,12 @@ static const signed short xpad_btn_pad[] = {
-1 /* terminating entry */
};
+static const signed short xpad360_btn[] = { /* buttons for x360 controller */
+ BTN_TL, BTN_TR, /* Button LB/RB */
+ BTN_MODE, /* The big X button */
+ -1
+};
+
static const signed short xpad_abs[] = {
ABS_X, ABS_Y, /* left stick */
ABS_RX, ABS_RY, /* right stick */
@@ -159,8 +172,12 @@ static const signed short xpad_abs_pad[] = {
-1 /* terminating entry */
};
+/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
+ * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
+ * but we need only one of them. */
static struct usb_device_id xpad_table [] = {
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
+ { USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) }, /* X-Box 360 controller */
{ }
};
@@ -174,9 +191,16 @@ struct usb_xpad {
unsigned char *idata; /* input data */
dma_addr_t idata_dma;
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+ struct urb *irq_out; /* urb for interrupt out report */
+ unsigned char *odata; /* output data */
+ dma_addr_t odata_dma;
+#endif
+
char phys[65]; /* physical device path */
int dpad_mapping; /* map d-pad to buttons or to axes */
+ int xtype; /* type of xbox device */
};
/*
@@ -212,8 +236,8 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
- input_report_key(dev, BTN_0, data[2] & 0x01); // up
- input_report_key(dev, BTN_1, data[2] & 0x02); // down
+ input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
+ input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
}
/* start/back buttons and stick press left/right */
@@ -235,6 +259,64 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
input_sync(dev);
}
+/*
+ * xpad360_process_packet
+ *
+ * Completes a request by converting the data into events for the
+ * input subsystem. It is version for xbox 360 controller
+ *
+ * The used report descriptor was taken from:
+ * http://www.free60.org/wiki/Gamepad
+ */
+
+static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
+{
+ struct input_dev *dev = xpad->dev;
+
+ /* digital pad */
+ if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
+ input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
+ input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+ } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
+ /* dpad as buttons (right, left, down, up) */
+ input_report_key(dev, BTN_LEFT, data[2] & 0x04);
+ input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
+ input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
+ input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
+ }
+
+ /* start/back buttons */
+ input_report_key(dev, BTN_START, data[2] & 0x10);
+ input_report_key(dev, BTN_BACK, data[2] & 0x20);
+
+ /* stick press left/right */
+ input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
+ input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
+
+ /* buttons A,B,X,Y,TL,TR and MODE */
+ input_report_key(dev, BTN_A, data[3] & 0x10);
+ input_report_key(dev, BTN_B, data[3] & 0x20);
+ input_report_key(dev, BTN_X, data[3] & 0x40);
+ input_report_key(dev, BTN_Y, data[3] & 0x80);
+ input_report_key(dev, BTN_TL, data[3] & 0x01);
+ input_report_key(dev, BTN_TR, data[3] & 0x02);
+ input_report_key(dev, BTN_MODE, data[3] & 0x04);
+
+ /* left stick */
+ input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6]));
+ input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8]));
+
+ /* right stick */
+ input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10]));
+ input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12]));
+
+ /* triggers left/right */
+ input_report_abs(dev, ABS_Z, data[4]);
+ input_report_abs(dev, ABS_RZ, data[5]);
+
+ input_sync(dev);
+}
+
static void xpad_irq_in(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
@@ -255,7 +337,10 @@ static void xpad_irq_in(struct urb *urb)
goto exit;
}
- xpad_process_packet(xpad, 0, xpad->idata);
+ if (xpad->xtype == XTYPE_XBOX360)
+ xpad360_process_packet(xpad, 0, xpad->idata);
+ else
+ xpad_process_packet(xpad, 0, xpad->idata);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -264,7 +349,114 @@ exit:
__FUNCTION__, retval);
}
-static int xpad_open (struct input_dev *dev)
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+static void xpad_irq_out(struct urb *urb)
+{
+ int retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+}
+
+static int xpad_play_effect(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct usb_xpad *xpad = input_get_drvdata(dev);
+
+ if (effect->type == FF_RUMBLE) {
+ __u16 strong = effect->u.rumble.strong_magnitude;
+ __u16 weak = effect->u.rumble.weak_magnitude;
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x08;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256;
+ xpad->odata[4] = weak / 256;
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ xpad->odata[7] = 0x00;
+ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+ }
+
+ return 0;
+}
+
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad)
+{
+ struct usb_endpoint_descriptor *ep_irq_out;
+ int error = -ENOMEM;
+
+ if (xpad->xtype != XTYPE_XBOX360)
+ return 0;
+
+ xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
+ GFP_ATOMIC, &xpad->odata_dma );
+ if (!xpad->odata)
+ goto fail1;
+
+ xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!xpad->irq_out)
+ goto fail2;
+
+ ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
+ usb_fill_int_urb(xpad->irq_out, xpad->udev,
+ usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
+ xpad->odata, XPAD_PKT_LEN,
+ xpad_irq_out, xpad, ep_irq_out->bInterval);
+ xpad->irq_out->transfer_dma = xpad->odata_dma;
+ xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+
+ error = input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+ if (error)
+ goto fail2;
+
+ return 0;
+
+ fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
+ fail1: return error;
+}
+
+static void xpad_stop_ff(struct usb_xpad *xpad)
+{
+ if (xpad->xtype == XTYPE_XBOX360)
+ usb_kill_urb(xpad->irq_out);
+}
+
+static void xpad_deinit_ff(struct usb_xpad *xpad)
+{
+ if (xpad->xtype == XTYPE_XBOX360) {
+ usb_free_urb(xpad->irq_out);
+ usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
+ xpad->odata, xpad->odata_dma);
+ }
+}
+
+#else
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
+static void xpad_stop_ff(struct usb_xpad *xpad) { }
+static void xpad_deinit_ff(struct usb_xpad *xpad) { }
+#endif
+
+static int xpad_open(struct input_dev *dev)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
@@ -275,11 +467,12 @@ static int xpad_open (struct input_dev *dev)
return 0;
}
-static void xpad_close (struct input_dev *dev)
+static void xpad_close(struct input_dev *dev)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
usb_kill_urb(xpad->irq_in);
+ xpad_stop_ff(xpad);
}
static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
@@ -335,6 +528,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->udev = udev;
xpad->dpad_mapping = xpad_device[i].dpad_mapping;
+ xpad->xtype = xpad_device[i].xtype;
if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
xpad->dpad_mapping = dpad_to_buttons;
xpad->dev = input_dev;
@@ -356,6 +550,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
/* set up buttons */
for (i = 0; xpad_btn[i] >= 0; i++)
set_bit(xpad_btn[i], input_dev->keybit);
+ if (xpad->xtype == XTYPE_XBOX360)
+ for (i = 0; xpad360_btn[i] >= 0; i++)
+ set_bit(xpad360_btn[i], input_dev->keybit);
if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
for (i = 0; xpad_btn_pad[i] >= 0; i++)
set_bit(xpad_btn_pad[i], input_dev->keybit);
@@ -367,6 +564,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
for (i = 0; xpad_abs_pad[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
+ error = xpad_init_ff(intf, xpad);
+ if (error)
+ goto fail2;
+
ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
usb_fill_int_urb(xpad->irq_in, udev,
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
@@ -396,10 +597,10 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (xpad) {
- usb_kill_urb(xpad->irq_in);
input_unregister_device(xpad->dev);
+ xpad_deinit_ff(xpad);
usb_free_urb(xpad->irq_in);
- usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN,
+ usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
xpad->idata, xpad->idata_dma);
kfree(xpad);
}
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 9950fcb33650..41fc3d03b6eb 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -89,7 +89,7 @@ static unsigned char atkbd_set2_keycode[512] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
- 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
+ 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142,
157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
@@ -111,7 +111,7 @@ static unsigned char atkbd_set3_keycode[512] = {
82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183,
184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0,
- 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
+ 0,139,172,163,165,115,152,172,166,140,160,154,113,114,167,168,
148,149,147,140
};
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
index f9e82c9ca421..ebe5eacf2990 100644
--- a/drivers/input/keyboard/pxa27x_keyboard.c
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -140,7 +140,7 @@ static int pxakbd_resume(struct platform_device *pdev)
KPREC = pdata->reg_kprec;
/* Enable unit clock */
- pxa_set_cken(CKEN19_KEYPAD, 1);
+ pxa_set_cken(CKEN_KEYPAD, 1);
}
mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 88e29074ac90..9b26574f1466 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -65,9 +65,13 @@ config INPUT_COBALT_BTNS
config INPUT_WISTRON_BTNS
tristate "x86 Wistron laptop button interface"
depends on X86 && !X86_64
+ select INPUT_POLLDEV
+ select NEW_LEDS
+ select LEDS_CLASS
help
Say Y here for support of Winstron laptop button interface, used on
- laptops of various brands, including Acer and Fujitsu-Siemens.
+ laptops of various brands, including Acer and Fujitsu-Siemens. If
+ available, mail and wifi leds will be controlable via /sys/class/leds.
To compile this driver as a module, choose M here: the module will
be called wistron_btns.
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 961aad7a0476..60121f10f8d9 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -20,37 +20,31 @@
#include <linux/io.h>
#include <linux/dmi.h>
#include <linux/init.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
#include <linux/interrupt.h>
+#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h>
#include <linux/preempt.h>
#include <linux/string.h>
-#include <linux/timer.h>
#include <linux/types.h>
#include <linux/platform_device.h>
+#include <linux/leds.h>
-/*
- * Number of attempts to read data from queue per poll;
- * the queue can hold up to 31 entries
- */
-#define MAX_POLL_ITERATIONS 64
-
-#define POLL_FREQUENCY 10 /* Number of polls per second */
-
-#if POLL_FREQUENCY > HZ
-#error "POLL_FREQUENCY too high"
-#endif
+/* How often we poll keys - msecs */
+#define POLL_INTERVAL_DEFAULT 500 /* when idle */
+#define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */
/* BIOS subsystem IDs */
#define WIFI 0x35
#define BLUETOOTH 0x34
+#define MAIL_LED 0x31
MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
MODULE_DESCRIPTION("Wistron laptop button driver");
MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.2");
+MODULE_VERSION("0.3");
static int force; /* = 0; */
module_param(force, bool, 0);
@@ -248,9 +242,10 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
#define FE_WIFI_LED 0x02
#define FE_UNTESTED 0x80
-static const struct key_entry *keymap; /* = NULL; Current key map */
+static struct key_entry *keymap; /* = NULL; Current key map */
static int have_wifi;
static int have_bluetooth;
+static int have_leds;
static int __init dmi_matched(struct dmi_system_id *dmi)
{
@@ -263,6 +258,8 @@ static int __init dmi_matched(struct dmi_system_id *dmi)
else if (key->type == KE_BLUETOOTH)
have_bluetooth = 1;
}
+ have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED);
+
return 1;
}
@@ -966,118 +963,163 @@ static int __init select_keymap(void)
/* Input layer interface */
-static struct input_dev *input_dev;
+static struct input_polled_dev *wistron_idev;
+static unsigned long jiffies_last_press;
+static int wifi_enabled;
+static int bluetooth_enabled;
-static int __devinit setup_input_dev(void)
+static void report_key(struct input_dev *dev, unsigned int keycode)
{
- const struct key_entry *key;
- int error;
+ input_report_key(dev, keycode, 1);
+ input_sync(dev);
+ input_report_key(dev, keycode, 0);
+ input_sync(dev);
+}
- input_dev = input_allocate_device();
- if (!input_dev)
- return -ENOMEM;
+static void report_switch(struct input_dev *dev, unsigned int code, int value)
+{
+ input_report_switch(dev, code, value);
+ input_sync(dev);
+}
- input_dev->name = "Wistron laptop buttons";
- input_dev->phys = "wistron/input0";
- input_dev->id.bustype = BUS_HOST;
- input_dev->cdev.dev = &wistron_device->dev;
- for (key = keymap; key->type != KE_END; key++) {
- switch (key->type) {
- case KE_KEY:
- set_bit(EV_KEY, input_dev->evbit);
- set_bit(key->keycode, input_dev->keybit);
- break;
+ /* led management */
+static void wistron_mail_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
+}
- case KE_SW:
- set_bit(EV_SW, input_dev->evbit);
- set_bit(key->sw.code, input_dev->swbit);
- break;
+/* same as setting up wifi card, but for laptops on which the led is managed */
+static void wistron_wifi_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
+}
- default:
- ;
- }
- }
+static struct led_classdev wistron_mail_led = {
+ .name = "mail:green",
+ .brightness_set = wistron_mail_led_set,
+};
- /* reads information flags on KE_END */
- if (key->code & FE_UNTESTED)
- printk(KERN_WARNING "Untested laptop multimedia keys, "
- "please report success or failure to eric.piel"
- "@tremplin-utc.net\n");
+static struct led_classdev wistron_wifi_led = {
+ .name = "wifi:red",
+ .brightness_set = wistron_wifi_led_set,
+};
- error = input_register_device(input_dev);
- if (error) {
- input_free_device(input_dev);
- return error;
+static void __devinit wistron_led_init(struct device *parent)
+{
+ if (have_leds & FE_WIFI_LED) {
+ u16 wifi = bios_get_default_setting(WIFI);
+ if (wifi & 1) {
+ wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
+ if (led_classdev_register(parent, &wistron_wifi_led))
+ have_leds &= ~FE_WIFI_LED;
+ else
+ bios_set_state(WIFI, wistron_wifi_led.brightness);
+
+ } else
+ have_leds &= ~FE_WIFI_LED;
}
- return 0;
+ if (have_leds & FE_MAIL_LED) {
+ /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
+ wistron_mail_led.brightness = LED_OFF;
+ if (led_classdev_register(parent, &wistron_mail_led))
+ have_leds &= ~FE_MAIL_LED;
+ else
+ bios_set_state(MAIL_LED, wistron_mail_led.brightness);
+ }
}
-static void report_key(unsigned keycode)
+static void __devexit wistron_led_remove(void)
{
- input_report_key(input_dev, keycode, 1);
- input_sync(input_dev);
- input_report_key(input_dev, keycode, 0);
- input_sync(input_dev);
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_unregister(&wistron_mail_led);
+
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_unregister(&wistron_wifi_led);
}
-static void report_switch(unsigned code, int value)
+static inline void wistron_led_suspend(void)
{
- input_report_switch(input_dev, code, value);
- input_sync(input_dev);
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_suspend(&wistron_mail_led);
+
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_suspend(&wistron_wifi_led);
}
- /* Driver core */
+static inline void wistron_led_resume(void)
+{
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_resume(&wistron_mail_led);
-static int wifi_enabled;
-static int bluetooth_enabled;
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_resume(&wistron_wifi_led);
+}
+
+static struct key_entry *wistron_get_entry_by_scancode(int code)
+{
+ struct key_entry *key;
-static void poll_bios(unsigned long);
+ for (key = keymap; key->type != KE_END; key++)
+ if (code == key->code)
+ return key;
-static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0);
+ return NULL;
+}
-static void handle_key(u8 code)
+static struct key_entry *wistron_get_entry_by_keycode(int keycode)
{
- const struct key_entry *key;
+ struct key_entry *key;
- for (key = keymap; key->type != KE_END; key++) {
- if (code == key->code) {
- switch (key->type) {
- case KE_KEY:
- report_key(key->keycode);
- break;
+ for (key = keymap; key->type != KE_END; key++)
+ if (key->type == KE_KEY && keycode == key->keycode)
+ return key;
- case KE_SW:
- report_switch(key->sw.code, key->sw.value);
- break;
+ return NULL;
+}
- case KE_WIFI:
- if (have_wifi) {
- wifi_enabled = !wifi_enabled;
- bios_set_state(WIFI, wifi_enabled);
- }
- break;
+static void handle_key(u8 code)
+{
+ const struct key_entry *key = wistron_get_entry_by_scancode(code);
- case KE_BLUETOOTH:
- if (have_bluetooth) {
- bluetooth_enabled = !bluetooth_enabled;
- bios_set_state(BLUETOOTH, bluetooth_enabled);
- }
- break;
+ if (key) {
+ switch (key->type) {
+ case KE_KEY:
+ report_key(wistron_idev->input, key->keycode);
+ break;
- case KE_END:
- break;
- default:
- BUG();
+ case KE_SW:
+ report_switch(wistron_idev->input,
+ key->sw.code, key->sw.value);
+ break;
+
+ case KE_WIFI:
+ if (have_wifi) {
+ wifi_enabled = !wifi_enabled;
+ bios_set_state(WIFI, wifi_enabled);
+ }
+ break;
+
+ case KE_BLUETOOTH:
+ if (have_bluetooth) {
+ bluetooth_enabled = !bluetooth_enabled;
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
}
- return;
+ break;
+
+ default:
+ BUG();
}
- }
- printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code);
+ jiffies_last_press = jiffies;
+ } else
+ printk(KERN_NOTICE
+ "wistron_btns: Unknown key code %02X\n", code);
}
-static void poll_bios(unsigned long discard)
+static void poll_bios(bool discard)
{
u8 qlen;
u16 val;
@@ -1090,15 +1132,118 @@ static void poll_bios(unsigned long discard)
if (val != 0 && !discard)
handle_key((u8)val);
}
+}
+
+static void wistron_flush(struct input_polled_dev *dev)
+{
+ /* Flush stale event queue */
+ poll_bios(true);
+}
+
+static void wistron_poll(struct input_polled_dev *dev)
+{
+ poll_bios(false);
+
+ /* Increase poll frequency if user is currently pressing keys (< 2s ago) */
+ if (time_before(jiffies, jiffies_last_press + 2 * HZ))
+ dev->poll_interval = POLL_INTERVAL_BURST;
+ else
+ dev->poll_interval = POLL_INTERVAL_DEFAULT;
+}
+
+static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+ const struct key_entry *key = wistron_get_entry_by_scancode(scancode);
+
+ if (key && key->type == KE_KEY) {
+ *keycode = key->keycode;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+ struct key_entry *key;
+ int old_keycode;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ key = wistron_get_entry_by_scancode(scancode);
+ if (key && key->type == KE_KEY) {
+ old_keycode = key->keycode;
+ key->keycode = keycode;
+ set_bit(keycode, dev->keybit);
+ if (!wistron_get_entry_by_keycode(old_keycode))
+ clear_bit(old_keycode, dev->keybit);
+ return 0;
+ }
- mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
+ return -EINVAL;
}
+static int __devinit setup_input_dev(void)
+{
+ const struct key_entry *key;
+ struct input_dev *input_dev;
+ int error;
+
+ wistron_idev = input_allocate_polled_device();
+ if (!wistron_idev)
+ return -ENOMEM;
+
+ wistron_idev->flush = wistron_flush;
+ wistron_idev->poll = wistron_poll;
+ wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
+
+ input_dev = wistron_idev->input;
+ input_dev->name = "Wistron laptop buttons";
+ input_dev->phys = "wistron/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &wistron_device->dev;
+
+ input_dev->getkeycode = wistron_getkeycode;
+ input_dev->setkeycode = wistron_setkeycode;
+
+ for (key = keymap; key->type != KE_END; key++) {
+ switch (key->type) {
+ case KE_KEY:
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(key->keycode, input_dev->keybit);
+ break;
+
+ case KE_SW:
+ set_bit(EV_SW, input_dev->evbit);
+ set_bit(key->sw.code, input_dev->swbit);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* reads information flags on KE_END */
+ if (key->code & FE_UNTESTED)
+ printk(KERN_WARNING "Untested laptop multimedia keys, "
+ "please report success or failure to eric.piel"
+ "@tremplin-utc.net\n");
+
+ error = input_register_polled_device(wistron_idev);
+ if (error) {
+ input_free_polled_device(wistron_idev);
+ return error;
+ }
+
+ return 0;
+}
+
+/* Driver core */
+
static int __devinit wistron_probe(struct platform_device *dev)
{
- int err = setup_input_dev();
- if (err)
- return err;
+ int err;
bios_attach();
cmos_address = bios_get_cmos_address();
@@ -1125,15 +1270,21 @@ static int __devinit wistron_probe(struct platform_device *dev)
bios_set_state(BLUETOOTH, bluetooth_enabled);
}
- poll_bios(1); /* Flush stale event queue and arm timer */
+ wistron_led_init(&dev->dev);
+ err = setup_input_dev();
+ if (err) {
+ bios_detach();
+ return err;
+ }
return 0;
}
static int __devexit wistron_remove(struct platform_device *dev)
{
- del_timer_sync(&poll_timer);
- input_unregister_device(input_dev);
+ wistron_led_remove();
+ input_unregister_polled_device(wistron_idev);
+ input_free_polled_device(wistron_idev);
bios_detach();
return 0;
@@ -1142,14 +1293,13 @@ static int __devexit wistron_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int wistron_suspend(struct platform_device *dev, pm_message_t state)
{
- del_timer_sync(&poll_timer);
-
if (have_wifi)
bios_set_state(WIFI, 0);
if (have_bluetooth)
bios_set_state(BLUETOOTH, 0);
+ wistron_led_suspend();
return 0;
}
@@ -1161,7 +1311,8 @@ static int wistron_resume(struct platform_device *dev)
if (have_bluetooth)
bios_set_state(BLUETOOTH, bluetooth_enabled);
- poll_bios(1);
+ wistron_led_resume();
+ poll_bios(true);
return 0;
}
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 50e06e8dd05d..7bbea097cda2 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -216,4 +216,20 @@ config MOUSE_HIL
help
Say Y here to support HIL pointers.
+config MOUSE_GPIO
+ tristate "GPIO mouse"
+ depends on GENERIC_GPIO
+ select INPUT_POLLDEV
+ help
+ This driver simulates a mouse on GPIO lines of various CPUs (and some
+ other chips).
+
+ Say Y here if your device has buttons or a simple joystick connected
+ directly to GPIO lines. Your board-specific setup logic must also
+ provide a platform device and platform data saying which GPIOs are
+ used.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gpio_mouse.
+
endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index aa4ba878533f..9e6e36330820 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
+obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
psmouse-objs := psmouse-base.o synaptics.o
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
new file mode 100644
index 000000000000..0936d6ba015c
--- /dev/null
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -0,0 +1,196 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/gpio_mouse.h>
+
+#include <asm/gpio.h>
+
+/*
+ * Timer function which is run every scan_ms ms when the device is opened.
+ * The dev input varaible is set to the the input_dev pointer.
+ */
+static void gpio_mouse_scan(struct input_polled_dev *dev)
+{
+ struct gpio_mouse_platform_data *gpio = dev->private;
+ struct input_dev *input = dev->input;
+ int x, y;
+
+ if (gpio->bleft >= 0)
+ input_report_key(input, BTN_LEFT,
+ gpio_get_value(gpio->bleft) ^ gpio->polarity);
+ if (gpio->bmiddle >= 0)
+ input_report_key(input, BTN_MIDDLE,
+ gpio_get_value(gpio->bmiddle) ^ gpio->polarity);
+ if (gpio->bright >= 0)
+ input_report_key(input, BTN_RIGHT,
+ gpio_get_value(gpio->bright) ^ gpio->polarity);
+
+ x = (gpio_get_value(gpio->right) ^ gpio->polarity)
+ - (gpio_get_value(gpio->left) ^ gpio->polarity);
+ y = (gpio_get_value(gpio->down) ^ gpio->polarity)
+ - (gpio_get_value(gpio->up) ^ gpio->polarity);
+
+ input_report_rel(input, REL_X, x);
+ input_report_rel(input, REL_Y, y);
+ input_sync(input);
+}
+
+static int __init gpio_mouse_probe(struct platform_device *pdev)
+{
+ struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
+ struct input_polled_dev *input_poll;
+ struct input_dev *input;
+ int pin, i;
+ int error;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ error = -ENXIO;
+ goto out;
+ }
+
+ if (pdata->scan_ms < 0) {
+ dev_err(&pdev->dev, "invalid scan time\n");
+ error = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+ pin = pdata->pins[i];
+
+ if (pin < 0) {
+
+ if (i <= GPIO_MOUSE_PIN_RIGHT) {
+ /* Mouse direction is required. */
+ dev_err(&pdev->dev,
+ "missing GPIO for directions\n");
+ error = -EINVAL;
+ goto out_free_gpios;
+ }
+
+ if (i == GPIO_MOUSE_PIN_BLEFT)
+ dev_dbg(&pdev->dev, "no left button defined\n");
+
+ } else {
+ error = gpio_request(pin, "gpio_mouse");
+ if (error) {
+ dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
+ pin, i);
+ goto out_free_gpios;
+ }
+
+ gpio_direction_input(pin);
+ }
+ }
+
+ input_poll = input_allocate_polled_device();
+ if (!input_poll) {
+ dev_err(&pdev->dev, "not enough memory for input device\n");
+ error = -ENOMEM;
+ goto out_free_gpios;
+ }
+
+ platform_set_drvdata(pdev, input_poll);
+
+ /* set input-polldev handlers */
+ input_poll->private = pdata;
+ input_poll->poll = gpio_mouse_scan;
+ input_poll->poll_interval = pdata->scan_ms;
+
+ input = input_poll->input;
+ input->name = pdev->name;
+ input->id.bustype = BUS_HOST;
+ input->dev.parent = &pdev->dev;
+
+ input_set_capability(input, EV_REL, REL_X);
+ input_set_capability(input, EV_REL, REL_Y);
+ if (pdata->bleft >= 0)
+ input_set_capability(input, EV_KEY, BTN_LEFT);
+ if (pdata->bmiddle >= 0)
+ input_set_capability(input, EV_KEY, BTN_MIDDLE);
+ if (pdata->bright >= 0)
+ input_set_capability(input, EV_KEY, BTN_RIGHT);
+
+ error = input_register_polled_device(input_poll);
+ if (error) {
+ dev_err(&pdev->dev, "could not register input device\n");
+ goto out_free_polldev;
+ }
+
+ dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",
+ pdata->scan_ms,
+ pdata->bleft < 0 ? "" : "left ",
+ pdata->bmiddle < 0 ? "" : "middle ",
+ pdata->bright < 0 ? "" : "right");
+
+ return 0;
+
+ out_free_polldev:
+ input_free_polled_device(input_poll);
+ platform_set_drvdata(pdev, NULL);
+
+ out_free_gpios:
+ while (--i >= 0) {
+ pin = pdata->pins[i];
+ if (pin)
+ gpio_free(pin);
+ }
+ out:
+ return error;
+}
+
+static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+{
+ struct input_polled_dev *input = platform_get_drvdata(pdev);
+ struct gpio_mouse_platform_data *pdata = input->private;
+ int pin, i;
+
+ input_unregister_polled_device(input);
+ input_free_polled_device(input);
+
+ for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+ pin = pdata->pins[i];
+ if (pin >= 0)
+ gpio_free(pin);
+ }
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+struct platform_driver gpio_mouse_device_driver = {
+ .remove = __devexit_p(gpio_mouse_remove),
+ .driver = {
+ .name = "gpio_mouse",
+ }
+};
+
+static int __init gpio_mouse_init(void)
+{
+ return platform_driver_probe(&gpio_mouse_device_driver,
+ gpio_mouse_probe);
+}
+module_init(gpio_mouse_init);
+
+static void __exit gpio_mouse_exit(void)
+{
+ platform_driver_unregister(&gpio_mouse_device_driver);
+}
+module_exit(gpio_mouse_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("GPIO mouse driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index f15f695777f8..b9f0fb2530e2 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -178,6 +178,15 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
}
/*
+ * Cortron PS2 Trackball reports SIDE button on the 4th bit of the first
+ * byte.
+ */
+ if (psmouse->type == PSMOUSE_CORTRON) {
+ input_report_key(dev, BTN_SIDE, (packet[0] >> 3) & 1);
+ packet[0] |= 0x08;
+ }
+
+/*
* Generic PS/2 Mouse
*/
@@ -539,6 +548,20 @@ static int ps2bare_detect(struct psmouse *psmouse, int set_properties)
return 0;
}
+/*
+ * Cortron PS/2 protocol detection. There's no special way to detect it, so it
+ * must be forced by sysfs protocol writing.
+ */
+static int cortron_detect(struct psmouse *psmouse, int set_properties)
+{
+ if (set_properties) {
+ psmouse->vendor = "Cortron";
+ psmouse->name = "PS/2 Trackball";
+ set_bit(BTN_SIDE, psmouse->dev->keybit);
+ }
+
+ return 0;
+}
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
@@ -740,6 +763,12 @@ static const struct psmouse_protocol psmouse_protocols[] = {
},
#endif
{
+ .type = PSMOUSE_CORTRON,
+ .name = "CortronPS/2",
+ .alias = "cortps",
+ .detect = cortron_detect,
+ },
+ {
.type = PSMOUSE_AUTO,
.name = "auto",
.alias = "any",
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 3964e8acbc54..27a68835b5ba 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -88,6 +88,7 @@ enum psmouse_type {
PSMOUSE_LIFEBOOK,
PSMOUSE_TRACKPOINT,
PSMOUSE_TOUCHKIT_PS2,
+ PSMOUSE_CORTRON,
PSMOUSE_AUTO /* This one should always be last */
};
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 3f4866d8d18c..9173916b8be5 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -64,6 +64,7 @@ struct mousedev {
wait_queue_head_t wait;
struct list_head client_list;
struct input_handle handle;
+ struct device dev;
struct list_head mixdev_node;
int mixdev_open;
@@ -112,7 +113,7 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
static struct input_handler mousedev_handler;
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
-static struct mousedev mousedev_mix;
+static struct mousedev *mousedev_mix;
static LIST_HEAD(mousedev_mix_list);
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
@@ -218,10 +219,10 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
if (value) {
set_bit(index, &mousedev->packet.buttons);
- set_bit(index, &mousedev_mix.packet.buttons);
+ set_bit(index, &mousedev_mix->packet.buttons);
} else {
clear_bit(index, &mousedev->packet.buttons);
- clear_bit(index, &mousedev_mix.packet.buttons);
+ clear_bit(index, &mousedev_mix->packet.buttons);
}
}
@@ -287,11 +288,11 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
* motion packet so we won't mess current position.
*/
set_bit(0, &mousedev->packet.buttons);
- set_bit(0, &mousedev_mix.packet.buttons);
- mousedev_notify_readers(mousedev, &mousedev_mix.packet);
- mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
+ set_bit(0, &mousedev_mix->packet.buttons);
+ mousedev_notify_readers(mousedev, &mousedev_mix->packet);
+ mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
clear_bit(0, &mousedev->packet.buttons);
- clear_bit(0, &mousedev_mix.packet.buttons);
+ clear_bit(0, &mousedev_mix->packet.buttons);
}
mousedev->touch = mousedev->pkt_count = 0;
mousedev->frac_dx = 0;
@@ -343,7 +344,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
}
mousedev_notify_readers(mousedev, &mousedev->packet);
- mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
+ mousedev_notify_readers(mousedev_mix, &mousedev->packet);
mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
mousedev->packet.abs_event = 0;
@@ -362,8 +363,10 @@ static int mousedev_fasync(int fd, struct file *file, int on)
return retval < 0 ? retval : 0;
}
-static void mousedev_free(struct mousedev *mousedev)
+static void mousedev_free(struct device *dev)
{
+ struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
+
mousedev_table[mousedev->minor] = NULL;
kfree(mousedev);
}
@@ -372,15 +375,16 @@ static int mixdev_add_device(struct mousedev *mousedev)
{
int error;
- if (mousedev_mix.open) {
+ if (mousedev_mix->open) {
error = input_open_device(&mousedev->handle);
if (error)
return error;
mousedev->open++;
- mousedev->mixdev_open++;
+ mousedev->mixdev_open = 1;
}
+ get_device(&mousedev->dev);
list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
return 0;
@@ -395,36 +399,40 @@ static void mixdev_remove_device(struct mousedev *mousedev)
}
list_del_init(&mousedev->mixdev_node);
+ put_device(&mousedev->dev);
}
static void mixdev_open_devices(void)
{
struct mousedev *mousedev;
+ if (mousedev_mix->open++)
+ return;
+
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
- if (mousedev->exist && !mousedev->open) {
- if (input_open_device(&mousedev->handle))
- continue;
+ if (!mousedev->mixdev_open) {
+ if (!mousedev->open && mousedev->exist)
+ if (input_open_device(&mousedev->handle))
+ continue;
mousedev->open++;
- mousedev->mixdev_open++;
+ mousedev->mixdev_open = 1;
}
}
}
static void mixdev_close_devices(void)
{
- struct mousedev *mousedev, *next;
+ struct mousedev *mousedev;
- list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+ if (--mousedev_mix->open)
+ return;
+
+ list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (mousedev->mixdev_open) {
mousedev->mixdev_open = 0;
- if (!--mousedev->open) {
- if (mousedev->exist)
- input_close_device(&mousedev->handle);
- else
- mousedev_free(mousedev);
- }
+ if (!--mousedev->open && mousedev->exist)
+ input_close_device(&mousedev->handle);
}
}
}
@@ -439,14 +447,12 @@ static int mousedev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--mousedev->open) {
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_close_devices();
- else if (mousedev->exist)
- input_close_device(&mousedev->handle);
- else
- mousedev_free(mousedev);
- }
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_close_devices();
+ else if (!--mousedev->open && mousedev->exist)
+ input_close_device(&mousedev->handle);
+
+ put_device(&mousedev->dev);
return 0;
}
@@ -473,9 +479,13 @@ static int mousedev_open(struct inode *inode, struct file *file)
if (!mousedev)
return -ENODEV;
+ get_device(&mousedev->dev);
+
client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_mousedev;
+ }
spin_lock_init(&client->packet_lock);
client->pos_x = xres / 2;
@@ -483,21 +493,23 @@ static int mousedev_open(struct inode *inode, struct file *file)
client->mousedev = mousedev;
list_add_tail(&client->node, &mousedev->client_list);
- if (!mousedev->open++) {
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_open_devices();
- else if (mousedev->exist) {
- error = input_open_device(&mousedev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
- }
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_open_devices();
+ else if (!mousedev->open++ && mousedev->exist) {
+ error = input_open_device(&mousedev->handle);
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_mousedev:
+ put_device(&mousedev->dev);
+ return error;
}
static inline int mousedev_limit_delta(int delta, int limit)
@@ -680,57 +692,96 @@ static const struct file_operations mousedev_fops = {
.fasync = mousedev_fasync,
};
-static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
- const struct input_device_id *id)
+static struct mousedev *mousedev_create(struct input_dev *dev,
+ struct input_handler *handler,
+ int minor)
{
struct mousedev *mousedev;
- struct class_device *cdev;
- dev_t devt;
- int minor;
int error;
- for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
- if (minor == MOUSEDEV_MINORS) {
- printk(KERN_ERR "mousedev: no more free mousedev devices\n");
- return -ENFILE;
- }
-
mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
- if (!mousedev)
- return -ENOMEM;
+ if (!mousedev) {
+ error = -ENOMEM;
+ goto err_out;
+ }
INIT_LIST_HEAD(&mousedev->client_list);
INIT_LIST_HEAD(&mousedev->mixdev_node);
init_waitqueue_head(&mousedev->wait);
+ if (minor == MOUSEDEV_MIX)
+ strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
+ else
+ snprintf(mousedev->name, sizeof(mousedev->name),
+ "mouse%d", minor);
+
mousedev->minor = minor;
mousedev->exist = 1;
mousedev->handle.dev = dev;
mousedev->handle.name = mousedev->name;
mousedev->handle.handler = handler;
mousedev->handle.private = mousedev;
- sprintf(mousedev->name, "mouse%d", minor);
- mousedev_table[minor] = mousedev;
+ strlcpy(mousedev->dev.bus_id, mousedev->name,
+ sizeof(mousedev->dev.bus_id));
+ mousedev->dev.class = &input_class;
+ if (dev)
+ mousedev->dev.parent = &dev->dev;
+ mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
+ mousedev->dev.release = mousedev_free;
+ device_initialize(&mousedev->dev);
- devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+ mousedev_table[minor] = mousedev;
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, mousedev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
+ error = device_add(&mousedev->dev);
+ if (error)
goto err_free_mousedev;
+
+ return mousedev;
+
+ err_free_mousedev:
+ put_device(&mousedev->dev);
+ err_out:
+ return ERR_PTR(error);
+}
+
+static void mousedev_destroy(struct mousedev *mousedev)
+{
+ struct mousedev_client *client;
+
+ device_del(&mousedev->dev);
+ mousedev->exist = 0;
+
+ if (mousedev->open) {
+ input_close_device(&mousedev->handle);
+ list_for_each_entry(client, &mousedev->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ wake_up_interruptible(&mousedev->wait);
}
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, mousedev->name);
- if (error)
- goto err_cdev_destroy;
+ put_device(&mousedev->dev);
+}
+
+static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct mousedev *mousedev;
+ int minor;
+ int error;
+
+ for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
+ if (minor == MOUSEDEV_MINORS) {
+ printk(KERN_ERR "mousedev: no more free mousedev devices\n");
+ return -ENFILE;
+ }
+
+ mousedev = mousedev_create(dev, handler, minor);
+ if (IS_ERR(mousedev))
+ return PTR_ERR(mousedev);
error = input_register_handle(&mousedev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_mousedev;
error = mixdev_add_device(mousedev);
if (error)
@@ -740,37 +791,18 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
err_unregister_handle:
input_unregister_handle(&mousedev->handle);
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
- err_free_mousedev:
- mousedev_table[minor] = NULL;
- kfree(mousedev);
+ err_delete_mousedev:
+ device_unregister(&mousedev->dev);
return error;
}
static void mousedev_disconnect(struct input_handle *handle)
{
struct mousedev *mousedev = handle->private;
- struct mousedev_client *client;
-
- input_unregister_handle(handle);
-
- sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
- mousedev->exist = 0;
mixdev_remove_device(mousedev);
-
- if (mousedev->open) {
- input_close_device(handle);
- list_for_each_entry(client, &mousedev->client_list, node)
- kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- wake_up_interruptible(&mousedev->wait);
- } else
- mousedev_free(mousedev);
+ input_unregister_handle(handle);
+ mousedev_destroy(mousedev);
}
static const struct input_device_id mousedev_ids[] = {
@@ -822,25 +854,16 @@ static int psaux_registered;
static int __init mousedev_init(void)
{
- struct class_device *cdev;
int error;
+ mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
+ if (IS_ERR(mousedev_mix))
+ return PTR_ERR(mousedev_mix);
+
error = input_register_handler(&mousedev_handler);
- if (error)
+ if (error) {
+ mousedev_destroy(mousedev_mix);
return error;
-
- memset(&mousedev_mix, 0, sizeof(struct mousedev));
- INIT_LIST_HEAD(&mousedev_mix.client_list);
- init_waitqueue_head(&mousedev_mix.wait);
- mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
- mousedev_mix.exist = 1;
- mousedev_mix.minor = MOUSEDEV_MIX;
-
- cdev = class_device_create(&input_class, NULL,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
- if (IS_ERR(cdev)) {
- input_unregister_handler(&mousedev_handler);
- return PTR_ERR(cdev);
}
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -863,9 +886,8 @@ static void __exit mousedev_exit(void)
if (psaux_registered)
misc_deregister(&psaux_mouse);
#endif
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
input_unregister_handler(&mousedev_handler);
+ mousedev_destroy(mousedev_mix);
}
module_init(mousedev_init);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 887357666c68..0403622ae267 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -160,7 +160,7 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t cou
{
struct serio_raw_list *list = file->private_data;
struct serio_raw *serio_raw = list->serio_raw;
- char c;
+ char uninitialized_var(c);
ssize_t retval = 0;
if (!serio_raw->serio)
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index cc0a498763d8..94683f58c9e1 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -82,8 +82,8 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.5 (May-15-2004)"
-#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio"
+#define DRIVER_VERSION "v2.3 (May 2, 2007)"
+#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio/Cedric Brun/Rene van Paassen"
#define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)"
/*
@@ -112,7 +112,7 @@
* (returned as Report 3 - absolute coordinates from the mouse)
*
* bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
- * byte0 0 0 0 0 0 0 1 0
+ * byte0 0 0 0 0 0 0 1 1
* byte1 X7 X6 X5 X4 X3 X2 X1 X0
* byte2 X15 X14 X13 X12 X11 X10 X9 X8
* byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
@@ -134,7 +134,7 @@
* (returned as Report 5 - macrokeys from the mouse)
*
* bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
- * byte0 0 0 0 0 0 1 0 0
+ * byte0 0 0 0 0 0 1 0 1
* byte1 0 0 0 BS2 BS Tip IR DV
* byte2 0 0 0 0 0 0 1 0
* byte3 0 0 0 K4 K3 K2 K1 K0
@@ -218,15 +218,9 @@
#define AIPTEK_WHEEL_DISABLE (-10101)
/* ToolCode values, which BTW are 0x140 .. 0x14f
- * We have things set up such that if TOOL_BUTTON_FIRED_BIT is
- * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx.
- *
- * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will
- * get reset.
+ * We have things set up such that if the tool button has changed,
+ * the tools get reset.
*/
-#define TOOL_BUTTON(x) ((x) & 0x14f)
-#define TOOL_BUTTON_FIRED(x) ((x) & 0x200)
-#define TOOL_BUTTON_FIRED_BIT 0x200
/* toolMode codes
*/
#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN
@@ -264,9 +258,9 @@
/* Mouse button programming
*/
-#define AIPTEK_MOUSE_LEFT_BUTTON 0x01
-#define AIPTEK_MOUSE_RIGHT_BUTTON 0x02
-#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04
+#define AIPTEK_MOUSE_LEFT_BUTTON 0x04
+#define AIPTEK_MOUSE_RIGHT_BUTTON 0x08
+#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x10
/* Stylus button programming
*/
@@ -294,7 +288,6 @@ struct aiptek_features {
int modelCode; /* Tablet model code (not unique) */
int firmwareCode; /* prom/eeprom version */
char usbPath[64 + 1]; /* device's physical usb path */
- char inputPath[64 + 1]; /* input device path */
};
struct aiptek_settings {
@@ -327,9 +320,32 @@ struct aiptek {
int inDelay; /* jitter: in jitter delay? */
unsigned long endDelay; /* jitter: time when delay ends */
int previousJitterable; /* jitterable prev value */
+
+ int lastMacro; /* macro key to reset */
+ int previousToolMode; /* pen, pencil, brush, etc. tool */
unsigned char *data; /* incoming packet data */
};
+static const int eventTypes[] = {
+ EV_KEY, EV_ABS, EV_REL, EV_MSC,
+};
+
+static const int absEvents[] = {
+ ABS_X, ABS_Y, ABS_PRESSURE, ABS_TILT_X, ABS_TILT_Y,
+ ABS_WHEEL, ABS_MISC,
+};
+
+static const int relEvents[] = {
+ REL_X, REL_Y, REL_WHEEL,
+};
+
+static const int buttonEvents[] = {
+ BTN_LEFT, BTN_RIGHT, BTN_MIDDLE,
+ BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH,
+ BTN_TOOL_BRUSH, BTN_TOOL_MOUSE, BTN_TOOL_LENS, BTN_TOUCH,
+ BTN_STYLUS, BTN_STYLUS2,
+};
+
/*
* Permit easy lookup of keyboard events to send, versus
* the bitmap which comes from the tablet. This hides the
@@ -345,23 +361,39 @@ static const int macroKeyEvents[] = {
};
/***********************************************************************
- * Relative reports deliver values in 2's complement format to
- * deal with negative offsets.
+ * Map values to strings and back. Every map shoudl have the following
+ * as its last element: { NULL, AIPTEK_INVALID_VALUE }.
*/
-static int aiptek_convert_from_2s_complement(unsigned char c)
+#define AIPTEK_INVALID_VALUE -1
+
+struct aiptek_map {
+ const char *string;
+ int value;
+};
+
+static int map_str_to_val(const struct aiptek_map *map, const char *str, size_t count)
{
- int ret;
- unsigned char b = c;
- int negate = 0;
+ const struct aiptek_map *p;
- if ((b & 0x80) != 0) {
- b = ~b;
- b--;
- negate = 1;
- }
- ret = b;
- ret = (negate == 1) ? -ret : ret;
- return ret;
+ if (str[count - 1] == '\n')
+ count--;
+
+ for (p = map; p->string; p++)
+ if (!strncmp(str, p->string, count))
+ return p->value;
+
+ return AIPTEK_INVALID_VALUE;
+}
+
+static const char *map_val_to_str(const struct aiptek_map *map, int val)
+{
+ const struct aiptek_map *p;
+
+ for (p = map; p->value != AIPTEK_INVALID_VALUE; p++)
+ if (val == p->value)
+ return p->string;
+
+ return "unknown";
}
/***********************************************************************
@@ -385,6 +417,9 @@ static int aiptek_convert_from_2s_complement(unsigned char c)
* Proximity. Why two events? I thought it interesting to know if the
* Proximity event occurred while the tablet was in absolute or relative
* mode.
+ * Update: REL_MISC proved not to be such a good idea. With REL_MISC you
+ * get an event transmitted each time. ABS_MISC works better, since it
+ * can be set and re-set. Thus, only using ABS_MISC from now on.
*
* Other tablets use the notion of a certain minimum stylus pressure
* to infer proximity. While that could have been done, that is yet
@@ -441,8 +476,8 @@ static void aiptek_irq(struct urb *urb)
aiptek->diagnostic =
AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE;
} else {
- x = aiptek_convert_from_2s_complement(data[2]);
- y = aiptek_convert_from_2s_complement(data[3]);
+ x = (signed char) data[2];
+ y = (signed char) data[3];
/* jitterable keeps track of whether any button has been pressed.
* We're also using it to remap the physical mouse button mask
@@ -451,18 +486,20 @@ static void aiptek_irq(struct urb *urb)
* that a non-zero value indicates that one or more
* mouse button was pressed.)
*/
- jitterable = data[5] & 0x07;
+ jitterable = data[1] & 0x07;
- left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
- right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
- middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
+ left = (data[1] & aiptek->curSetting.mouseButtonLeft >> 2) != 0 ? 1 : 0;
+ right = (data[1] & aiptek->curSetting.mouseButtonRight >> 2) != 0 ? 1 : 0;
+ middle = (data[1] & aiptek->curSetting.mouseButtonMiddle >> 2) != 0 ? 1 : 0;
input_report_key(inputdev, BTN_LEFT, left);
input_report_key(inputdev, BTN_MIDDLE, middle);
input_report_key(inputdev, BTN_RIGHT, right);
+
+ input_report_abs(inputdev, ABS_MISC,
+ 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
input_report_rel(inputdev, REL_X, x);
input_report_rel(inputdev, REL_Y, y);
- input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
/* Wheel support is in the form of a single-event
* firing.
@@ -472,6 +509,11 @@ static void aiptek_irq(struct urb *urb)
aiptek->curSetting.wheel);
aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
}
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -489,8 +531,8 @@ static void aiptek_irq(struct urb *urb)
y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
- p = (data[5] & 0x01) != 0 ? 1 : 0;
- dv = (data[5] & 0x02) != 0 ? 1 : 0;
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
tip = (data[5] & 0x04) != 0 ? 1 : 0;
/* Use jitterable to re-arrange button masks
@@ -505,16 +547,18 @@ static void aiptek_irq(struct urb *urb)
* all 'bad' reports...
*/
if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED
- (aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
if (p != 0) {
@@ -550,6 +594,11 @@ static void aiptek_irq(struct urb *urb)
}
}
input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS);
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -568,23 +617,25 @@ static void aiptek_irq(struct urb *urb)
jitterable = data[5] & 0x1c;
- p = (data[5] & 0x01) != 0 ? 1 : 0;
- dv = (data[5] & 0x02) != 0 ? 1 : 0;
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED
- (aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
if (p != 0) {
@@ -605,7 +656,12 @@ static void aiptek_irq(struct urb *urb)
aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
}
}
- input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+ input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -615,98 +671,83 @@ static void aiptek_irq(struct urb *urb)
else if (data[0] == 4) {
jitterable = data[1] & 0x18;
- p = (data[1] & 0x01) != 0 ? 1 : 0;
- dv = (data[1] & 0x02) != 0 ? 1 : 0;
+ dv = (data[1] & 0x01) != 0 ? 1 : 0;
+ p = (data[1] & 0x02) != 0 ? 1 : 0;
tip = (data[1] & 0x04) != 0 ? 1 : 0;
bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0;
pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
- macro = data[3];
+ macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
- if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ if (dv) {
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
+ }
- if (p != 0) {
- input_report_key(inputdev, BTN_TOUCH, tip);
- input_report_key(inputdev, BTN_STYLUS, bs);
- input_report_key(inputdev, BTN_STYLUS2, pck);
- input_report_abs(inputdev, ABS_PRESSURE, z);
- }
+ if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+ input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
- /* For safety, we're sending key 'break' codes for the
- * neighboring macro keys.
- */
- if (macro > 0) {
- input_report_key(inputdev,
- macroKeyEvents[macro - 1], 0);
- }
- if (macro < 25) {
- input_report_key(inputdev,
- macroKeyEvents[macro + 1], 0);
- }
- input_report_key(inputdev, macroKeyEvents[macro], p);
- input_report_abs(inputdev, ABS_MISC,
- p | AIPTEK_REPORT_TOOL_STYLUS);
- input_sync(inputdev);
+ if (macro != -1 && macro != aiptek->lastMacro) {
+ input_report_key(inputdev, macroKeyEvents[macro], 1);
+ aiptek->lastMacro = macro;
}
+ input_report_abs(inputdev, ABS_MISC,
+ p | AIPTEK_REPORT_TOOL_STYLUS);
+ input_sync(inputdev);
}
/* Report 5s come from the macro keys when pressed by mouse
*/
else if (data[0] == 5) {
jitterable = data[1] & 0x1c;
- p = (data[1] & 0x01) != 0 ? 1 : 0;
- dv = (data[1] & 0x02) != 0 ? 1 : 0;
+ dv = (data[1] & 0x01) != 0 ? 1 : 0;
+ p = (data[1] & 0x02) != 0 ? 1 : 0;
left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
- macro = data[3];
+ macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0;
- if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ if (dv) {
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
- input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
- 1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
- }
-
- if (p != 0) {
- input_report_key(inputdev, BTN_LEFT, left);
- input_report_key(inputdev, BTN_MIDDLE, middle);
- input_report_key(inputdev, BTN_RIGHT, right);
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
+ input_report_key(inputdev,
+ aiptek->curSetting.toolMode, 1);
+ aiptek->previousToolMode = aiptek->curSetting.toolMode;
}
+ }
- /* For safety, we're sending key 'break' codes for the
- * neighboring macro keys.
- */
- if (macro > 0) {
- input_report_key(inputdev,
- macroKeyEvents[macro - 1], 0);
- }
- if (macro < 25) {
- input_report_key(inputdev,
- macroKeyEvents[macro + 1], 0);
- }
+ if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+ input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
+ if (macro != -1 && macro != aiptek->lastMacro) {
input_report_key(inputdev, macroKeyEvents[macro], 1);
- input_report_rel(inputdev, ABS_MISC,
- p | AIPTEK_REPORT_TOOL_MOUSE);
- input_sync(inputdev);
+ aiptek->lastMacro = macro;
}
+
+ input_report_abs(inputdev, ABS_MISC,
+ p | AIPTEK_REPORT_TOOL_MOUSE);
+ input_sync(inputdev);
}
/* We have no idea which tool can generate a report 6. Theoretically,
* neither need to, having been given reports 4 & 5 for such use.
@@ -725,15 +766,18 @@ static void aiptek_irq(struct urb *urb)
0);
}
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
- */
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+ /* If the selected tool changed, reset the old
+ tool key, and set the new one.
+ */
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.
- toolMode), 1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->curSetting.toolMode,
+ 1);
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
input_report_key(inputdev, macroKeyEvents[macro], 1);
@@ -1007,9 +1051,6 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%dx%d\n",
aiptek->inputdev->absmax[ABS_X] + 1,
aiptek->inputdev->absmax[ABS_Y] + 1);
@@ -1024,117 +1065,35 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL);
/***********************************************************************
- * support routines for the 'product_id' file
- */
-static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "0x%04x\n",
- aiptek->inputdev->id.product);
-}
-
-static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor_id' file
- */
-static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);
-}
-
-static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor' file
- */
-static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
- int retval;
-
- if (aiptek == NULL)
- return 0;
-
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer);
- return retval;
-}
-
-static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL);
-
-/***********************************************************************
- * support routines for the 'product' file
- */
-static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
- int retval;
-
- if (aiptek == NULL)
- return 0;
-
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product);
- return retval;
-}
-
-static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL);
-
-/***********************************************************************
* support routines for the 'pointer_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+static struct aiptek_map pointer_mode_map[] = {
+ { "stylus", AIPTEK_POINTER_ONLY_STYLUS_MODE },
+ { "mouse", AIPTEK_POINTER_ONLY_MOUSE_MODE },
+ { "either", AIPTEK_POINTER_EITHER_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.pointerMode) {
- case AIPTEK_POINTER_ONLY_STYLUS_MODE:
- s = "stylus";
- break;
-
- case AIPTEK_POINTER_ONLY_MOUSE_MODE:
- s = "mouse";
- break;
-
- case AIPTEK_POINTER_EITHER_MODE:
- s = "either";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(pointer_mode_map,
+ aiptek->curSetting.pointerMode));
}
static ssize_t
store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(pointer_mode_map, buf, count);
- if (strcmp(buf, "stylus") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_POINTER_ONLY_STYLUS_MODE;
- } else if (strcmp(buf, "mouse") == 0) {
- aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE;
- } else if (strcmp(buf, "either") == 0) {
- aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+
+ aiptek->newSetting.pointerMode = new_mode;
return count;
}
@@ -1146,44 +1105,32 @@ static DEVICE_ATTR(pointer_mode,
* support routines for the 'coordinate_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+
+static struct aiptek_map coordinate_mode_map[] = {
+ { "absolute", AIPTEK_COORDINATE_ABSOLUTE_MODE },
+ { "relative", AIPTEK_COORDINATE_RELATIVE_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.coordinateMode) {
- case AIPTEK_COORDINATE_ABSOLUTE_MODE:
- s = "absolute";
- break;
-
- case AIPTEK_COORDINATE_RELATIVE_MODE:
- s = "relative";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(coordinate_mode_map,
+ aiptek->curSetting.coordinateMode));
}
static ssize_t
store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(coordinate_mode_map, buf, count);
- if (strcmp(buf, "absolute") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_COORDINATE_ABSOLUTE_MODE;
- } else if (strcmp(buf, "relative") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_COORDINATE_RELATIVE_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+
+ aiptek->newSetting.coordinateMode = new_mode;
return count;
}
@@ -1195,73 +1142,37 @@ static DEVICE_ATTR(coordinate_mode,
* support routines for the 'tool_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+
+static struct aiptek_map tool_mode_map[] = {
+ { "mouse", AIPTEK_TOOL_BUTTON_MOUSE_MODE },
+ { "eraser", AIPTEK_TOOL_BUTTON_ERASER_MODE },
+ { "pencil", AIPTEK_TOOL_BUTTON_PENCIL_MODE },
+ { "pen", AIPTEK_TOOL_BUTTON_PEN_MODE },
+ { "brush", AIPTEK_TOOL_BUTTON_BRUSH_MODE },
+ { "airbrush", AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE },
+ { "lens", AIPTEK_TOOL_BUTTON_LENS_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) {
- case AIPTEK_TOOL_BUTTON_MOUSE_MODE:
- s = "mouse";
- break;
-
- case AIPTEK_TOOL_BUTTON_ERASER_MODE:
- s = "eraser";
- break;
-
- case AIPTEK_TOOL_BUTTON_PENCIL_MODE:
- s = "pencil";
- break;
-
- case AIPTEK_TOOL_BUTTON_PEN_MODE:
- s = "pen";
- break;
-
- case AIPTEK_TOOL_BUTTON_BRUSH_MODE:
- s = "brush";
- break;
-
- case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE:
- s = "airbrush";
- break;
-
- case AIPTEK_TOOL_BUTTON_LENS_MODE:
- s = "lens";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(tool_mode_map,
+ aiptek->curSetting.toolMode));
}
static ssize_t
store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(tool_mode_map, buf, count);
- if (strcmp(buf, "mouse") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE;
- } else if (strcmp(buf, "eraser") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE;
- } else if (strcmp(buf, "pencil") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE;
- } else if (strcmp(buf, "pen") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE;
- } else if (strcmp(buf, "brush") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE;
- } else if (strcmp(buf, "airbrush") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE;
- } else if (strcmp(buf, "lens") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+ aiptek->newSetting.toolMode = new_mode;
return count;
}
@@ -1277,9 +1188,6 @@ static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1294,9 +1202,6 @@ store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char
struct aiptek *aiptek = dev_get_drvdata(dev);
int x;
- if (aiptek == NULL)
- return 0;
-
if (strcmp(buf, "disable") == 0) {
aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE;
} else {
@@ -1319,9 +1224,6 @@ static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1336,9 +1238,6 @@ store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char
struct aiptek *aiptek = dev_get_drvdata(dev);
int y;
- if (aiptek == NULL)
- return 0;
-
if (strcmp(buf, "disable") == 0) {
aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE;
} else {
@@ -1361,9 +1260,6 @@ static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribut
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay);
}
@@ -1372,9 +1268,6 @@ store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1391,9 +1284,6 @@ static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_at
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%d\n",
aiptek->curSetting.programmableDelay);
}
@@ -1403,9 +1293,6 @@ store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr,
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1415,23 +1302,6 @@ static DEVICE_ATTR(delay,
show_tabletProgrammableDelay, store_tabletProgrammableDelay);
/***********************************************************************
- * support routines for the 'input_path' file. Note that this file
- * only displays current setting.
- */
-static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n",
- aiptek->features.inputPath);
-}
-
-static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL);
-
-/***********************************************************************
* support routines for the 'event_count' file. Note that this file
* only displays current setting.
*/
@@ -1439,9 +1309,6 @@ static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attri
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount);
}
@@ -1456,9 +1323,6 @@ static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_at
struct aiptek *aiptek = dev_get_drvdata(dev);
char *retMsg;
- if (aiptek == NULL)
- return 0;
-
switch (aiptek->diagnostic) {
case AIPTEK_DIAGNOSTIC_NA:
retMsg = "no errors\n";
@@ -1493,45 +1357,32 @@ static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL);
* support routines for the 'stylus_upper' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
+static struct aiptek_map stylus_button_map[] = {
+ { "upper", AIPTEK_STYLUS_UPPER_BUTTON },
+ { "lower", AIPTEK_STYLUS_LOWER_BUTTON },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.stylusButtonUpper) {
- case AIPTEK_STYLUS_UPPER_BUTTON:
- s = "upper";
- break;
-
- case AIPTEK_STYLUS_LOWER_BUTTON:
- s = "lower";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(stylus_button_map,
+ aiptek->curSetting.stylusButtonUpper));
}
static ssize_t
store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(stylus_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "upper") == 0) {
- aiptek->newSetting.stylusButtonUpper =
- AIPTEK_STYLUS_UPPER_BUTTON;
- } else if (strcmp(buf, "lower") == 0) {
- aiptek->newSetting.stylusButtonUpper =
- AIPTEK_STYLUS_LOWER_BUTTON;
- }
+ aiptek->newSetting.stylusButtonUpper = new_button;
return count;
}
@@ -1543,45 +1394,26 @@ static DEVICE_ATTR(stylus_upper,
* support routines for the 'stylus_lower' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.stylusButtonLower) {
- case AIPTEK_STYLUS_UPPER_BUTTON:
- s = "upper";
- break;
-
- case AIPTEK_STYLUS_LOWER_BUTTON:
- s = "lower";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(stylus_button_map,
+ aiptek->curSetting.stylusButtonLower));
}
static ssize_t
store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(stylus_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "upper") == 0) {
- aiptek->newSetting.stylusButtonLower =
- AIPTEK_STYLUS_UPPER_BUTTON;
- } else if (strcmp(buf, "lower") == 0) {
- aiptek->newSetting.stylusButtonLower =
- AIPTEK_STYLUS_LOWER_BUTTON;
- }
+ aiptek->newSetting.stylusButtonLower = new_button;
return count;
}
@@ -1593,49 +1425,33 @@ static DEVICE_ATTR(stylus_lower,
* support routines for the 'mouse_left' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
+static struct aiptek_map mouse_button_map[] = {
+ { "left", AIPTEK_MOUSE_LEFT_BUTTON },
+ { "middle", AIPTEK_MOUSE_MIDDLE_BUTTON },
+ { "right", AIPTEK_MOUSE_RIGHT_BUTTON },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonLeft) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
-
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonLeft));
}
static ssize_t
store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonLeft = new_button;
return count;
}
@@ -1650,48 +1466,22 @@ static DEVICE_ATTR(mouse_left,
static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonMiddle) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
-
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonMiddle));
}
static ssize_t
store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonMiddle =
- AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonMiddle =
- AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonMiddle = new_button;
return count;
}
@@ -1706,47 +1496,22 @@ static DEVICE_ATTR(mouse_middle,
static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonRight) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonRight));
}
static ssize_t
store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonRight =
- AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonRight = new_button;
return count;
}
@@ -1762,9 +1527,6 @@ static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1778,9 +1540,6 @@ store_tabletWheel(struct device *dev, struct device_attribute *attr, const char
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1794,11 +1553,6 @@ static DEVICE_ATTR(wheel,
*/
static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
/* There is nothing useful to display, so a one-line manual
* is in order...
*/
@@ -1811,9 +1565,6 @@ store_tabletExecute(struct device *dev, struct device_attribute *attr, const cha
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
/* We do not care what you write to this file. Merely the action
* of writing to this file triggers a tablet reprogramming.
*/
@@ -1837,9 +1588,6 @@ static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *a
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode);
}
@@ -1853,9 +1601,6 @@ static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode);
}
@@ -1869,86 +1614,39 @@ static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *at
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%04x\n",
aiptek->features.firmwareCode);
}
static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);
-/***********************************************************************
- * This routine removes all existing sysfs files managed by this device
- * driver.
- */
-static void aiptek_delete_files(struct device *dev)
-{
- device_remove_file(dev, &dev_attr_size);
- device_remove_file(dev, &dev_attr_product_id);
- device_remove_file(dev, &dev_attr_vendor_id);
- device_remove_file(dev, &dev_attr_vendor);
- device_remove_file(dev, &dev_attr_product);
- device_remove_file(dev, &dev_attr_pointer_mode);
- device_remove_file(dev, &dev_attr_coordinate_mode);
- device_remove_file(dev, &dev_attr_tool_mode);
- device_remove_file(dev, &dev_attr_xtilt);
- device_remove_file(dev, &dev_attr_ytilt);
- device_remove_file(dev, &dev_attr_jitter);
- device_remove_file(dev, &dev_attr_delay);
- device_remove_file(dev, &dev_attr_input_path);
- device_remove_file(dev, &dev_attr_event_count);
- device_remove_file(dev, &dev_attr_diagnostic);
- device_remove_file(dev, &dev_attr_odm_code);
- device_remove_file(dev, &dev_attr_model_code);
- device_remove_file(dev, &dev_attr_firmware_code);
- device_remove_file(dev, &dev_attr_stylus_lower);
- device_remove_file(dev, &dev_attr_stylus_upper);
- device_remove_file(dev, &dev_attr_mouse_left);
- device_remove_file(dev, &dev_attr_mouse_middle);
- device_remove_file(dev, &dev_attr_mouse_right);
- device_remove_file(dev, &dev_attr_wheel);
- device_remove_file(dev, &dev_attr_execute);
-}
-
-/***********************************************************************
- * This routine creates the sysfs files managed by this device
- * driver.
- */
-static int aiptek_add_files(struct device *dev)
-{
- int ret;
+static struct attribute *aiptek_attributes[] = {
+ &dev_attr_size.attr,
+ &dev_attr_pointer_mode.attr,
+ &dev_attr_coordinate_mode.attr,
+ &dev_attr_tool_mode.attr,
+ &dev_attr_xtilt.attr,
+ &dev_attr_ytilt.attr,
+ &dev_attr_jitter.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_event_count.attr,
+ &dev_attr_diagnostic.attr,
+ &dev_attr_odm_code.attr,
+ &dev_attr_model_code.attr,
+ &dev_attr_firmware_code.attr,
+ &dev_attr_stylus_lower.attr,
+ &dev_attr_stylus_upper.attr,
+ &dev_attr_mouse_left.attr,
+ &dev_attr_mouse_middle.attr,
+ &dev_attr_mouse_right.attr,
+ &dev_attr_wheel.attr,
+ &dev_attr_execute.attr,
+ NULL
+};
- if ((ret = device_create_file(dev, &dev_attr_size)) ||
- (ret = device_create_file(dev, &dev_attr_product_id)) ||
- (ret = device_create_file(dev, &dev_attr_vendor_id)) ||
- (ret = device_create_file(dev, &dev_attr_vendor)) ||
- (ret = device_create_file(dev, &dev_attr_product)) ||
- (ret = device_create_file(dev, &dev_attr_pointer_mode)) ||
- (ret = device_create_file(dev, &dev_attr_coordinate_mode)) ||
- (ret = device_create_file(dev, &dev_attr_tool_mode)) ||
- (ret = device_create_file(dev, &dev_attr_xtilt)) ||
- (ret = device_create_file(dev, &dev_attr_ytilt)) ||
- (ret = device_create_file(dev, &dev_attr_jitter)) ||
- (ret = device_create_file(dev, &dev_attr_delay)) ||
- (ret = device_create_file(dev, &dev_attr_input_path)) ||
- (ret = device_create_file(dev, &dev_attr_event_count)) ||
- (ret = device_create_file(dev, &dev_attr_diagnostic)) ||
- (ret = device_create_file(dev, &dev_attr_odm_code)) ||
- (ret = device_create_file(dev, &dev_attr_model_code)) ||
- (ret = device_create_file(dev, &dev_attr_firmware_code)) ||
- (ret = device_create_file(dev, &dev_attr_stylus_lower)) ||
- (ret = device_create_file(dev, &dev_attr_stylus_upper)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_left)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_middle)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_right)) ||
- (ret = device_create_file(dev, &dev_attr_wheel)) ||
- (ret = device_create_file(dev, &dev_attr_execute))) {
- err("aiptek: killing own sysfs device files\n");
- aiptek_delete_files(dev);
- }
- return ret;
-}
+static struct attribute_group aiptek_attribute_group = {
+ .attrs = aiptek_attributes,
+};
/***********************************************************************
* This routine is called when a tablet has been identified. It basically
@@ -1961,8 +1659,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_endpoint_descriptor *endpoint;
struct aiptek *aiptek;
struct input_dev *inputdev;
- struct input_handle *inputhandle;
- struct list_head *node, *next;
int i;
int speeds[] = { 0,
AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -1984,17 +1680,23 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
inputdev = input_allocate_device();
- if (!aiptek || !inputdev)
+ if (!aiptek || !inputdev) {
+ warn("aiptek: cannot allocate memory or input device");
goto fail1;
+ }
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma);
- if (!aiptek->data)
+ if (!aiptek->data) {
+ warn("aiptek: cannot allocate usb buffer");
goto fail1;
+ }
aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!aiptek->urb)
+ if (!aiptek->urb) {
+ warn("aiptek: cannot allocate urb");
goto fail2;
+ }
aiptek->inputdev = inputdev;
aiptek->usbdev = usbdev;
@@ -2002,6 +1704,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek->inDelay = 0;
aiptek->endDelay = 0;
aiptek->previousJitterable = 0;
+ aiptek->lastMacro = -1;
/* Set up the curSettings struct. Said struct contains the current
* programmable parameters. The newSetting struct contains changes
@@ -2054,36 +1757,23 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Now program the capacities of the tablet, in terms of being
* an input device.
*/
- inputdev->evbit[0] |= BIT(EV_KEY)
- | BIT(EV_ABS)
- | BIT(EV_REL)
- | BIT(EV_MSC);
-
- inputdev->absbit[0] |= BIT(ABS_MISC);
+ for (i = 0; i < ARRAY_SIZE(eventTypes); ++i)
+ __set_bit(eventTypes[i], inputdev->evbit);
- inputdev->relbit[0] |=
- (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
+ for (i = 0; i < ARRAY_SIZE(absEvents); ++i)
+ __set_bit(absEvents[i], inputdev->absbit);
- inputdev->keybit[LONG(BTN_LEFT)] |=
- (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
+ for (i = 0; i < ARRAY_SIZE(relEvents); ++i)
+ __set_bit(relEvents[i], inputdev->relbit);
- inputdev->keybit[LONG(BTN_DIGI)] |=
- (BIT(BTN_TOOL_PEN) |
- BIT(BTN_TOOL_RUBBER) |
- BIT(BTN_TOOL_PENCIL) |
- BIT(BTN_TOOL_AIRBRUSH) |
- BIT(BTN_TOOL_BRUSH) |
- BIT(BTN_TOOL_MOUSE) |
- BIT(BTN_TOOL_LENS) |
- BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
+ __set_bit(MSC_SERIAL, inputdev->mscbit);
- inputdev->mscbit[0] = BIT(MSC_SERIAL);
+ /* Set up key and button codes */
+ for (i = 0; i < ARRAY_SIZE(buttonEvents); ++i)
+ __set_bit(buttonEvents[i], inputdev->keybit);
- /* Programming the tablet macro keys needs to be done with a for loop
- * as the keycodes are discontiguous.
- */
for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
- set_bit(macroKeyEvents[i], inputdev->keybit);
+ __set_bit(macroKeyEvents[i], inputdev->keybit);
/*
* Program the input device coordinate capacities. We do not yet
@@ -2134,25 +1824,11 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
}
- /* Register the tablet as an Input Device
- */
- err = input_register_device(aiptek->inputdev);
- if (err)
+ /* Murphy says that some day someone will have a tablet that fails the
+ above test. That's you, Frederic Rodrigo */
+ if (i == ARRAY_SIZE(speeds)) {
+ info("input: Aiptek tried all speeds, no sane response");
goto fail2;
-
- /* We now will look for the evdev device which is mapped to
- * the tablet. The partial name is kept in the link list of
- * input_handles associated with this input device.
- * What identifies an evdev input_handler is that it begins
- * with 'event', continues with a digit, and that in turn
- * is mapped to input/eventN.
- */
- list_for_each_safe(node, next, &inputdev->h_list) {
- inputhandle = to_handle(node);
- if (strncmp(inputhandle->name, "event", 5) == 0) {
- strcpy(aiptek->features.inputPath, inputhandle->name);
- break;
- }
}
/* Associate this driver's struct with the usb interface.
@@ -2161,18 +1837,27 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Set up the sysfs files
*/
- aiptek_add_files(&intf->dev);
+ err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);
+ if (err) {
+ warn("aiptek: cannot create sysfs group err: %d", err);
+ goto fail3;
+ }
- /* Make sure the evdev module is loaded. Assuming evdev IS a module :-)
+ /* Register the tablet as an Input Device
*/
- if (request_module("evdev") != 0)
- info("aiptek: error loading 'evdev' module");
-
+ err = input_register_device(aiptek->inputdev);
+ if (err) {
+ warn("aiptek: input_register_device returned err: %d", err);
+ goto fail4;
+ }
return 0;
+ fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
+ fail3: usb_free_urb(aiptek->urb);
fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
aiptek->data_dma);
- fail1: input_free_device(inputdev);
+ fail1: usb_set_intfdata(intf, NULL);
+ input_free_device(inputdev);
kfree(aiptek);
return err;
}
@@ -2192,7 +1877,7 @@ static void aiptek_disconnect(struct usb_interface *intf)
*/
usb_kill_urb(aiptek->urb);
input_unregister_device(aiptek->inputdev);
- aiptek_delete_files(&intf->dev);
+ sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
usb_free_urb(aiptek->urb);
usb_buffer_free(interface_to_usbdev(intf),
AIPTEK_PACKET_LENGTH,
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index ef01a807ec0f..6542edb6f76e 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -11,7 +11,7 @@
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
- * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2007 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -62,8 +62,9 @@
* - Minor data report fix
* v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
* - where wacom_sys.c deals with system specific code,
- * - and wacom_wac.c deals with Wacom specific code
+ * - and wacom_wac.c deals with Wacom specific code
* - Support Intuos3 4x6
+ * v1.47 (pc) - Added support for Bamboo
*/
/*
@@ -84,7 +85,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.46"
+#define DRIVER_VERSION "v1.47"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -123,6 +124,7 @@ extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wa
extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern __u16 wacom_le16_to_cpu(unsigned char *data);
extern __u16 wacom_be16_to_cpu(unsigned char *data);
extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 83bddef66067..064e123c9b76 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -138,6 +138,12 @@ static void wacom_close(struct input_dev *dev)
usb_kill_urb(wacom->irq);
}
+void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_1) | BIT(BTN_5);
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+}
+
void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->evbit[0] |= BIT(EV_MSC);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 7661f03a2db2..fc03ba256f4c 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -178,7 +178,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
case 2: /* Mouse with wheel */
wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
- if (wacom->features->type == WACOM_G4) {
+ if (wacom->features->type == WACOM_G4 ||
+ wacom->features->type == WACOM_MO) {
rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
wacom_report_rel(wcombo, REL_WHEEL, -rw);
} else
@@ -190,7 +191,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
id = CURSOR_DEVICE_ID;
wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
- if (wacom->features->type == WACOM_G4)
+ if (wacom->features->type == WACOM_G4 ||
+ wacom->features->type == WACOM_MO)
wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
else
wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
@@ -226,7 +228,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
}
/* send pad data */
- if (wacom->features->type == WACOM_G4) {
+ switch (wacom->features->type) {
+ case WACOM_G4:
if (data[7] & 0xf8) {
wacom_input_sync(wcombo); /* sync last event */
wacom->id[1] = 1;
@@ -247,6 +250,33 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_abs(wcombo, ABS_MISC, 0);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
}
+ break;
+ case WACOM_MO:
+ if ((data[7] & 0xf8) || (data[8] & 0x80)) {
+ wacom_input_sync(wcombo); /* sync last event */
+ wacom->id[1] = 1;
+ wacom->serial[1] = (data[7] & 0xf8);
+ wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+ wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+ wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+ wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+ wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+ wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+ wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+ wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+ } else if (wacom->id[1]) {
+ wacom_input_sync(wcombo); /* sync last event */
+ wacom->id[1] = 0;
+ wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+ wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+ wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+ wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+ wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+ wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+ wacom_report_abs(wcombo, ABS_MISC, 0);
+ wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+ }
+ break;
}
return 1;
}
@@ -331,7 +361,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_EXTRA, 0);
wacom_report_abs(wcombo, ABS_THROTTLE, 0);
wacom_report_abs(wcombo, ABS_RZ, 0);
- } else {
+ } else {
wacom_report_abs(wcombo, ABS_PRESSURE, 0);
wacom_report_abs(wcombo, ABS_TILT_X, 0);
wacom_report_abs(wcombo, ABS_TILT_Y, 0);
@@ -423,9 +453,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
return result-1;
/* Only large I3 and I1 & I2 support Lense Cursor */
- if((wacom->tool[idx] == BTN_TOOL_LENS)
+ if ((wacom->tool[idx] == BTN_TOOL_LENS)
&& ((wacom->features->type == INTUOS3)
- || (wacom->features->type == INTUOS3S)))
+ || (wacom->features->type == INTUOS3S)))
return 0;
/* Cintiq doesn't send data when RDY bit isn't set */
@@ -517,6 +547,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
break;
case WACOM_G4:
case GRAPHIRE:
+ case WACOM_MO:
return (wacom_graphire_irq(wacom_wac, wcombo));
break;
case PTU:
@@ -538,6 +569,8 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
switch (wacom_wac->features->type) {
+ case WACOM_MO:
+ input_dev_mo(input_dev, wacom_wac);
case WACOM_G4:
input_dev_g4(input_dev, wacom_wac);
/* fall through */
@@ -579,6 +612,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE },
{ "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE },
+ { "Wacom Bamboo", 9, 14760, 9225, 511, 63, WACOM_MO },
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS },
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS },
@@ -627,6 +661,7 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index a5e12e8756de..a302e229bb8a 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -25,6 +25,7 @@ enum {
INTUOS3,
INTUOS3L,
CINTIQ,
+ WACOM_MO,
MAX_TYPE
};
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index e5cca9bd0406..69371779806a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -177,6 +177,7 @@ config TOUCHSCREEN_USB_COMPOSITE
- some other eTurboTouch
- Gunze AHL61
- DMC TSC-10/25
+ - IRTOUCHSYSTEMS/UNITOP
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
@@ -219,4 +220,9 @@ config TOUCHSCREEN_USB_DMC_TSC10
bool "DMC TSC-10/25 device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
+config TOUCHSCREEN_USB_IRTOUCH
+ default y
+ bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
+ depends on TOUCHSCREEN_USB_COMPOSITE
+
endif
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index e3f22852bd09..b407028ffc59 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -9,6 +9,7 @@
* - eTurboTouch
* - Gunze AHL61
* - DMC TSC-10/25
+ * - IRTOUCHSYSTEMS/UNITOP
*
* Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -110,6 +111,7 @@ enum {
DEVTYPE_ETURBO,
DEVTYPE_GUNZE,
DEVTYPE_DMC_TSC10,
+ DEVTYPE_IRTOUCH,
};
static struct usb_device_id usbtouch_devices[] = {
@@ -150,6 +152,11 @@ static struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
#endif
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+ {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+ {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+#endif
+
{}
};
@@ -416,6 +423,21 @@ static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
/*****************************************************************************
+ * IRTOUCH Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+ dev->x = (pkt[3] << 8) | pkt[2];
+ dev->y = (pkt[5] << 8) | pkt[4];
+ dev->touch = (pkt[1] & 0x03) ? 1 : 0;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
* the different device descriptors
*/
static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -504,6 +526,17 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.read_data = dmc_tsc10_read_data,
},
#endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+ [DEVTYPE_IRTOUCH] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .rept_size = 8,
+ .read_data = irtouch_read_data,
+ },
+#endif
};
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 2db364898e15..d2f882e98e5e 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -109,9 +109,11 @@ struct tsdev {
int open;
int minor;
char name[8];
+ struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
- struct input_handle handle;
+ struct device dev;
+
int x, y, pressure;
struct ts_calibration cal;
};
@@ -163,9 +165,13 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (!tsdev || !tsdev->exist)
return -ENODEV;
+ get_device(&tsdev->dev);
+
client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_tsdev;
+ }
client->tsdev = tsdev;
client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
@@ -173,19 +179,25 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (!tsdev->open++ && tsdev->exist) {
error = input_open_device(&tsdev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_tsdev:
+ put_device(&tsdev->dev);
+ return error;
}
-static void tsdev_free(struct tsdev *tsdev)
+static void tsdev_free(struct device *dev)
{
+ struct tsdev *tsdev = container_of(dev, struct tsdev, dev);
+
tsdev_table[tsdev->minor] = NULL;
kfree(tsdev);
}
@@ -200,12 +212,10 @@ static int tsdev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--tsdev->open) {
- if (tsdev->exist)
- input_close_device(&tsdev->handle);
- else
- tsdev_free(tsdev);
- }
+ if (!--tsdev->open && tsdev->exist)
+ input_close_device(&tsdev->handle);
+
+ put_device(&tsdev->dev);
return 0;
}
@@ -361,7 +371,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
int x, y, tmp;
do_gettimeofday(&time);
- client->event[client->head].millisecs = time.tv_usec / 100;
+ client->event[client->head].millisecs = time.tv_usec / 1000;
client->event[client->head].pressure = tsdev->pressure;
x = tsdev->x;
@@ -388,8 +398,6 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct tsdev *tsdev;
- struct class_device *cdev;
- dev_t devt;
int minor, delta;
int error;
@@ -407,14 +415,13 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
INIT_LIST_HEAD(&tsdev->client_list);
init_waitqueue_head(&tsdev->wait);
- sprintf(tsdev->name, "ts%d", minor);
-
tsdev->exist = 1;
tsdev->minor = minor;
tsdev->handle.dev = dev;
tsdev->handle.name = tsdev->name;
tsdev->handle.handler = handler;
tsdev->handle.private = tsdev;
+ snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
/* Precompute the rough calibration matrix */
delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
@@ -429,36 +436,30 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
tsdev->cal.yscale = (yres << 8) / delta;
tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
- tsdev_table[minor] = tsdev;
-
- devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+ snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
+ "ts%d", minor);
+ tsdev->dev.class = &input_class;
+ tsdev->dev.parent = &dev->dev;
+ tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor);
+ tsdev->dev.release = tsdev_free;
+ device_initialize(&tsdev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, tsdev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_tsdev;
- }
+ tsdev_table[minor] = tsdev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, tsdev->name);
+ error = device_add(&tsdev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_tsdev;
error = input_register_handle(&tsdev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_tsdev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_tsdev:
+ device_del(&tsdev->dev);
err_free_tsdev:
- tsdev_table[minor] = NULL;
- kfree(tsdev);
+ put_device(&tsdev->dev);
return error;
}
@@ -468,10 +469,8 @@ static void tsdev_disconnect(struct input_handle *handle)
struct tsdev_client *client;
input_unregister_handle(handle);
+ device_del(&tsdev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
tsdev->exist = 0;
if (tsdev->open) {
@@ -479,8 +478,9 @@ static void tsdev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &tsdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&tsdev->wait);
- } else
- tsdev_free(tsdev);
+ }
+
+ put_device(&tsdev->dev);
}
static const struct input_device_id tsdev_ids[] = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 616eee9c04f1..bd601efa7bd1 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -34,6 +34,11 @@ config PHANTOM
If you choose to build module, its name will be phantom. If unsure,
say N here.
+config EEPROM_93CX6
+ tristate "EEPROM 93CX6 support"
+ ---help---
+ This is a driver for the EEPROM chipsets 93c46 and 93c66.
+ The driver supports both read as well as write commands.
If unsure, say N.
@@ -187,5 +192,4 @@ config THINKPAD_ACPI_BAY
If you are not sure, say Y here.
-
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 8abbf2f07a65..b5ce0e3dba86 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
+obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 000000000000..ac515b0ef67c
--- /dev/null
+++ b/drivers/misc/eeprom_93cx6.c
@@ -0,0 +1,241 @@
+/*
+ Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Module: eeprom_93cx6
+ Abstract: EEPROM reader routines for 93cx6 chipsets.
+ Supported chipsets: 93c46 & 93c66.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/eeprom_93cx6.h>
+
+MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
+MODULE_LICENSE("GPL");
+
+static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
+{
+ eeprom->reg_data_clock = 1;
+ eeprom->register_write(eeprom);
+
+ /*
+ * Add a short delay for the pulse to work.
+ * According to the specifications the "maximum minimum"
+ * time should be 450ns.
+ */
+ ndelay(450);
+}
+
+static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
+{
+ eeprom->reg_data_clock = 0;
+ eeprom->register_write(eeprom);
+
+ /*
+ * Add a short delay for the pulse to work.
+ * According to the specifications the minimal time
+ * should be 450ns so a 1us delay is sufficient.
+ */
+ udelay(1);
+}
+
+static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
+{
+ /*
+ * Clear all flags, and enable chip select.
+ */
+ eeprom->register_read(eeprom);
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+ eeprom->reg_data_clock = 0;
+ eeprom->reg_chip_select = 1;
+ eeprom->register_write(eeprom);
+
+ /*
+ * kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
+{
+ /*
+ * Clear chip_select and data_in flags.
+ */
+ eeprom->register_read(eeprom);
+ eeprom->reg_data_in = 0;
+ eeprom->reg_chip_select = 0;
+ eeprom->register_write(eeprom);
+
+ /*
+ * kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
+ const u16 data, const u16 count)
+{
+ unsigned int i;
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data flags.
+ */
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+
+ /*
+ * Start writing all bits.
+ */
+ for (i = count; i > 0; i--) {
+ /*
+ * Check if this bit needs to be set.
+ */
+ eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+
+ /*
+ * Write the bit to the eeprom register.
+ */
+ eeprom->register_write(eeprom);
+
+ /*
+ * Kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
+ eeprom->reg_data_in = 0;
+ eeprom->register_write(eeprom);
+}
+
+static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
+ u16 *data, const u16 count)
+{
+ unsigned int i;
+ u16 buf = 0;
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data flags.
+ */
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+
+ /*
+ * Start reading all bits.
+ */
+ for (i = count; i > 0; i--) {
+ eeprom_93cx6_pulse_high(eeprom);
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data_in flag.
+ */
+ eeprom->reg_data_in = 0;
+
+ /*
+ * Read if the bit has been set.
+ */
+ if (eeprom->reg_data_out)
+ buf |= (1 << (i - 1));
+
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
+ *data = buf;
+}
+
+/**
+ * eeprom_93cx6_read - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read the eeprom data as host-endian word
+ * into the given data pointer.
+ */
+void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
+ u16 *data)
+{
+ u16 command;
+
+ /*
+ * Initialize the eeprom register
+ */
+ eeprom_93cx6_startup(eeprom);
+
+ /*
+ * Select the read opcode and the word to be read.
+ */
+ command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
+ eeprom_93cx6_write_bits(eeprom, command,
+ PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+ /*
+ * Read the requested 16 bits.
+ */
+ eeprom_93cx6_read_bits(eeprom, data, 16);
+
+ /*
+ * Cleanup eeprom register.
+ */
+ eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
+
+/**
+ * eeprom_93cx6_multiread - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of words that should be read.
+ *
+ * This function will read all requested words from the eeprom,
+ * this is done by calling eeprom_93cx6_read() multiple times.
+ * But with the additional change that while the eeprom_93cx6_read
+ * will return host ordered bytes, this method will return little
+ * endian words.
+ */
+void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
+ __le16 *data, const u16 words)
+{
+ unsigned int i;
+ u16 tmp;
+
+ for (i = 0; i < words; i++) {
+ tmp = 0;
+ eeprom_93cx6_read(eeprom, word + i, &tmp);
+ data[i] = cpu_to_le16(tmp);
+ }
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
+
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 78872c3f3760..b96ac8e119dc 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -84,7 +84,7 @@ static unsigned long __initdata doc_locations[] = {
#elif defined(CONFIG_MOMENCO_OCELOT)
0x2f000000,
0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
##else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b665e4ac2208..f88ebc5b685e 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -258,12 +258,6 @@ config MTD_TSUNAMI
help
Support for the flash chip on Tsunami TIG bus.
-config MTD_LASAT
- tristate "LASAT flash device"
- depends on LASAT && MTD_CFI
- help
- Support for the flash chips on the Lasat 100 and 200 boards.
-
config MTD_NETtel
tristate "CFI flash device on SnapGear/SecureEdge"
depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 3acbb5d01ca4..970b189271a2 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -47,7 +47,6 @@ obj-$(CONFIG_MTD_OCELOT) += ocelot.o
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
obj-$(CONFIG_MTD_PCI) += pci.o
obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o
-obj-$(CONFIG_MTD_LASAT) += lasat.o
obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_IMPA7) += impa7.o
diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c
deleted file mode 100644
index e34376321050..000000000000
--- a/drivers/mtd/maps/lasat.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Flash device on Lasat 100 and 200 boards
- *
- * (C) 2002 Brian Murphy <brian@murphy.dk>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/lasat/lasat.h>
-
-static struct mtd_info *lasat_mtd;
-
-static struct mtd_partition partition_info[LASAT_MTD_LAST];
-static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
-
-static void lasat_set_vpp(struct map_info *map, int vpp)
-{
- if (vpp)
- *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
- else
- *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
-}
-
-static struct map_info lasat_map = {
- .name = "LASAT flash",
- .bankwidth = 4,
- .set_vpp = lasat_set_vpp
-};
-
-static int __init init_lasat(void)
-{
- int i;
- /* since we use AMD chips and set_vpp is not implimented
- * for these (yet) we still have to permanently enable flash write */
- printk(KERN_NOTICE "Unprotecting flash\n");
- ENABLE_VPP((&lasat_map));
-
- lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
- lasat_map.virt = ioremap_nocache(
- lasat_map.phys, lasat_board_info.li_flash_size);
- lasat_map.size = lasat_board_info.li_flash_size;
-
- simple_map_init(&lasat_map);
-
- for (i=0; i < LASAT_MTD_LAST; i++)
- partition_info[i].name = lasat_mtd_partnames[i];
-
- lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
-
- if (!lasat_mtd)
- lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
-
- if (lasat_mtd) {
- u32 size, offset = 0;
-
- lasat_mtd->owner = THIS_MODULE;
-
- for (i=0; i < LASAT_MTD_LAST; i++) {
- size = lasat_flash_partition_size(i);
- partition_info[i].size = size;
- partition_info[i].offset = offset;
- offset += size;
- }
-
- add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
- return 0;
- }
-
- iounmap(lasat_map.virt);
- return -ENXIO;
-}
-
-static void __exit cleanup_lasat(void)
-{
- if (lasat_mtd) {
- del_mtd_partitions(lasat_mtd);
- map_destroy(lasat_mtd);
- }
- if (lasat_map.virt) {
- iounmap(lasat_map.virt);
- lasat_map.virt = 0;
- }
-}
-
-module_init(init_lasat);
-module_exit(cleanup_lasat);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
-MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver");
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 595208f965a5..17c868034aad 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -59,7 +59,7 @@ static unsigned long __initdata doc_locations[] = {
#elif defined(CONFIG_MOMENCO_OCELOT)
0x2f000000,
0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index a804965e6542..58bbc3e6d0de 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -107,11 +107,6 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered mu
#define PFX DRV_NAME ": "
-#ifndef TRUE
-#define FALSE 0
-#define TRUE (!FALSE)
-#endif
-
#define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
NETIF_MSG_LINK)
@@ -661,7 +656,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
if (status & (TxOK | TxErr | TxEmpty | SWInt))
cp_tx(cp);
if (status & LinkChg)
- mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
spin_unlock(&cp->lock);
@@ -1188,7 +1183,7 @@ static int cp_open (struct net_device *dev)
goto err_out_hw;
netif_carrier_off(dev);
- mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
netif_start_queue(dev);
return 0;
@@ -2050,7 +2045,7 @@ static int cp_resume (struct pci_dev *pdev)
spin_lock_irqsave (&cp->lock, flags);
- mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
spin_unlock_irqrestore (&cp->lock, flags);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b49375abb5f4..627316db3744 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3,10 +3,7 @@
# Network device configuration
#
-menu "Network device support"
- depends on NET
-
-config NETDEVICES
+menuconfig NETDEVICES
default y if UML
bool "Network device support"
---help---
@@ -151,11 +148,9 @@ source "drivers/net/phy/Kconfig"
# Ethernet
#
-menu "Ethernet (10 or 100Mbit)"
- depends on !UML
-
-config NET_ETHERNET
+menuconfig NET_ETHERNET
bool "Ethernet (10 or 100Mbit)"
+ depends on !UML
---help---
Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
type of Local Area Network (LAN) in universities and companies.
@@ -180,9 +175,10 @@ config NET_ETHERNET
kernel: saying N will just cause the configurator to skip all
the questions about Ethernet network cards. If unsure, say N.
+if NET_ETHERNET
+
config MII
tristate "Generic Media Independent Interface device support"
- depends on NET_ETHERNET
help
Most ethernet controllers have MII transceiver either as an external
or internal device. It is safe to say Y or M here even if your
@@ -190,7 +186,7 @@ config MII
config MACB
tristate "Atmel MACB support"
- depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263)
+ depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
select MII
help
The Atmel MACB ethernet interface is found on many AT32 and AT91
@@ -203,7 +199,7 @@ source "drivers/net/arm/Kconfig"
config MACE
tristate "MACE (Power Mac ethernet) support"
- depends on NET_ETHERNET && PPC_PMAC && PPC32
+ depends on PPC_PMAC && PPC32
select CRC32
help
Power Macintoshes and clones with Ethernet built-in on the
@@ -226,7 +222,7 @@ config MACE_AAUI_PORT
config BMAC
tristate "BMAC (G3 ethernet) support"
- depends on NET_ETHERNET && PPC_PMAC && PPC32
+ depends on PPC_PMAC && PPC32
select CRC32
help
Say Y for support of BMAC Ethernet interfaces. These are used on G3
@@ -237,7 +233,7 @@ config BMAC
config ARIADNE
tristate "Ariadne support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
help
If you have a Village Tronic Ariadne Ethernet adapter, say Y.
Otherwise, say N.
@@ -247,7 +243,7 @@ config ARIADNE
config A2065
tristate "A2065 support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
@@ -258,7 +254,7 @@ config A2065
config HYDRA
tristate "Hydra support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
@@ -268,7 +264,7 @@ config HYDRA
config ZORRO8390
tristate "Zorro NS8390-based Ethernet support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
This driver is for Zorro Ethernet cards using an NS8390-compatible
@@ -281,7 +277,7 @@ config ZORRO8390
config APNE
tristate "PCMCIA NE2000 support"
- depends on NET_ETHERNET && AMIGA_PCMCIA
+ depends on AMIGA_PCMCIA
select CRC32
help
If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
@@ -292,7 +288,7 @@ config APNE
config APOLLO_ELPLUS
tristate "Apollo 3c505 support"
- depends on NET_ETHERNET && APOLLO
+ depends on APOLLO
help
Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
If you don't have one made for Apollos, you can use one from a PC,
@@ -301,7 +297,7 @@ config APOLLO_ELPLUS
config MAC8390
bool "Macintosh NS 8390 based ethernet cards"
- depends on NET_ETHERNET && MAC
+ depends on MAC
select CRC32
help
If you want to include a driver to support Nubus or LC-PDS
@@ -311,7 +307,7 @@ config MAC8390
config MAC89x0
tristate "Macintosh CS89x0 based ethernet cards"
- depends on NET_ETHERNET && MAC
+ depends on MAC
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
Nubus or LC-PDS network (Ethernet) card of this type, say Y and
@@ -324,7 +320,7 @@ config MAC89x0
config MACSONIC
tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
- depends on NET_ETHERNET && MAC
+ depends on MAC
---help---
Support for NatSemi SONIC based Ethernet devices. This includes
the onboard Ethernet in many Quadras as well as some LC-PDS,
@@ -338,7 +334,7 @@ config MACSONIC
config MACMACE
bool "Macintosh (AV) onboard MACE ethernet"
- depends on NET_ETHERNET && MAC
+ depends on MAC
select CRC32
help
Support for the onboard AMD 79C940 MACE Ethernet controller used in
@@ -348,7 +344,7 @@ config MACMACE
config MVME147_NET
tristate "MVME147 (Lance) Ethernet support"
- depends on NET_ETHERNET && MVME147
+ depends on MVME147
select CRC32
help
Support for the on-board Ethernet interface on the Motorola MVME147
@@ -358,7 +354,7 @@ config MVME147_NET
config MVME16x_NET
tristate "MVME16x Ethernet support"
- depends on NET_ETHERNET && MVME16x
+ depends on MVME16x
help
This is the driver for the Ethernet interface on the Motorola
MVME162, 166, 167, 172 and 177 boards. Say Y here to include the
@@ -367,7 +363,7 @@ config MVME16x_NET
config BVME6000_NET
tristate "BVME6000 Ethernet support"
- depends on NET_ETHERNET && BVME6000
+ depends on BVME6000
help
This is the driver for the Ethernet interface on BVME4000 and
BVME6000 VME boards. Say Y here to include the driver for this chip
@@ -376,7 +372,7 @@ config BVME6000_NET
config ATARILANCE
tristate "Atari Lance support"
- depends on NET_ETHERNET && ATARI
+ depends on ATARI
help
Say Y to include support for several Atari Ethernet adapters based
on the AMD Lance chipset: RieblCard (with or without battery), or
@@ -384,7 +380,7 @@ config ATARILANCE
config ATARI_BIONET
tristate "BioNet-100 support"
- depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
+ depends on ATARI && ATARI_ACSI && BROKEN
help
Say Y to include support for BioData's BioNet-100 Ethernet adapter
for the ACSI port. The driver works (has to work...) with a polled
@@ -392,7 +388,7 @@ config ATARI_BIONET
config ATARI_PAMSNET
tristate "PAMsNet support"
- depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
+ depends on ATARI && ATARI_ACSI && BROKEN
help
Say Y to include support for the PAMsNet Ethernet adapter for the
ACSI port ("ACSI node"). The driver works (has to work...) with a
@@ -400,7 +396,7 @@ config ATARI_PAMSNET
config SUN3LANCE
tristate "Sun3/Sun3x on-board LANCE support"
- depends on NET_ETHERNET && (SUN3 || SUN3X)
+ depends on SUN3 || SUN3X
help
Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
featured an AMD Lance 10Mbit Ethernet controller on board; say Y
@@ -413,7 +409,7 @@ config SUN3LANCE
config SUN3_82586
bool "Sun3 on-board Intel 82586 support"
- depends on NET_ETHERNET && SUN3
+ depends on SUN3
help
This driver enables support for the on-board Intel 82586 based
Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note
@@ -422,7 +418,7 @@ config SUN3_82586
config HPLANCE
bool "HP on-board LANCE support"
- depends on NET_ETHERNET && DIO
+ depends on DIO
select CRC32
help
If you want to use the builtin "LANCE" Ethernet controller on an
@@ -430,21 +426,28 @@ config HPLANCE
config LASI_82596
tristate "Lasi ethernet"
- depends on NET_ETHERNET && GSC
+ depends on GSC
help
Say Y here to support the builtin Intel 82596 ethernet controller
found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
+config SNI_82596
+ tristate "SNI RM ethernet"
+ depends on NET_ETHERNET && SNI_RM
+ help
+ Say Y here to support the on-board Intel 82596 ethernet controller
+ built into SNI RM machines.
+
config MIPS_JAZZ_SONIC
tristate "MIPS JAZZ onboard SONIC Ethernet support"
- depends on NET_ETHERNET && MACH_JAZZ
+ depends on MACH_JAZZ
help
This is the driver for the onboard card of MIPS Magnum 4000,
Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
- depends on NET_ETHERNET && SOC_AU1X00
+ depends on SOC_AU1X00
select PHYLIB
select CRC32
help
@@ -453,11 +456,11 @@ config MIPS_AU1X00_ENET
config NET_SB1250_MAC
tristate "SB1250 Ethernet support"
- depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC
+ depends on SIBYTE_SB1xxx_SOC
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
- depends on NET_ETHERNET && PCI && SGI_IP27
+ depends on PCI && SGI_IP27
select CRC32
select MII
help
@@ -487,7 +490,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM
config MIPS_SIM_NET
tristate "MIPS simulator Network device"
- depends on NET_ETHERNET && MIPS_SIM
+ depends on MIPS_SIM
help
The MIPSNET device is a simple Ethernet network device which is
emulated by the MIPS Simulator.
@@ -495,11 +498,11 @@ config MIPS_SIM_NET
config SGI_O2MACE_ETH
tristate "SGI O2 MACE Fast Ethernet support"
- depends on NET_ETHERNET && SGI_IP32=y
+ depends on SGI_IP32=y
config STNIC
tristate "National DP83902AV support"
- depends on NET_ETHERNET && SUPERH
+ depends on SUPERH
select CRC32
help
Support for cards based on the National Semiconductor DP83902AV
@@ -511,7 +514,7 @@ config STNIC
config SUNLANCE
tristate "Sun LANCE support"
- depends on NET_ETHERNET && SBUS
+ depends on SBUS
select CRC32
help
This driver supports the "le" interface present on all 32-bit Sparc
@@ -524,7 +527,7 @@ config SUNLANCE
config HAPPYMEAL
tristate "Sun Happy Meal 10/100baseT support"
- depends on NET_ETHERNET && (SBUS || PCI)
+ depends on SBUS || PCI
select CRC32
help
This driver supports the "hme" interface present on most Ultra
@@ -537,7 +540,7 @@ config HAPPYMEAL
config SUNBMAC
tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
- depends on NET_ETHERNET && SBUS && EXPERIMENTAL
+ depends on SBUS && EXPERIMENTAL
select CRC32
help
This driver supports the "be" interface available as an Sbus option.
@@ -548,7 +551,7 @@ config SUNBMAC
config SUNQE
tristate "Sun QuadEthernet support"
- depends on NET_ETHERNET && SBUS
+ depends on SBUS
select CRC32
help
This driver supports the "qe" 10baseT Ethernet device, available as
@@ -560,7 +563,7 @@ config SUNQE
config SUNGEM
tristate "Sun GEM support"
- depends on NET_ETHERNET && PCI
+ depends on PCI
select CRC32
help
Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
@@ -568,7 +571,7 @@ config SUNGEM
config CASSINI
tristate "Sun Cassini support"
- depends on NET_ETHERNET && PCI
+ depends on PCI
select CRC32
help
Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
@@ -576,7 +579,7 @@ config CASSINI
config NET_VENDOR_3COM
bool "3COM cards"
- depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
+ depends on ISA || EISA || MCA || PCI
help
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -736,7 +739,7 @@ config TYPHOON
config LANCE
tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
- depends on NET_ETHERNET && ISA && ISA_DMA_API
+ depends on ISA && ISA_DMA_API
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@@ -748,7 +751,7 @@ config LANCE
config NET_VENDOR_SMC
bool "Western Digital/SMC cards"
- depends on NET_ETHERNET && (ISA || MCA || EISA || MAC)
+ depends on ISA || MCA || EISA || MAC
help
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -818,11 +821,27 @@ config ULTRA32
<file:Documentation/networking/net-modules.txt>. The module
will be called smc-ultra32.
+config SMC9194
+ tristate "SMC 9194 support"
+ depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
+ select CRC32
+ ---help---
+ This is support for the SMC9xxx based Ethernet cards. Choose this
+ option if you have a DELL laptop with the docking station, or
+ another SMC9192/9194 based chipset. Say Y if you want it compiled
+ into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module
+ will be called smc9194.
+
config SMC91X
tristate "SMC 91C9x/91C1xxx support"
select CRC32
select MII
- depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN)
+ depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN
help
This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -836,26 +855,10 @@ config SMC91X
module, say M here and read <file:Documentation/kbuild/modules.txt>
as well as <file:Documentation/networking/net-modules.txt>.
-config SMC9194
- tristate "SMC 9194 support"
- depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
- select CRC32
- ---help---
- This is support for the SMC9xxx based Ethernet cards. Choose this
- option if you have a DELL laptop with the docking station, or
- another SMC9192/9194 based chipset. Say Y if you want it compiled
- into the kernel, and read the file
- <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
- will be called smc9194.
-
config NET_NETX
tristate "NetX Ethernet support"
select MII
- depends on NET_ETHERNET && ARCH_NETX
+ depends on ARCH_NETX
help
This is support for the Hilscher netX builtin Ethernet ports
@@ -865,7 +868,7 @@ config NET_NETX
config DM9000
tristate "DM9000 support"
- depends on (ARM || MIPS) && NET_ETHERNET
+ depends on ARM || MIPS
select CRC32
select MII
---help---
@@ -879,7 +882,7 @@ config SMC911X
tristate "SMSC LAN911[5678] support"
select CRC32
select MII
- depends on NET_ETHERNET && ARCH_PXA
+ depends on ARCH_PXA
help
This is a driver for SMSC's LAN911x series of Ethernet chipsets
including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -893,7 +896,7 @@ config SMC911X
config NET_VENDOR_RACAL
bool "Racal-Interlan (Micom) NI cards"
- depends on NET_ETHERNET && ISA
+ depends on ISA
help
If you have a network (Ethernet) card belonging to this class, such
as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
@@ -945,7 +948,7 @@ source "drivers/net/tulip/Kconfig"
config AT1700
tristate "AT1700/1720 support (EXPERIMENTAL)"
- depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL
+ depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@@ -958,7 +961,7 @@ config AT1700
config DEPCA
tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
- depends on NET_ETHERNET && (ISA || EISA || MCA)
+ depends on ISA || EISA || MCA
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@@ -972,7 +975,7 @@ config DEPCA
config HP100
tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
- depends on NET_ETHERNET && (ISA || EISA || PCI)
+ depends on ISA || EISA || PCI
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@@ -984,7 +987,7 @@ config HP100
config NET_ISA
bool "Other ISA cards"
- depends on NET_ETHERNET && ISA
+ depends on ISA
---help---
If your network (Ethernet) card hasn't been mentioned yet and its
bus system (that's the way the cards talks to the other components
@@ -1147,7 +1150,7 @@ config SEEQ8005
config NE2_MCA
tristate "NE/2 (ne2000 MCA version) support"
- depends on NET_ETHERNET && MCA_LEGACY
+ depends on MCA_LEGACY
select CRC32
help
If you have a network (Ethernet) card of this type, say Y and read
@@ -1160,7 +1163,7 @@ config NE2_MCA
config IBMLANA
tristate "IBM LAN Adapter/A support"
- depends on NET_ETHERNET && MCA && MCA_LEGACY
+ depends on MCA && MCA_LEGACY
---help---
This is a Micro Channel Ethernet adapter. You need to set
CONFIG_MCA to use this driver. It is both available as an in-kernel
@@ -1176,7 +1179,7 @@ config IBMLANA
config IBMVETH
tristate "IBM LAN Virtual Ethernet support"
- depends on NET_ETHERNET && PPC_PSERIES
+ depends on PPC_PSERIES
---help---
This driver supports virtual ethernet adapters on newer IBM iSeries
and pSeries systems.
@@ -1257,7 +1260,7 @@ config IBM_EMAC_TAH
config NET_PCI
bool "EISA, VLB, PCI and on board controllers"
- depends on NET_ETHERNET && (ISA || EISA || PCI)
+ depends on ISA || EISA || PCI
help
This is another class of network cards which attach directly to the
bus. If you have one of those, say Y and read the Ethernet-HOWTO,
@@ -1313,6 +1316,7 @@ config AMD8111_ETH
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module
will be called amd8111e.
+
config AMD8111E_NAPI
bool "Enable NAPI support"
depends on AMD8111_ETH
@@ -1778,7 +1782,7 @@ config SC92031
config NET_POCKET
bool "Pocket and portable adapters"
- depends on NET_ETHERNET && PARPORT
+ depends on PARPORT
---help---
Cute little network (Ethernet) devices which attach to the parallel
port ("pocket adapters"), commonly used with laptops. If you have
@@ -1847,14 +1851,14 @@ config DE620
config SGISEEQ
tristate "SGI Seeq ethernet controller support"
- depends on NET_ETHERNET && SGI_IP22
+ depends on SGI_IP22
help
Say Y here if you have an Seeq based Ethernet network card. This is
used in many Silicon Graphics machines.
config DECLANCE
tristate "DEC LANCE ethernet controller support"
- depends on NET_ETHERNET && MACH_DECSTATION
+ depends on MACH_DECSTATION
select CRC32
help
This driver is for the series of Ethernet controllers produced by
@@ -1884,7 +1888,7 @@ config FEC2
config NE_H8300
tristate "NE2000 compatible support for H8/300"
- depends on H8300 && NET_ETHERNET
+ depends on H8300
help
Say Y here if you want to use the NE2000 compatible
controller on the Renesas H8/300 processor.
@@ -1892,7 +1896,7 @@ config NE_H8300
source "drivers/net/fec_8xx/Kconfig"
source "drivers/net/fs_enet/Kconfig"
-endmenu
+endif # NET_ETHERNET
#
# Gigabit Ethernet
@@ -2303,7 +2307,7 @@ config UGETH_TX_ON_DEMAND
config MV643XX_ETH
tristate "MV-643XX Ethernet support"
- depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32)
+ depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32)
select MII
help
This driver supports the gigabit Ethernet on the Marvell MV643XX
@@ -2948,8 +2952,6 @@ config NETCONSOLE
If you want to log kernel messages over the network, enable this.
See <file:Documentation/networking/netconsole.txt> for details.
-endif #NETDEVICES
-
config NETPOLL
def_bool NETCONSOLE
@@ -2961,4 +2963,4 @@ config NETPOLL_TRAP
config NET_POLL_CONTROLLER
def_bool NETPOLL
-endmenu
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a77affa4f6e6..eb62fb48e4b7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -157,6 +157,7 @@ obj-$(CONFIG_ELPLUS) += 3c505.o
obj-$(CONFIG_AC3200) += ac3200.o 8390.o
obj-$(CONFIG_APRICOT) += 82596.o
obj-$(CONFIG_LASI_82596) += lasi_82596.o
+obj-$(CONFIG_SNI_82596) += sni_82596.o
obj-$(CONFIG_MVME16x_NET) += 82596.o
obj-$(CONFIG_BVME6000_NET) += 82596.o
obj-$(CONFIG_SC92031) += sc92031.o
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 04382f979c99..b78a4e5ceeb2 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -159,10 +159,6 @@ static struct pci_device_id acenic_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
-#ifndef SET_NETDEV_DEV
-#define SET_NETDEV_DEV(net, pdev) do{} while(0)
-#endif
-
#define ace_sync_irq(irq) synchronize_irq(irq)
#ifndef offset_in_page
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 678e4f48d36b..5bf2d33887ac 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -4,7 +4,7 @@
#
config ARM_AM79C961A
bool "ARM EBSA110 AM79C961A support"
- depends on NET_ETHERNET && ARM && ARCH_EBSA110
+ depends on ARM && ARCH_EBSA110
select CRC32
help
If you wish to compile a kernel for the EBSA-110, then you should
@@ -12,21 +12,21 @@ config ARM_AM79C961A
config ARM_ETHER1
tristate "Acorn Ether1 support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
help
If you have an Acorn system with one of these (AKA25) network cards,
you should say Y to this option if you wish to use it with Linux.
config ARM_ETHER3
tristate "Acorn/ANT Ether3 support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
help
If you have an Acorn system with one of these network cards, you
should say Y to this option if you wish to use it with Linux.
config ARM_ETHERH
tristate "I-cubed EtherH/ANT EtherM support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
select CRC32
help
If you have an Acorn system with one of these network cards, you
@@ -34,7 +34,7 @@ config ARM_ETHERH
config ARM_AT91_ETHER
tristate "AT91RM9200 Ethernet support"
- depends on NET_ETHERNET && ARM && ARCH_AT91RM9200
+ depends on ARM && ARCH_AT91RM9200
select MII
help
If you wish to compile a kernel for the AT91RM9200 and enable
@@ -42,7 +42,7 @@ config ARM_AT91_ETHER
config EP93XX_ETH
tristate "EP93xx Ethernet support"
- depends on NET_ETHERNET && ARM && ARCH_EP93XX
+ depends on ARM && ARCH_EP93XX
help
This is a driver for the ethernet hardware included in EP93xx CPUs.
Say Y if you are building a kernel for EP93xx based devices.
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 879a2fff474e..96fb0ec905a7 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -15,6 +15,7 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/delay.h>
@@ -68,8 +69,8 @@
(BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
-#define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64)
-#define TX_PKT_BUF_SZ (B44_MAX_MTU + ETH_HLEN + 8)
+#define RX_PKT_OFFSET 30
+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
@@ -599,8 +600,7 @@ static void b44_timer(unsigned long __opaque)
spin_unlock_irq(&bp->lock);
- bp->timer.expires = jiffies + HZ;
- add_timer(&bp->timer);
+ mod_timer(&bp->timer, round_jiffies(jiffies + HZ));
}
static void b44_tx(struct b44 *bp)
@@ -653,7 +653,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
src_map = &bp->rx_buffers[src_idx];
dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
map = &bp->rx_buffers[dest_idx];
- skb = dev_alloc_skb(RX_PKT_BUF_SZ);
+ skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ);
if (skb == NULL)
return -ENOMEM;
@@ -669,7 +669,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
- skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+ skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
if (skb == NULL)
return -ENOMEM;
mapping = pci_map_single(bp->pdev, skb->data,
@@ -684,11 +684,9 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
}
}
- skb->dev = bp->dev;
- skb_reserve(skb, bp->rx_offset);
+ rh = (struct rx_header *) skb->data;
+ skb_reserve(skb, RX_PKT_OFFSET);
- rh = (struct rx_header *)
- (skb->data - bp->rx_offset);
rh->len = 0;
rh->flags = 0;
@@ -698,13 +696,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (src_map != NULL)
src_map->skb = NULL;
- ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset));
+ ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= DESC_CTRL_EOT;
dp = &bp->rx_ring[dest_idx];
dp->ctrl = cpu_to_le32(ctrl);
- dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
+ dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
if (bp->flags & B44_FLAG_RX_RING_HACK)
b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
@@ -783,7 +781,7 @@ static int b44_rx(struct b44 *bp, int budget)
PCI_DMA_FROMDEVICE);
rh = (struct rx_header *) skb->data;
len = le16_to_cpu(rh->len);
- if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
+ if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
(rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
drop_it:
b44_recycle_rx(bp, cons, bp->rx_prod);
@@ -815,8 +813,8 @@ static int b44_rx(struct b44 *bp, int budget)
pci_unmap_single(bp->pdev, map,
skb_size, PCI_DMA_FROMDEVICE);
/* Leave out rx_header */
- skb_put(skb, len+bp->rx_offset);
- skb_pull(skb,bp->rx_offset);
+ skb_put(skb, len + RX_PKT_OFFSET);
+ skb_pull(skb, RX_PKT_OFFSET);
} else {
struct sk_buff *copy_skb;
@@ -828,7 +826,7 @@ static int b44_rx(struct b44 *bp, int budget)
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
/* DMA sync done above, copy just the actual packet */
- skb_copy_from_linear_data_offset(skb, bp->rx_offset,
+ skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET,
copy_skb->data, len);
skb = copy_skb;
}
@@ -969,7 +967,6 @@ static void b44_tx_timeout(struct net_device *dev)
static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct b44 *bp = netdev_priv(dev);
- struct sk_buff *bounce_skb;
int rc = NETDEV_TX_OK;
dma_addr_t mapping;
u32 len, entry, ctrl;
@@ -987,12 +984,13 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
+ struct sk_buff *bounce_skb;
+
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
- bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
- GFP_ATOMIC|GFP_DMA);
+ bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb)
goto err_out;
@@ -1001,13 +999,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping,
- len, PCI_DMA_TODEVICE);
+ len, PCI_DMA_TODEVICE);
dev_kfree_skb_any(bounce_skb);
goto err_out;
}
- skb_copy_from_linear_data(skb, skb_put(bounce_skb, len),
- skb->len);
+ skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
dev_kfree_skb_any(skb);
skb = bounce_skb;
}
@@ -1396,12 +1393,12 @@ static void b44_init_hw(struct b44 *bp, int reset_kind)
bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
if (reset_kind == B44_PARTIAL_RESET) {
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
- (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
} else {
bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
- (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
@@ -2093,11 +2090,6 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->phy_addr = eeprom[90] & 0x1f;
- /* With this, plus the rx_header prepended to the data by the
- * hardware, we'll land the ethernet header on a 2-byte boundary.
- */
- bp->rx_offset = 30;
-
bp->imask = IMASK_DEF;
bp->core_unit = ssb_core_unit(bp);
@@ -2348,11 +2340,11 @@ static int b44_resume(struct pci_dev *pdev)
netif_device_attach(bp->dev);
spin_unlock_irq(&bp->lock);
- bp->timer.expires = jiffies + HZ;
- add_timer(&bp->timer);
-
b44_enable_ints(bp);
netif_wake_queue(dev);
+
+ mod_timer(&bp->timer, jiffies + 1);
+
return 0;
}
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 18fc13336628..e537e63f292e 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -443,8 +443,6 @@ struct b44 {
#define B44_FLAG_TX_RING_HACK 0x40000000
#define B44_FLAG_WOL_ENABLE 0x80000000
- u32 rx_offset;
-
u32 msg_enable;
struct timer_list timer;
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 80c3d8f268a7..ab72563b81ee 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -71,27 +71,29 @@ enum { /* adapter flags */
QUEUES_BOUND = (1 << 3),
};
+struct fl_pg_chunk {
+ struct page *page;
+ void *va;
+ unsigned int offset;
+};
+
struct rx_desc;
struct rx_sw_desc;
-struct sge_fl_page {
- struct skb_frag_struct frag;
- unsigned char *va;
-};
-
-struct sge_fl { /* SGE per free-buffer list state */
- unsigned int buf_size; /* size of each Rx buffer */
- unsigned int credits; /* # of available Rx buffers */
- unsigned int size; /* capacity of free list */
- unsigned int cidx; /* consumer index */
- unsigned int pidx; /* producer index */
- unsigned int gen; /* free list generation */
- unsigned int cntxt_id; /* SGE context id for the free list */
- struct sge_fl_page page;
- struct rx_desc *desc; /* address of HW Rx descriptor ring */
- struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
- dma_addr_t phys_addr; /* physical address of HW ring start */
- unsigned long empty; /* # of times queue ran out of buffers */
+struct sge_fl { /* SGE per free-buffer list state */
+ unsigned int buf_size; /* size of each Rx buffer */
+ unsigned int credits; /* # of available Rx buffers */
+ unsigned int size; /* capacity of free list */
+ unsigned int cidx; /* consumer index */
+ unsigned int pidx; /* producer index */
+ unsigned int gen; /* free list generation */
+ struct fl_pg_chunk pg_chunk;/* page chunk cache */
+ unsigned int use_pages; /* whether FL uses pages or sk_buffs */
+ struct rx_desc *desc; /* address of HW Rx descriptor ring */
+ struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
+ dma_addr_t phys_addr; /* physical address of HW ring start */
+ unsigned int cntxt_id; /* SGE context id for the free list */
+ unsigned long empty; /* # of times queue ran out of buffers */
unsigned long alloc_failed; /* # of times buffer allocation failed */
};
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 8d1379633698..16378004507a 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -101,6 +101,7 @@ enum {
TCB_SIZE = 128, /* TCB size */
NMTUS = 16, /* size of MTU table */
NCCTRL_WIN = 32, /* # of congestion control windows */
+ PROTO_SRAM_LINES = 128, /* size of TP sram */
};
#define MAX_RX_COALESCING_LEN 16224U
@@ -124,6 +125,30 @@ enum { /* adapter interrupt-maintained statistics */
};
enum {
+ TP_VERSION_MAJOR = 1,
+ TP_VERSION_MINOR = 0,
+ TP_VERSION_MICRO = 44
+};
+
+#define S_TP_VERSION_MAJOR 16
+#define M_TP_VERSION_MAJOR 0xFF
+#define V_TP_VERSION_MAJOR(x) ((x) << S_TP_VERSION_MAJOR)
+#define G_TP_VERSION_MAJOR(x) \
+ (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR)
+
+#define S_TP_VERSION_MINOR 8
+#define M_TP_VERSION_MINOR 0xFF
+#define V_TP_VERSION_MINOR(x) ((x) << S_TP_VERSION_MINOR)
+#define G_TP_VERSION_MINOR(x) \
+ (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR)
+
+#define S_TP_VERSION_MICRO 0
+#define M_TP_VERSION_MICRO 0xFF
+#define V_TP_VERSION_MICRO(x) ((x) << S_TP_VERSION_MICRO)
+#define G_TP_VERSION_MICRO(x) \
+ (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO)
+
+enum {
SGE_QSETS = 8, /* # of SGE Tx/Rx/RspQ sets */
SGE_RXQ_PER_SET = 2, /* # of Rx queues per set */
SGE_TXQ_PER_SET = 3 /* # of Tx queues per set */
@@ -654,6 +679,9 @@ const struct adapter_info *t3_get_adapter_info(unsigned int board_id);
int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);
int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data);
int t3_seeprom_wp(struct adapter *adapter, int enable);
+int t3_check_tpsram_version(struct adapter *adapter);
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size);
+int t3_set_proto_sram(struct adapter *adap, u8 *data);
int t3_read_flash(struct adapter *adapter, unsigned int addr,
unsigned int nwords, u32 *data, int byte_oriented);
int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index d8a1f5452c51..15defe4c4f05 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -2088,6 +2088,42 @@ static void cxgb_netpoll(struct net_device *dev)
}
#endif
+#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin"
+int update_tpsram(struct adapter *adap)
+{
+ const struct firmware *tpsram;
+ char buf[64];
+ struct device *dev = &adap->pdev->dev;
+ int ret;
+ char rev;
+
+ rev = adap->params.rev == T3_REV_B2 ? 'b' : 'a';
+
+ snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
+ TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+
+ ret = request_firmware(&tpsram, buf, dev);
+ if (ret < 0) {
+ dev_err(dev, "could not load TP SRAM: unable to load %s\n",
+ buf);
+ return ret;
+ }
+
+ ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
+ if (ret)
+ goto release_tpsram;
+
+ ret = t3_set_proto_sram(adap, tpsram->data);
+ if (ret)
+ dev_err(dev, "loading protocol SRAM failed\n");
+
+release_tpsram:
+ release_firmware(tpsram);
+
+ return ret;
+}
+
+
/*
* Periodic accumulation of MAC statistics.
*/
@@ -2437,6 +2473,13 @@ static int __devinit init_one(struct pci_dev *pdev,
goto out_free_dev;
}
+ err = t3_check_tpsram_version(adapter);
+ if (err == -EINVAL)
+ err = update_tpsram(adapter);
+
+ if (err)
+ goto out_free_dev;
+
/*
* The card is now ready to go. If any errors occur during device
* registration we do not fail the whole card but rather proceed only
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index 020859c855d7..aa80313c922e 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -1160,6 +1160,8 @@
#define A_TP_MOD_CHANNEL_WEIGHT 0x434
+#define A_TP_MOD_RATE_LIMIT 0x438
+
#define A_TP_PIO_ADDR 0x440
#define A_TP_PIO_DATA 0x444
@@ -1214,6 +1216,15 @@
#define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \
M_TXDROPCNTCH0RCVD)
+#define A_TP_PROXY_FLOW_CNTL 0x4b0
+
+#define A_TP_EMBED_OP_FIELD0 0x4e8
+#define A_TP_EMBED_OP_FIELD1 0x4ec
+#define A_TP_EMBED_OP_FIELD2 0x4f0
+#define A_TP_EMBED_OP_FIELD3 0x4f4
+#define A_TP_EMBED_OP_FIELD4 0x4f8
+#define A_TP_EMBED_OP_FIELD5 0x4fc
+
#define A_ULPRX_CTL 0x500
#define S_ROUND_ROBIN 4
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index a60ec4d4707c..a2cfd68ac757 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -46,23 +46,16 @@
#define SGE_RX_SM_BUF_SIZE 1536
-/*
- * If USE_RX_PAGE is defined, the small freelist populated with (partial)
- * pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must
- * be a multiple of the host page size).
- */
-#define USE_RX_PAGE
-#define RX_PAGE_SIZE 2048
-
-/*
- * skb freelist packets are copied into a new skb (and the freelist one is
- * reused) if their len is <=
- */
#define SGE_RX_COPY_THRES 256
+#define SGE_RX_PULL_LEN 128
/*
- * Minimum number of freelist entries before we start dropping TUNNEL frames.
+ * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
+ * It must be a divisor of PAGE_SIZE. If set to 0 FL0 will use sk_buffs
+ * directly.
*/
+#define FL0_PG_CHUNK_SIZE 2048
+
#define SGE_RX_DROP_THRES 16
/*
@@ -100,12 +93,12 @@ struct tx_sw_desc { /* SW state per Tx descriptor */
struct sk_buff *skb;
};
-struct rx_sw_desc { /* SW state per Rx descriptor */
+struct rx_sw_desc { /* SW state per Rx descriptor */
union {
struct sk_buff *skb;
- struct sge_fl_page page;
- } t;
- DECLARE_PCI_UNMAP_ADDR(dma_addr);
+ struct fl_pg_chunk pg_chunk;
+ };
+ DECLARE_PCI_UNMAP_ADDR(dma_addr);
};
struct rsp_desc { /* response queue descriptor */
@@ -351,27 +344,26 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr),
q->buf_size, PCI_DMA_FROMDEVICE);
-
- if (q->buf_size != RX_PAGE_SIZE) {
- kfree_skb(d->t.skb);
- d->t.skb = NULL;
+ if (q->use_pages) {
+ put_page(d->pg_chunk.page);
+ d->pg_chunk.page = NULL;
} else {
- if (d->t.page.frag.page)
- put_page(d->t.page.frag.page);
- d->t.page.frag.page = NULL;
+ kfree_skb(d->skb);
+ d->skb = NULL;
}
if (++cidx == q->size)
cidx = 0;
}
- if (q->page.frag.page)
- put_page(q->page.frag.page);
- q->page.frag.page = NULL;
+ if (q->pg_chunk.page) {
+ __free_page(q->pg_chunk.page);
+ q->pg_chunk.page = NULL;
+ }
}
/**
* add_one_rx_buf - add a packet buffer to a free-buffer list
- * @va: va of the buffer to add
+ * @va: buffer start VA
* @len: the buffer length
* @d: the HW Rx descriptor to write
* @sd: the SW Rx descriptor to write
@@ -381,7 +373,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
* Add a buffer of the given length to the supplied HW and SW Rx
* descriptors.
*/
-static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
+static inline void add_one_rx_buf(void *va, unsigned int len,
struct rx_desc *d, struct rx_sw_desc *sd,
unsigned int gen, struct pci_dev *pdev)
{
@@ -397,6 +389,27 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
}
+static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
+{
+ if (!q->pg_chunk.page) {
+ q->pg_chunk.page = alloc_page(gfp);
+ if (unlikely(!q->pg_chunk.page))
+ return -ENOMEM;
+ q->pg_chunk.va = page_address(q->pg_chunk.page);
+ q->pg_chunk.offset = 0;
+ }
+ sd->pg_chunk = q->pg_chunk;
+
+ q->pg_chunk.offset += q->buf_size;
+ if (q->pg_chunk.offset == PAGE_SIZE)
+ q->pg_chunk.page = NULL;
+ else {
+ q->pg_chunk.va += q->buf_size;
+ get_page(q->pg_chunk.page);
+ }
+ return 0;
+}
+
/**
* refill_fl - refill an SGE free-buffer list
* @adapter: the adapter
@@ -410,49 +423,29 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
*/
static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
{
+ void *buf_start;
struct rx_sw_desc *sd = &q->sdesc[q->pidx];
struct rx_desc *d = &q->desc[q->pidx];
- struct sge_fl_page *p = &q->page;
while (n--) {
- unsigned char *va;
-
- if (unlikely(q->buf_size != RX_PAGE_SIZE)) {
- struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
-
- if (!skb) {
- q->alloc_failed++;
+ if (q->use_pages) {
+ if (unlikely(alloc_pg_chunk(q, sd, gfp))) {
+nomem: q->alloc_failed++;
break;
}
- va = skb->data;
- sd->t.skb = skb;
+ buf_start = sd->pg_chunk.va;
} else {
- if (!p->frag.page) {
- p->frag.page = alloc_pages(gfp, 0);
- if (unlikely(!p->frag.page)) {
- q->alloc_failed++;
- break;
- } else {
- p->frag.size = RX_PAGE_SIZE;
- p->frag.page_offset = 0;
- p->va = page_address(p->frag.page);
- }
- }
+ struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
- memcpy(&sd->t, p, sizeof(*p));
- va = p->va;
+ if (!skb)
+ goto nomem;
- p->frag.page_offset += RX_PAGE_SIZE;
- BUG_ON(p->frag.page_offset > PAGE_SIZE);
- p->va += RX_PAGE_SIZE;
- if (p->frag.page_offset == PAGE_SIZE)
- p->frag.page = NULL;
- else
- get_page(p->frag.page);
+ sd->skb = skb;
+ buf_start = skb->data;
}
- add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev);
-
+ add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen,
+ adap->pdev);
d++;
sd++;
if (++q->pidx == q->size) {
@@ -487,7 +480,7 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
struct rx_desc *from = &q->desc[idx];
struct rx_desc *to = &q->desc[q->pidx];
- memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc));
+ q->sdesc[q->pidx] = q->sdesc[idx];
to->addr_lo = from->addr_lo; /* already big endian */
to->addr_hi = from->addr_hi; /* likewise */
wmb();
@@ -650,6 +643,132 @@ static inline unsigned int flits_to_desc(unsigned int n)
}
/**
+ * get_packet - return the next ingress packet buffer from a free list
+ * @adap: the adapter that received the packet
+ * @fl: the SGE free list holding the packet
+ * @len: the packet length including any SGE padding
+ * @drop_thres: # of remaining buffers before we start dropping packets
+ *
+ * Get the next packet from a free list and complete setup of the
+ * sk_buff. If the packet is small we make a copy and recycle the
+ * original buffer, otherwise we use the original buffer itself. If a
+ * positive drop threshold is supplied packets are dropped and their
+ * buffers recycled if (a) the number of remaining buffers is under the
+ * threshold and the packet is too big to copy, or (b) the packet should
+ * be copied but there is no memory for the copy.
+ */
+static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
+ unsigned int len, unsigned int drop_thres)
+{
+ struct sk_buff *skb = NULL;
+ struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+ prefetch(sd->skb->data);
+ fl->credits--;
+
+ if (len <= SGE_RX_COPY_THRES) {
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (likely(skb != NULL)) {
+ __skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, sd->skb->data, len);
+ pci_dma_sync_single_for_device(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ } else if (!drop_thres)
+ goto use_orig_buf;
+recycle:
+ recycle_rx_buf(adap, fl, fl->cidx);
+ return skb;
+ }
+
+ if (unlikely(fl->credits < drop_thres))
+ goto recycle;
+
+use_orig_buf:
+ pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+ fl->buf_size, PCI_DMA_FROMDEVICE);
+ skb = sd->skb;
+ skb_put(skb, len);
+ __refill_fl(adap, fl);
+ return skb;
+}
+
+/**
+ * get_packet_pg - return the next ingress packet buffer from a free list
+ * @adap: the adapter that received the packet
+ * @fl: the SGE free list holding the packet
+ * @len: the packet length including any SGE padding
+ * @drop_thres: # of remaining buffers before we start dropping packets
+ *
+ * Get the next packet from a free list populated with page chunks.
+ * If the packet is small we make a copy and recycle the original buffer,
+ * otherwise we attach the original buffer as a page fragment to a fresh
+ * sk_buff. If a positive drop threshold is supplied packets are dropped
+ * and their buffers recycled if (a) the number of remaining buffers is
+ * under the threshold and the packet is too big to copy, or (b) there's
+ * no system memory.
+ *
+ * Note: this function is similar to @get_packet but deals with Rx buffers
+ * that are page chunks rather than sk_buffs.
+ */
+static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
+ unsigned int len, unsigned int drop_thres)
+{
+ struct sk_buff *skb = NULL;
+ struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+ if (len <= SGE_RX_COPY_THRES) {
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (likely(skb != NULL)) {
+ __skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, sd->pg_chunk.va, len);
+ pci_dma_sync_single_for_device(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ } else if (!drop_thres)
+ return NULL;
+recycle:
+ fl->credits--;
+ recycle_rx_buf(adap, fl, fl->cidx);
+ return skb;
+ }
+
+ if (unlikely(fl->credits <= drop_thres))
+ goto recycle;
+
+ skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
+ if (unlikely(!skb)) {
+ if (!drop_thres)
+ return NULL;
+ goto recycle;
+ }
+
+ pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+ fl->buf_size, PCI_DMA_FROMDEVICE);
+ __skb_put(skb, SGE_RX_PULL_LEN);
+ memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
+ skb_fill_page_desc(skb, 0, sd->pg_chunk.page,
+ sd->pg_chunk.offset + SGE_RX_PULL_LEN,
+ len - SGE_RX_PULL_LEN);
+ skb->len = len;
+ skb->data_len = len - SGE_RX_PULL_LEN;
+ skb->truesize += skb->data_len;
+
+ fl->credits--;
+ /*
+ * We do not refill FLs here, we let the caller do it to overlap a
+ * prefetch.
+ */
+ return skb;
+}
+
+/**
* get_imm_packet - return the next ingress packet buffer from a response
* @resp: the response descriptor containing the packet data
*
@@ -1715,85 +1834,6 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
netif_rx(skb);
}
-#define SKB_DATA_SIZE 128
-
-static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p,
- unsigned int len)
-{
- skb->len = len;
- if (len <= SKB_DATA_SIZE) {
- skb_copy_to_linear_data(skb, p->va, len);
- skb->tail += len;
- put_page(p->frag.page);
- } else {
- skb_copy_to_linear_data(skb, p->va, SKB_DATA_SIZE);
- skb_shinfo(skb)->frags[0].page = p->frag.page;
- skb_shinfo(skb)->frags[0].page_offset =
- p->frag.page_offset + SKB_DATA_SIZE;
- skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE;
- skb_shinfo(skb)->nr_frags = 1;
- skb->data_len = len - SKB_DATA_SIZE;
- skb->tail += SKB_DATA_SIZE;
- skb->truesize += skb->data_len;
- }
-}
-
-/**
-* get_packet - return the next ingress packet buffer from a free list
-* @adap: the adapter that received the packet
-* @fl: the SGE free list holding the packet
-* @len: the packet length including any SGE padding
-* @drop_thres: # of remaining buffers before we start dropping packets
-*
-* Get the next packet from a free list and complete setup of the
-* sk_buff. If the packet is small we make a copy and recycle the
-* original buffer, otherwise we use the original buffer itself. If a
-* positive drop threshold is supplied packets are dropped and their
-* buffers recycled if (a) the number of remaining buffers is under the
-* threshold and the packet is too big to copy, or (b) the packet should
-* be copied but there is no memory for the copy.
-*/
-static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
- unsigned int len, unsigned int drop_thres)
-{
- struct sk_buff *skb = NULL;
- struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-
- prefetch(sd->t.skb->data);
-
- if (len <= SGE_RX_COPY_THRES) {
- skb = alloc_skb(len, GFP_ATOMIC);
- if (likely(skb != NULL)) {
- struct rx_desc *d = &fl->desc[fl->cidx];
- dma_addr_t mapping =
- (dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 |
- be32_to_cpu(d->addr_lo));
-
- __skb_put(skb, len);
- pci_dma_sync_single_for_cpu(adap->pdev, mapping, len,
- PCI_DMA_FROMDEVICE);
- skb_copy_from_linear_data(sd->t.skb, skb->data, len);
- pci_dma_sync_single_for_device(adap->pdev, mapping, len,
- PCI_DMA_FROMDEVICE);
- } else if (!drop_thres)
- goto use_orig_buf;
-recycle:
- recycle_rx_buf(adap, fl, fl->cidx);
- return skb;
- }
-
- if (unlikely(fl->credits < drop_thres))
- goto recycle;
-
-use_orig_buf:
- pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
- fl->buf_size, PCI_DMA_FROMDEVICE);
- skb = sd->t.skb;
- skb_put(skb, len);
- __refill_fl(adap, fl);
- return skb;
-}
-
/**
* handle_rsp_cntrl_info - handles control information in a response
* @qs: the queue set corresponding to the response
@@ -1935,7 +1975,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
} else if (flags & F_RSPD_IMM_DATA_VALID) {
skb = get_imm_packet(r);
if (unlikely(!skb)) {
- no_mem:
+no_mem:
q->next_holdoff = NOMEM_INTR_DELAY;
q->nomem++;
/* consume one credit since we tried */
@@ -1945,53 +1985,29 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
q->imm_data++;
ethpad = 0;
} else if ((len = ntohl(r->len_cq)) != 0) {
- struct sge_fl *fl =
- (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+ struct sge_fl *fl;
- if (fl->buf_size == RX_PAGE_SIZE) {
- struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
- struct sge_fl_page *p = &sd->t.page;
-
- prefetch(p->va);
- prefetch(p->va + L1_CACHE_BYTES);
+ fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+ if (fl->use_pages) {
+ void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
+ prefetch(addr);
+#if L1_CACHE_BYTES < 128
+ prefetch(addr + L1_CACHE_BYTES);
+#endif
__refill_fl(adap, fl);
- pci_unmap_single(adap->pdev,
- pci_unmap_addr(sd, dma_addr),
- fl->buf_size,
- PCI_DMA_FROMDEVICE);
-
- if (eth) {
- if (unlikely(fl->credits <
- SGE_RX_DROP_THRES))
- goto eth_recycle;
-
- skb = alloc_skb(SKB_DATA_SIZE,
- GFP_ATOMIC);
- if (unlikely(!skb)) {
-eth_recycle:
- q->rx_drops++;
- recycle_rx_buf(adap, fl,
- fl->cidx);
- goto eth_done;
- }
- } else {
- skb = alloc_skb(SKB_DATA_SIZE,
- GFP_ATOMIC);
- if (unlikely(!skb))
- goto no_mem;
- }
-
- skb_data_init(skb, p, G_RSPD_LEN(len));
-eth_done:
- fl->credits--;
- q->eth_pkts++;
- } else {
- fl->credits--;
+ skb = get_packet_pg(adap, fl, G_RSPD_LEN(len),
+ eth ? SGE_RX_DROP_THRES : 0);
+ } else
skb = get_packet(adap, fl, G_RSPD_LEN(len),
eth ? SGE_RX_DROP_THRES : 0);
- }
+ if (unlikely(!skb)) {
+ if (!eth)
+ goto no_mem;
+ q->rx_drops++;
+ } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
+ __skb_pull(skb, 2);
if (++fl->cidx == fl->size)
fl->cidx = 0;
@@ -2016,20 +2032,15 @@ eth_done:
q->credits = 0;
}
- if (skb) {
- /* Preserve the RSS info in csum & priority */
- skb->csum = rss_hi;
- skb->priority = rss_lo;
-
+ if (likely(skb != NULL)) {
if (eth)
rx_eth(adap, q, skb, ethpad);
else {
- if (unlikely(r->rss_hdr.opcode ==
- CPL_TRACE_PKT))
- __skb_pull(skb, ethpad);
-
- ngathered = rx_offload(&adap->tdev, q,
- skb, offload_skbs,
+ /* Preserve the RSS info in csum & priority */
+ skb->csum = rss_hi;
+ skb->priority = rss_lo;
+ ngathered = rx_offload(&adap->tdev, q, skb,
+ offload_skbs,
ngathered);
}
}
@@ -2635,25 +2646,15 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
q->txq[TXQ_ETH].stop_thres = nports *
flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
- if (!is_offload(adapter)) {
-#ifdef USE_RX_PAGE
- q->fl[0].buf_size = RX_PAGE_SIZE;
+#if FL0_PG_CHUNK_SIZE > 0
+ q->fl[0].buf_size = FL0_PG_CHUNK_SIZE;
#else
- q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 +
- sizeof(struct cpl_rx_pkt);
+ q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data);
#endif
- q->fl[1].buf_size = MAX_FRAME_SIZE + 2 +
- sizeof(struct cpl_rx_pkt);
- } else {
-#ifdef USE_RX_PAGE
- q->fl[0].buf_size = RX_PAGE_SIZE;
-#else
- q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE +
- sizeof(struct cpl_rx_data);
-#endif
- q->fl[1].buf_size = (16 * 1024) -
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- }
+ q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0;
+ q->fl[1].buf_size = is_offload(adapter) ?
+ (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
+ MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
spin_lock(&adapter->sge.reg_lock);
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index fb485d0a43d8..dd3149d94ba8 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -847,6 +847,64 @@ static int t3_write_flash(struct adapter *adapter, unsigned int addr,
return 0;
}
+/**
+ * t3_check_tpsram_version - read the tp sram version
+ * @adapter: the adapter
+ *
+ * Reads the protocol sram version from serial eeprom.
+ */
+int t3_check_tpsram_version(struct adapter *adapter)
+{
+ int ret;
+ u32 vers;
+ unsigned int major, minor;
+
+ /* Get version loaded in SRAM */
+ t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
+ ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
+ 1, 1, 5, 1);
+ if (ret)
+ return ret;
+
+ vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
+
+ major = G_TP_VERSION_MAJOR(vers);
+ minor = G_TP_VERSION_MINOR(vers);
+
+ if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * t3_check_tpsram - check if provided protocol SRAM
+ * is compatible with this driver
+ * @adapter: the adapter
+ * @tp_sram: the firmware image to write
+ * @size: image size
+ *
+ * Checks if an adapter's tp sram is compatible with the driver.
+ * Returns 0 if the versions are compatible, a negative error otherwise.
+ */
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size)
+{
+ u32 csum;
+ unsigned int i;
+ const u32 *p = (const u32 *)tp_sram;
+
+ /* Verify checksum */
+ for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+ csum += ntohl(p[i]);
+ if (csum != 0xffffffff) {
+ CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
+ csum);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
enum fw_version_type {
FW_VERSION_N3,
FW_VERSION_T3
@@ -921,7 +979,7 @@ static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end)
/*
* t3_load_fw - download firmware
* @adapter: the adapter
- * @fw_data: the firrware image to write
+ * @fw_data: the firmware image to write
* @size: image size
*
* Write the supplied firmware image to the card's serial flash.
@@ -2362,7 +2420,7 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
F_MTUENABLE | V_WINDOWSCALEMODE(1) |
- V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
+ V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1));
t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
@@ -2371,16 +2429,18 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
F_IPV6ENABLE | F_NICMODE);
t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
- t3_set_reg_field(adap, A_TP_PARA_REG6,
- adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
- 0);
+ t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
+ adap->params.rev > 0 ? F_ENABLEESND :
+ F_T3A_ENABLEESND);
t3_set_reg_field(adap, A_TP_PC_CONFIG,
- F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
- F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
- F_RXCONGESTIONMODE);
+ F_ENABLEEPCMDAFULL,
+ F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
+ F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
-
+ t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
+ t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
+
if (adap->params.rev > 0) {
tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
@@ -2390,9 +2450,10 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
} else
t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
- t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212);
- t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212);
- t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212);
+ t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
+ t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
+ t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
+ t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
}
/* Desired TP timer resolution in usec */
@@ -2468,6 +2529,7 @@ int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh)
val |= F_RXCOALESCEENABLE;
if (psh)
val |= F_RXCOALESCEPSHEN;
+ size = min(MAX_RX_COALESCING_LEN, size);
t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
V_MAXRXDATA(MAX_RX_COALESCING_LEN));
}
@@ -2496,11 +2558,11 @@ static void __devinit init_mtus(unsigned short mtus[])
* it can accomodate max size TCP/IP headers when SACK and timestamps
* are enabled and still have at least 8 bytes of payload.
*/
- mtus[0] = 88;
- mtus[1] = 256;
- mtus[2] = 512;
- mtus[3] = 576;
- mtus[4] = 808;
+ mtus[1] = 88;
+ mtus[1] = 88;
+ mtus[2] = 256;
+ mtus[3] = 512;
+ mtus[4] = 576;
mtus[5] = 1024;
mtus[6] = 1280;
mtus[7] = 1492;
@@ -2682,6 +2744,34 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p)
t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
}
+/**
+ * t3_set_proto_sram - set the contents of the protocol sram
+ * @adapter: the adapter
+ * @data: the protocol image
+ *
+ * Write the contents of the protocol SRAM.
+ */
+int t3_set_proto_sram(struct adapter *adap, u8 *data)
+{
+ int i;
+ u32 *buf = (u32 *)data;
+
+ for (i = 0; i < PROTO_SRAM_LINES; i++) {
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++));
+
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
+ if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
+ return -EIO;
+ }
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
+
+ return 0;
+}
+
void t3_config_trace_filter(struct adapter *adapter,
const struct trace_params *tp, int filter_index,
int invert, int enable)
@@ -2802,7 +2892,7 @@ static void init_hw_for_avail_ports(struct adapter *adap, int nports)
t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN |
F_PORT0ACTIVE | F_ENFORCEPKT);
- t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000);
+ t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff);
} else {
t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
@@ -3097,7 +3187,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
else
t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
- t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000);
+ t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
init_hw_for_avail_ports(adapter, adapter->params.nports);
t3_sge_init(adapter, &adapter->params.sge);
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
index b112317f033e..8eddd23a3a51 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/cxgb3/version.h
@@ -39,6 +39,6 @@
/* Firmware version */
#define FW_VERSION_MAJOR 4
-#define FW_VERSION_MINOR 0
+#define FW_VERSION_MINOR 1
#define FW_VERSION_MICRO 0
#endif /* __CHELSIO_VERSION_H */
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index c0f81b5a30fb..abaf3ac94936 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0064"
+#define DRV_VERSION "EHEA_0065"
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -136,10 +136,10 @@ void ehea_dump(void *adr, int len, char *msg);
(0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff))
#define EHEA_BMASK_SET(mask, value) \
- ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
+ ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
#define EHEA_BMASK_GET(mask, value) \
- (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
+ (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
/*
* Generic ehea page
@@ -190,7 +190,7 @@ struct ehea_av;
* Queue attributes passed to ehea_create_qp()
*/
struct ehea_qp_init_attr {
- /* input parameter */
+ /* input parameter */
u32 qp_token; /* queue token */
u8 low_lat_rq1;
u8 signalingtype; /* cqe generation flag */
@@ -212,7 +212,7 @@ struct ehea_qp_init_attr {
u64 recv_cq_handle;
u64 aff_eq_handle;
- /* output parameter */
+ /* output parameter */
u32 qp_nr;
u16 act_nr_send_wqes;
u16 act_nr_rwqes_rq1;
@@ -279,12 +279,12 @@ struct ehea_qp {
* Completion Queue attributes
*/
struct ehea_cq_attr {
- /* input parameter */
+ /* input parameter */
u32 max_nr_of_cqes;
u32 cq_token;
u64 eq_handle;
- /* output parameter */
+ /* output parameter */
u32 act_nr_of_cqes;
u32 nr_pages;
};
diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ehea/ehea_hw.h
index 1246757f2c22..1af7ca499ec5 100644
--- a/drivers/net/ehea/ehea_hw.h
+++ b/drivers/net/ehea/ehea_hw.h
@@ -211,34 +211,34 @@ static inline void epa_store_acc(struct h_epa epa, u32 offset, u64 value)
}
#define epa_store_eq(epa, offset, value)\
- epa_store(epa, EQTEMM_OFFSET(offset), value)
+ epa_store(epa, EQTEMM_OFFSET(offset), value)
#define epa_load_eq(epa, offset)\
- epa_load(epa, EQTEMM_OFFSET(offset))
+ epa_load(epa, EQTEMM_OFFSET(offset))
#define epa_store_cq(epa, offset, value)\
- epa_store(epa, CQTEMM_OFFSET(offset), value)
+ epa_store(epa, CQTEMM_OFFSET(offset), value)
#define epa_load_cq(epa, offset)\
- epa_load(epa, CQTEMM_OFFSET(offset))
+ epa_load(epa, CQTEMM_OFFSET(offset))
#define epa_store_qp(epa, offset, value)\
- epa_store(epa, QPTEMM_OFFSET(offset), value)
+ epa_store(epa, QPTEMM_OFFSET(offset), value)
#define epa_load_qp(epa, offset)\
- epa_load(epa, QPTEMM_OFFSET(offset))
+ epa_load(epa, QPTEMM_OFFSET(offset))
#define epa_store_qped(epa, offset, value)\
- epa_store(epa, QPEDMM_OFFSET(offset), value)
+ epa_store(epa, QPEDMM_OFFSET(offset), value)
#define epa_load_qped(epa, offset)\
- epa_load(epa, QPEDMM_OFFSET(offset))
+ epa_load(epa, QPEDMM_OFFSET(offset))
#define epa_store_mrmw(epa, offset, value)\
- epa_store(epa, MRMWMM_OFFSET(offset), value)
+ epa_store(epa, MRMWMM_OFFSET(offset), value)
#define epa_load_mrmw(epa, offset)\
- epa_load(epa, MRMWMM_OFFSET(offset))
+ epa_load(epa, MRMWMM_OFFSET(offset))
#define epa_store_base(epa, offset, value)\
- epa_store(epa, HCAGR_OFFSET(offset), value)
+ epa_store(epa, HCAGR_OFFSET(offset), value)
#define epa_load_base(epa, offset)\
- epa_load(epa, HCAGR_OFFSET(offset))
+ epa_load(epa, HCAGR_OFFSET(offset))
static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes)
{
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 9e13433a268a..bdb52419dbf5 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -81,7 +81,7 @@ MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
static int port_name_cnt = 0;
static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
- const struct of_device_id *id);
+ const struct of_device_id *id);
static int __devexit ehea_remove(struct ibmebus_dev *dev);
@@ -236,7 +236,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
rwqe = ehea_get_next_rwqe(qp, rq_nr);
rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
- | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
+ | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
rwqe->sg_list[0].vaddr = (u64)skb->data;
rwqe->sg_list[0].len = packet_size;
@@ -427,7 +427,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
break;
}
skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
- cqe->num_bytes_transfered - 4);
+ cqe->num_bytes_transfered - 4);
ehea_fill_skb(port->netdev, skb, cqe);
} else if (rq == 2) { /* RQ2 */
skb = get_skb_by_index(skb_arr_rq2,
@@ -618,7 +618,7 @@ static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
for (i = 0; i < EHEA_MAX_PORTS; i++)
if (adapter->port[i])
- if (adapter->port[i]->logical_port_id == logical_port)
+ if (adapter->port[i]->logical_port_id == logical_port)
return adapter->port[i];
return NULL;
}
@@ -1695,6 +1695,7 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
{
if (skb->protocol == htons(ETH_P_IP)) {
const struct iphdr *iph = ip_hdr(skb);
+
/* IPv4 */
swqe->tx_control |= EHEA_SWQE_CRC
| EHEA_SWQE_IP_CHECKSUM
@@ -1705,13 +1706,12 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
write_ip_start_end(swqe, skb);
if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
+ if ((iph->frag_off & IP_MF)
+ || (iph->frag_off & IP_OFFSET))
/* IP fragment, so don't change cs */
swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
else
write_udp_offset_end(swqe, skb);
-
} else if (iph->protocol == IPPROTO_TCP) {
write_tcp_offset_end(swqe, skb);
}
@@ -1739,6 +1739,7 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
if (skb->protocol == htons(ETH_P_IP)) {
const struct iphdr *iph = ip_hdr(skb);
+
/* IPv4 */
write_ip_start_end(swqe, skb);
@@ -1751,8 +1752,8 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
write_tcp_offset_end(swqe, skb);
} else if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
+ if ((iph->frag_off & IP_MF)
+ || (iph->frag_off & IP_OFFSET))
/* IP fragment, so don't change cs */
swqe->tx_control |= EHEA_SWQE_CRC
| EHEA_SWQE_IMM_DATA_PRESENT;
@@ -2407,7 +2408,7 @@ static void __devinit logical_port_release(struct device *dev)
}
static int ehea_driver_sysfs_add(struct device *dev,
- struct device_driver *driver)
+ struct device_driver *driver)
{
int ret;
@@ -2424,7 +2425,7 @@ static int ehea_driver_sysfs_add(struct device *dev,
}
static void ehea_driver_sysfs_remove(struct device *dev,
- struct device_driver *driver)
+ struct device_driver *driver)
{
struct device_driver *drv = driver;
@@ -2453,7 +2454,7 @@ static struct device *ehea_register_port(struct ehea_port *port,
}
ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
- if (ret) {
+ if (ret) {
ehea_error("failed to register attributes, ret=%d", ret);
goto out_unreg_of_dev;
}
@@ -2601,6 +2602,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
{
struct device_node *lhea_dn;
struct device_node *eth_dn = NULL;
+
const u32 *dn_log_port_id;
int i = 0;
@@ -2608,7 +2610,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
- NULL);
+ NULL);
if (!dn_log_port_id) {
ehea_error("bad device node: eth_dn name=%s",
eth_dn->full_name);
@@ -2648,7 +2650,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
- NULL);
+ NULL);
if (dn_log_port_id)
if (*dn_log_port_id == logical_port_id)
return eth_dn;
@@ -2789,7 +2791,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
adapter->ebus_dev = dev;
adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
- NULL);
+ NULL);
if (adapter_handle)
adapter->handle = *adapter_handle;
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index f24a8862977d..29eaa46948b0 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -211,7 +211,7 @@ u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
u64 hret;
u64 adapter_handle = cq->adapter->handle;
- /* deregister all previous registered pages */
+ /* deregister all previous registered pages */
hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force);
if (hret != H_SUCCESS)
return hret;
@@ -362,7 +362,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
if (hret != H_SUCCESS) {
ehea_error("destroy EQ failed");
return -EIO;
- }
+ }
return 0;
}
@@ -507,44 +507,44 @@ out_freemem:
u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
{
- u64 hret;
- struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
+ u64 hret;
+ struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
- ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
- hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
- if (hret != H_SUCCESS)
- return hret;
+ ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
+ hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
+ if (hret != H_SUCCESS)
+ return hret;
- hw_queue_dtor(&qp->hw_squeue);
- hw_queue_dtor(&qp->hw_rqueue1);
+ hw_queue_dtor(&qp->hw_squeue);
+ hw_queue_dtor(&qp->hw_rqueue1);
- if (qp_attr->rq_count > 1)
- hw_queue_dtor(&qp->hw_rqueue2);
- if (qp_attr->rq_count > 2)
- hw_queue_dtor(&qp->hw_rqueue3);
- kfree(qp);
+ if (qp_attr->rq_count > 1)
+ hw_queue_dtor(&qp->hw_rqueue2);
+ if (qp_attr->rq_count > 2)
+ hw_queue_dtor(&qp->hw_rqueue3);
+ kfree(qp);
- return hret;
+ return hret;
}
int ehea_destroy_qp(struct ehea_qp *qp)
{
- u64 hret;
- if (!qp)
- return 0;
+ u64 hret;
+ if (!qp)
+ return 0;
- if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
- ehea_error_data(qp->adapter, qp->fw_handle);
- hret = ehea_destroy_qp_res(qp, FORCE_FREE);
- }
+ if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
+ ehea_error_data(qp->adapter, qp->fw_handle);
+ hret = ehea_destroy_qp_res(qp, FORCE_FREE);
+ }
- if (hret != H_SUCCESS) {
- ehea_error("destroy QP failed");
- return -EIO;
- }
+ if (hret != H_SUCCESS) {
+ ehea_error("destroy QP failed");
+ return -EIO;
+ }
- return 0;
+ return 0;
}
int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
index a84c232395e3..afb34ded26ee 100644
--- a/drivers/net/fec_8xx/Kconfig
+++ b/drivers/net/fec_8xx/Kconfig
@@ -1,6 +1,6 @@
config FEC_8XX
tristate "Motorola 8xx FEC driver"
- depends on NET_ETHERNET && 8xx
+ depends on 8XX
select MII
config FEC_8XX_GENERIC_PHY
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 6aaee67dd4b7..e27ee210b605 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -1,6 +1,6 @@
config FS_ENET
tristate "Freescale Ethernet Driver"
- depends on NET_ETHERNET && (CPM1 || CPM2)
+ depends on CPM1 || CPM2
select MII
config FS_ENET_HAS_SCC
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 1b854bf07b09..d7a1a58de766 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -130,6 +130,9 @@ static int gfar_remove(struct platform_device *pdev);
static void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
+static void gfar_configure_serdes(struct net_device *dev);
+extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value);
+extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum);
#ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget);
#endif
@@ -451,6 +454,9 @@ static int init_phy(struct net_device *dev)
phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
+ if (interface == PHY_INTERFACE_MODE_SGMII)
+ gfar_configure_serdes(dev);
+
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
return PTR_ERR(phydev);
@@ -465,6 +471,27 @@ static int init_phy(struct net_device *dev)
return 0;
}
+static void gfar_configure_serdes(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_mii __iomem *regs =
+ (void __iomem *)&priv->regs->gfar_mii_regs;
+
+ /* Initialise TBI i/f to communicate with serdes (lynx phy) */
+
+ /* Single clk mode, mii mode off(for aerdes communication) */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
+
+ /* Supported pause and full-duplex, no half-duplex */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE,
+ ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
+ ADVERTISE_1000XPSE_ASYM);
+
+ /* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
+ BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
+}
+
static void init_registers(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 39e9e321fcbc..d8e779c102fa 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -136,6 +136,12 @@ extern const char gfar_driver_version[];
#define MIIMCFG_RESET 0x80000000
#define MIIMIND_BUSY 0x00000001
+/* TBI register addresses */
+#define MII_TBICON 0x11
+
+/* TBICON register bit fields */
+#define TBICON_CLK_SELECT 0x0020
+
/* MAC register bits */
#define MACCFG1_SOFT_RESET 0x80000000
#define MACCFG1_RESET_RX_MC 0x00080000
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index bcc6b82f4a33..5dd34a1a7b89 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -43,13 +43,18 @@
#include "gianfar.h"
#include "gianfar_mii.h"
-/* Write value to the PHY at mii_id at register regnum,
- * on the bus, waiting until the write is done before returning.
- * All PHY configuration is done through the TSEC1 MIIM regs */
-int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+/*
+ * Write value to the PHY at mii_id at register regnum,
+ * on the bus attached to the local interface, which may be different from the
+ * generic mdio bus (tied to a single interface), waiting until the write is
+ * done before returning. This is helpful in programming interfaces like
+ * the TBI which control interfaces like onchip SERDES and are always tied to
+ * the local mdio pins, which may not be the same as system mdio bus, used for
+ * controlling the external PHYs, for example.
+ */
+int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id,
+ int regnum, u16 value)
{
- struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
-
/* Set the PHY address and the register address we want to write */
gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
@@ -63,12 +68,19 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
return 0;
}
-/* Read the bus for PHY at addr mii_id, register regnum, and
- * return the value. Clears miimcom first. All PHY
- * configuration has to be done through the TSEC1 MIIM regs */
-int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+/*
+ * Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY operation
+ * done on the bus attached to the local interface,
+ * which may be different from the generic mdio bus
+ * This is helpful in programming interfaces like
+ * the TBI which, inturn, control interfaces like onchip SERDES
+ * and are always tied to the local mdio pins, which may not be the
+ * same as system mdio bus, used for controlling the external PHYs, for eg.
+ */
+int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum)
+
{
- struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
u16 value;
/* Set the PHY address and the register address we want to read */
@@ -88,6 +100,27 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
return value;
}
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+ /* Write to the local MII regs */
+ return(gfar_local_mdio_write(regs, mii_id, regnum, value));
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+ /* Read the local MII regs */
+ return(gfar_local_mdio_read(regs, mii_id, regnum));
+}
/* Reset the MIIM registers, and wait for the bus to free */
int gfar_mdio_reset(struct mii_bus *bus)
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 741780e14b2c..efbae4b8398e 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -86,93 +86,36 @@
#include <linux/dma-mapping.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/pdc.h>
-#include <asm/cache.h>
#include <asm/parisc-device.h>
#define LASI_82596_DRIVER_VERSION "LASI 82596 driver - Revision: 1.30"
-/* DEBUG flags
- */
-
-#define DEB_INIT 0x0001
-#define DEB_PROBE 0x0002
-#define DEB_SERIOUS 0x0004
-#define DEB_ERRORS 0x0008
-#define DEB_MULTI 0x0010
-#define DEB_TDR 0x0020
-#define DEB_OPEN 0x0040
-#define DEB_RESET 0x0080
-#define DEB_ADDCMD 0x0100
-#define DEB_STATUS 0x0200
-#define DEB_STARTTX 0x0400
-#define DEB_RXADDR 0x0800
-#define DEB_TXADDR 0x1000
-#define DEB_RXFRAME 0x2000
-#define DEB_INTS 0x4000
-#define DEB_STRUCT 0x8000
-#define DEB_ANY 0xffff
-
-
-#define DEB(x,y) if (i596_debug & (x)) { y; }
-
-
-#define CHECK_WBACK(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0)
-
-#define CHECK_INV(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0)
-
-#define CHECK_WBACK_INV(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
-
-
#define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/
#define PA_CPU_PORT_L_ACCESS 4
#define PA_CHANNEL_ATTENTION 8
+#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */
-/*
- * Define various macros for Channel Attention, word swapping etc., dependent
- * on architecture. MVME and BVME are 680x0 based, otherwise it is Intel.
- */
+#define DMA_ALLOC dma_alloc_noncoherent
+#define DMA_FREE dma_free_noncoherent
+#define DMA_WBACK(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0)
-#ifdef __BIG_ENDIAN
-#define WSWAPrfd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPrbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPiscp(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPscb(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPcmd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPtbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPchar(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define ISCP_BUSY 0x00010000
-#define MACH_IS_APRICOT 0
-#else
-#define WSWAPrfd(x) ((struct i596_rfd *)(x))
-#define WSWAPrbd(x) ((struct i596_rbd *)(x))
-#define WSWAPiscp(x) ((struct i596_iscp *)(x))
-#define WSWAPscb(x) ((struct i596_scb *)(x))
-#define WSWAPcmd(x) ((struct i596_cmd *)(x))
-#define WSWAPtbd(x) ((struct i596_tbd *)(x))
-#define WSWAPchar(x) ((char *)(x))
-#define ISCP_BUSY 0x0001
-#define MACH_IS_APRICOT 1
-#endif
+#define DMA_INV(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_FROM_DEVICE); } while (0)
-/*
- * The MPU_PORT command allows direct access to the 82596. With PORT access
- * the following commands are available (p5-18). The 32-bit port command
- * must be word-swapped with the most significant word written first.
- * This only applies to VME boards.
- */
-#define PORT_RESET 0x00 /* reset 82596 */
-#define PORT_SELFTEST 0x01 /* selftest */
-#define PORT_ALTSCP 0x02 /* alternate SCB address */
-#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */
+#define DMA_WBACK_INV(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
+
+#define SYSBUS 0x0000006c;
+
+/* big endian CPU, 82596 "big" endian mode */
+#define SWAP32(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
+#define SWAP16(x) (x)
-static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+#include "lib82596.c"
MODULE_AUTHOR("Richard Hirst");
MODULE_DESCRIPTION("i82596 driver");
@@ -180,255 +123,15 @@ MODULE_LICENSE("GPL");
module_param(i596_debug, int, 0);
MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask");
-/* Copy frames shorter than rx_copybreak, otherwise pass on up in
- * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha).
- */
-static int rx_copybreak = 100;
-
-#define MAX_DRIVERS 4 /* max count of drivers */
-
-#define PKT_BUF_SZ 1536
-#define MAX_MC_CNT 64
-
-#define I596_NULL ((u32)0xffffffff)
-
-#define CMD_EOL 0x8000 /* The last command of the list, stop. */
-#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */
-#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */
-
-#define CMD_FLEX 0x0008 /* Enable flexible memory model */
-
-enum commands {
- CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
- CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
-};
-
-#define STAT_C 0x8000 /* Set to 0 after execution */
-#define STAT_B 0x4000 /* Command being executed */
-#define STAT_OK 0x2000 /* Command executed ok */
-#define STAT_A 0x1000 /* Command aborted */
-
-#define CUC_START 0x0100
-#define CUC_RESUME 0x0200
-#define CUC_SUSPEND 0x0300
-#define CUC_ABORT 0x0400
-#define RX_START 0x0010
-#define RX_RESUME 0x0020
-#define RX_SUSPEND 0x0030
-#define RX_ABORT 0x0040
-
-#define TX_TIMEOUT 5
-
-#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */
-
-
-struct i596_reg {
- unsigned short porthi;
- unsigned short portlo;
- u32 ca;
-};
-
-#define EOF 0x8000
-#define SIZE_MASK 0x3fff
-
-struct i596_tbd {
- unsigned short size;
- unsigned short pad;
- dma_addr_t next;
- dma_addr_t data;
- u32 cache_pad[5]; /* Total 32 bytes... */
-};
-
-/* The command structure has two 'next' pointers; v_next is the address of
- * the next command as seen by the CPU, b_next is the address of the next
- * command as seen by the 82596. The b_next pointer, as used by the 82596
- * always references the status field of the next command, rather than the
- * v_next field, because the 82596 is unaware of v_next. It may seem more
- * logical to put v_next at the end of the structure, but we cannot do that
- * because the 82596 expects other fields to be there, depending on command
- * type.
- */
-
-struct i596_cmd {
- struct i596_cmd *v_next; /* Address from CPUs viewpoint */
- unsigned short status;
- unsigned short command;
- dma_addr_t b_next; /* Address from i596 viewpoint */
-};
-
-struct tx_cmd {
- struct i596_cmd cmd;
- dma_addr_t tbd;
- unsigned short size;
- unsigned short pad;
- struct sk_buff *skb; /* So we can free it after tx */
- dma_addr_t dma_addr;
-#ifdef __LP64__
- u32 cache_pad[6]; /* Total 64 bytes... */
-#else
- u32 cache_pad[1]; /* Total 32 bytes... */
-#endif
-};
-
-struct tdr_cmd {
- struct i596_cmd cmd;
- unsigned short status;
- unsigned short pad;
-};
-
-struct mc_cmd {
- struct i596_cmd cmd;
- short mc_cnt;
- char mc_addrs[MAX_MC_CNT*6];
-};
-
-struct sa_cmd {
- struct i596_cmd cmd;
- char eth_addr[8];
-};
-
-struct cf_cmd {
- struct i596_cmd cmd;
- char i596_config[16];
-};
-
-struct i596_rfd {
- unsigned short stat;
- unsigned short cmd;
- dma_addr_t b_next; /* Address from i596 viewpoint */
- dma_addr_t rbd;
- unsigned short count;
- unsigned short size;
- struct i596_rfd *v_next; /* Address from CPUs viewpoint */
- struct i596_rfd *v_prev;
-#ifndef __LP64__
- u32 cache_pad[2]; /* Total 32 bytes... */
-#endif
-};
-
-struct i596_rbd {
- /* hardware data */
- unsigned short count;
- unsigned short zero1;
- dma_addr_t b_next;
- dma_addr_t b_data; /* Address from i596 viewpoint */
- unsigned short size;
- unsigned short zero2;
- /* driver data */
- struct sk_buff *skb;
- struct i596_rbd *v_next;
- dma_addr_t b_addr; /* This rbd addr from i596 view */
- unsigned char *v_data; /* Address from CPUs viewpoint */
- /* Total 32 bytes... */
-#ifdef __LP64__
- u32 cache_pad[4];
-#endif
-};
-
-/* These values as chosen so struct i596_private fits in one page... */
-
-#define TX_RING_SIZE 32
-#define RX_RING_SIZE 16
-
-struct i596_scb {
- unsigned short status;
- unsigned short command;
- dma_addr_t cmd;
- dma_addr_t rfd;
- u32 crc_err;
- u32 align_err;
- u32 resource_err;
- u32 over_err;
- u32 rcvdt_err;
- u32 short_err;
- unsigned short t_on;
- unsigned short t_off;
-};
-
-struct i596_iscp {
- u32 stat;
- dma_addr_t scb;
-};
-
-struct i596_scp {
- u32 sysbus;
- u32 pad;
- dma_addr_t iscp;
-};
-
-struct i596_private {
- volatile struct i596_scp scp __attribute__((aligned(32)));
- volatile struct i596_iscp iscp __attribute__((aligned(32)));
- volatile struct i596_scb scb __attribute__((aligned(32)));
- struct sa_cmd sa_cmd __attribute__((aligned(32)));
- struct cf_cmd cf_cmd __attribute__((aligned(32)));
- struct tdr_cmd tdr_cmd __attribute__((aligned(32)));
- struct mc_cmd mc_cmd __attribute__((aligned(32)));
- struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32)));
- struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32)));
- struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32)));
- struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32)));
- u32 stat;
- int last_restart;
- struct i596_rfd *rfd_head;
- struct i596_rbd *rbd_head;
- struct i596_cmd *cmd_tail;
- struct i596_cmd *cmd_head;
- int cmd_backlog;
- u32 last_cmd;
- struct net_device_stats stats;
- int next_tx_cmd;
- int options;
- spinlock_t lock;
- dma_addr_t dma_addr;
- struct device *dev;
-};
-
-static const char init_setup[] =
-{
- 0x8E, /* length, prefetch on */
- 0xC8, /* fifo to 8, monitor off */
- 0x80, /* don't save bad frames */
- 0x2E, /* No source address insertion, 8 byte preamble */
- 0x00, /* priority and backoff defaults */
- 0x60, /* interframe spacing */
- 0x00, /* slot time LSB */
- 0xf2, /* slot time and retries */
- 0x00, /* promiscuous mode */
- 0x00, /* collision detect */
- 0x40, /* minimum frame length */
- 0xff,
- 0x00,
- 0x7f /* *multi IA */ };
-
-static int i596_open(struct net_device *dev);
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id);
-static int i596_close(struct net_device *dev);
-static struct net_device_stats *i596_get_stats(struct net_device *dev);
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
-static void i596_tx_timeout (struct net_device *dev);
-static void print_eth(unsigned char *buf, char *str);
-static void set_multicast_list(struct net_device *dev);
-
-static int rx_ring_size = RX_RING_SIZE;
-static int ticks_limit = 100;
-static int max_cmd_backlog = TX_RING_SIZE-1;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev);
-#endif
-
-
-static inline void CA(struct net_device *dev)
+static inline void ca(struct net_device *dev)
{
gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION);
}
-static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
u32 v = (u32) (c) | (u32) (x);
u16 a, b;
@@ -446,1078 +149,15 @@ static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS);
}
-
-static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
- CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
- while (--delcnt && lp->iscp.stat) {
- udelay(10);
- CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
- }
- if (!delcnt) {
- printk("%s: %s, iscp.stat %04x, didn't clear\n",
- dev->name, str, lp->iscp.stat);
- return -1;
- }
- else
- return 0;
-}
-
-
-static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
- CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- while (--delcnt && lp->scb.command) {
- udelay(10);
- CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- }
- if (!delcnt) {
- printk("%s: %s, status %4.4x, cmd %4.4x.\n",
- dev->name, str, lp->scb.status, lp->scb.command);
- return -1;
- }
- else
- return 0;
-}
-
-
-static void i596_display_data(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_cmd *cmd;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
-
- printk("lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
- &lp->scp, lp->scp.sysbus, lp->scp.iscp);
- printk("iscp at %p, iscp.stat = %08x, .scb = %08x\n",
- &lp->iscp, lp->iscp.stat, lp->iscp.scb);
- printk("scb at %p, scb.status = %04x, .command = %04x,"
- " .cmd = %08x, .rfd = %08x\n",
- &lp->scb, lp->scb.status, lp->scb.command,
- lp->scb.cmd, lp->scb.rfd);
- printk(" errors: crc %x, align %x, resource %x,"
- " over %x, rcvdt %x, short %x\n",
- lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err,
- lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err);
- cmd = lp->cmd_head;
- while (cmd != NULL) {
- printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %08x\n",
- cmd, cmd->status, cmd->command, cmd->b_next);
- cmd = cmd->v_next;
- }
- rfd = lp->rfd_head;
- printk("rfd_head = %p\n", rfd);
- do {
- printk(" %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
- " count %04x\n",
- rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd,
- rfd->count);
- rfd = rfd->v_next;
- } while (rfd != lp->rfd_head);
- rbd = lp->rbd_head;
- printk("rbd_head = %p\n", rbd);
- do {
- printk(" %p .count %04x, b_next %08x, b_data %08x, size %04x\n",
- rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
- rbd = rbd->v_next;
- } while (rbd != lp->rbd_head);
- CHECK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static void i596_error(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
- pcc2[0x28] = 1;
- pcc2[0x2b] = 0x1d;
- printk("%s: Error interrupt\n", dev->name);
- i596_display_data(dev);
-}
-#endif
-
-#define virt_to_dma(lp,v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)(lp)))
-
-static inline void init_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int i;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
-
- /* First build the Receive Buffer Descriptor List */
-
- for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
- dma_addr_t dma_addr;
- struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4);
-
- if (skb == NULL)
- panic("%s: alloc_skb() failed", __FILE__);
- skb_reserve(skb, 2);
- dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ,
- DMA_FROM_DEVICE);
- skb->dev = dev;
- rbd->v_next = rbd+1;
- rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1));
- rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd));
- rbd->skb = skb;
- rbd->v_data = skb->data;
- rbd->b_data = WSWAPchar(dma_addr);
- rbd->size = PKT_BUF_SZ;
- }
- lp->rbd_head = lp->rbds;
- rbd = lp->rbds + rx_ring_size - 1;
- rbd->v_next = lp->rbds;
- rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
- /* Now build the Receive Frame Descriptor List */
-
- for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
- rfd->rbd = I596_NULL;
- rfd->v_next = rfd+1;
- rfd->v_prev = rfd-1;
- rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1));
- rfd->cmd = CMD_FLEX;
- }
- lp->rfd_head = lp->rfds;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- rfd = lp->rfds;
- rfd->rbd = WSWAPrbd(virt_to_dma(lp,lp->rbd_head));
- rfd->v_prev = lp->rfds + rx_ring_size - 1;
- rfd = lp->rfds + rx_ring_size - 1;
- rfd->v_next = lp->rfds;
- rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- rfd->cmd = CMD_EOL|CMD_FLEX;
-
- CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-static inline void remove_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_rbd *rbd;
- int i;
-
- for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
- if (rbd->skb == NULL)
- break;
- dma_unmap_single(lp->dev,
- (dma_addr_t)WSWAPchar(rbd->b_data),
- PKT_BUF_SZ, DMA_FROM_DEVICE);
- dev_kfree_skb(rbd->skb);
- }
-}
-
-
-static void rebuild_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int i;
-
- /* Ensure rx frame/buffer descriptors are tidy */
-
- for (i = 0; i < rx_ring_size; i++) {
- lp->rfds[i].rbd = I596_NULL;
- lp->rfds[i].cmd = CMD_FLEX;
- }
- lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
- lp->rfd_head = lp->rfds;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- lp->rbd_head = lp->rbds;
- lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
- CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-static int init_i596_mem(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- disable_irq(dev->irq); /* disable IRQs from LAN */
- DEB(DEB_INIT,
- printk("RESET 82596 port: %lx (with IRQ %d disabled)\n",
- (dev->base_addr + PA_I82596_RESET),
- dev->irq));
-
- gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
- udelay(100); /* Wait 100us - seems to help */
-
- /* change the scp address */
-
- lp->last_cmd = jiffies;
-
-
- lp->scp.sysbus = 0x0000006c;
- lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp)));
- lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb)));
- lp->iscp.stat = ISCP_BUSY;
- lp->cmd_backlog = 0;
-
- lp->cmd_head = NULL;
- lp->scb.cmd = I596_NULL;
-
- DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name));
-
- CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp));
- CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp));
-
- MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp));
-
- CA(dev);
-
- if (wait_istat(dev, lp, 1000, "initialization timed out"))
- goto failed;
- DEB(DEB_INIT, printk("%s: i82596 initialization successful\n", dev->name));
-
- /* Ensure rx frame/buffer descriptors are tidy */
- rebuild_rx_bufs(dev);
-
- lp->scb.command = 0;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
- enable_irq(dev->irq); /* enable IRQs from LAN */
-
- DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name));
- memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup));
- lp->cf_cmd.cmd.command = CmdConfigure;
- CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd));
- i596_add_cmd(dev, &lp->cf_cmd.cmd);
-
- DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name));
- memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
- lp->sa_cmd.cmd.command = CmdSASetup;
- CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd));
- i596_add_cmd(dev, &lp->sa_cmd.cmd);
-
- DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name));
- lp->tdr_cmd.cmd.command = CmdTDR;
- CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd));
- i596_add_cmd(dev, &lp->tdr_cmd.cmd);
-
- spin_lock_irqsave (&lp->lock, flags);
-
- if (wait_cmd(dev, lp, 1000, "timed out waiting to issue RX_START")) {
- spin_unlock_irqrestore (&lp->lock, flags);
- goto failed;
- }
- DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name));
- lp->scb.command = RX_START;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
- CA(dev);
-
- spin_unlock_irqrestore (&lp->lock, flags);
-
- if (wait_cmd(dev, lp, 1000, "RX_START not processed"))
- goto failed;
- DEB(DEB_INIT, printk("%s: Receive unit started OK\n", dev->name));
-
- return 0;
-
-failed:
- printk("%s: Failed to initialise 82596\n", dev->name);
- MPU_PORT(dev, PORT_RESET, 0);
- return -1;
-}
-
-
-static inline int i596_rx(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
- int frames = 0;
-
- DEB(DEB_RXFRAME, printk("i596_rx(), rfd_head %p, rbd_head %p\n",
- lp->rfd_head, lp->rbd_head));
-
-
- rfd = lp->rfd_head; /* Ref next frame to check */
-
- CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
- while ((rfd->stat) & STAT_C) { /* Loop while complete frames */
- if (rfd->rbd == I596_NULL)
- rbd = NULL;
- else if (rfd->rbd == lp->rbd_head->b_addr) {
- rbd = lp->rbd_head;
- CHECK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
- else {
- printk("%s: rbd chain broken!\n", dev->name);
- /* XXX Now what? */
- rbd = NULL;
- }
- DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
- rfd, rfd->rbd, rfd->stat));
-
- if (rbd != NULL && ((rfd->stat) & STAT_OK)) {
- /* a good frame */
- int pkt_len = rbd->count & 0x3fff;
- struct sk_buff *skb = rbd->skb;
- int rx_in_place = 0;
-
- DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));
- frames++;
-
- /* Check if the packet is long enough to just accept
- * without copying to a properly sized skbuff.
- */
-
- if (pkt_len > rx_copybreak) {
- struct sk_buff *newskb;
- dma_addr_t dma_addr;
-
- dma_unmap_single(lp->dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- /* Get fresh skbuff to replace filled one. */
- newskb = dev_alloc_skb(PKT_BUF_SZ + 4);
- if (newskb == NULL) {
- skb = NULL; /* drop pkt */
- goto memory_squeeze;
- }
- skb_reserve(newskb, 2);
-
- /* Pass up the skb already on the Rx ring. */
- skb_put(skb, pkt_len);
- rx_in_place = 1;
- rbd->skb = newskb;
- newskb->dev = dev;
- dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE);
- rbd->v_data = newskb->data;
- rbd->b_data = WSWAPchar(dma_addr);
- CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
- else
- skb = dev_alloc_skb(pkt_len + 2);
-memory_squeeze:
- if (skb == NULL) {
- /* XXX tulip.c can defer packets here!! */
- printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- }
- else {
- if (!rx_in_place) {
- /* 16 byte align the data fields */
- dma_sync_single_for_cpu(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- skb_reserve(skb, 2);
- memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);
- dma_sync_single_for_device(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- }
- skb->len = pkt_len;
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
- lp->stats.rx_bytes+=pkt_len;
- }
- }
- else {
- DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n",
- dev->name, rfd->stat));
- lp->stats.rx_errors++;
- if ((rfd->stat) & 0x0001)
- lp->stats.collisions++;
- if ((rfd->stat) & 0x0080)
- lp->stats.rx_length_errors++;
- if ((rfd->stat) & 0x0100)
- lp->stats.rx_over_errors++;
- if ((rfd->stat) & 0x0200)
- lp->stats.rx_fifo_errors++;
- if ((rfd->stat) & 0x0400)
- lp->stats.rx_frame_errors++;
- if ((rfd->stat) & 0x0800)
- lp->stats.rx_crc_errors++;
- if ((rfd->stat) & 0x1000)
- lp->stats.rx_length_errors++;
- }
-
- /* Clear the buffer descriptor count and EOF + F flags */
-
- if (rbd != NULL && (rbd->count & 0x4000)) {
- rbd->count = 0;
- lp->rbd_head = rbd->v_next;
- CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
-
- /* Tidy the frame descriptor, marking it as end of list */
-
- rfd->rbd = I596_NULL;
- rfd->stat = 0;
- rfd->cmd = CMD_EOL|CMD_FLEX;
- rfd->count = 0;
-
- /* Remove end-of-list from old end descriptor */
-
- rfd->v_prev->cmd = CMD_FLEX;
-
- /* Update record of next frame descriptor to process */
-
- lp->scb.rfd = rfd->b_next;
- lp->rfd_head = rfd->v_next;
- CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd));
- CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd));
- rfd = lp->rfd_head;
- CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
- }
-
- DEB(DEB_RXFRAME, printk("frames %d\n", frames));
-
- return 0;
-}
-
-
-static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
-{
- struct i596_cmd *ptr;
-
- while (lp->cmd_head != NULL) {
- ptr = lp->cmd_head;
- lp->cmd_head = ptr->v_next;
- lp->cmd_backlog--;
-
- switch ((ptr->command) & 0x7) {
- case CmdTx:
- {
- struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
- struct sk_buff *skb = tx_cmd->skb;
- dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
-
- dev_kfree_skb(skb);
-
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
-
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- tx_cmd->cmd.command = 0; /* Mark as free */
- break;
- }
- default:
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- }
- CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd));
- }
-
- wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out");
- lp->scb.cmd = I596_NULL;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-}
-
-
-static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
-{
- unsigned long flags;
-
- DEB(DEB_RESET, printk("i596_reset\n"));
-
- spin_lock_irqsave (&lp->lock, flags);
-
- wait_cmd(dev, lp, 100, "i596_reset timed out");
-
- netif_stop_queue(dev);
-
- /* FIXME: this command might cause an lpmc */
- lp->scb.command = CUC_ABORT | RX_ABORT;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
- CA(dev);
-
- /* wait for shutdown */
- wait_cmd(dev, lp, 1000, "i596_reset 2 timed out");
- spin_unlock_irqrestore (&lp->lock, flags);
-
- i596_cleanup_cmd(dev,lp);
- i596_rx(dev);
-
- netif_start_queue(dev);
- init_i596_mem(dev);
-}
-
-
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- DEB(DEB_ADDCMD, printk("i596_add_cmd cmd_head %p\n", lp->cmd_head));
-
- cmd->status = 0;
- cmd->command |= (CMD_EOL | CMD_INTR);
- cmd->v_next = NULL;
- cmd->b_next = I596_NULL;
- CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd));
-
- spin_lock_irqsave (&lp->lock, flags);
-
- if (lp->cmd_head != NULL) {
- lp->cmd_tail->v_next = cmd;
- lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status));
- CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd));
- } else {
- lp->cmd_head = cmd;
- wait_cmd(dev, lp, 100, "i596_add_cmd timed out");
- lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status));
- lp->scb.command = CUC_START;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
- CA(dev);
- }
- lp->cmd_tail = cmd;
- lp->cmd_backlog++;
-
- spin_unlock_irqrestore (&lp->lock, flags);
-
- if (lp->cmd_backlog > max_cmd_backlog) {
- unsigned long tickssofar = jiffies - lp->last_cmd;
-
- if (tickssofar < ticks_limit)
- return;
-
- printk("%s: command unit timed out, status resetting.\n", dev->name);
-#if 1
- i596_reset(dev, lp);
-#endif
- }
-}
-
-#if 0
-/* this function makes a perfectly adequate probe... but we have a
- device list */
-static int i596_test(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- volatile int *tint;
- u32 data;
-
- tint = (volatile int *)(&(lp->scp));
- data = virt_to_dma(lp,tint);
-
- tint[1] = -1;
- CHECK_WBACK(lp, tint, PAGE_SIZE);
-
- MPU_PORT(dev, 1, data);
-
- for(data = 1000000; data; data--) {
- CHECK_INV(lp, tint, PAGE_SIZE);
- if(tint[1] != -1)
- break;
-
- }
-
- printk("i596_test result %d\n", tint[1]);
-
-}
-#endif
-
-
-static int i596_open(struct net_device *dev)
-{
- DEB(DEB_OPEN, printk("%s: i596_open() irq %d.\n", dev->name, dev->irq));
-
- if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
- printk("%s: IRQ %d not free\n", dev->name, dev->irq);
- goto out;
- }
-
- init_rx_bufs(dev);
-
- if (init_i596_mem(dev)) {
- printk("%s: Failed to init memory\n", dev->name);
- goto out_remove_rx_bufs;
- }
-
- netif_start_queue(dev);
-
- return 0;
-
-out_remove_rx_bufs:
- remove_rx_bufs(dev);
- free_irq(dev->irq, dev);
-out:
- return -EAGAIN;
-}
-
-static void i596_tx_timeout (struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
-
- /* Transmitter timeout, serious problems. */
- DEB(DEB_ERRORS, printk("%s: transmit timed out, status resetting.\n",
- dev->name));
-
- lp->stats.tx_errors++;
-
- /* Try to restart the adaptor */
- if (lp->last_restart == lp->stats.tx_packets) {
- DEB(DEB_ERRORS, printk("Resetting board.\n"));
- /* Shutdown and restart */
- i596_reset (dev, lp);
- } else {
- /* Issue a channel attention signal */
- DEB(DEB_ERRORS, printk("Kicking board.\n"));
- lp->scb.command = CUC_START | RX_START;
- CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- CA (dev);
- lp->last_restart = lp->stats.tx_packets;
- }
-
- dev->trans_start = jiffies;
- netif_wake_queue (dev);
-}
-
-
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct tx_cmd *tx_cmd;
- struct i596_tbd *tbd;
- short length = skb->len;
- dev->trans_start = jiffies;
-
- DEB(DEB_STARTTX, printk("%s: i596_start_xmit(%x,%p) called\n", dev->name,
- skb->len, skb->data));
-
- if (length < ETH_ZLEN) {
- if (skb_padto(skb, ETH_ZLEN))
- return 0;
- length = ETH_ZLEN;
- }
-
- netif_stop_queue(dev);
-
- tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
- tbd = lp->tbds + lp->next_tx_cmd;
-
- if (tx_cmd->cmd.command) {
- DEB(DEB_ERRORS, printk("%s: xmit ring full, dropping packet.\n",
- dev->name));
- lp->stats.tx_dropped++;
-
- dev_kfree_skb(skb);
- } else {
- if (++lp->next_tx_cmd == TX_RING_SIZE)
- lp->next_tx_cmd = 0;
- tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd));
- tbd->next = I596_NULL;
-
- tx_cmd->cmd.command = CMD_FLEX | CmdTx;
- tx_cmd->skb = skb;
-
- tx_cmd->pad = 0;
- tx_cmd->size = 0;
- tbd->pad = 0;
- tbd->size = EOF | length;
-
- tx_cmd->dma_addr = dma_map_single(lp->dev, skb->data, skb->len,
- DMA_TO_DEVICE);
- tbd->data = WSWAPchar(tx_cmd->dma_addr);
-
- DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
- CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd));
- CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd));
- i596_add_cmd(dev, &tx_cmd->cmd);
-
- lp->stats.tx_packets++;
- lp->stats.tx_bytes += length;
- }
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-static void print_eth(unsigned char *add, char *str)
-{
- int i;
-
- printk("i596 0x%p, ", add);
- for (i = 0; i < 6; i++)
- printk(" %02X", add[i + 6]);
- printk(" -->");
- for (i = 0; i < 6; i++)
- printk(" %02X", add[i]);
- printk(" %02X%02X, %s\n", add[12], add[13], str);
-}
-
-
#define LAN_PROM_ADDR 0xF0810000
-static int __devinit i82596_probe(struct net_device *dev,
- struct device *gen_dev)
-{
- int i;
- struct i596_private *lp;
- char eth_addr[6];
- dma_addr_t dma_addr;
-
- /* This lot is ensure things have been cache line aligned. */
- BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
- BUILD_BUG_ON(sizeof(struct i596_rbd) & 31);
- BUILD_BUG_ON(sizeof(struct tx_cmd) & 31);
- BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
-#ifndef __LP64__
- BUILD_BUG_ON(sizeof(struct i596_private) > 4096);
-#endif
-
- if (!dev->base_addr || !dev->irq)
- return -ENODEV;
-
- if (pdc_lan_station_id(eth_addr, dev->base_addr)) {
- for (i=0; i < 6; i++) {
- eth_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
- }
- printk(KERN_INFO "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
- }
-
- dev->mem_start = (unsigned long) dma_alloc_noncoherent(gen_dev,
- sizeof(struct i596_private), &dma_addr, GFP_KERNEL);
- if (!dev->mem_start) {
- printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
- return -ENOMEM;
- }
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = eth_addr[i];
-
- /* The 82596-specific entries in the device structure. */
- dev->open = i596_open;
- dev->stop = i596_close;
- dev->hard_start_xmit = i596_start_xmit;
- dev->get_stats = i596_get_stats;
- dev->set_multicast_list = set_multicast_list;
- dev->tx_timeout = i596_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = i596_poll_controller;
-#endif
-
- dev->priv = (void *)(dev->mem_start);
-
- lp = dev->priv;
- memset(lp, 0, sizeof(struct i596_private));
-
- lp->scb.command = 0;
- lp->scb.cmd = I596_NULL;
- lp->scb.rfd = I596_NULL;
- spin_lock_init(&lp->lock);
- lp->dma_addr = dma_addr;
- lp->dev = gen_dev;
-
- CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private));
-
- i = register_netdev(dev);
- if (i) {
- lp = dev->priv;
- dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
- (void *)dev->mem_start, lp->dma_addr);
- return i;
- };
-
- DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr));
- for (i = 0; i < 6; i++)
- DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
- DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
- DEB(DEB_INIT, printk(KERN_INFO "%s: lp at 0x%p (%d bytes), lp->scb at 0x%p\n",
- dev->name, lp, (int)sizeof(struct i596_private), &lp->scb));
-
- return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev)
-{
- disable_irq(dev->irq);
- i596_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-static irqreturn_t i596_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct i596_private *lp;
- unsigned short status, ack_cmd = 0;
-
- if (dev == NULL) {
- printk("%s: irq %d for unknown device.\n", __FUNCTION__, irq);
- return IRQ_NONE;
- }
-
- lp = dev->priv;
-
- spin_lock (&lp->lock);
-
- wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
- status = lp->scb.status;
-
- DEB(DEB_INTS, printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n",
- dev->name, irq, status));
-
- ack_cmd = status & 0xf000;
-
- if (!ack_cmd) {
- DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name));
- spin_unlock (&lp->lock);
- return IRQ_NONE;
- }
-
- if ((status & 0x8000) || (status & 0x2000)) {
- struct i596_cmd *ptr;
-
- if ((status & 0x8000))
- DEB(DEB_INTS, printk("%s: i596 interrupt completed command.\n", dev->name));
- if ((status & 0x2000))
- DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
-
- while (lp->cmd_head != NULL) {
- CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd));
- if (!(lp->cmd_head->status & STAT_C))
- break;
-
- ptr = lp->cmd_head;
-
- DEB(DEB_STATUS, printk("cmd_head->status = %04x, ->command = %04x\n",
- lp->cmd_head->status, lp->cmd_head->command));
- lp->cmd_head = ptr->v_next;
- lp->cmd_backlog--;
-
- switch ((ptr->command) & 0x7) {
- case CmdTx:
- {
- struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
- struct sk_buff *skb = tx_cmd->skb;
-
- if ((ptr->status) & STAT_OK) {
- DEB(DEB_TXADDR, print_eth(skb->data, "tx-done"));
- } else {
- lp->stats.tx_errors++;
- if ((ptr->status) & 0x0020)
- lp->stats.collisions++;
- if (!((ptr->status) & 0x0040))
- lp->stats.tx_heartbeat_errors++;
- if ((ptr->status) & 0x0400)
- lp->stats.tx_carrier_errors++;
- if ((ptr->status) & 0x0800)
- lp->stats.collisions++;
- if ((ptr->status) & 0x1000)
- lp->stats.tx_aborted_errors++;
- }
- dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
- dev_kfree_skb_irq(skb);
-
- tx_cmd->cmd.command = 0; /* Mark free */
- break;
- }
- case CmdTDR:
- {
- unsigned short status = ((struct tdr_cmd *)ptr)->status;
-
- if (status & 0x8000) {
- DEB(DEB_ANY, printk("%s: link ok.\n", dev->name));
- } else {
- if (status & 0x4000)
- printk("%s: Transceiver problem.\n", dev->name);
- if (status & 0x2000)
- printk("%s: Termination problem.\n", dev->name);
- if (status & 0x1000)
- printk("%s: Short circuit.\n", dev->name);
-
- DEB(DEB_TDR, printk("%s: Time %d.\n", dev->name, status & 0x07ff));
- }
- break;
- }
- case CmdConfigure:
- /* Zap command so set_multicast_list() knows it is free */
- ptr->command = 0;
- break;
- }
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd));
- lp->last_cmd = jiffies;
- }
-
- /* This mess is arranging that only the last of any outstanding
- * commands has the interrupt bit set. Should probably really
- * only add to the cmd queue when the CU is stopped.
- */
- ptr = lp->cmd_head;
- while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
- struct i596_cmd *prev = ptr;
-
- ptr->command &= 0x1fff;
- ptr = ptr->v_next;
- CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd));
- }
-
- if ((lp->cmd_head != NULL))
- ack_cmd |= CUC_START;
- lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status));
- CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb));
- }
- if ((status & 0x1000) || (status & 0x4000)) {
- if ((status & 0x4000))
- DEB(DEB_INTS, printk("%s: i596 interrupt received a frame.\n", dev->name));
- i596_rx(dev);
- /* Only RX_START if stopped - RGH 07-07-96 */
- if (status & 0x1000) {
- if (netif_running(dev)) {
- DEB(DEB_ERRORS, printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status));
- ack_cmd |= RX_START;
- lp->stats.rx_errors++;
- lp->stats.rx_fifo_errors++;
- rebuild_rx_bufs(dev);
- }
- }
- }
- wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
- lp->scb.command = ack_cmd;
- CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
- /* DANGER: I suspect that some kind of interrupt
- acknowledgement aside from acking the 82596 might be needed
- here... but it's running acceptably without */
-
- CA(dev);
-
- wait_cmd(dev, lp, 100, "i596 interrupt, exit timeout");
- DEB(DEB_INTS, printk("%s: exiting interrupt.\n", dev->name));
-
- spin_unlock (&lp->lock);
- return IRQ_HANDLED;
-}
-
-static int i596_close(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- netif_stop_queue(dev);
-
- DEB(DEB_INIT, printk("%s: Shutting down ethercard, status was %4.4x.\n",
- dev->name, lp->scb.status));
-
- spin_lock_irqsave(&lp->lock, flags);
-
- wait_cmd(dev, lp, 100, "close1 timed out");
- lp->scb.command = CUC_ABORT | RX_ABORT;
- CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
- CA(dev);
-
- wait_cmd(dev, lp, 100, "close2 timed out");
- spin_unlock_irqrestore(&lp->lock, flags);
- DEB(DEB_STRUCT,i596_display_data(dev));
- i596_cleanup_cmd(dev,lp);
-
- disable_irq(dev->irq);
-
- free_irq(dev->irq, dev);
- remove_rx_bufs(dev);
-
- return 0;
-}
-
-static struct net_device_stats *
- i596_get_stats(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
-
- return &lp->stats;
-}
-
-/*
- * Set or clear the multicast filter for this adaptor.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int config = 0, cnt;
-
- DEB(DEB_MULTI, printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
- dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF",
- dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
-
- if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) {
- lp->cf_cmd.i596_config[8] |= 0x01;
- config = 1;
- }
- if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) {
- lp->cf_cmd.i596_config[8] &= ~0x01;
- config = 1;
- }
- if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) {
- lp->cf_cmd.i596_config[11] &= ~0x20;
- config = 1;
- }
- if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) {
- lp->cf_cmd.i596_config[11] |= 0x20;
- config = 1;
- }
- if (config) {
- if (lp->cf_cmd.cmd.command)
- printk("%s: config change request already queued\n",
- dev->name);
- else {
- lp->cf_cmd.cmd.command = CmdConfigure;
- CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd));
- i596_add_cmd(dev, &lp->cf_cmd.cmd);
- }
- }
-
- cnt = dev->mc_count;
- if (cnt > MAX_MC_CNT)
- {
- cnt = MAX_MC_CNT;
- printk("%s: Only %d multicast addresses supported",
- dev->name, cnt);
- }
-
- if (dev->mc_count > 0) {
- struct dev_mc_list *dmi;
- unsigned char *cp;
- struct mc_cmd *cmd;
-
- cmd = &lp->mc_cmd;
- cmd->cmd.command = CmdMulticastList;
- cmd->mc_cnt = dev->mc_count * 6;
- cp = cmd->mc_addrs;
- for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
- memcpy(cp, dmi->dmi_addr, 6);
- if (i596_debug > 1)
- DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
- dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5]));
- }
- CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd));
- i596_add_cmd(dev, &cmd->cmd);
- }
-}
-
-static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "lasi_82596 debug mask");
-
-static int num_drivers;
-static struct net_device *netdevs[MAX_DRIVERS];
-
static int __devinit
lan_init_chip(struct parisc_device *dev)
{
struct net_device *netdevice;
+ struct i596_private *lp;
int retval;
-
- if (num_drivers >= MAX_DRIVERS) {
- /* max count of possible i82596 drivers reached */
- return -ENOMEM;
- }
-
- if (num_drivers == 0)
- printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
+ int i;
if (!dev->irq) {
printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
@@ -1528,28 +168,45 @@ lan_init_chip(struct parisc_device *dev)
printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
dev->irq);
- netdevice = alloc_etherdev(0);
+ netdevice = alloc_etherdev(sizeof(struct i596_private));
if (!netdevice)
return -ENOMEM;
+ SET_NETDEV_DEV(netdevice, &dev->dev);
+ parisc_set_drvdata (dev, netdevice);
netdevice->base_addr = dev->hpa.start;
netdevice->irq = dev->irq;
- retval = i82596_probe(netdevice, &dev->dev);
+ if (pdc_lan_station_id(netdevice->dev_addr, netdevice->base_addr)) {
+ for (i = 0; i < 6; i++) {
+ netdevice->dev_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
+ }
+ printk(KERN_INFO
+ "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
+ }
+
+ lp = netdev_priv(netdevice);
+ lp->options = dev->id.sversion == 0x72 ? OPT_SWAP_PORT : 0;
+
+ retval = i82596_probe(netdevice);
if (retval) {
free_netdev(netdevice);
return -ENODEV;
}
-
- if (dev->id.sversion == 0x72) {
- ((struct i596_private *)netdevice->priv)->options = OPT_SWAP_PORT;
- }
-
- netdevs[num_drivers++] = netdevice;
-
return retval;
}
+static int __devexit lan_remove_chip (struct parisc_device *pdev)
+{
+ struct net_device *dev = parisc_get_drvdata(pdev);
+ struct i596_private *lp = netdev_priv(dev);
+
+ unregister_netdev (dev);
+ DMA_FREE(&pdev->dev, sizeof(struct i596_private),
+ (void *)lp->dma, lp->dma_addr);
+ free_netdev (dev);
+ return 0;
+}
static struct parisc_device_id lan_tbl[] = {
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a },
@@ -1563,12 +220,12 @@ static struct parisc_driver lan_driver = {
.name = "lasi_82596",
.id_table = lan_tbl,
.probe = lan_init_chip,
+ .remove = __devexit_p(lan_remove_chip),
};
static int __devinit lasi_82596_init(void)
{
- if (debug >= 0)
- i596_debug = debug;
+ printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
return register_parisc_driver(&lan_driver);
}
@@ -1576,25 +233,6 @@ module_init(lasi_82596_init);
static void __exit lasi_82596_exit(void)
{
- int i;
-
- for (i=0; i<MAX_DRIVERS; i++) {
- struct i596_private *lp;
- struct net_device *netdevice;
-
- netdevice = netdevs[i];
- if (!netdevice)
- continue;
-
- unregister_netdev(netdevice);
-
- lp = netdevice->priv;
- dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
- (void *)netdevice->mem_start, lp->dma_addr);
- free_netdev(netdevice);
- }
- num_drivers = 0;
-
unregister_parisc_driver(&lan_driver);
}
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
new file mode 100644
index 000000000000..5884f5bd04a4
--- /dev/null
+++ b/drivers/net/lib82596.c
@@ -0,0 +1,1434 @@
+/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
+ munged into HPPA boxen .
+
+ This driver is based upon 82596.c, original credits are below...
+ but there were too many hoops which HP wants jumped through to
+ keep this code in there in a sane manner.
+
+ 3 primary sources of the mess --
+ 1) hppa needs *lots* of cacheline flushing to keep this kind of
+ MMIO running.
+
+ 2) The 82596 needs to see all of its pointers as their physical
+ address. Thus virt_to_bus/bus_to_virt are *everywhere*.
+
+ 3) The implementation HP is using seems to be significantly pickier
+ about when and how the command and RX units are started. some
+ command ordering was changed.
+
+ Examination of the mach driver leads one to believe that there
+ might be a saner way to pull this off... anyone who feels like a
+ full rewrite can be my guest.
+
+ Split 02/13/2000 Sam Creasey (sammy@oh.verio.com)
+
+ 02/01/2000 Initial modifications for parisc by Helge Deller (deller@gmx.de)
+ 03/02/2000 changes for better/correct(?) cache-flushing (deller)
+*/
+
+/* 82596.c: A generic 82596 ethernet driver for linux. */
+/*
+ Based on Apricot.c
+ Written 1994 by Mark Evans.
+ This driver is for the Apricot 82596 bus-master interface
+
+ Modularised 12/94 Mark Evans
+
+
+ Modified to support the 82596 ethernet chips on 680x0 VME boards.
+ by Richard Hirst <richard@sleepie.demon.co.uk>
+ Renamed to be 82596.c
+
+ 980825: Changed to receive directly in to sk_buffs which are
+ allocated at open() time. Eliminates copy on incoming frames
+ (small ones are still copied). Shared data now held in a
+ non-cached page, so we can run on 68060 in copyback mode.
+
+ TBD:
+ * look at deferring rx frames rather than discarding (as per tulip)
+ * handle tx ring full as per tulip
+ * performace test to tune rx_copybreak
+
+ Most of my modifications relate to the braindead big-endian
+ implementation by Intel. When the i596 is operating in
+ 'big-endian' mode, it thinks a 32 bit value of 0x12345678
+ should be stored as 0x56781234. This is a real pain, when
+ you have linked lists which are shared by the 680x0 and the
+ i596.
+
+ Driver skeleton
+ Written 1993 by Donald Becker.
+ Copyright 1993 United States Government as represented by the Director,
+ National Security Agency. This software may only be used and distributed
+ according to the terms of the GNU General Public License as modified by SRC,
+ incorporated herein by reference.
+
+ The author may be reached as becker@scyld.com, or C/O
+ Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+/* DEBUG flags
+ */
+
+#define DEB_INIT 0x0001
+#define DEB_PROBE 0x0002
+#define DEB_SERIOUS 0x0004
+#define DEB_ERRORS 0x0008
+#define DEB_MULTI 0x0010
+#define DEB_TDR 0x0020
+#define DEB_OPEN 0x0040
+#define DEB_RESET 0x0080
+#define DEB_ADDCMD 0x0100
+#define DEB_STATUS 0x0200
+#define DEB_STARTTX 0x0400
+#define DEB_RXADDR 0x0800
+#define DEB_TXADDR 0x1000
+#define DEB_RXFRAME 0x2000
+#define DEB_INTS 0x4000
+#define DEB_STRUCT 0x8000
+#define DEB_ANY 0xffff
+
+
+#define DEB(x, y) if (i596_debug & (x)) { y; }
+
+
+/*
+ * The MPU_PORT command allows direct access to the 82596. With PORT access
+ * the following commands are available (p5-18). The 32-bit port command
+ * must be word-swapped with the most significant word written first.
+ * This only applies to VME boards.
+ */
+#define PORT_RESET 0x00 /* reset 82596 */
+#define PORT_SELFTEST 0x01 /* selftest */
+#define PORT_ALTSCP 0x02 /* alternate SCB address */
+#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */
+
+static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+
+/* Copy frames shorter than rx_copybreak, otherwise pass on up in
+ * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha).
+ */
+static int rx_copybreak = 100;
+
+#define PKT_BUF_SZ 1536
+#define MAX_MC_CNT 64
+
+#define ISCP_BUSY 0x0001
+
+#define I596_NULL ((u32)0xffffffff)
+
+#define CMD_EOL 0x8000 /* The last command of the list, stop. */
+#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */
+#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */
+
+#define CMD_FLEX 0x0008 /* Enable flexible memory model */
+
+enum commands {
+ CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
+ CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
+};
+
+#define STAT_C 0x8000 /* Set to 0 after execution */
+#define STAT_B 0x4000 /* Command being executed */
+#define STAT_OK 0x2000 /* Command executed ok */
+#define STAT_A 0x1000 /* Command aborted */
+
+#define CUC_START 0x0100
+#define CUC_RESUME 0x0200
+#define CUC_SUSPEND 0x0300
+#define CUC_ABORT 0x0400
+#define RX_START 0x0010
+#define RX_RESUME 0x0020
+#define RX_SUSPEND 0x0030
+#define RX_ABORT 0x0040
+
+#define TX_TIMEOUT 5
+
+
+struct i596_reg {
+ unsigned short porthi;
+ unsigned short portlo;
+ u32 ca;
+};
+
+#define EOF 0x8000
+#define SIZE_MASK 0x3fff
+
+struct i596_tbd {
+ unsigned short size;
+ unsigned short pad;
+ dma_addr_t next;
+ dma_addr_t data;
+ u32 cache_pad[5]; /* Total 32 bytes... */
+};
+
+/* The command structure has two 'next' pointers; v_next is the address of
+ * the next command as seen by the CPU, b_next is the address of the next
+ * command as seen by the 82596. The b_next pointer, as used by the 82596
+ * always references the status field of the next command, rather than the
+ * v_next field, because the 82596 is unaware of v_next. It may seem more
+ * logical to put v_next at the end of the structure, but we cannot do that
+ * because the 82596 expects other fields to be there, depending on command
+ * type.
+ */
+
+struct i596_cmd {
+ struct i596_cmd *v_next; /* Address from CPUs viewpoint */
+ unsigned short status;
+ unsigned short command;
+ dma_addr_t b_next; /* Address from i596 viewpoint */
+};
+
+struct tx_cmd {
+ struct i596_cmd cmd;
+ dma_addr_t tbd;
+ unsigned short size;
+ unsigned short pad;
+ struct sk_buff *skb; /* So we can free it after tx */
+ dma_addr_t dma_addr;
+#ifdef __LP64__
+ u32 cache_pad[6]; /* Total 64 bytes... */
+#else
+ u32 cache_pad[1]; /* Total 32 bytes... */
+#endif
+};
+
+struct tdr_cmd {
+ struct i596_cmd cmd;
+ unsigned short status;
+ unsigned short pad;
+};
+
+struct mc_cmd {
+ struct i596_cmd cmd;
+ short mc_cnt;
+ char mc_addrs[MAX_MC_CNT*6];
+};
+
+struct sa_cmd {
+ struct i596_cmd cmd;
+ char eth_addr[8];
+};
+
+struct cf_cmd {
+ struct i596_cmd cmd;
+ char i596_config[16];
+};
+
+struct i596_rfd {
+ unsigned short stat;
+ unsigned short cmd;
+ dma_addr_t b_next; /* Address from i596 viewpoint */
+ dma_addr_t rbd;
+ unsigned short count;
+ unsigned short size;
+ struct i596_rfd *v_next; /* Address from CPUs viewpoint */
+ struct i596_rfd *v_prev;
+#ifndef __LP64__
+ u32 cache_pad[2]; /* Total 32 bytes... */
+#endif
+};
+
+struct i596_rbd {
+ /* hardware data */
+ unsigned short count;
+ unsigned short zero1;
+ dma_addr_t b_next;
+ dma_addr_t b_data; /* Address from i596 viewpoint */
+ unsigned short size;
+ unsigned short zero2;
+ /* driver data */
+ struct sk_buff *skb;
+ struct i596_rbd *v_next;
+ dma_addr_t b_addr; /* This rbd addr from i596 view */
+ unsigned char *v_data; /* Address from CPUs viewpoint */
+ /* Total 32 bytes... */
+#ifdef __LP64__
+ u32 cache_pad[4];
+#endif
+};
+
+/* These values as chosen so struct i596_dma fits in one page... */
+
+#define TX_RING_SIZE 32
+#define RX_RING_SIZE 16
+
+struct i596_scb {
+ unsigned short status;
+ unsigned short command;
+ dma_addr_t cmd;
+ dma_addr_t rfd;
+ u32 crc_err;
+ u32 align_err;
+ u32 resource_err;
+ u32 over_err;
+ u32 rcvdt_err;
+ u32 short_err;
+ unsigned short t_on;
+ unsigned short t_off;
+};
+
+struct i596_iscp {
+ u32 stat;
+ dma_addr_t scb;
+};
+
+struct i596_scp {
+ u32 sysbus;
+ u32 pad;
+ dma_addr_t iscp;
+};
+
+struct i596_dma {
+ struct i596_scp scp __attribute__((aligned(32)));
+ volatile struct i596_iscp iscp __attribute__((aligned(32)));
+ volatile struct i596_scb scb __attribute__((aligned(32)));
+ struct sa_cmd sa_cmd __attribute__((aligned(32)));
+ struct cf_cmd cf_cmd __attribute__((aligned(32)));
+ struct tdr_cmd tdr_cmd __attribute__((aligned(32)));
+ struct mc_cmd mc_cmd __attribute__((aligned(32)));
+ struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32)));
+ struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32)));
+ struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32)));
+ struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32)));
+};
+
+struct i596_private {
+ struct i596_dma *dma;
+ u32 stat;
+ int last_restart;
+ struct i596_rfd *rfd_head;
+ struct i596_rbd *rbd_head;
+ struct i596_cmd *cmd_tail;
+ struct i596_cmd *cmd_head;
+ int cmd_backlog;
+ u32 last_cmd;
+ struct net_device_stats stats;
+ int next_tx_cmd;
+ int options;
+ spinlock_t lock; /* serialize access to chip */
+ dma_addr_t dma_addr;
+ void __iomem *mpu_port;
+ void __iomem *ca;
+};
+
+static const char init_setup[] =
+{
+ 0x8E, /* length, prefetch on */
+ 0xC8, /* fifo to 8, monitor off */
+ 0x80, /* don't save bad frames */
+ 0x2E, /* No source address insertion, 8 byte preamble */
+ 0x00, /* priority and backoff defaults */
+ 0x60, /* interframe spacing */
+ 0x00, /* slot time LSB */
+ 0xf2, /* slot time and retries */
+ 0x00, /* promiscuous mode */
+ 0x00, /* collision detect */
+ 0x40, /* minimum frame length */
+ 0xff,
+ 0x00,
+ 0x7f /* *multi IA */ };
+
+static int i596_open(struct net_device *dev);
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t i596_interrupt(int irq, void *dev_id);
+static int i596_close(struct net_device *dev);
+static struct net_device_stats *i596_get_stats(struct net_device *dev);
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
+static void i596_tx_timeout (struct net_device *dev);
+static void print_eth(unsigned char *buf, char *str);
+static void set_multicast_list(struct net_device *dev);
+static inline void ca(struct net_device *dev);
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x);
+
+static int rx_ring_size = RX_RING_SIZE;
+static int ticks_limit = 100;
+static int max_cmd_backlog = TX_RING_SIZE-1;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev);
+#endif
+
+
+static inline int wait_istat(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+ DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ while (--delcnt && dma->iscp.stat) {
+ udelay(10);
+ DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ }
+ if (!delcnt) {
+ printk(KERN_ERR "%s: %s, iscp.stat %04x, didn't clear\n",
+ dev->name, str, SWAP16(dma->iscp.stat));
+ return -1;
+ } else
+ return 0;
+}
+
+
+static inline int wait_cmd(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+ DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+ while (--delcnt && dma->scb.command) {
+ udelay(10);
+ DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+ }
+ if (!delcnt) {
+ printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n",
+ dev->name, str,
+ SWAP16(dma->scb.status),
+ SWAP16(dma->scb.command));
+ return -1;
+ } else
+ return 0;
+}
+
+
+static void i596_display_data(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ struct i596_cmd *cmd;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+
+ printk(KERN_DEBUG "lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
+ &dma->scp, dma->scp.sysbus, SWAP32(dma->scp.iscp));
+ printk(KERN_DEBUG "iscp at %p, iscp.stat = %08x, .scb = %08x\n",
+ &dma->iscp, SWAP32(dma->iscp.stat), SWAP32(dma->iscp.scb));
+ printk(KERN_DEBUG "scb at %p, scb.status = %04x, .command = %04x,"
+ " .cmd = %08x, .rfd = %08x\n",
+ &dma->scb, SWAP16(dma->scb.status), SWAP16(dma->scb.command),
+ SWAP16(dma->scb.cmd), SWAP32(dma->scb.rfd));
+ printk(KERN_DEBUG " errors: crc %x, align %x, resource %x,"
+ " over %x, rcvdt %x, short %x\n",
+ SWAP32(dma->scb.crc_err), SWAP32(dma->scb.align_err),
+ SWAP32(dma->scb.resource_err), SWAP32(dma->scb.over_err),
+ SWAP32(dma->scb.rcvdt_err), SWAP32(dma->scb.short_err));
+ cmd = lp->cmd_head;
+ while (cmd != NULL) {
+ printk(KERN_DEBUG
+ "cmd at %p, .status = %04x, .command = %04x,"
+ " .b_next = %08x\n",
+ cmd, SWAP16(cmd->status), SWAP16(cmd->command),
+ SWAP32(cmd->b_next));
+ cmd = cmd->v_next;
+ }
+ rfd = lp->rfd_head;
+ printk(KERN_DEBUG "rfd_head = %p\n", rfd);
+ do {
+ printk(KERN_DEBUG
+ " %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
+ " count %04x\n",
+ rfd, SWAP16(rfd->stat), SWAP16(rfd->cmd),
+ SWAP32(rfd->b_next), SWAP32(rfd->rbd),
+ SWAP16(rfd->count));
+ rfd = rfd->v_next;
+ } while (rfd != lp->rfd_head);
+ rbd = lp->rbd_head;
+ printk(KERN_DEBUG "rbd_head = %p\n", rbd);
+ do {
+ printk(KERN_DEBUG
+ " %p .count %04x, b_next %08x, b_data %08x,"
+ " size %04x\n",
+ rbd, SWAP16(rbd->count), SWAP32(rbd->b_next),
+ SWAP32(rbd->b_data), SWAP16(rbd->size));
+ rbd = rbd->v_next;
+ } while (rbd != lp->rbd_head);
+ DMA_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+#define virt_to_dma(lp, v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)((lp)->dma)))
+
+static inline int init_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int i;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+
+ /* First build the Receive Buffer Descriptor List */
+
+ for (i = 0, rbd = dma->rbds; i < rx_ring_size; i++, rbd++) {
+ dma_addr_t dma_addr;
+ struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+
+ if (skb == NULL)
+ return -1;
+ skb_reserve(skb, 2);
+ dma_addr = dma_map_single(dev->dev.parent, skb->data,
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ rbd->v_next = rbd+1;
+ rbd->b_next = SWAP32(virt_to_dma(lp, rbd+1));
+ rbd->b_addr = SWAP32(virt_to_dma(lp, rbd));
+ rbd->skb = skb;
+ rbd->v_data = skb->data;
+ rbd->b_data = SWAP32(dma_addr);
+ rbd->size = SWAP16(PKT_BUF_SZ);
+ }
+ lp->rbd_head = dma->rbds;
+ rbd = dma->rbds + rx_ring_size - 1;
+ rbd->v_next = dma->rbds;
+ rbd->b_next = SWAP32(virt_to_dma(lp, dma->rbds));
+
+ /* Now build the Receive Frame Descriptor List */
+
+ for (i = 0, rfd = dma->rfds; i < rx_ring_size; i++, rfd++) {
+ rfd->rbd = I596_NULL;
+ rfd->v_next = rfd+1;
+ rfd->v_prev = rfd-1;
+ rfd->b_next = SWAP32(virt_to_dma(lp, rfd+1));
+ rfd->cmd = SWAP16(CMD_FLEX);
+ }
+ lp->rfd_head = dma->rfds;
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ rfd = dma->rfds;
+ rfd->rbd = SWAP32(virt_to_dma(lp, lp->rbd_head));
+ rfd->v_prev = dma->rfds + rx_ring_size - 1;
+ rfd = dma->rfds + rx_ring_size - 1;
+ rfd->v_next = dma->rfds;
+ rfd->b_next = SWAP32(virt_to_dma(lp, dma->rfds));
+ rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+ return 0;
+}
+
+static inline void remove_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_rbd *rbd;
+ int i;
+
+ for (i = 0, rbd = lp->dma->rbds; i < rx_ring_size; i++, rbd++) {
+ if (rbd->skb == NULL)
+ break;
+ dma_unmap_single(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ dev_kfree_skb(rbd->skb);
+ }
+}
+
+
+static void rebuild_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int i;
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+
+ for (i = 0; i < rx_ring_size; i++) {
+ dma->rfds[i].rbd = I596_NULL;
+ dma->rfds[i].cmd = SWAP16(CMD_FLEX);
+ }
+ dma->rfds[rx_ring_size-1].cmd = SWAP16(CMD_EOL|CMD_FLEX);
+ lp->rfd_head = dma->rfds;
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ lp->rbd_head = dma->rbds;
+ dma->rfds[0].rbd = SWAP32(virt_to_dma(lp, dma->rbds));
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+static int init_i596_mem(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ unsigned long flags;
+
+ mpu_port(dev, PORT_RESET, 0);
+ udelay(100); /* Wait 100us - seems to help */
+
+ /* change the scp address */
+
+ lp->last_cmd = jiffies;
+
+ dma->scp.sysbus = SYSBUS;
+ dma->scp.iscp = SWAP32(virt_to_dma(lp, &(dma->iscp)));
+ dma->iscp.scb = SWAP32(virt_to_dma(lp, &(dma->scb)));
+ dma->iscp.stat = SWAP32(ISCP_BUSY);
+ lp->cmd_backlog = 0;
+
+ lp->cmd_head = NULL;
+ dma->scb.cmd = I596_NULL;
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: starting i82596.\n", dev->name));
+
+ DMA_WBACK(dev, &(dma->scp), sizeof(struct i596_scp));
+ DMA_WBACK(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ mpu_port(dev, PORT_ALTSCP, virt_to_dma(lp, &dma->scp));
+ ca(dev);
+ if (wait_istat(dev, dma, 1000, "initialization timed out"))
+ goto failed;
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: i82596 initialization successful\n",
+ dev->name));
+
+ if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
+ printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
+ goto failed;
+ }
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+ rebuild_rx_bufs(dev);
+
+ dma->scb.command = 0;
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: queuing CmdConfigure\n", dev->name));
+ memcpy(dma->cf_cmd.i596_config, init_setup, 14);
+ dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+ DMA_WBACK(dev, &(dma->cf_cmd), sizeof(struct cf_cmd));
+ i596_add_cmd(dev, &dma->cf_cmd.cmd);
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdSASetup\n", dev->name));
+ memcpy(dma->sa_cmd.eth_addr, dev->dev_addr, 6);
+ dma->sa_cmd.cmd.command = SWAP16(CmdSASetup);
+ DMA_WBACK(dev, &(dma->sa_cmd), sizeof(struct sa_cmd));
+ i596_add_cmd(dev, &dma->sa_cmd.cmd);
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdTDR\n", dev->name));
+ dma->tdr_cmd.cmd.command = SWAP16(CmdTDR);
+ DMA_WBACK(dev, &(dma->tdr_cmd), sizeof(struct tdr_cmd));
+ i596_add_cmd(dev, &dma->tdr_cmd.cmd);
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ if (wait_cmd(dev, dma, 1000, "timed out waiting to issue RX_START")) {
+ spin_unlock_irqrestore (&lp->lock, flags);
+ goto failed_free_irq;
+ }
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: Issuing RX_START\n", dev->name));
+ dma->scb.command = SWAP16(RX_START);
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ ca(dev);
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+ if (wait_cmd(dev, dma, 1000, "RX_START not processed"))
+ goto failed_free_irq;
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: Receive unit started OK\n", dev->name));
+ return 0;
+
+failed_free_irq:
+ free_irq(dev->irq, dev);
+failed:
+ printk(KERN_ERR "%s: Failed to initialise 82596\n", dev->name);
+ mpu_port(dev, PORT_RESET, 0);
+ return -1;
+}
+
+
+static inline int i596_rx(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+ int frames = 0;
+
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG
+ "i596_rx(), rfd_head %p, rbd_head %p\n",
+ lp->rfd_head, lp->rbd_head));
+
+
+ rfd = lp->rfd_head; /* Ref next frame to check */
+
+ DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+ while (rfd->stat & SWAP16(STAT_C)) { /* Loop while complete frames */
+ if (rfd->rbd == I596_NULL)
+ rbd = NULL;
+ else if (rfd->rbd == lp->rbd_head->b_addr) {
+ rbd = lp->rbd_head;
+ DMA_INV(dev, rbd, sizeof(struct i596_rbd));
+ } else {
+ printk(KERN_ERR "%s: rbd chain broken!\n", dev->name);
+ /* XXX Now what? */
+ rbd = NULL;
+ }
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG
+ " rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
+ rfd, rfd->rbd, rfd->stat));
+
+ if (rbd != NULL && (rfd->stat & SWAP16(STAT_OK))) {
+ /* a good frame */
+ int pkt_len = SWAP16(rbd->count) & 0x3fff;
+ struct sk_buff *skb = rbd->skb;
+ int rx_in_place = 0;
+
+ DEB(DEB_RXADDR, print_eth(rbd->v_data, "received"));
+ frames++;
+
+ /* Check if the packet is long enough to just accept
+ * without copying to a properly sized skbuff.
+ */
+
+ if (pkt_len > rx_copybreak) {
+ struct sk_buff *newskb;
+ dma_addr_t dma_addr;
+
+ dma_unmap_single(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ /* Get fresh skbuff to replace filled one. */
+ newskb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+ if (newskb == NULL) {
+ skb = NULL; /* drop pkt */
+ goto memory_squeeze;
+ }
+ skb_reserve(newskb, 2);
+
+ /* Pass up the skb already on the Rx ring. */
+ skb_put(skb, pkt_len);
+ rx_in_place = 1;
+ rbd->skb = newskb;
+ dma_addr = dma_map_single(dev->dev.parent,
+ newskb->data,
+ PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
+ rbd->v_data = newskb->data;
+ rbd->b_data = SWAP32(dma_addr);
+ DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+ } else
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
+memory_squeeze:
+ if (skb == NULL) {
+ /* XXX tulip.c can defer packets here!! */
+ printk(KERN_ERR
+ "%s: i596_rx Memory squeeze, dropping packet.\n",
+ dev->name);
+ lp->stats.rx_dropped++;
+ } else {
+ if (!rx_in_place) {
+ /* 16 byte align the data fields */
+ dma_sync_single_for_cpu(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb, pkt_len), rbd->v_data, pkt_len);
+ dma_sync_single_for_device(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ }
+ skb->len = pkt_len;
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes += pkt_len;
+ }
+ } else {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: Error, rfd.stat = 0x%04x\n",
+ dev->name, rfd->stat));
+ lp->stats.rx_errors++;
+ if (rfd->stat & SWAP16(0x0100))
+ lp->stats.collisions++;
+ if (rfd->stat & SWAP16(0x8000))
+ lp->stats.rx_length_errors++;
+ if (rfd->stat & SWAP16(0x0001))
+ lp->stats.rx_over_errors++;
+ if (rfd->stat & SWAP16(0x0002))
+ lp->stats.rx_fifo_errors++;
+ if (rfd->stat & SWAP16(0x0004))
+ lp->stats.rx_frame_errors++;
+ if (rfd->stat & SWAP16(0x0008))
+ lp->stats.rx_crc_errors++;
+ if (rfd->stat & SWAP16(0x0010))
+ lp->stats.rx_length_errors++;
+ }
+
+ /* Clear the buffer descriptor count and EOF + F flags */
+
+ if (rbd != NULL && (rbd->count & SWAP16(0x4000))) {
+ rbd->count = 0;
+ lp->rbd_head = rbd->v_next;
+ DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+ }
+
+ /* Tidy the frame descriptor, marking it as end of list */
+
+ rfd->rbd = I596_NULL;
+ rfd->stat = 0;
+ rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+ rfd->count = 0;
+
+ /* Update record of next frame descriptor to process */
+
+ lp->dma->scb.rfd = rfd->b_next;
+ lp->rfd_head = rfd->v_next;
+ DMA_WBACK_INV(dev, rfd, sizeof(struct i596_rfd));
+
+ /* Remove end-of-list from old end descriptor */
+
+ rfd->v_prev->cmd = SWAP16(CMD_FLEX);
+ DMA_WBACK_INV(dev, rfd->v_prev, sizeof(struct i596_rfd));
+ rfd = lp->rfd_head;
+ DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+ }
+
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG "frames %d\n", frames));
+
+ return 0;
+}
+
+
+static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+{
+ struct i596_cmd *ptr;
+
+ while (lp->cmd_head != NULL) {
+ ptr = lp->cmd_head;
+ lp->cmd_head = ptr->v_next;
+ lp->cmd_backlog--;
+
+ switch (SWAP16(ptr->command) & 0x7) {
+ case CmdTx:
+ {
+ struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+ struct sk_buff *skb = tx_cmd->skb;
+ dma_unmap_single(dev->dev.parent,
+ tx_cmd->dma_addr,
+ skb->len, DMA_TO_DEVICE);
+
+ dev_kfree_skb(skb);
+
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ tx_cmd->cmd.command = 0; /* Mark as free */
+ break;
+ }
+ default:
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ }
+ DMA_WBACK_INV(dev, ptr, sizeof(struct i596_cmd));
+ }
+
+ wait_cmd(dev, lp->dma, 100, "i596_cleanup_cmd timed out");
+ lp->dma->scb.cmd = I596_NULL;
+ DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+}
+
+
+static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
+{
+ unsigned long flags;
+
+ DEB(DEB_RESET, printk(KERN_DEBUG "i596_reset\n"));
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ wait_cmd(dev, lp->dma, 100, "i596_reset timed out");
+
+ netif_stop_queue(dev);
+
+ /* FIXME: this command might cause an lpmc */
+ lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+ DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+ ca(dev);
+
+ /* wait for shutdown */
+ wait_cmd(dev, lp->dma, 1000, "i596_reset 2 timed out");
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ i596_cleanup_cmd(dev, lp);
+ i596_rx(dev);
+
+ netif_start_queue(dev);
+ init_i596_mem(dev);
+}
+
+
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ unsigned long flags;
+
+ DEB(DEB_ADDCMD, printk(KERN_DEBUG "i596_add_cmd cmd_head %p\n",
+ lp->cmd_head));
+
+ cmd->status = 0;
+ cmd->command |= SWAP16(CMD_EOL | CMD_INTR);
+ cmd->v_next = NULL;
+ cmd->b_next = I596_NULL;
+ DMA_WBACK(dev, cmd, sizeof(struct i596_cmd));
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ if (lp->cmd_head != NULL) {
+ lp->cmd_tail->v_next = cmd;
+ lp->cmd_tail->b_next = SWAP32(virt_to_dma(lp, &cmd->status));
+ DMA_WBACK(dev, lp->cmd_tail, sizeof(struct i596_cmd));
+ } else {
+ lp->cmd_head = cmd;
+ wait_cmd(dev, dma, 100, "i596_add_cmd timed out");
+ dma->scb.cmd = SWAP32(virt_to_dma(lp, &cmd->status));
+ dma->scb.command = SWAP16(CUC_START);
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+ ca(dev);
+ }
+ lp->cmd_tail = cmd;
+ lp->cmd_backlog++;
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ if (lp->cmd_backlog > max_cmd_backlog) {
+ unsigned long tickssofar = jiffies - lp->last_cmd;
+
+ if (tickssofar < ticks_limit)
+ return;
+
+ printk(KERN_ERR
+ "%s: command unit timed out, status resetting.\n",
+ dev->name);
+#if 1
+ i596_reset(dev, lp);
+#endif
+ }
+}
+
+static int i596_open(struct net_device *dev)
+{
+ DEB(DEB_OPEN, printk(KERN_DEBUG
+ "%s: i596_open() irq %d.\n", dev->name, dev->irq));
+
+ if (init_rx_bufs(dev)) {
+ printk(KERN_ERR "%s: Failed to init rx bufs\n", dev->name);
+ return -EAGAIN;
+ }
+ if (init_i596_mem(dev)) {
+ printk(KERN_ERR "%s: Failed to init memory\n", dev->name);
+ goto out_remove_rx_bufs;
+ }
+ netif_start_queue(dev);
+
+ return 0;
+
+out_remove_rx_bufs:
+ remove_rx_bufs(dev);
+ return -EAGAIN;
+}
+
+static void i596_tx_timeout (struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ /* Transmitter timeout, serious problems. */
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: transmit timed out, status resetting.\n",
+ dev->name));
+
+ lp->stats.tx_errors++;
+
+ /* Try to restart the adaptor */
+ if (lp->last_restart == lp->stats.tx_packets) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG "Resetting board.\n"));
+ /* Shutdown and restart */
+ i596_reset (dev, lp);
+ } else {
+ /* Issue a channel attention signal */
+ DEB(DEB_ERRORS, printk(KERN_DEBUG "Kicking board.\n"));
+ lp->dma->scb.command = SWAP16(CUC_START | RX_START);
+ DMA_WBACK_INV(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+ ca (dev);
+ lp->last_restart = lp->stats.tx_packets;
+ }
+
+ dev->trans_start = jiffies;
+ netif_wake_queue (dev);
+}
+
+
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct tx_cmd *tx_cmd;
+ struct i596_tbd *tbd;
+ short length = skb->len;
+ dev->trans_start = jiffies;
+
+ DEB(DEB_STARTTX, printk(KERN_DEBUG
+ "%s: i596_start_xmit(%x,%p) called\n",
+ dev->name, skb->len, skb->data));
+
+ if (length < ETH_ZLEN) {
+ if (skb_padto(skb, ETH_ZLEN))
+ return 0;
+ length = ETH_ZLEN;
+ }
+
+ netif_stop_queue(dev);
+
+ tx_cmd = lp->dma->tx_cmds + lp->next_tx_cmd;
+ tbd = lp->dma->tbds + lp->next_tx_cmd;
+
+ if (tx_cmd->cmd.command) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: xmit ring full, dropping packet.\n",
+ dev->name));
+ lp->stats.tx_dropped++;
+
+ dev_kfree_skb(skb);
+ } else {
+ if (++lp->next_tx_cmd == TX_RING_SIZE)
+ lp->next_tx_cmd = 0;
+ tx_cmd->tbd = SWAP32(virt_to_dma(lp, tbd));
+ tbd->next = I596_NULL;
+
+ tx_cmd->cmd.command = SWAP16(CMD_FLEX | CmdTx);
+ tx_cmd->skb = skb;
+
+ tx_cmd->pad = 0;
+ tx_cmd->size = 0;
+ tbd->pad = 0;
+ tbd->size = SWAP16(EOF | length);
+
+ tx_cmd->dma_addr = dma_map_single(dev->dev.parent, skb->data,
+ skb->len, DMA_TO_DEVICE);
+ tbd->data = SWAP32(tx_cmd->dma_addr);
+
+ DEB(DEB_TXADDR, print_eth(skb->data, "tx-queued"));
+ DMA_WBACK_INV(dev, tx_cmd, sizeof(struct tx_cmd));
+ DMA_WBACK_INV(dev, tbd, sizeof(struct i596_tbd));
+ i596_add_cmd(dev, &tx_cmd->cmd);
+
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += length;
+ }
+
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static void print_eth(unsigned char *add, char *str)
+{
+ int i;
+
+ printk(KERN_DEBUG "i596 0x%p, ", add);
+ for (i = 0; i < 6; i++)
+ printk(" %02X", add[i + 6]);
+ printk(" -->");
+ for (i = 0; i < 6; i++)
+ printk(" %02X", add[i]);
+ printk(" %02X%02X, %s\n", add[12], add[13], str);
+}
+
+static int __devinit i82596_probe(struct net_device *dev)
+{
+ int i;
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma;
+
+ /* This lot is ensure things have been cache line aligned. */
+ BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
+ BUILD_BUG_ON(sizeof(struct i596_rbd) & 31);
+ BUILD_BUG_ON(sizeof(struct tx_cmd) & 31);
+ BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
+#ifndef __LP64__
+ BUILD_BUG_ON(sizeof(struct i596_dma) > 4096);
+#endif
+
+ if (!dev->base_addr || !dev->irq)
+ return -ENODEV;
+
+ dma = (struct i596_dma *) DMA_ALLOC(dev->dev.parent,
+ sizeof(struct i596_dma), &lp->dma_addr, GFP_KERNEL);
+ if (!dma) {
+ printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
+ return -ENOMEM;
+ }
+
+ /* The 82596-specific entries in the device structure. */
+ dev->open = i596_open;
+ dev->stop = i596_close;
+ dev->hard_start_xmit = i596_start_xmit;
+ dev->get_stats = i596_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->tx_timeout = i596_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = i596_poll_controller;
+#endif
+
+ memset(dma, 0, sizeof(struct i596_dma));
+ lp->dma = dma;
+
+ dma->scb.command = 0;
+ dma->scb.cmd = I596_NULL;
+ dma->scb.rfd = I596_NULL;
+ spin_lock_init(&lp->lock);
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+
+ i = register_netdev(dev);
+ if (i) {
+ DMA_FREE(dev->dev.parent, sizeof(struct i596_dma),
+ (void *)dma, lp->dma_addr);
+ return i;
+ };
+
+ DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,",
+ dev->name, dev->base_addr));
+ for (i = 0; i < 6; i++)
+ DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
+ DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
+ DEB(DEB_INIT, printk(KERN_INFO
+ "%s: dma at 0x%p (%d bytes), lp->scb at 0x%p\n",
+ dev->name, dma, (int)sizeof(struct i596_dma),
+ &dma->scb));
+
+ return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ i596_interrupt(dev->irq, dev);
+ enable_irq(dev->irq);
+}
+#endif
+
+static irqreturn_t i596_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct i596_private *lp;
+ struct i596_dma *dma;
+ unsigned short status, ack_cmd = 0;
+
+ if (dev == NULL) {
+ printk(KERN_WARNING "%s: irq %d for unknown device.\n",
+ __FUNCTION__, irq);
+ return IRQ_NONE;
+ }
+
+ lp = netdev_priv(dev);
+ dma = lp->dma;
+
+ spin_lock (&lp->lock);
+
+ wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+ status = SWAP16(dma->scb.status);
+
+ DEB(DEB_INTS, printk(KERN_DEBUG
+ "%s: i596 interrupt, IRQ %d, status %4.4x.\n",
+ dev->name, irq, status));
+
+ ack_cmd = status & 0xf000;
+
+ if (!ack_cmd) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: interrupt with no events\n",
+ dev->name));
+ spin_unlock (&lp->lock);
+ return IRQ_NONE;
+ }
+
+ if ((status & 0x8000) || (status & 0x2000)) {
+ struct i596_cmd *ptr;
+
+ if ((status & 0x8000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt completed command.\n",
+ dev->name));
+ if ((status & 0x2000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt command unit inactive %x.\n",
+ dev->name, status & 0x0700));
+
+ while (lp->cmd_head != NULL) {
+ DMA_INV(dev, lp->cmd_head, sizeof(struct i596_cmd));
+ if (!(lp->cmd_head->status & SWAP16(STAT_C)))
+ break;
+
+ ptr = lp->cmd_head;
+
+ DEB(DEB_STATUS,
+ printk(KERN_DEBUG
+ "cmd_head->status = %04x, ->command = %04x\n",
+ SWAP16(lp->cmd_head->status),
+ SWAP16(lp->cmd_head->command)));
+ lp->cmd_head = ptr->v_next;
+ lp->cmd_backlog--;
+
+ switch (SWAP16(ptr->command) & 0x7) {
+ case CmdTx:
+ {
+ struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+ struct sk_buff *skb = tx_cmd->skb;
+
+ if (ptr->status & SWAP16(STAT_OK)) {
+ DEB(DEB_TXADDR,
+ print_eth(skb->data, "tx-done"));
+ } else {
+ lp->stats.tx_errors++;
+ if (ptr->status & SWAP16(0x0020))
+ lp->stats.collisions++;
+ if (!(ptr->status & SWAP16(0x0040)))
+ lp->stats.tx_heartbeat_errors++;
+ if (ptr->status & SWAP16(0x0400))
+ lp->stats.tx_carrier_errors++;
+ if (ptr->status & SWAP16(0x0800))
+ lp->stats.collisions++;
+ if (ptr->status & SWAP16(0x1000))
+ lp->stats.tx_aborted_errors++;
+ }
+ dma_unmap_single(dev->dev.parent,
+ tx_cmd->dma_addr,
+ skb->len, DMA_TO_DEVICE);
+ dev_kfree_skb_irq(skb);
+
+ tx_cmd->cmd.command = 0; /* Mark free */
+ break;
+ }
+ case CmdTDR:
+ {
+ unsigned short status = SWAP16(((struct tdr_cmd *)ptr)->status);
+
+ if (status & 0x8000) {
+ DEB(DEB_ANY,
+ printk(KERN_DEBUG "%s: link ok.\n",
+ dev->name));
+ } else {
+ if (status & 0x4000)
+ printk(KERN_ERR
+ "%s: Transceiver problem.\n",
+ dev->name);
+ if (status & 0x2000)
+ printk(KERN_ERR
+ "%s: Termination problem.\n",
+ dev->name);
+ if (status & 0x1000)
+ printk(KERN_ERR
+ "%s: Short circuit.\n",
+ dev->name);
+
+ DEB(DEB_TDR,
+ printk(KERN_DEBUG "%s: Time %d.\n",
+ dev->name, status & 0x07ff));
+ }
+ break;
+ }
+ case CmdConfigure:
+ /*
+ * Zap command so set_multicast_list() know
+ * it is free
+ */
+ ptr->command = 0;
+ break;
+ }
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ DMA_WBACK(dev, ptr, sizeof(struct i596_cmd));
+ lp->last_cmd = jiffies;
+ }
+
+ /* This mess is arranging that only the last of any outstanding
+ * commands has the interrupt bit set. Should probably really
+ * only add to the cmd queue when the CU is stopped.
+ */
+ ptr = lp->cmd_head;
+ while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
+ struct i596_cmd *prev = ptr;
+
+ ptr->command &= SWAP16(0x1fff);
+ ptr = ptr->v_next;
+ DMA_WBACK_INV(dev, prev, sizeof(struct i596_cmd));
+ }
+
+ if (lp->cmd_head != NULL)
+ ack_cmd |= CUC_START;
+ dma->scb.cmd = SWAP32(virt_to_dma(lp, &lp->cmd_head->status));
+ DMA_WBACK_INV(dev, &dma->scb, sizeof(struct i596_scb));
+ }
+ if ((status & 0x1000) || (status & 0x4000)) {
+ if ((status & 0x4000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt received a frame.\n",
+ dev->name));
+ i596_rx(dev);
+ /* Only RX_START if stopped - RGH 07-07-96 */
+ if (status & 0x1000) {
+ if (netif_running(dev)) {
+ DEB(DEB_ERRORS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt receive unit inactive, status 0x%x\n",
+ dev->name, status));
+ ack_cmd |= RX_START;
+ lp->stats.rx_errors++;
+ lp->stats.rx_fifo_errors++;
+ rebuild_rx_bufs(dev);
+ }
+ }
+ }
+ wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+ dma->scb.command = SWAP16(ack_cmd);
+ DMA_WBACK(dev, &dma->scb, sizeof(struct i596_scb));
+
+ /* DANGER: I suspect that some kind of interrupt
+ acknowledgement aside from acking the 82596 might be needed
+ here... but it's running acceptably without */
+
+ ca(dev);
+
+ wait_cmd(dev, dma, 100, "i596 interrupt, exit timeout");
+ DEB(DEB_INTS, printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name));
+
+ spin_unlock (&lp->lock);
+ return IRQ_HANDLED;
+}
+
+static int i596_close(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+
+ DEB(DEB_INIT,
+ printk(KERN_DEBUG
+ "%s: Shutting down ethercard, status was %4.4x.\n",
+ dev->name, SWAP16(lp->dma->scb.status)));
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ wait_cmd(dev, lp->dma, 100, "close1 timed out");
+ lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+ DMA_WBACK(dev, &lp->dma->scb, sizeof(struct i596_scb));
+
+ ca(dev);
+
+ wait_cmd(dev, lp->dma, 100, "close2 timed out");
+ spin_unlock_irqrestore(&lp->lock, flags);
+ DEB(DEB_STRUCT, i596_display_data(dev));
+ i596_cleanup_cmd(dev, lp);
+
+ free_irq(dev->irq, dev);
+ remove_rx_bufs(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *i596_get_stats(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ return &lp->stats;
+}
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int config = 0, cnt;
+
+ DEB(DEB_MULTI,
+ printk(KERN_DEBUG
+ "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
+ dev->name, dev->mc_count,
+ dev->flags & IFF_PROMISC ? "ON" : "OFF",
+ dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
+
+ if ((dev->flags & IFF_PROMISC) &&
+ !(dma->cf_cmd.i596_config[8] & 0x01)) {
+ dma->cf_cmd.i596_config[8] |= 0x01;
+ config = 1;
+ }
+ if (!(dev->flags & IFF_PROMISC) &&
+ (dma->cf_cmd.i596_config[8] & 0x01)) {
+ dma->cf_cmd.i596_config[8] &= ~0x01;
+ config = 1;
+ }
+ if ((dev->flags & IFF_ALLMULTI) &&
+ (dma->cf_cmd.i596_config[11] & 0x20)) {
+ dma->cf_cmd.i596_config[11] &= ~0x20;
+ config = 1;
+ }
+ if (!(dev->flags & IFF_ALLMULTI) &&
+ !(dma->cf_cmd.i596_config[11] & 0x20)) {
+ dma->cf_cmd.i596_config[11] |= 0x20;
+ config = 1;
+ }
+ if (config) {
+ if (dma->cf_cmd.cmd.command)
+ printk(KERN_INFO
+ "%s: config change request already queued\n",
+ dev->name);
+ else {
+ dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+ DMA_WBACK_INV(dev, &dma->cf_cmd, sizeof(struct cf_cmd));
+ i596_add_cmd(dev, &dma->cf_cmd.cmd);
+ }
+ }
+
+ cnt = dev->mc_count;
+ if (cnt > MAX_MC_CNT) {
+ cnt = MAX_MC_CNT;
+ printk(KERN_NOTICE "%s: Only %d multicast addresses supported",
+ dev->name, cnt);
+ }
+
+ if (dev->mc_count > 0) {
+ struct dev_mc_list *dmi;
+ unsigned char *cp;
+ struct mc_cmd *cmd;
+
+ cmd = &dma->mc_cmd;
+ cmd->cmd.command = SWAP16(CmdMulticastList);
+ cmd->mc_cnt = SWAP16(dev->mc_count * 6);
+ cp = cmd->mc_addrs;
+ for (dmi = dev->mc_list;
+ cnt && dmi != NULL;
+ dmi = dmi->next, cnt--, cp += 6) {
+ memcpy(cp, dmi->dmi_addr, 6);
+ if (i596_debug > 1)
+ DEB(DEB_MULTI,
+ printk(KERN_DEBUG
+ "%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]));
+ }
+ DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd));
+ i596_add_cmd(dev, &cmd->cmd);
+ }
+}
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 7f8b7d55b6e1..492cfaaaa75c 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -113,8 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
struct mlx4_cmd_mailbox *mailbox;
int ret = 0;
- if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
- new_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
+ if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE ||
!op[cur_state][new_state])
return -EINVAL;
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 75102d30730f..05e0577a0e10 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -724,7 +724,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
__u32 mac_cfg0;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ if (port > NETXEN_NIU_MAX_GBE_PORTS)
return -EINVAL;
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
@@ -757,7 +757,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
__u32 reg;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ if (port > NETXEN_NIU_MAX_GBE_PORTS)
return -EINVAL;
/* save previous contents */
@@ -894,7 +894,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
__u32 reg;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
+ if (port > NETXEN_NIU_MAX_XG_PORTS)
return -EINVAL;
if (netxen_nic_hw_read_wx(adapter,
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 8d38425e46c3..0b3066a6fe40 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -755,7 +755,7 @@ static int pasemi_mac_open(struct net_device *dev)
flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
- PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
+ PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 808fae1577e0..50dff1b81d34 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -521,6 +521,7 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
static int axnet_open(struct net_device *dev)
{
+ int ret;
axnet_dev_t *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
@@ -529,9 +530,11 @@ static int axnet_open(struct net_device *dev)
if (!pcmcia_dev_present(link))
return -ENODEV;
- link->open++;
+ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+ if (ret)
+ return ret;
- request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+ link->open++;
info->link_status = 0x00;
init_timer(&info->watchdog);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 3f93d4933235..85d5f2ca4bb5 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -109,7 +109,7 @@ static const struct ethtool_ops netdev_ethtool_ops;
card type
*/
typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
- XXX10304
+ XXX10304, NEC, KME
} cardtype_t;
/*
@@ -374,6 +374,18 @@ static int fmvj18x_config(struct pcmcia_device *link)
link->io.NumPorts2 = 8;
}
break;
+ case MANFID_NEC:
+ cardtype = NEC; /* MultiFunction Card */
+ link->conf.ConfigBase = 0x800;
+ link->conf.ConfigIndex = 0x47;
+ link->io.NumPorts2 = 8;
+ break;
+ case MANFID_KME:
+ cardtype = KME; /* MultiFunction Card */
+ link->conf.ConfigBase = 0x800;
+ link->conf.ConfigIndex = 0x47;
+ link->io.NumPorts2 = 8;
+ break;
case MANFID_CONTEC:
cardtype = CONTEC;
break;
@@ -450,6 +462,8 @@ static int fmvj18x_config(struct pcmcia_device *link)
case TDK:
case LA501:
case CONTEC:
+ case NEC:
+ case KME:
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
@@ -469,6 +483,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
card_name = "TDK LAK-CD021";
} else if( cardtype == LA501 ) {
card_name = "LA501";
+ } else if( cardtype == NEC ) {
+ card_name = "PK-UG-J001";
+ } else if( cardtype == KME ) {
+ card_name = "Panasonic";
} else {
card_name = "C-NET(PC)C";
}
@@ -678,8 +696,11 @@ static struct pcmcia_device_id fmvj18x_ids[] = {
PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
+ PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
+ PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index d88e9b2e93cf..f2613c29b008 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -960,6 +960,7 @@ static void mii_phy_probe(struct net_device *dev)
static int pcnet_open(struct net_device *dev)
{
+ int ret;
pcnet_dev_t *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
@@ -968,10 +969,12 @@ static int pcnet_open(struct net_device *dev)
if (!pcmcia_dev_present(link))
return -ENODEV;
- link->open++;
-
set_misc_reg(dev);
- request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+ if (ret)
+ return ret;
+
+ link->open++;
info->phy_id = info->eth_phy;
info->link_status = 0x00;
@@ -1552,6 +1555,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+ PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 09b6f259eb92..dd09011c7ee5 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -55,6 +55,11 @@ config BROADCOM_PHY
---help---
Currently supports the BCM5411, BCM5421 and BCM5461 PHYs.
+config ICPLUS_PHY
+ tristate "Drivers for ICPlus PHYs"
+ ---help---
+ Currently supports the IP175C PHY.
+
config FIXED_PHY
tristate "Drivers for PHY emulation on fixed speed/link"
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index bcd1efbd2a18..8885650647ff 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -11,4 +11,5 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
+obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_FIXED_PHY) += fixed.o
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
new file mode 100644
index 000000000000..af3f1f2a9f87
--- /dev/null
+++ b/drivers/net/phy/icplus.c
@@ -0,0 +1,134 @@
+/*
+ * Driver for ICPlus PHYs
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_AUTHOR("Michael Barkowski");
+MODULE_LICENSE("GPL");
+
+static int ip175c_config_init(struct phy_device *phydev)
+{
+ int err, i;
+ static int full_reset_performed = 0;
+
+ if (full_reset_performed == 0) {
+
+ /* master reset */
+ err = phydev->bus->write(phydev->bus, 30, 0, 0x175c);
+ if (err < 0)
+ return err;
+
+ /* ensure no bus delays overlap reset period */
+ err = phydev->bus->read(phydev->bus, 30, 0);
+
+ /* data sheet specifies reset period is 2 msec */
+ mdelay(2);
+
+ /* enable IP175C mode */
+ err = phydev->bus->write(phydev->bus, 29, 31, 0x175c);
+ if (err < 0)
+ return err;
+
+ /* Set MII0 speed and duplex (in PHY mode) */
+ err = phydev->bus->write(phydev->bus, 29, 22, 0x420);
+ if (err < 0)
+ return err;
+
+ /* reset switch ports */
+ for (i = 0; i < 5; i++) {
+ err = phydev->bus->write(phydev->bus, i,
+ MII_BMCR, BMCR_RESET);
+ if (err < 0)
+ return err;
+ }
+
+ for (i = 0; i < 5; i++)
+ err = phydev->bus->read(phydev->bus, i, MII_BMCR);
+
+ mdelay(2);
+
+ full_reset_performed = 1;
+ }
+
+ if (phydev->addr != 4) {
+ phydev->state = PHY_RUNNING;
+ phydev->speed = SPEED_100;
+ phydev->duplex = DUPLEX_FULL;
+ phydev->link = 1;
+ netif_carrier_on(phydev->attached_dev);
+ }
+
+ return 0;
+}
+
+static int ip175c_read_status(struct phy_device *phydev)
+{
+ if (phydev->addr == 4) /* WAN port */
+ genphy_read_status(phydev);
+ else
+ /* Don't need to read status for switch ports */
+ phydev->irq = PHY_IGNORE_INTERRUPT;
+
+ return 0;
+}
+
+static int ip175c_config_aneg(struct phy_device *phydev)
+{
+ if (phydev->addr == 4) /* WAN port */
+ genphy_config_aneg(phydev);
+
+ return 0;
+}
+
+static struct phy_driver ip175c_driver = {
+ .phy_id = 0x02430d80,
+ .name = "ICPlus IP175C",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .config_init = &ip175c_config_init,
+ .config_aneg = &ip175c_config_aneg,
+ .read_status = &ip175c_read_status,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init ip175c_init(void)
+{
+ return phy_driver_register(&ip175c_driver);
+}
+
+static void __exit ip175c_exit(void)
+{
+ phy_driver_unregister(&ip175c_driver);
+}
+
+module_init(ip175c_init);
+module_exit(ip175c_exit);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index b87f8d2a888b..fbe1104e9a07 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -60,6 +60,7 @@
#define MII_M1111_PHY_EXT_SR 0x1b
#define MII_M1111_HWCFG_MODE_MASK 0xf
#define MII_M1111_HWCFG_MODE_RGMII 0xb
+#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
MODULE_DESCRIPTION("Marvell PHY driver");
MODULE_AUTHOR("Andy Fleming");
@@ -169,6 +170,21 @@ static int m88e1111_config_init(struct phy_device *phydev)
return err;
}
+ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+ int temp;
+
+ temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
+ if (temp < 0)
+ return temp;
+
+ temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+ temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
+
+ err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+ if (err < 0)
+ return err;
+ }
+
err = phy_write(phydev, MII_BMCR, BMCR_RESET);
if (err < 0)
return err;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 585be044ebbb..8be8be451ada 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2433,37 +2433,22 @@ static int ql_get_seg_count(struct ql3_adapter *qdev,
return -1;
}
-static void ql_hw_csum_setup(struct sk_buff *skb,
+static void ql_hw_csum_setup(const struct sk_buff *skb,
struct ob_mac_iocb_req *mac_iocb_ptr)
{
- struct ethhdr *eth;
- struct iphdr *ip = NULL;
- u8 offset = ETH_HLEN;
+ const struct iphdr *ip = ip_hdr(skb);
- eth = (struct ethhdr *)(skb->data);
+ mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb);
+ mac_iocb_ptr->ip_hdr_len = ip->ihl;
- if (eth->h_proto == __constant_htons(ETH_P_IP)) {
- ip = (struct iphdr *)&skb->data[ETH_HLEN];
- } else if (eth->h_proto == htons(ETH_P_8021Q) &&
- ((struct vlan_ethhdr *)skb->data)->
- h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) {
- ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN];
- offset = VLAN_ETH_HLEN;
- }
-
- if (ip) {
- if (ip->protocol == IPPROTO_TCP) {
- mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
+ if (ip->protocol == IPPROTO_TCP) {
+ mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
OB_3032MAC_IOCB_REQ_IC;
- mac_iocb_ptr->ip_hdr_off = offset;
- mac_iocb_ptr->ip_hdr_len = ip->ihl;
- } else if (ip->protocol == IPPROTO_UDP) {
- mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
+ } else {
+ mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
OB_3032MAC_IOCB_REQ_IC;
- mac_iocb_ptr->ip_hdr_off = offset;
- mac_iocb_ptr->ip_hdr_len = ip->ihl;
- }
}
+
}
/*
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 5ec7752caa48..982a9010c7a9 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1,53 +1,11 @@
/*
-=========================================================================
- r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x.
- --------------------------------------------------------------------
-
- History:
- Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>.
- May 20 2002 - Add link status force-mode and TBI mode support.
- 2004 - Massive updates. See kernel SCM system for details.
-=========================================================================
- 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
- Command: 'insmod r8169 media = SET_MEDIA'
- Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
-
- SET_MEDIA can be:
- _10_Half = 0x01
- _10_Full = 0x02
- _100_Half = 0x04
- _100_Full = 0x08
- _1000_Full = 0x10
-
- 2. Support TBI mode.
-=========================================================================
-VERSION 1.1 <2002/10/4>
-
- The bit4:0 of MII register 4 is called "selector field", and have to be
- 00001b to indicate support of IEEE std 802.3 during NWay process of
- exchanging Link Code Word (FLP).
-
-VERSION 1.2 <2002/11/30>
-
- - Large style cleanup
- - Use ether_crc in stock kernel (linux/crc32.h)
- - Copy mc_filter setup code from 8139cp
- (includes an optimization, and avoids set_bit use)
-
-VERSION 1.6LK <2004/04/14>
-
- - Merge of Realtek's version 1.6
- - Conversion to DMA API
- - Suspend/resume
- - Endianness
- - Misc Rx/Tx bugs
-
-VERSION 2.2LK <2005/01/25>
-
- - RX csum, TX csum/SG, TSO
- - VLAN
- - baby (< 7200) Jumbo frames support
- - Merge of Realtek's version 2.2 (new phy)
+ * r8169.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
*/
#include <linux/module.h>
@@ -108,11 +66,6 @@ VERSION 2.2LK <2005/01/25>
#define rtl8169_rx_quota(count, quota) count
#endif
-/* media options */
-#define MAX_UNITS 8
-static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-static int num_media = 0;
-
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static const int max_interrupt_work = 20;
@@ -126,7 +79,7 @@ static const int multicast_filter_limit = 32;
#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
-#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
+#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */
#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
@@ -151,16 +104,17 @@ static const int multicast_filter_limit = 32;
#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
enum mac_version {
- RTL_GIGA_MAC_VER_01 = 0x00,
- RTL_GIGA_MAC_VER_02 = 0x01,
- RTL_GIGA_MAC_VER_03 = 0x02,
- RTL_GIGA_MAC_VER_04 = 0x03,
- RTL_GIGA_MAC_VER_05 = 0x04,
- RTL_GIGA_MAC_VER_11 = 0x0b,
- RTL_GIGA_MAC_VER_12 = 0x0c,
- RTL_GIGA_MAC_VER_13 = 0x0d,
- RTL_GIGA_MAC_VER_14 = 0x0e,
- RTL_GIGA_MAC_VER_15 = 0x0f
+ RTL_GIGA_MAC_VER_01 = 0x01, // 8169
+ RTL_GIGA_MAC_VER_02 = 0x02, // 8169S
+ RTL_GIGA_MAC_VER_03 = 0x03, // 8110S
+ RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB
+ RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
+ RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
+ RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
+ RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf
+ RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec
+ RTL_GIGA_MAC_VER_14 = 0x0e, // 8101
+ RTL_GIGA_MAC_VER_15 = 0x0f // 8101
};
enum phy_version {
@@ -180,11 +134,12 @@ static const struct {
u8 mac_version;
u32 RxConfigMask; /* Clears the bits supported by this chip */
} rtl_chip_info[] = {
- _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880),
- _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_02, 0xff7e1880),
- _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880),
- _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880),
- _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880),
+ _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169
+ _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S
+ _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S
+ _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
+ _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
+ _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
_R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
@@ -199,20 +154,15 @@ enum cfg_version {
RTL_CFG_2
};
-static const struct {
- unsigned int region;
- unsigned int align;
-} rtl_cfg_info[] = {
- [RTL_CFG_0] = { 1, NET_IP_ALIGN },
- [RTL_CFG_1] = { 2, NET_IP_ALIGN },
- [RTL_CFG_2] = { 2, 8 }
-};
+static void rtl_hw_start_8169(struct net_device *);
+static void rtl_hw_start_8168(struct net_device *);
+static void rtl_hw_start_8101(struct net_device *);
static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_2 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(0x1259, 0xc107), 0, 0, RTL_CFG_0 },
@@ -230,62 +180,63 @@ static struct {
u32 msg_enable;
} debug = { -1 };
-enum RTL8169_registers {
- MAC0 = 0, /* Ethernet hardware address. */
- MAR0 = 8, /* Multicast filter. */
- CounterAddrLow = 0x10,
- CounterAddrHigh = 0x14,
- TxDescStartAddrLow = 0x20,
- TxDescStartAddrHigh = 0x24,
- TxHDescStartAddrLow = 0x28,
- TxHDescStartAddrHigh = 0x2c,
- FLASH = 0x30,
- ERSR = 0x36,
- ChipCmd = 0x37,
- TxPoll = 0x38,
- IntrMask = 0x3C,
- IntrStatus = 0x3E,
- TxConfig = 0x40,
- RxConfig = 0x44,
- RxMissed = 0x4C,
- Cfg9346 = 0x50,
- Config0 = 0x51,
- Config1 = 0x52,
- Config2 = 0x53,
- Config3 = 0x54,
- Config4 = 0x55,
- Config5 = 0x56,
- MultiIntr = 0x5C,
- PHYAR = 0x60,
- TBICSR = 0x64,
- TBI_ANAR = 0x68,
- TBI_LPAR = 0x6A,
- PHYstatus = 0x6C,
- RxMaxSize = 0xDA,
- CPlusCmd = 0xE0,
- IntrMitigate = 0xE2,
- RxDescAddrLow = 0xE4,
- RxDescAddrHigh = 0xE8,
- EarlyTxThres = 0xEC,
- FuncEvent = 0xF0,
- FuncEventMask = 0xF4,
- FuncPresetState = 0xF8,
- FuncForceEvent = 0xFC,
+enum rtl_registers {
+ MAC0 = 0, /* Ethernet hardware address. */
+ MAC4 = 4,
+ MAR0 = 8, /* Multicast filter. */
+ CounterAddrLow = 0x10,
+ CounterAddrHigh = 0x14,
+ TxDescStartAddrLow = 0x20,
+ TxDescStartAddrHigh = 0x24,
+ TxHDescStartAddrLow = 0x28,
+ TxHDescStartAddrHigh = 0x2c,
+ FLASH = 0x30,
+ ERSR = 0x36,
+ ChipCmd = 0x37,
+ TxPoll = 0x38,
+ IntrMask = 0x3c,
+ IntrStatus = 0x3e,
+ TxConfig = 0x40,
+ RxConfig = 0x44,
+ RxMissed = 0x4c,
+ Cfg9346 = 0x50,
+ Config0 = 0x51,
+ Config1 = 0x52,
+ Config2 = 0x53,
+ Config3 = 0x54,
+ Config4 = 0x55,
+ Config5 = 0x56,
+ MultiIntr = 0x5c,
+ PHYAR = 0x60,
+ TBICSR = 0x64,
+ TBI_ANAR = 0x68,
+ TBI_LPAR = 0x6a,
+ PHYstatus = 0x6c,
+ RxMaxSize = 0xda,
+ CPlusCmd = 0xe0,
+ IntrMitigate = 0xe2,
+ RxDescAddrLow = 0xe4,
+ RxDescAddrHigh = 0xe8,
+ EarlyTxThres = 0xec,
+ FuncEvent = 0xf0,
+ FuncEventMask = 0xf4,
+ FuncPresetState = 0xf8,
+ FuncForceEvent = 0xfc,
};
-enum RTL8169_register_content {
+enum rtl_register_content {
/* InterruptStatusBits */
- SYSErr = 0x8000,
- PCSTimeout = 0x4000,
- SWInt = 0x0100,
- TxDescUnavail = 0x80,
- RxFIFOOver = 0x40,
- LinkChg = 0x20,
- RxOverflow = 0x10,
- TxErr = 0x08,
- TxOK = 0x04,
- RxErr = 0x02,
- RxOK = 0x01,
+ SYSErr = 0x8000,
+ PCSTimeout = 0x4000,
+ SWInt = 0x0100,
+ TxDescUnavail = 0x0080,
+ RxFIFOOver = 0x0040,
+ LinkChg = 0x0020,
+ RxOverflow = 0x0010,
+ TxErr = 0x0008,
+ TxOK = 0x0004,
+ RxErr = 0x0002,
+ RxOK = 0x0001,
/* RxStatusDesc */
RxFOVF = (1 << 23),
@@ -295,26 +246,31 @@ enum RTL8169_register_content {
RxCRC = (1 << 19),
/* ChipCmdBits */
- CmdReset = 0x10,
- CmdRxEnb = 0x08,
- CmdTxEnb = 0x04,
- RxBufEmpty = 0x01,
+ CmdReset = 0x10,
+ CmdRxEnb = 0x08,
+ CmdTxEnb = 0x04,
+ RxBufEmpty = 0x01,
+
+ /* TXPoll register p.5 */
+ HPQ = 0x80, /* Poll cmd on the high prio queue */
+ NPQ = 0x40, /* Poll cmd on the low prio queue */
+ FSWInt = 0x01, /* Forced software interrupt */
/* Cfg9346Bits */
- Cfg9346_Lock = 0x00,
- Cfg9346_Unlock = 0xC0,
+ Cfg9346_Lock = 0x00,
+ Cfg9346_Unlock = 0xc0,
/* rx_mode_bits */
- AcceptErr = 0x20,
- AcceptRunt = 0x10,
- AcceptBroadcast = 0x08,
- AcceptMulticast = 0x04,
- AcceptMyPhys = 0x02,
- AcceptAllPhys = 0x01,
+ AcceptErr = 0x20,
+ AcceptRunt = 0x10,
+ AcceptBroadcast = 0x08,
+ AcceptMulticast = 0x04,
+ AcceptMyPhys = 0x02,
+ AcceptAllPhys = 0x01,
/* RxConfigBits */
- RxCfgFIFOShift = 13,
- RxCfgDMAShift = 8,
+ RxCfgFIFOShift = 13,
+ RxCfgDMAShift = 8,
/* TxConfigBits */
TxInterFrameGapShift = 24,
@@ -323,6 +279,10 @@ enum RTL8169_register_content {
/* Config1 register p.24 */
PMEnable = (1 << 0), /* Power Management Enable */
+ /* Config2 register p. 25 */
+ PCI_Clock_66MHz = 0x01,
+ PCI_Clock_33MHz = 0x00,
+
/* Config3 register p.25 */
MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
@@ -343,36 +303,34 @@ enum RTL8169_register_content {
TBINwComplete = 0x01000000,
/* CPlusCmd p.31 */
+ PktCntrDisable = (1 << 7), // 8168
RxVlan = (1 << 6),
RxChkSum = (1 << 5),
PCIDAC = (1 << 4),
PCIMulRW = (1 << 3),
+ INTT_0 = 0x0000, // 8168
+ INTT_1 = 0x0001, // 8168
+ INTT_2 = 0x0002, // 8168
+ INTT_3 = 0x0003, // 8168
/* rtl8169_PHYstatus */
- TBI_Enable = 0x80,
- TxFlowCtrl = 0x40,
- RxFlowCtrl = 0x20,
- _1000bpsF = 0x10,
- _100bps = 0x08,
- _10bps = 0x04,
- LinkStatus = 0x02,
- FullDup = 0x01,
-
- /* _MediaType */
- _10_Half = 0x01,
- _10_Full = 0x02,
- _100_Half = 0x04,
- _100_Full = 0x08,
- _1000_Full = 0x10,
+ TBI_Enable = 0x80,
+ TxFlowCtrl = 0x40,
+ RxFlowCtrl = 0x20,
+ _1000bpsF = 0x10,
+ _100bps = 0x08,
+ _10bps = 0x04,
+ LinkStatus = 0x02,
+ FullDup = 0x01,
/* _TBICSRBit */
- TBILinkOK = 0x02000000,
+ TBILinkOK = 0x02000000,
/* DumpCounterCommand */
- CounterDump = 0x8,
+ CounterDump = 0x8,
};
-enum _DescStatusBit {
+enum desc_status_bit {
DescOwn = (1 << 31), /* Descriptor is owned by NIC */
RingEnd = (1 << 30), /* End of descriptor ring */
FirstFrag = (1 << 29), /* First segment of a packet */
@@ -405,15 +363,15 @@ enum _DescStatusBit {
#define RsvdMask 0x3fffc000
struct TxDesc {
- u32 opts1;
- u32 opts2;
- u64 addr;
+ __le32 opts1;
+ __le32 opts2;
+ __le64 addr;
};
struct RxDesc {
- u32 opts1;
- u32 opts2;
- u64 addr;
+ __le32 opts1;
+ __le32 opts2;
+ __le64 addr;
};
struct ring_info {
@@ -446,6 +404,8 @@ struct rtl8169_private {
unsigned rx_buf_sz;
struct timer_list timer;
u16 cp_cmd;
+ u16 intr_event;
+ u16 napi_event;
u16 intr_mask;
int phy_auto_nego_reg;
int phy_1000_ctrl_reg;
@@ -455,6 +415,7 @@ struct rtl8169_private {
int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
void (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(void __iomem *);
+ void (*hw_start)(struct net_device *);
unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *);
struct delayed_work task;
@@ -463,8 +424,6 @@ struct rtl8169_private {
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param_array(media, int, &num_media, 0);
-MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
module_param(rx_copybreak, int, 0);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
module_param(use_dac, int, 0);
@@ -478,9 +437,9 @@ static int rtl8169_open(struct net_device *dev);
static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance);
static int rtl8169_init_ring(struct net_device *dev);
-static void rtl8169_hw_start(struct net_device *dev);
+static void rtl_hw_start(struct net_device *dev);
static int rtl8169_close(struct net_device *dev);
-static void rtl8169_set_rx_mode(struct net_device *dev);
+static void rtl_set_rx_mode(struct net_device *dev);
static void rtl8169_tx_timeout(struct net_device *dev);
static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
@@ -493,35 +452,37 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp);
static int rtl8169_poll(struct net_device *dev, int *budget);
#endif
-static const u16 rtl8169_intr_mask =
- SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
-static const u16 rtl8169_napi_event =
- RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
static const unsigned int rtl8169_rx_config =
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
-static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
+static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
{
int i;
- RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
+ RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value);
for (i = 20; i > 0; i--) {
- /* Check if the RTL8169 has completed writing to the specified MII register */
+ /*
+ * Check if the RTL8169 has completed writing to the specified
+ * MII register.
+ */
if (!(RTL_R32(PHYAR) & 0x80000000))
break;
udelay(25);
}
}
-static int mdio_read(void __iomem *ioaddr, int RegAddr)
+static int mdio_read(void __iomem *ioaddr, int reg_addr)
{
int i, value = -1;
- RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
+ RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16);
for (i = 20; i > 0; i--) {
- /* Check if the RTL8169 has completed retrieving data from the specified MII register */
+ /*
+ * Check if the RTL8169 has completed retrieving data from
+ * the specified MII register.
+ */
if (RTL_R32(PHYAR) & 0x80000000) {
value = (int) (RTL_R32(PHYAR) & 0xFFFF);
break;
@@ -579,7 +540,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
}
static void rtl8169_check_link_status(struct net_device *dev,
- struct rtl8169_private *tp, void __iomem *ioaddr)
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned long flags;
@@ -596,38 +558,6 @@ static void rtl8169_check_link_status(struct net_device *dev,
spin_unlock_irqrestore(&tp->lock, flags);
}
-static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
-{
- struct {
- u16 speed;
- u8 duplex;
- u8 autoneg;
- u8 media;
- } link_settings[] = {
- { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half },
- { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full },
- { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half },
- { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full },
- { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full },
- /* Make TBI happy */
- { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff }
- }, *p;
- unsigned char option;
-
- option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
-
- if ((option != 0xff) && !idx && netif_msg_drv(&debug))
- printk(KERN_WARNING PFX "media option is deprecated.\n");
-
- for (p = link_settings; p->media != 0xff; p++) {
- if (p->media == option)
- break;
- }
- *autoneg = p->autoneg;
- *speed = p->speed;
- *duplex = p->duplex;
-}
-
static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -667,7 +597,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- int i;
+ unsigned int i;
static struct {
u32 opt;
u16 reg;
@@ -893,8 +823,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
int ret;
if (tp->vlgrp && (opts2 & RxVlanTag)) {
- rtl8169_rx_hwaccel_skb(skb, tp->vlgrp,
- swab16(opts2 & 0xffff));
+ rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff));
ret = 0;
} else
ret = -1;
@@ -1115,7 +1044,6 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
}
}
-
static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
@@ -1141,8 +1069,8 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_perm_addr = ethtool_op_get_perm_addr,
};
-static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
- int bitval)
+static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg,
+ int bitnum, int bitval)
{
int val;
@@ -1152,8 +1080,20 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum
mdio_write(ioaddr, reg, val & 0xffff);
}
-static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_mac_version(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
+ /*
+ * The driver currently handles the 8168Bf and the 8168Be identically
+ * but they can be identified more specifically through the test below
+ * if needed:
+ *
+ * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
+ *
+ * Same thing for the 8101Eb and the 8101Ec:
+ *
+ * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
+ */
const struct {
u32 mask;
int mac_version;
@@ -1163,6 +1103,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
{ 0x34000000, RTL_GIGA_MAC_VER_13 },
{ 0x30800000, RTL_GIGA_MAC_VER_14 },
{ 0x30000000, RTL_GIGA_MAC_VER_11 },
+ { 0x98000000, RTL_GIGA_MAC_VER_06 },
{ 0x18000000, RTL_GIGA_MAC_VER_05 },
{ 0x10000000, RTL_GIGA_MAC_VER_04 },
{ 0x04000000, RTL_GIGA_MAC_VER_03 },
@@ -1171,7 +1112,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
}, *p = mac_info;
u32 reg;
- reg = RTL_R32(TxConfig) & 0x7c800000;
+ reg = RTL_R32(TxConfig) & 0xfc800000;
while ((reg & p->mask) != p->mask)
p++;
tp->mac_version = p->mac_version;
@@ -1182,7 +1123,8 @@ static void rtl8169_print_mac_version(struct rtl8169_private *tp)
dprintk("mac_version = 0x%02x\n", tp->mac_version);
}
-static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_phy_version(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
const struct {
u16 mask;
@@ -1259,7 +1201,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
0xbf00 } //w 0 15 0 bf00
}
}, *p = phy_magic;
- int i;
+ unsigned int i;
rtl8169_print_mac_version(tp);
rtl8169_print_phy_version(tp);
@@ -1393,7 +1335,7 @@ static void rtl8169_phy_reset(struct net_device *dev,
struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- int i;
+ unsigned int i;
tp->phy_reset_enable(ioaddr);
for (i = 0; i < 100; i++) {
@@ -1408,21 +1350,16 @@ static void rtl8169_phy_reset(struct net_device *dev,
static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- static int board_idx = -1;
- u8 autoneg, duplex;
- u16 speed;
-
- board_idx++;
rtl8169_hw_phy_config(dev);
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
- if (tp->mac_version < RTL_GIGA_MAC_VER_03) {
- dprintk("Set PCI Latency=0x40\n");
- pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
- }
+ pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
+
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+ pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
@@ -1431,16 +1368,52 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
}
- rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
-
rtl8169_phy_reset(dev, tp);
- rtl8169_set_speed(dev, autoneg, speed, duplex);
+ /*
+ * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
+ * only 8101. Don't panic.
+ */
+ rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
}
+static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ u32 high;
+ u32 low;
+
+ low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
+ high = addr[4] | (addr[5] << 8);
+
+ spin_lock_irq(&tp->lock);
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+ RTL_W32(MAC0, low);
+ RTL_W32(MAC4, high);
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ spin_unlock_irq(&tp->lock);
+}
+
+static int rtl_set_mac_address(struct net_device *dev, void *p)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ rtl_rar_set(tp, dev->dev_addr);
+
+ return 0;
+}
+
static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -1467,15 +1440,49 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EOPNOTSUPP;
}
+static const struct rtl_cfg_info {
+ void (*hw_start)(struct net_device *);
+ unsigned int region;
+ unsigned int align;
+ u16 intr_event;
+ u16 napi_event;
+} rtl_cfg_infos [] = {
+ [RTL_CFG_0] = {
+ .hw_start = rtl_hw_start_8169,
+ .region = 1,
+ .align = 0,
+ .intr_event = SYSErr | LinkChg | RxOverflow |
+ RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ },
+ [RTL_CFG_1] = {
+ .hw_start = rtl_hw_start_8168,
+ .region = 2,
+ .align = 8,
+ .intr_event = SYSErr | LinkChg | RxOverflow |
+ TxErr | TxOK | RxOK | RxErr,
+ .napi_event = TxErr | TxOK | RxOK | RxOverflow
+ },
+ [RTL_CFG_2] = {
+ .hw_start = rtl_hw_start_8101,
+ .region = 2,
+ .align = 8,
+ .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
+ RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ }
+};
+
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- const unsigned int region = rtl_cfg_info[ent->driver_data].region;
+ const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
+ const unsigned int region = cfg->region;
struct rtl8169_private *tp;
struct net_device *dev;
void __iomem *ioaddr;
- unsigned int pm_cap;
- int i, rc;
+ unsigned int i;
+ int rc;
if (netif_msg_drv(&debug)) {
printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
@@ -1508,20 +1515,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc < 0)
goto err_out_disable_2;
- /* save power state before pci_enable_device overwrites it */
- pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
- if (pm_cap) {
- u16 pwr_command, acpi_idle_state;
-
- pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
- acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
- } else {
- if (netif_msg_probe(tp)) {
- dev_err(&pdev->dev,
- "PowerManagement capability not found.\n");
- }
- }
-
/* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
if (netif_msg_probe(tp)) {
@@ -1585,7 +1578,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */
- for (i = 100; i > 0; i--) {
+ for (i = 0; i < 100; i++) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break;
msleep_interruptible(1);
@@ -1647,11 +1640,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
dev->stop = rtl8169_close;
dev->tx_timeout = rtl8169_tx_timeout;
- dev->set_multicast_list = rtl8169_set_rx_mode;
+ dev->set_multicast_list = rtl_set_rx_mode;
dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr;
dev->change_mtu = rtl8169_change_mtu;
+ dev->set_mac_address = rtl_set_mac_address;
#ifdef CONFIG_R8169_NAPI
dev->poll = rtl8169_poll;
@@ -1670,7 +1664,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->intr_mask = 0xffff;
tp->pci_dev = pdev;
tp->mmio_addr = ioaddr;
- tp->align = rtl_cfg_info[ent->driver_data].align;
+ tp->align = cfg->align;
+ tp->hw_start = cfg->hw_start;
+ tp->intr_event = cfg->intr_event;
+ tp->napi_event = cfg->napi_event;
init_timer(&tp->timer);
tp->timer.data = (unsigned long) dev;
@@ -1685,15 +1682,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
if (netif_msg_probe(tp)) {
+ u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff;
+
printk(KERN_INFO "%s: %s at 0x%lx, "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
- "IRQ %d\n",
+ "XID %08x IRQ %d\n",
dev->name,
rtl_chip_info[tp->chipset].name,
dev->base_addr,
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
- dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+ dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq);
}
rtl8169_init_phy(dev, tp);
@@ -1714,15 +1713,11 @@ err_out_free_dev_1:
goto out;
}
-static void __devexit
-rtl8169_remove_one(struct pci_dev *pdev)
+static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
- assert(dev != NULL);
- assert(tp != NULL);
-
flush_scheduled_work();
unregister_netdev(dev);
@@ -1774,7 +1769,7 @@ static int rtl8169_open(struct net_device *dev)
if (retval < 0)
goto err_release_ring_2;
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
rtl8169_request_timer(dev);
@@ -1805,7 +1800,7 @@ static void rtl8169_hw_reset(void __iomem *ioaddr)
RTL_R8(ChipCmd);
}
-static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
+static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
u32 cfg = rtl8169_rx_config;
@@ -1818,45 +1813,90 @@ static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
(InterFrameGap << TxInterFrameGapShift));
}
-static void rtl8169_hw_start(struct net_device *dev)
+static void rtl_hw_start(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- struct pci_dev *pdev = tp->pci_dev;
- u16 cmd;
- u32 i;
+ unsigned int i;
/* Soft reset the chip. */
RTL_W8(ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */
- for (i = 100; i > 0; i--) {
+ for (i = 0; i < 100; i++) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break;
msleep_interruptible(1);
}
- if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
- RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
- }
+ tp->hw_start(dev);
- if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
- pci_write_config_word(pdev, 0x68, 0x00);
- pci_write_config_word(pdev, 0x69, 0x08);
- }
+ netif_start_queue(dev);
+}
- /* Undocumented stuff. */
- if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
- /* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
- if ((RTL_R8(Config2) & 0x07) & 0x01)
- RTL_W32(0x7c, 0x0007ffff);
- RTL_W32(0x7c, 0x0007ff00);
+static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
+{
+ /*
+ * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
+ * register to be written before TxDescAddrLow to work.
+ * Switching from MMIO to I/O access fixes the issue as well.
+ */
+ RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
+ RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK);
+ RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
+ RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK);
+}
+
+static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
+{
+ u16 cmd;
+
+ cmd = RTL_R16(CPlusCmd);
+ RTL_W16(CPlusCmd, cmd);
+ return cmd;
+}
+
+static void rtl_set_rx_max_size(void __iomem *ioaddr)
+{
+ /* Low hurts. Let's disable the filtering. */
+ RTL_W16(RxMaxSize, 16383);
+}
+
+static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
+{
+ struct {
+ u32 mac_version;
+ u32 clk;
+ u32 val;
+ } cfg2_info [] = {
+ { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
+ { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
+ { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
+ { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
+ }, *p = cfg2_info;
+ unsigned int i;
+ u32 clk;
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- cmd = cmd & 0xef;
- pci_write_config_word(pdev, PCI_COMMAND, cmd);
+ clk = RTL_R8(Config2) & PCI_Clock_66MHz;
+ for (i = 0; i < ARRAY_SIZE(cfg2_info); i++) {
+ if ((p->mac_version == mac_version) && (p->clk == clk)) {
+ RTL_W32(0x7c, p->val);
+ break;
+ }
+ }
+}
+
+static void rtl_hw_start_8169(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
}
RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -1868,19 +1908,11 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W8(EarlyTxThres, EarlyTxThld);
- /* Low hurts. Let's disable the filtering. */
- RTL_W16(RxMaxSize, 16383);
-
- if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_04))
- rtl8169_set_rx_tx_config_registers(tp);
+ rtl_set_rx_max_size(ioaddr);
- cmd = RTL_R16(CPlusCmd);
- RTL_W16(CPlusCmd, cmd);
+ rtl_set_rx_tx_config_registers(tp);
- tp->cp_cmd |= cmd | PCIMulRW;
+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(tp->mac_version == RTL_GIGA_MAC_VER_03)) {
@@ -1891,29 +1923,15 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W16(CPlusCmd, tp->cp_cmd);
+ rtl8169_set_magic_reg(ioaddr, tp->mac_version);
+
/*
* Undocumented corner. Supposedly:
* (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
*/
RTL_W16(IntrMitigate, 0x0000);
- /*
- * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
- * register to be written before TxDescAddrLow to work.
- * Switching from MMIO to I/O access fixes the issue as well.
- */
- RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
- RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
- RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
- RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
-
- if ((tp->mac_version != RTL_GIGA_MAC_VER_01) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_02) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_03) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_04)) {
- RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
- rtl8169_set_rx_tx_config_registers(tp);
- }
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
RTL_W8(Cfg9346, Cfg9346_Lock);
@@ -1922,15 +1940,107 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W32(RxMissed, 0);
- rtl8169_set_rx_mode(dev);
+ rtl_set_rx_mode(dev);
/* no early-rx interrupts */
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
/* Enable all known interrupts by setting the interrupt mask. */
- RTL_W16(IntrMask, rtl8169_intr_mask);
+ RTL_W16(IntrMask, tp->intr_event);
- netif_start_queue(dev);
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+}
+
+static void rtl_hw_start_8168(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+ u8 ctl;
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ rtl_set_rx_tx_config_registers(tp);
+
+ tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ /* Tx performance tweak. */
+ pci_read_config_byte(pdev, 0x69, &ctl);
+ ctl = (ctl & ~0x70) | 0x50;
+ pci_write_config_byte(pdev, 0x69, ctl);
+
+ RTL_W16(IntrMitigate, 0x5151);
+
+ /* Work around for RxFIFO overflow. */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
+ tp->intr_event |= RxFIFOOver | PCSTimeout;
+ tp->intr_event &= ~RxOverflow;
+ }
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ RTL_R8(IntrMask);
+
+ RTL_W32(RxMissed, 0);
+
+ rtl_set_rx_mode(dev);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
+
+ RTL_W16(IntrMask, tp->intr_event);
+}
+
+static void rtl_hw_start_8101(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
+ pci_write_config_word(pdev, 0x68, 0x00);
+ pci_write_config_word(pdev, 0x69, 0x08);
+ }
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ RTL_W16(IntrMitigate, 0x0000);
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+ rtl_set_rx_tx_config_registers(tp);
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ RTL_R8(IntrMask);
+
+ RTL_W32(RxMissed, 0);
+
+ rtl_set_rx_mode(dev);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
+
+ RTL_W16(IntrMask, tp->intr_event);
}
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
@@ -1956,7 +2066,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
netif_poll_enable(dev);
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
rtl8169_request_timer(dev);
@@ -1997,38 +2107,38 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
rtl8169_mark_to_asic(desc, rx_buf_sz);
}
-static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
- struct RxDesc *desc, int rx_buf_sz,
- unsigned int align)
+static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
+ struct net_device *dev,
+ struct RxDesc *desc, int rx_buf_sz,
+ unsigned int align)
{
struct sk_buff *skb;
dma_addr_t mapping;
- int ret = 0;
+ unsigned int pad;
- skb = dev_alloc_skb(rx_buf_sz + align);
+ pad = align ? align : NET_IP_ALIGN;
+
+ skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
if (!skb)
goto err_out;
- skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
- *sk_buff = skb;
+ skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
PCI_DMA_FROMDEVICE);
rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
-
out:
- return ret;
+ return skb;
err_out:
- ret = -ENOMEM;
rtl8169_make_unusable_by_asic(desc);
goto out;
}
static void rtl8169_rx_clear(struct rtl8169_private *tp)
{
- int i;
+ unsigned int i;
for (i = 0; i < NUM_RX_DESC; i++) {
if (tp->Rx_skbuff[i]) {
@@ -2043,16 +2153,22 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
{
u32 cur;
- for (cur = start; end - cur > 0; cur++) {
- int ret, i = cur % NUM_RX_DESC;
+ for (cur = start; end - cur != 0; cur++) {
+ struct sk_buff *skb;
+ unsigned int i = cur % NUM_RX_DESC;
+
+ WARN_ON((s32)(end - cur) < 0);
if (tp->Rx_skbuff[i])
continue;
- ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
- tp->RxDescArray + i, tp->rx_buf_sz, tp->align);
- if (ret < 0)
+ skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
+ tp->RxDescArray + i,
+ tp->rx_buf_sz, tp->align);
+ if (!skb)
break;
+
+ tp->Rx_skbuff[i] = skb;
}
return cur - start;
}
@@ -2164,14 +2280,9 @@ static void rtl8169_reinit_task(struct work_struct *work)
ret = rtl8169_open(dev);
if (unlikely(ret < 0)) {
- if (net_ratelimit()) {
- struct rtl8169_private *tp = netdev_priv(dev);
-
- if (netif_msg_drv(tp)) {
- printk(PFX KERN_ERR
- "%s: reinit failure (status = %d)."
- " Rescheduling.\n", dev->name, ret);
- }
+ if (net_ratelimit() && netif_msg_drv(tp)) {
+ printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+ " Rescheduling.\n", dev->name, ret);
}
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
@@ -2198,16 +2309,12 @@ static void rtl8169_reset_task(struct work_struct *work)
if (tp->dirty_rx == tp->cur_rx) {
rtl8169_init_ring_indexes(tp);
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
netif_wake_queue(dev);
} else {
- if (net_ratelimit()) {
- struct rtl8169_private *tp = netdev_priv(dev);
-
- if (netif_msg_intr(tp)) {
- printk(PFX KERN_EMERG
- "%s: Rx buffers shortage\n", dev->name);
- }
+ if (net_ratelimit() && netif_msg_intr(tp)) {
+ printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+ dev->name);
}
rtl8169_schedule_work(dev, rtl8169_reset_task);
}
@@ -2344,7 +2451,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
smp_wmb();
- RTL_W8(TxPoll, 0x40); /* set polling bit */
+ RTL_W8(TxPoll, NPQ); /* set polling bit */
if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
netif_stop_queue(dev);
@@ -2414,16 +2521,12 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
-static void
-rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
- void __iomem *ioaddr)
+static void rtl8169_tx_interrupt(struct net_device *dev,
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned int dirty_tx, tx_left;
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
dirty_tx = tp->dirty_tx;
smp_rmb();
tx_left = tp->cur_tx - dirty_tx;
@@ -2480,38 +2583,37 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
skb->ip_summed = CHECKSUM_NONE;
}
-static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
- struct RxDesc *desc, int rx_buf_sz,
- unsigned int align)
+static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
+ struct rtl8169_private *tp, int pkt_size,
+ dma_addr_t addr)
{
- int ret = -1;
+ struct sk_buff *skb;
+ bool done = false;
- if (pkt_size < rx_copybreak) {
- struct sk_buff *skb;
+ if (pkt_size >= rx_copybreak)
+ goto out;
- skb = dev_alloc_skb(pkt_size + align);
- if (skb) {
- skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
- eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
- *sk_buff = skb;
- rtl8169_mark_to_asic(desc, rx_buf_sz);
- ret = 0;
- }
- }
- return ret;
+ skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN);
+ if (!skb)
+ goto out;
+
+ pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
+ PCI_DMA_FROMDEVICE);
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
+ *sk_buff = skb;
+ done = true;
+out:
+ return done;
}
-static int
-rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
- void __iomem *ioaddr)
+static int rtl8169_rx_interrupt(struct net_device *dev,
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned int cur_rx, rx_left;
unsigned int delta, count;
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
cur_rx = tp->cur_rx;
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
@@ -2544,9 +2646,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
} else {
struct sk_buff *skb = tp->Rx_skbuff[entry];
+ dma_addr_t addr = le64_to_cpu(desc->addr);
int pkt_size = (status & 0x00001FFF) - 4;
- void (*pci_action)(struct pci_dev *, dma_addr_t,
- size_t, int) = pci_dma_sync_single_for_device;
+ struct pci_dev *pdev = tp->pci_dev;
/*
* The driver does not support incoming fragmented
@@ -2562,19 +2664,16 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rtl8169_rx_csum(skb, desc);
- pci_dma_sync_single_for_cpu(tp->pci_dev,
- le64_to_cpu(desc->addr), tp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
-
- if (rtl8169_try_rx_copy(&skb, pkt_size, desc,
- tp->rx_buf_sz, tp->align)) {
- pci_action = pci_unmap_single;
+ if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
+ pci_dma_sync_single_for_device(pdev, addr,
+ pkt_size, PCI_DMA_FROMDEVICE);
+ rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+ } else {
+ pci_unmap_single(pdev, addr, pkt_size,
+ PCI_DMA_FROMDEVICE);
tp->Rx_skbuff[entry] = NULL;
}
- pci_action(tp->pci_dev, le64_to_cpu(desc->addr),
- tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, dev);
@@ -2585,6 +2684,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
}
+
+ /* Work around for AMD plateform. */
+ if ((desc->opts2 & 0xfffe000) &&
+ (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
+ desc->opts2 = 0;
+ cur_rx++;
+ }
}
count = cur_rx - tp->cur_rx;
@@ -2608,11 +2714,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
return count;
}
-/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
-static irqreturn_t
-rtl8169_interrupt(int irq, void *dev_instance)
+static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
{
- struct net_device *dev = (struct net_device *) dev_instance;
+ struct net_device *dev = dev_instance;
struct rtl8169_private *tp = netdev_priv(dev);
int boguscnt = max_interrupt_work;
void __iomem *ioaddr = tp->mmio_addr;
@@ -2637,9 +2741,17 @@ rtl8169_interrupt(int irq, void *dev_instance)
RTL_W16(IntrStatus,
(status & RxFIFOOver) ? (status | RxOverflow) : status);
- if (!(status & rtl8169_intr_mask))
+ if (!(status & tp->intr_event))
break;
+ /* Work around for rx fifo overflow */
+ if (unlikely(status & RxFIFOOver) &&
+ (tp->mac_version == RTL_GIGA_MAC_VER_11)) {
+ netif_stop_queue(dev);
+ rtl8169_tx_timeout(dev);
+ break;
+ }
+
if (unlikely(status & SYSErr)) {
rtl8169_pcierr_interrupt(dev);
break;
@@ -2649,8 +2761,8 @@ rtl8169_interrupt(int irq, void *dev_instance)
rtl8169_check_link_status(dev, tp, ioaddr);
#ifdef CONFIG_R8169_NAPI
- RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
- tp->intr_mask = ~rtl8169_napi_event;
+ RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
+ tp->intr_mask = ~tp->napi_event;
if (likely(netif_rx_schedule_prep(dev)))
__netif_rx_schedule(dev);
@@ -2661,9 +2773,9 @@ rtl8169_interrupt(int irq, void *dev_instance)
break;
#else
/* Rx interrupt */
- if (status & (RxOK | RxOverflow | RxFIFOOver)) {
+ if (status & (RxOK | RxOverflow | RxFIFOOver))
rtl8169_rx_interrupt(dev, tp, ioaddr);
- }
+
/* Tx interrupt */
if (status & (TxOK | TxErr))
rtl8169_tx_interrupt(dev, tp, ioaddr);
@@ -2707,7 +2819,7 @@ static int rtl8169_poll(struct net_device *dev, int *budget)
* write is safe - FR
*/
smp_wmb();
- RTL_W16(IntrMask, rtl8169_intr_mask);
+ RTL_W16(IntrMask, tp->intr_event);
}
return (work_done >= work_to_do);
@@ -2789,14 +2901,13 @@ static int rtl8169_close(struct net_device *dev)
return 0;
}
-static void
-rtl8169_set_rx_mode(struct net_device *dev)
+static void rtl_set_rx_mode(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
u32 mc_filter[2]; /* Multicast hash filter */
- int i, rx_mode;
+ int rx_mode;
u32 tmp = 0;
if (dev->flags & IFF_PROMISC) {
@@ -2816,6 +2927,8 @@ rtl8169_set_rx_mode(struct net_device *dev)
mc_filter[1] = mc_filter[0] = 0xffffffff;
} else {
struct dev_mc_list *mclist;
+ unsigned int i;
+
rx_mode = AcceptBroadcast | AcceptMyPhys;
mc_filter[1] = mc_filter[0] = 0;
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
@@ -2840,10 +2953,11 @@ rtl8169_set_rx_mode(struct net_device *dev)
mc_filter[1] = 0xffffffff;
}
- RTL_W32(RxConfig, tmp);
RTL_W32(MAR0 + 0, mc_filter[0]);
RTL_W32(MAR0 + 4, mc_filter[1]);
+ RTL_W32(RxConfig, tmp);
+
spin_unlock_irqrestore(&tp->lock, flags);
}
@@ -2931,14 +3045,12 @@ static struct pci_driver rtl8169_pci_driver = {
#endif
};
-static int __init
-rtl8169_init_module(void)
+static int __init rtl8169_init_module(void)
{
return pci_register_driver(&rtl8169_pci_driver);
}
-static void __exit
-rtl8169_cleanup_module(void)
+static void __exit rtl8169_cleanup_module(void)
{
pci_unregister_driver(&rtl8169_pci_driver);
}
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 09078ff84cd2..2d826fff7e2e 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -469,11 +469,18 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, s2io_tbl);
+static struct pci_error_handlers s2io_err_handler = {
+ .error_detected = s2io_io_error_detected,
+ .slot_reset = s2io_io_slot_reset,
+ .resume = s2io_io_resume,
+};
+
static struct pci_driver s2io_driver = {
.name = "S2IO",
.id_table = s2io_tbl,
.probe = s2io_init_nic,
.remove = __devexit_p(s2io_rem_nic),
+ .err_handler = &s2io_err_handler,
};
/* A simplifier macro used both by init and free shared_mem Fns(). */
@@ -2689,6 +2696,9 @@ static void s2io_netpoll(struct net_device *dev)
u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
int i;
+ if (pci_channel_offline(nic->pdev))
+ return;
+
disable_irq(dev->irq);
atomic_inc(&nic->isr_cnt);
@@ -3215,6 +3225,8 @@ static void alarm_intr_handler(struct s2io_nic *nic)
int i;
if (atomic_read(&nic->card_state) == CARD_DOWN)
return;
+ if (pci_channel_offline(nic->pdev))
+ return;
nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
/* Handling the XPAK counters update */
if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
@@ -3958,7 +3970,6 @@ static int s2io_close(struct net_device *dev)
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
- sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
}
@@ -4314,6 +4325,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
struct mac_info *mac_control;
struct config_param *config;
+ /* Pretend we handled any irq's from a disconnected card */
+ if (pci_channel_offline(sp->pdev))
+ return IRQ_NONE;
+
atomic_inc(&sp->isr_cnt);
mac_control = &sp->mac_control;
config = &sp->config;
@@ -6569,7 +6584,7 @@ static void s2io_rem_isr(struct s2io_nic * sp)
} while(cnt < 5);
}
-static void s2io_card_down(struct s2io_nic * sp)
+static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
{
int cnt = 0;
struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -6584,7 +6599,8 @@ static void s2io_card_down(struct s2io_nic * sp)
atomic_set(&sp->card_state, CARD_DOWN);
/* disable Tx and Rx traffic on the NIC */
- stop_nic(sp);
+ if (do_io)
+ stop_nic(sp);
s2io_rem_isr(sp);
@@ -6592,7 +6608,7 @@ static void s2io_card_down(struct s2io_nic * sp)
tasklet_kill(&sp->task);
/* Check if the device is Quiescent and then Reset the NIC */
- do {
+ while(do_io) {
/* As per the HW requirement we need to replenish the
* receive buffer to avoid the ring bump. Since there is
* no intention of processing the Rx frame at this pointwe are
@@ -6617,8 +6633,9 @@ static void s2io_card_down(struct s2io_nic * sp)
(unsigned long long) val64);
break;
}
- } while (1);
- s2io_reset(sp);
+ }
+ if (do_io)
+ s2io_reset(sp);
spin_lock_irqsave(&sp->tx_lock, flags);
/* Free all Tx buffers */
@@ -6633,6 +6650,11 @@ static void s2io_card_down(struct s2io_nic * sp)
clear_bit(0, &(sp->link_state));
}
+static void s2io_card_down(struct s2io_nic * sp)
+{
+ do_s2io_card_down(sp, 1);
+}
+
static int s2io_card_up(struct s2io_nic * sp)
{
int i, ret = 0;
@@ -8010,3 +8032,85 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
return;
}
+
+/**
+ * s2io_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev)) {
+ /* Bring down the card, while avoiding PCI I/O */
+ do_s2io_card_down(sp, 0);
+ }
+ pci_disable_device(pdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * s2io_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ * At this point, the card has exprienced a hard reset,
+ * followed by fixups by BIOS, and has its config space
+ * set up identically to what it was at cold boot.
+ */
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR "s2io: "
+ "Cannot re-enable PCI device after reset.\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ pci_set_master(pdev);
+ s2io_reset(sp);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * s2io_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells
+ * us that its OK to resume normal operation.
+ */
+static void s2io_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ if (netif_running(netdev)) {
+ if (s2io_card_up(sp)) {
+ printk(KERN_ERR "s2io: "
+ "Can't bring device back up after reset.\n");
+ return;
+ }
+
+ if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
+ s2io_card_down(sp);
+ printk(KERN_ERR "s2io: "
+ "Can't resetore mac addr after reset.\n");
+ return;
+ }
+ }
+
+ netif_device_attach(netdev);
+ netif_wake_queue(netdev);
+}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 54baa0b8ec7c..58592780f519 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -794,7 +794,6 @@ struct s2io_nic {
struct net_device_stats stats;
int high_dma_flag;
- int device_close_flag;
int device_enabled_once;
char name[60];
@@ -1052,6 +1051,11 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
struct sk_buff *skb, u32 tcp_len);
static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state);
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev);
+static void s2io_io_resume(struct pci_dev *pdev);
+
#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index fe01b961b597..b51d73c8f817 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -50,7 +50,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.14"
+#define DRV_VERSION "1.15"
#define PFX DRV_NAME " "
/*
@@ -130,7 +130,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
-// { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
{ 0 }
};
@@ -217,13 +217,24 @@ static void sky2_power_on(struct sky2_hw *hw)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
- u32 reg1;
+ u32 reg;
- sky2_pci_write32(hw, PCI_DEV_REG3, 0);
- reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
- reg1 &= P_ASPM_CONTROL_MSK;
- sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
- sky2_pci_write32(hw, PCI_DEV_REG5, 0);
+ reg = sky2_pci_read32(hw, PCI_DEV_REG4);
+ /* set all bits to 0 except bits 15..12 and 8 */
+ reg &= P_ASPM_CONTROL_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG4, reg);
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG5);
+ /* set all bits to 0 except bits 28 & 27 */
+ reg &= P_CTL_TIM_VMAIN_AV_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG5, reg);
+
+ sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
+
+ /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
+ reg = sky2_read32(hw, B2_GP_IO);
+ reg |= GLB_GPIO_STAT_RACE_DIS;
+ sky2_write32(hw, B2_GP_IO, reg);
}
}
@@ -650,6 +661,30 @@ static void sky2_wol_init(struct sky2_port *sky2)
}
+static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
+{
+ if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_STFW_ENA |
+ (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
+ } else {
+ if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+ /* set Tx GMAC FIFO Almost Empty Threshold */
+ sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+ (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_ENA | TX_STFW_DIS);
+
+ /* Can't do offload because of lack of store/forward */
+ hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
+ | NETIF_F_ALL_CSUM);
+ } else
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_DIS | TX_STFW_ENA);
+ }
+}
+
static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
{
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -730,8 +765,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
/* Configure Rx MAC FIFO */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
- sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
- GMF_OPER_ON | GMF_RX_F_FL_ON);
+ reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ reg |= GMF_RX_OVER_ON;
+
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
/* Flush Rx MAC FIFO on any flow control or error */
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
@@ -747,16 +785,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
- /* set Tx GMAC FIFO Almost Empty Threshold */
- sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
- (ECU_JUMBO_WM << 16) | ECU_AE_THR);
-
- if (hw->dev[port]->mtu > ETH_DATA_LEN)
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_ENA | TX_STFW_DIS);
- else
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_DIS | TX_STFW_ENA);
+ sky2_set_tx_stfwd(hw, port);
}
}
@@ -939,14 +968,16 @@ static void rx_set_checksum(struct sky2_port *sky2)
{
struct sky2_rx_le *le;
- le = sky2_next_rx(sky2);
- le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
- le->ctrl = 0;
- le->opcode = OP_TCPSTART | HW_OWNER;
+ if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
+ le = sky2_next_rx(sky2);
+ le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
- sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[sky2->port], Q_CSR),
- sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ }
}
@@ -1134,7 +1165,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
(hw->chip_rev == CHIP_REV_YU_EC_U_A1
|| hw->chip_rev == CHIP_REV_YU_EC_U_B0))
- sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
+ sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS);
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
@@ -1285,6 +1316,10 @@ static int sky2_up(struct net_device *dev)
sky2_qset(hw, txqaddr[port]);
+ /* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */
+ if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0)
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF);
+
/* Set almost empty threshold */
if (hw->chip_id == CHIP_ID_YUKON_EC_U
&& hw->chip_rev == CHIP_REV_YU_EC_U_A0)
@@ -1393,14 +1428,16 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* Check for TCP Segmentation Offload */
mss = skb_shinfo(skb)->gso_size;
if (mss != 0) {
- mss += tcp_optlen(skb); /* TCP options */
- mss += ip_hdrlen(skb) + sizeof(struct tcphdr);
- mss += ETH_HLEN;
-
- if (mss != sky2->tx_last_mss) {
- le = get_tx_le(sky2);
- le->addr = cpu_to_le32(mss);
- le->opcode = OP_LRGLEN | HW_OWNER;
+ if (hw->chip_id != CHIP_ID_YUKON_EX)
+ mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
+
+ if (mss != sky2->tx_last_mss) {
+ le = get_tx_le(sky2);
+ le->addr = cpu_to_le32(mss);
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ le->opcode = OP_MSS | HW_OWNER;
+ else
+ le->opcode = OP_LRGLEN | HW_OWNER;
sky2->tx_last_mss = mss;
}
}
@@ -1422,24 +1459,30 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* Handle TCP checksum offload */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- const unsigned offset = skb_transport_offset(skb);
- u32 tcpsum;
-
- tcpsum = offset << 16; /* sum start */
- tcpsum |= offset + skb->csum_offset; /* sum write */
-
- ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
- if (ip_hdr(skb)->protocol == IPPROTO_UDP)
- ctrl |= UDPTCP;
-
- if (tcpsum != sky2->tx_tcpsum) {
- sky2->tx_tcpsum = tcpsum;
-
- le = get_tx_le(sky2);
- le->addr = cpu_to_le32(tcpsum);
- le->length = 0; /* initial checksum value */
- le->ctrl = 1; /* one packet */
- le->opcode = OP_TCPLISW | HW_OWNER;
+ /* On Yukon EX (some versions) encoding change. */
+ if (hw->chip_id == CHIP_ID_YUKON_EX
+ && hw->chip_rev != CHIP_REV_YU_EX_B0)
+ ctrl |= CALSUM; /* auto checksum */
+ else {
+ const unsigned offset = skb_transport_offset(skb);
+ u32 tcpsum;
+
+ tcpsum = offset << 16; /* sum start */
+ tcpsum |= offset + skb->csum_offset; /* sum write */
+
+ ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+ if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ ctrl |= UDPTCP;
+
+ if (tcpsum != sky2->tx_tcpsum) {
+ sky2->tx_tcpsum = tcpsum;
+
+ le = get_tx_le(sky2);
+ le->addr = cpu_to_le32(tcpsum);
+ le->length = 0; /* initial checksum value */
+ le->ctrl = 1; /* one packet */
+ le->opcode = OP_TCPLISW | HW_OWNER;
+ }
}
}
@@ -1913,15 +1956,8 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
synchronize_irq(hw->pdev->irq);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
- if (new_mtu > ETH_DATA_LEN) {
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_ENA | TX_STFW_DIS);
- dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
- } else
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_DIS | TX_STFW_ENA);
- }
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+ sky2_set_tx_stfwd(hw, port);
ctl = gma_read16(hw, port, GM_GP_CTRL);
gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
@@ -2118,6 +2154,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
while (hw->st_idx != hwidx) {
struct sky2_status_le *le = hw->st_le + hw->st_idx;
+ unsigned port = le->css & CSS_LINK_BIT;
struct net_device *dev;
struct sk_buff *skb;
u32 status;
@@ -2125,9 +2162,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
- BUG_ON(le->link >= 2);
- dev = hw->dev[le->link];
-
+ dev = hw->dev[port];
sky2 = netdev_priv(dev);
length = le16_to_cpu(le->length);
status = le32_to_cpu(le->status);
@@ -2140,6 +2175,16 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
goto force_update;
}
+ /* This chip reports checksum status differently */
+ if (hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (sky2->rx_csum &&
+ (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
+ (le->css & CSS_TCPUDPCSOK))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+
skb->protocol = eth_type_trans(skb, dev);
sky2->net_stats.rx_packets++;
sky2->net_stats.rx_bytes += skb->len;
@@ -2155,10 +2200,10 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
netif_receive_skb(skb);
/* Update receiver after 16 frames */
- if (++buf_write[le->link] == RX_BUF_WRITE) {
+ if (++buf_write[port] == RX_BUF_WRITE) {
force_update:
- sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put);
- buf_write[le->link] = 0;
+ sky2_put_idx(hw, rxqaddr[port], sky2->rx_put);
+ buf_write[port] = 0;
}
/* Stop after net poll weight */
@@ -2179,6 +2224,9 @@ force_update:
if (!sky2->rx_csum)
break;
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ break;
+
/* Both checksum counters are programmed to start at
* the same offset, so unless there is a problem they
* should match. This failure is an early indication that
@@ -2194,7 +2242,7 @@ force_update:
dev->name, status);
sky2->rx_csum = 0;
sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[le->link], Q_CSR),
+ Q_ADDR(rxqaddr[port], Q_CSR),
BMU_DIS_RX_CHKSUM);
}
break;
@@ -2513,6 +2561,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
{
u8 t8;
+ /* Enable all clocks */
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
sky2_write8(hw, B0_CTST, CS_RST_CLR);
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
@@ -2522,14 +2573,6 @@ static int __devinit sky2_init(struct sky2_hw *hw)
return -EOPNOTSUPP;
}
- if (hw->chip_id == CHIP_ID_YUKON_EX)
- dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n"
- "Please report success or failure to <netdev@vger.kernel.org>\n");
-
- /* Make sure and enable all clocks */
- if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
- sky2_pci_write32(hw, PCI_DEV_REG3, 0);
-
hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
/* This rev is really old, and requires untested workarounds */
@@ -2589,6 +2632,11 @@ static void sky2_reset(struct sky2_hw *hw)
for (i = 0; i < hw->ports; i++) {
sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ sky2_write16(hw, SK_REG(i, GMAC_CTRL),
+ GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
+ | GMC_BYP_RETR_ON);
}
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
@@ -2735,7 +2783,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
sky2->wol = wol->wolopts;
- if (hw->chip_id == CHIP_ID_YUKON_EC_U)
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
sky2_write32(hw, B0_CTST, sky2->wol
? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
@@ -3330,7 +3378,7 @@ static int sky2_get_regs_len(struct net_device *dev)
/*
* Returns copy of control register region
- * Note: access to the RAM address register set will cause timeouts.
+ * Note: ethtool_get_regs always provides full size (16k) buffer
*/
static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
@@ -3338,15 +3386,19 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
const struct sky2_port *sky2 = netdev_priv(dev);
const void __iomem *io = sky2->hw->regs;
- BUG_ON(regs->len < B3_RI_WTO_R1);
regs->version = 1;
memset(p, 0, regs->len);
memcpy_fromio(p, io, B3_RAM_ADDR);
- memcpy_fromio(p + B3_RI_WTO_R1,
- io + B3_RI_WTO_R1,
- regs->len - B3_RI_WTO_R1);
+ /* skip diagnostic ram region */
+ memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1);
+
+ /* copy GMAC registers */
+ memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000);
+ if (sky2->hw->ports > 1)
+ memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000);
+
}
/* In order to do Jumbo packets on these chips, need to turn off the
@@ -3357,9 +3409,7 @@ static int no_tx_offload(struct net_device *dev)
const struct sky2_port *sky2 = netdev_priv(dev);
const struct sky2_hw *hw = sky2->hw;
- return dev->mtu > ETH_DATA_LEN &&
- (hw->chip_id == CHIP_ID_YUKON_EX
- || hw->chip_id == CHIP_ID_YUKON_EC_U);
+ return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U;
}
static int sky2_set_tx_csum(struct net_device *dev, u32 data)
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index b8c4a3b5eadf..8df4643493d1 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -14,6 +14,8 @@ enum {
PCI_DEV_REG3 = 0x80,
PCI_DEV_REG4 = 0x84,
PCI_DEV_REG5 = 0x88,
+ PCI_CFG_REG_0 = 0x90,
+ PCI_CFG_REG_1 = 0x94,
};
enum {
@@ -28,6 +30,7 @@ enum {
enum pci_dev_reg_1 {
PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */
+ PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */
PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
@@ -67,6 +70,80 @@ enum pci_dev_reg_4 {
| P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
};
+/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */
+enum pci_dev_reg_5 {
+ /* Bit 31..27: for A3 & later */
+ P_CTL_DIV_CORE_CLK_ENA = 1<<31, /* Divide Core Clock Enable */
+ P_CTL_SRESET_VMAIN_AV = 1<<30, /* Soft Reset for Vmain_av De-Glitch */
+ P_CTL_BYPASS_VMAIN_AV = 1<<29, /* Bypass En. for Vmain_av De-Glitch */
+ P_CTL_TIM_VMAIN_AV_MSK = 3<<27, /* Bit 28..27: Timer Vmain_av Mask */
+ /* Bit 26..16: Release Clock on Event */
+ P_REL_PCIE_RST_DE_ASS = 1<<26, /* PCIe Reset De-Asserted */
+ P_REL_GPHY_REC_PACKET = 1<<25, /* GPHY Received Packet */
+ P_REL_INT_FIFO_N_EMPTY = 1<<24, /* Internal FIFO Not Empty */
+ P_REL_MAIN_PWR_AVAIL = 1<<23, /* Main Power Available */
+ P_REL_CLKRUN_REQ_REL = 1<<22, /* CLKRUN Request Release */
+ P_REL_PCIE_RESET_ASS = 1<<21, /* PCIe Reset Asserted */
+ P_REL_PME_ASSERTED = 1<<20, /* PME Asserted */
+ P_REL_PCIE_EXIT_L1_ST = 1<<19, /* PCIe Exit L1 State */
+ P_REL_LOADER_NOT_FIN = 1<<18, /* EPROM Loader Not Finished */
+ P_REL_PCIE_RX_EX_IDLE = 1<<17, /* PCIe Rx Exit Electrical Idle State */
+ P_REL_GPHY_LINK_UP = 1<<16, /* GPHY Link Up */
+
+ /* Bit 10.. 0: Mask for Gate Clock */
+ P_GAT_PCIE_RST_ASSERTED = 1<<10,/* PCIe Reset Asserted */
+ P_GAT_GPHY_N_REC_PACKET = 1<<9, /* GPHY Not Received Packet */
+ P_GAT_INT_FIFO_EMPTY = 1<<8, /* Internal FIFO Empty */
+ P_GAT_MAIN_PWR_N_AVAIL = 1<<7, /* Main Power Not Available */
+ P_GAT_CLKRUN_REQ_REL = 1<<6, /* CLKRUN Not Requested */
+ P_GAT_PCIE_RESET_ASS = 1<<5, /* PCIe Reset Asserted */
+ P_GAT_PME_DE_ASSERTED = 1<<4, /* PME De-Asserted */
+ P_GAT_PCIE_ENTER_L1_ST = 1<<3, /* PCIe Enter L1 State */
+ P_GAT_LOADER_FINISHED = 1<<2, /* EPROM Loader Finished */
+ P_GAT_PCIE_RX_EL_IDLE = 1<<1, /* PCIe Rx Electrical Idle State */
+ P_GAT_GPHY_LINK_DOWN = 1<<0, /* GPHY Link Down */
+
+ PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET |
+ P_REL_INT_FIFO_N_EMPTY |
+ P_REL_PCIE_EXIT_L1_ST |
+ P_REL_PCIE_RX_EX_IDLE |
+ P_GAT_GPHY_N_REC_PACKET |
+ P_GAT_INT_FIFO_EMPTY |
+ P_GAT_PCIE_ENTER_L1_ST |
+ P_GAT_PCIE_RX_EL_IDLE,
+};
+
+#/* PCI_CFG_REG_1 32 bit Config Register 1 (Yukon-Ext only) */
+enum pci_cfg_reg1 {
+ P_CF1_DIS_REL_EVT_RST = 1<<24, /* Dis. Rel. Event during PCIE reset */
+ /* Bit 23..21: Release Clock on Event */
+ P_CF1_REL_LDR_NOT_FIN = 1<<23, /* EEPROM Loader Not Finished */
+ P_CF1_REL_VMAIN_AVLBL = 1<<22, /* Vmain available */
+ P_CF1_REL_PCIE_RESET = 1<<21, /* PCI-E reset */
+ /* Bit 20..18: Gate Clock on Event */
+ P_CF1_GAT_LDR_NOT_FIN = 1<<20, /* EEPROM Loader Finished */
+ P_CF1_GAT_PCIE_RX_IDLE = 1<<19, /* PCI-E Rx Electrical idle */
+ P_CF1_GAT_PCIE_RESET = 1<<18, /* PCI-E Reset */
+ P_CF1_PRST_PHY_CLKREQ = 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */
+ P_CF1_PCIE_RST_CLKREQ = 1<<16, /* Enable PCI-E rst generate CLKREQ */
+
+ P_CF1_ENA_CFG_LDR_DONE = 1<<8, /* Enable core level Config loader done */
+
+ P_CF1_ENA_TXBMU_RD_IDLE = 1<<1, /* Enable TX BMU Read IDLE for ASPM */
+ P_CF1_ENA_TXBMU_WR_IDLE = 1<<0, /* Enable TX BMU Write IDLE for ASPM */
+
+ PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST |
+ P_CF1_REL_LDR_NOT_FIN |
+ P_CF1_REL_VMAIN_AVLBL |
+ P_CF1_REL_PCIE_RESET |
+ P_CF1_GAT_LDR_NOT_FIN |
+ P_CF1_GAT_PCIE_RESET |
+ P_CF1_PRST_PHY_CLKREQ |
+ P_CF1_ENA_CFG_LDR_DONE |
+ P_CF1_ENA_TXBMU_RD_IDLE |
+ P_CF1_ENA_TXBMU_WR_IDLE,
+};
+
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -364,6 +441,20 @@ enum {
TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
};
+/* B2_GPIO */
+enum {
+ GLB_GPIO_CLK_DEB_ENA = 1<<31, /* Clock Debug Enable */
+ GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */
+
+ GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */
+ GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */
+ GLB_GPIO_STAT_RACE_DIS = 1<<13, /* Status Race Disable */
+ GLB_GPIO_TEST_SEL_MSK = 3<<11, /* Testmode Select */
+ GLB_GPIO_TEST_SEL_BASE = 1<<11,
+ GLB_GPIO_RAND_ENA = 1<<10, /* Random Enable */
+ GLB_GPIO_RAND_BIT_1 = 1<<9, /* Random Bit 1 */
+};
+
/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
enum {
CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */
@@ -392,6 +483,11 @@ enum {
CHIP_REV_YU_FE_A2 = 2,
};
+enum yukon_ex_rev {
+ CHIP_REV_YU_EX_A0 = 1,
+ CHIP_REV_YU_EX_B0 = 2,
+};
+
/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
enum {
@@ -515,23 +611,15 @@ enum {
enum {
B8_Q_REGS = 0x0400, /* base of Queue registers */
Q_D = 0x00, /* 8*32 bit Current Descriptor */
- Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */
- Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */
+ Q_VLAN = 0x20, /* 16 bit Current VLAN Tag */
+ Q_DONE = 0x24, /* 16 bit Done Index */
Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */
Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */
Q_BC = 0x30, /* 32 bit Current Byte Counter */
Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */
- Q_F = 0x38, /* 32 bit Flag Register */
- Q_T1 = 0x3c, /* 32 bit Test Register 1 */
- Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */
- Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */
- Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */
- Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */
- Q_T2 = 0x40, /* 32 bit Test Register 2 */
- Q_T3 = 0x44, /* 32 bit Test Register 3 */
+ Q_TEST = 0x38, /* 32 bit Test/Control Register */
/* Yukon-2 */
- Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */
Q_WM = 0x40, /* 16 bit FIFO Watermark */
Q_AL = 0x42, /* 8 bit FIFO Alignment */
Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */
@@ -545,15 +633,16 @@ enum {
};
#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
-/* Q_F 32 bit Flag Register */
+/* Q_TEST 32 bit Test Register */
enum {
- F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
- F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
- F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
- F_WM_REACHED = 1<<25, /* Watermark reached */
+ /* Transmit */
+ F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */
+ F_TX_CHK_AUTO_ON = 1<<30, /* Tx checksum auto calc off (Yukon EX) */
+
+ /* Receive */
F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */
- F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
- F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
+
+ /* Hardware testbits not used */
};
/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
@@ -1608,6 +1697,16 @@ enum {
RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */
RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */
+ RX_MACSEC_FLUSH_ON = 1<<23,
+ RX_MACSEC_FLUSH_OFF = 1<<22,
+ RX_MACSEC_ASF_FLUSH_ON = 1<<21,
+ RX_MACSEC_ASF_FLUSH_OFF = 1<<20,
+
+ GMF_RX_OVER_ON = 1<<19, /* enable flushing on receive overrun */
+ GMF_RX_OVER_OFF = 1<<18, /* disable flushing on receive overrun */
+ GMF_ASF_RX_OVER_ON = 1<<17, /* enable flushing of ASF when overrun */
+ GMF_ASF_RX_OVER_OFF = 1<<16, /* disable flushing of ASF when overrun */
+
GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */
GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */
GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */
@@ -1720,6 +1819,15 @@ enum {
/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
enum {
+ GMC_SET_RST = 1<<15,/* MAC SEC RST */
+ GMC_SEC_RST_OFF = 1<<14,/* MAC SEC RSt OFF */
+ GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */
+ GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */
+ GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */
+ GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX off*/
+ GMC_BYP_RETR_ON = 1<<9, /* Bypass retransmit FIFO On */
+ GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */
+
GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */
GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */
GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */
@@ -1805,9 +1913,13 @@ enum {
OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN,
OP_LRGLEN = 0x24,
OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN,
+ OP_MSS = 0x28,
+ OP_MSSVLAN = OP_MSS | OP_VLAN,
+
OP_BUFFER = 0x40,
OP_PACKET = 0x41,
OP_LARGESEND = 0x43,
+ OP_LSOV2 = 0x45,
/* YUKON-2 STATUS opcodes defines */
OP_RXSTAT = 0x60,
@@ -1818,6 +1930,19 @@ enum {
OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN,
OP_RSS_HASH = 0x65,
OP_TXINDEXLE = 0x68,
+ OP_MACSEC = 0x6c,
+ OP_PUTIDX = 0x70,
+};
+
+enum status_css {
+ CSS_TCPUDPCSOK = 1<<7, /* TCP / UDP checksum is ok */
+ CSS_ISUDP = 1<<6, /* packet is a UDP packet */
+ CSS_ISTCP = 1<<5, /* packet is a TCP packet */
+ CSS_ISIPFRAG = 1<<4, /* packet is a TCP/UDP frag, CS calc not done */
+ CSS_ISIPV6 = 1<<3, /* packet is a IPv6 packet */
+ CSS_IPV4CSUMOK = 1<<2, /* IP v4: TCP header checksum is ok */
+ CSS_ISIPV4 = 1<<1, /* packet is a IPv4 packet */
+ CSS_LINK_BIT = 1<<0, /* port number (legacy) */
};
/* Yukon 2 hardware interface */
@@ -1838,7 +1963,7 @@ struct sky2_rx_le {
struct sky2_status_le {
__le32 status; /* also checksum */
__le16 length; /* also vlan tag */
- u8 link;
+ u8 css;
u8 opcode;
} __attribute((packed));
diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c
new file mode 100644
index 000000000000..2cf6794acb4f
--- /dev/null
+++ b/drivers/net/sni_82596.c
@@ -0,0 +1,185 @@
+/*
+ * sni_82596.c -- driver for intel 82596 ethernet controller, as
+ * used in older SNI RM machines
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#define SNI_82596_DRIVER_VERSION "SNI RM 82596 driver - Revision: 0.01"
+
+static const char sni_82596_string[] = "snirm_82596";
+
+#define DMA_ALLOC dma_alloc_coherent
+#define DMA_FREE dma_free_coherent
+#define DMA_WBACK(priv, addr, len) do { } while (0)
+#define DMA_INV(priv, addr, len) do { } while (0)
+#define DMA_WBACK_INV(priv, addr, len) do { } while (0)
+
+#define SYSBUS 0x00004400
+
+/* big endian CPU, 82596 little endian */
+#define SWAP32(x) cpu_to_le32((u32)(x))
+#define SWAP16(x) cpu_to_le16((u16)(x))
+
+#define OPT_MPU_16BIT 0x01
+
+#include "lib82596.c"
+
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("i82596 driver");
+MODULE_LICENSE("GPL");
+module_param(i596_debug, int, 0);
+MODULE_PARM_DESC(i596_debug, "82596 debug mask");
+
+static inline void ca(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ writel(0, lp->ca);
+}
+
+
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ u32 v = (u32) (c) | (u32) (x);
+
+ if (lp->options & OPT_MPU_16BIT) {
+ writew(v & 0xffff, lp->mpu_port);
+ wmb(); /* order writes to MPU port */
+ udelay(1);
+ writew(v >> 16, lp->mpu_port);
+ } else {
+ writel(v, lp->mpu_port);
+ wmb(); /* order writes to MPU port */
+ udelay(1);
+ writel(v, lp->mpu_port);
+ }
+}
+
+
+static int __devinit sni_82596_probe(struct platform_device *dev)
+{
+ struct net_device *netdevice;
+ struct i596_private *lp;
+ struct resource *res, *ca, *idprom, *options;
+ int retval = -ENOMEM;
+ void __iomem *mpu_addr;
+ void __iomem *ca_addr;
+ u8 __iomem *eth_addr;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ ca = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ options = platform_get_resource(dev, 0, 0);
+ idprom = platform_get_resource(dev, IORESOURCE_MEM, 2);
+ if (!res || !ca || !options || !idprom)
+ return -ENODEV;
+ mpu_addr = ioremap_nocache(res->start, 4);
+ if (!mpu_addr)
+ return -ENOMEM;
+ ca_addr = ioremap_nocache(ca->start, 4);
+ if (!ca_addr)
+ goto probe_failed_free_mpu;
+
+ printk(KERN_INFO "Found i82596 at 0x%x\n", res->start);
+
+ netdevice = alloc_etherdev(sizeof(struct i596_private));
+ if (!netdevice)
+ goto probe_failed_free_ca;
+
+ SET_NETDEV_DEV(netdevice, &dev->dev);
+ platform_set_drvdata (dev, netdevice);
+
+ netdevice->base_addr = res->start;
+ netdevice->irq = platform_get_irq(dev, 0);
+
+ eth_addr = ioremap_nocache(idprom->start, 0x10);
+ if (!eth_addr)
+ goto probe_failed;
+
+ /* someone seems to like messed up stuff */
+ netdevice->dev_addr[0] = readb(eth_addr + 0x0b);
+ netdevice->dev_addr[1] = readb(eth_addr + 0x0a);
+ netdevice->dev_addr[2] = readb(eth_addr + 0x09);
+ netdevice->dev_addr[3] = readb(eth_addr + 0x08);
+ netdevice->dev_addr[4] = readb(eth_addr + 0x07);
+ netdevice->dev_addr[5] = readb(eth_addr + 0x06);
+ iounmap(eth_addr);
+
+ if (!netdevice->irq) {
+ printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
+ __FILE__, netdevice->base_addr);
+ goto probe_failed;
+ }
+
+ lp = netdev_priv(netdevice);
+ lp->options = options->flags & IORESOURCE_BITS;
+ lp->ca = ca_addr;
+ lp->mpu_port = mpu_addr;
+
+ retval = i82596_probe(netdevice);
+ if (retval == 0)
+ return 0;
+
+probe_failed:
+ free_netdev(netdevice);
+probe_failed_free_ca:
+ iounmap(ca_addr);
+probe_failed_free_mpu:
+ iounmap(mpu_addr);
+ return retval;
+}
+
+static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct i596_private *lp = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ DMA_FREE(dev->dev.parent, sizeof(struct i596_private),
+ lp->dma, lp->dma_addr);
+ iounmap(lp->ca);
+ iounmap(lp->mpu_port);
+ free_netdev (dev);
+ return 0;
+}
+
+static struct platform_driver sni_82596_driver = {
+ .probe = sni_82596_probe,
+ .remove = __devexit_p(sni_82596_driver_remove),
+ .driver = {
+ .name = sni_82596_string,
+ },
+};
+
+static int __devinit sni_82596_init(void)
+{
+ printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
+ return platform_driver_register(&sni_82596_driver);
+}
+
+
+static void __exit sni_82596_exit(void)
+{
+ platform_driver_unregister(&sni_82596_driver);
+}
+
+module_init(sni_82596_init);
+module_exit(sni_82596_exit);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 7a4aa6a9f949..f5abb5279d4d 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -434,7 +434,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
if (!descr->skb) {
if (netif_msg_rx_err(card) && net_ratelimit())
- pr_err("Not enough memory to allocate rx buffer\n");
+ dev_err(&card->netdev->dev,
+ "Not enough memory to allocate rx buffer\n");
card->spider_stats.alloc_rx_skb_error++;
return -ENOMEM;
}
@@ -455,7 +456,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
dev_kfree_skb_any(descr->skb);
descr->skb = NULL;
if (netif_msg_rx_err(card) && net_ratelimit())
- pr_err("Could not iommu-map rx buffer\n");
+ dev_err(&card->netdev->dev, "Could not iommu-map rx buffer\n");
card->spider_stats.rx_iommu_map_error++;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
} else {
@@ -500,6 +501,20 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
}
/**
+ * spider_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_disable_rxdmac terminates processing on the DMA controller
+ * by turing off the DMA controller, with the force-end flag set.
+ */
+static inline void
+spider_net_disable_rxdmac(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+ SPIDER_NET_DMA_RX_FEND_VALUE);
+}
+
+/**
* spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
* @card: card structure
*
@@ -655,20 +670,6 @@ write_hash:
}
/**
- * spider_net_disable_rxdmac - disables the receive DMA controller
- * @card: card structure
- *
- * spider_net_disable_rxdmac terminates processing on the DMA controller by
- * turing off DMA and issueing a force end
- */
-static void
-spider_net_disable_rxdmac(struct spider_net_card *card)
-{
- spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
- SPIDER_NET_DMA_RX_FEND_VALUE);
-}
-
-/**
* spider_net_prepare_tx_descr - fill tx descriptor with skb data
* @card: card structure
* @descr: descriptor structure to fill out
@@ -692,7 +693,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(buf)) {
if (netif_msg_tx_err(card) && net_ratelimit())
- pr_err("could not iommu-map packet (%p, %i). "
+ dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). "
"Dropping packet\n", skb->data, skb->len);
card->spider_stats.tx_iommu_map_error++;
return -ENOMEM;
@@ -715,7 +716,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
hwdescr->data_status = 0;
hwdescr->dmac_cmd_status =
- SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+ SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_TXFRMTL;
spin_unlock_irqrestore(&chain->lock, flags);
if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -832,9 +833,8 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
case SPIDER_NET_DESCR_PROTECTION_ERROR:
case SPIDER_NET_DESCR_FORCE_END:
if (netif_msg_tx_err(card))
- pr_err("%s: forcing end of tx descriptor "
- "with status x%02x\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev, "forcing end of tx descriptor "
+ "with status x%02x\n", status);
card->netdev_stats.tx_errors++;
break;
@@ -1022,34 +1022,94 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
netif_receive_skb(skb);
}
-#ifdef DEBUG
static void show_rx_chain(struct spider_net_card *card)
{
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *start= chain->tail;
struct spider_net_descr *descr= start;
+ struct spider_net_hw_descr *hwd = start->hwdescr;
+ struct device *dev = &card->netdev->dev;
+ u32 curr_desc, next_desc;
int status;
+ int tot = 0;
int cnt = 0;
- int cstat = spider_net_get_descr_status(descr);
- printk(KERN_INFO "RX chain tail at descr=%ld\n",
- (start - card->descr) - card->tx_chain.num_desc);
+ int off = start - chain->ring;
+ int cstat = hwd->dmac_cmd_status;
+
+ dev_info(dev, "Total number of descrs=%d\n",
+ chain->num_desc);
+ dev_info(dev, "Chain tail located at descr=%d, status=0x%x\n",
+ off, cstat);
+
+ curr_desc = spider_net_read_reg(card, SPIDER_NET_GDACTDPA);
+ next_desc = spider_net_read_reg(card, SPIDER_NET_GDACNEXTDA);
+
status = cstat;
do
{
- status = spider_net_get_descr_status(descr);
+ hwd = descr->hwdescr;
+ off = descr - chain->ring;
+ status = hwd->dmac_cmd_status;
+
+ if (descr == chain->head)
+ dev_info(dev, "Chain head is at %d, head status=0x%x\n",
+ off, status);
+
+ if (curr_desc == descr->bus_addr)
+ dev_info(dev, "HW curr desc (GDACTDPA) is at %d, status=0x%x\n",
+ off, status);
+
+ if (next_desc == descr->bus_addr)
+ dev_info(dev, "HW next desc (GDACNEXTDA) is at %d, status=0x%x\n",
+ off, status);
+
+ if (hwd->next_descr_addr == 0)
+ dev_info(dev, "chain is cut at %d\n", off);
+
if (cstat != status) {
- printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat);
+ int from = (chain->num_desc + off - cnt) % chain->num_desc;
+ int to = (chain->num_desc + off - 1) % chain->num_desc;
+ dev_info(dev, "Have %d (from %d to %d) descrs "
+ "with stat=0x%08x\n", cnt, from, to, cstat);
cstat = status;
cnt = 0;
}
+
cnt ++;
+ tot ++;
+ descr = descr->next;
+ } while (descr != start);
+
+ dev_info(dev, "Last %d descrs with stat=0x%08x "
+ "for a total of %d descrs\n", cnt, cstat, tot);
+
+#ifdef DEBUG
+ /* Now dump the whole ring */
+ descr = start;
+ do
+ {
+ struct spider_net_hw_descr *hwd = descr->hwdescr;
+ status = spider_net_get_descr_status(hwd);
+ cnt = descr - chain->ring;
+ dev_info(dev, "Descr %d stat=0x%08x skb=%p\n",
+ cnt, status, descr->skb);
+ dev_info(dev, "bus addr=%08x buf addr=%08x sz=%d\n",
+ descr->bus_addr, hwd->buf_addr, hwd->buf_size);
+ dev_info(dev, "next=%08x result sz=%d valid sz=%d\n",
+ hwd->next_descr_addr, hwd->result_size,
+ hwd->valid_size);
+ dev_info(dev, "dmac=%08x data stat=%08x data err=%08x\n",
+ hwd->dmac_cmd_status, hwd->data_status,
+ hwd->data_error);
+ dev_info(dev, "\n");
+
descr = descr->next;
} while (descr != start);
- printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat);
-}
#endif
+}
+
/**
* spider_net_resync_head_ptr - Advance head ptr past empty descrs
*
@@ -1127,6 +1187,7 @@ spider_net_decode_one_descr(struct spider_net_card *card)
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *descr = chain->tail;
struct spider_net_hw_descr *hwdescr = descr->hwdescr;
+ u32 hw_buf_addr;
int status;
status = spider_net_get_descr_status(hwdescr);
@@ -1140,15 +1201,17 @@ spider_net_decode_one_descr(struct spider_net_card *card)
chain->tail = descr->next;
/* unmap descriptor */
- pci_unmap_single(card->pdev, hwdescr->buf_addr,
+ hw_buf_addr = hwdescr->buf_addr;
+ hwdescr->buf_addr = 0xffffffff;
+ pci_unmap_single(card->pdev, hw_buf_addr,
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
(status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
(status == SPIDER_NET_DESCR_FORCE_END) ) {
if (netif_msg_rx_err(card))
- pr_err("%s: dropping RX descriptor with state %d\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev,
+ "dropping RX descriptor with state %d\n", status);
card->netdev_stats.rx_dropped++;
goto bad_desc;
}
@@ -1156,8 +1219,8 @@ spider_net_decode_one_descr(struct spider_net_card *card)
if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
(status != SPIDER_NET_DESCR_FRAME_END) ) {
if (netif_msg_rx_err(card))
- pr_err("%s: RX descriptor with unknown state %d\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev,
+ "RX descriptor with unknown state %d\n", status);
card->spider_stats.rx_desc_unk_state++;
goto bad_desc;
}
@@ -1165,18 +1228,17 @@ spider_net_decode_one_descr(struct spider_net_card *card)
/* The cases we'll throw away the packet immediately */
if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
if (netif_msg_rx_err(card))
- pr_err("%s: error in received descriptor found, "
+ dev_err(&card->netdev->dev,
+ "error in received descriptor found, "
"data_status=x%08x, data_error=x%08x\n",
- card->netdev->name,
hwdescr->data_status, hwdescr->data_error);
goto bad_desc;
}
- if (hwdescr->dmac_cmd_status & 0xfcf4) {
- pr_err("%s: bad status, cmd_status=x%08x\n",
- card->netdev->name,
+ if (hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_BAD_STATUS) {
+ dev_err(&card->netdev->dev, "bad status, cmd_status=x%08x\n",
hwdescr->dmac_cmd_status);
- pr_err("buf_addr=x%08x\n", hwdescr->buf_addr);
+ pr_err("buf_addr=x%08x\n", hw_buf_addr);
pr_err("buf_size=x%08x\n", hwdescr->buf_size);
pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr);
pr_err("result_size=x%08x\n", hwdescr->result_size);
@@ -1196,6 +1258,8 @@ spider_net_decode_one_descr(struct spider_net_card *card)
return 1;
bad_desc:
+ if (netif_msg_rx_err(card))
+ show_rx_chain(card);
dev_kfree_skb_irq(descr->skb);
descr->skb = NULL;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
@@ -1221,7 +1285,6 @@ spider_net_poll(struct net_device *netdev, int *budget)
int packets_to_do, packets_done = 0;
int no_more_packets = 0;
- spider_net_cleanup_tx_ring(card);
packets_to_do = min(*budget, netdev->quota);
while (packets_to_do) {
@@ -1246,6 +1309,8 @@ spider_net_poll(struct net_device *netdev, int *budget)
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
+ spider_net_cleanup_tx_ring(card);
+
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
if (no_more_packets) {
@@ -1415,7 +1480,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GPWFFINT:
/* PHY command queue full */
if (netif_msg_intr(card))
- pr_err("PHY write queue full\n");
+ dev_err(&card->netdev->dev, "PHY write queue full\n");
show_error = 0;
break;
@@ -1582,9 +1647,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
}
if ((show_error) && (netif_msg_intr(card)) && net_ratelimit())
- pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, "
+ dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, "
"GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
- card->netdev->name,
status_reg, error_reg1, error_reg2);
/* clear interrupt sources */
@@ -1849,7 +1913,8 @@ spider_net_init_firmware(struct spider_net_card *card)
SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
- pr_err("Incorrect size of spidernet firmware in " \
+ dev_err(&card->netdev->dev,
+ "Incorrect size of spidernet firmware in " \
"filesystem. Looking in host firmware...\n");
goto try_host_fw;
}
@@ -1873,8 +1938,8 @@ try_host_fw:
if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
- pr_err("Incorrect size of spidernet firmware in " \
- "host firmware\n");
+ dev_err(&card->netdev->dev,
+ "Incorrect size of spidernet firmware in host firmware\n");
goto done;
}
@@ -1884,7 +1949,8 @@ done:
return err;
out_err:
if (netif_msg_probe(card))
- pr_err("Couldn't find spidernet firmware in filesystem " \
+ dev_err(&card->netdev->dev,
+ "Couldn't find spidernet firmware in filesystem " \
"or host firmware\n");
return err;
}
@@ -2279,13 +2345,14 @@ spider_net_setup_netdev(struct spider_net_card *card)
result = spider_net_set_mac(netdev, &addr);
if ((result) && (netif_msg_probe(card)))
- pr_err("Failed to set MAC address: %i\n", result);
+ dev_err(&card->netdev->dev,
+ "Failed to set MAC address: %i\n", result);
result = register_netdev(netdev);
if (result) {
if (netif_msg_probe(card))
- pr_err("Couldn't register net_device: %i\n",
- result);
+ dev_err(&card->netdev->dev,
+ "Couldn't register net_device: %i\n", result);
return result;
}
@@ -2363,17 +2430,19 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
unsigned long mmio_start, mmio_len;
if (pci_enable_device(pdev)) {
- pr_err("Couldn't enable PCI device\n");
+ dev_err(&pdev->dev, "Couldn't enable PCI device\n");
return NULL;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
- pr_err("Couldn't find proper PCI device base address.\n");
+ dev_err(&pdev->dev,
+ "Couldn't find proper PCI device base address.\n");
goto out_disable_dev;
}
if (pci_request_regions(pdev, spider_net_driver_name)) {
- pr_err("Couldn't obtain PCI resources, aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't obtain PCI resources, aborting.\n");
goto out_disable_dev;
}
@@ -2381,8 +2450,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
card = spider_net_alloc_card();
if (!card) {
- pr_err("Couldn't allocate net_device structure, "
- "aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't allocate net_device structure, aborting.\n");
goto out_release_regions;
}
card->pdev = pdev;
@@ -2396,7 +2465,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
card->regs = ioremap(mmio_start, mmio_len);
if (!card->regs) {
- pr_err("Couldn't obtain PCI resources, aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't obtain PCI resources, aborting.\n");
goto out_release_regions;
}
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 1d054aa71504..dbbdb8cee3c6 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -349,11 +349,23 @@ enum spider_net_int2_status {
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
#define SPIDER_NET_DMAC_NOINTR_COMPLETE 0x00800000
-#define SPIDER_NET_DMAC_NOCS 0x00040000
+#define SPIDER_NET_DMAC_TXFRMTL 0x00040000
#define SPIDER_NET_DMAC_TCP 0x00020000
#define SPIDER_NET_DMAC_UDP 0x00030000
#define SPIDER_NET_TXDCEST 0x08000000
+#define SPIDER_NET_DESCR_RXFDIS 0x00000001
+#define SPIDER_NET_DESCR_RXDCEIS 0x00000002
+#define SPIDER_NET_DESCR_RXDEN0IS 0x00000004
+#define SPIDER_NET_DESCR_RXINVDIS 0x00000008
+#define SPIDER_NET_DESCR_RXRERRIS 0x00000010
+#define SPIDER_NET_DESCR_RXFDCIMS 0x00000100
+#define SPIDER_NET_DESCR_RXDCEIMS 0x00000200
+#define SPIDER_NET_DESCR_RXDEN0IMS 0x00000400
+#define SPIDER_NET_DESCR_RXINVDIMS 0x00000800
+#define SPIDER_NET_DESCR_RXRERRMIS 0x00001000
+#define SPIDER_NET_DESCR_UNUSED 0x077fe0e0
+
#define SPIDER_NET_DESCR_IND_PROC_MASK 0xF0000000
#define SPIDER_NET_DESCR_COMPLETE 0x00000000 /* used in rx and tx */
#define SPIDER_NET_DESCR_RESPONSE_ERROR 0x10000000 /* used in rx and tx */
@@ -364,6 +376,13 @@ enum spider_net_int2_status {
#define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000
#define SPIDER_NET_DESCR_TXDESFLG 0x00800000
+#define SPIDER_NET_DESCR_BAD_STATUS (SPIDER_NET_DESCR_RXDEN0IS | \
+ SPIDER_NET_DESCR_RXRERRIS | \
+ SPIDER_NET_DESCR_RXDEN0IMS | \
+ SPIDER_NET_DESCR_RXINVDIMS | \
+ SPIDER_NET_DESCR_RXRERRMIS | \
+ SPIDER_NET_DESCR_UNUSED)
+
/* Descriptor, as defined by the hardware */
struct spider_net_hw_descr {
u32 buf_addr;
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 463d600ed83d..75655add3f34 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -23,9 +23,9 @@
*/
#ifdef TC35815_NAPI
-#define DRV_VERSION "1.35-NAPI"
+#define DRV_VERSION "1.36-NAPI"
#else
-#define DRV_VERSION "1.35"
+#define DRV_VERSION "1.36"
#endif
static const char *version = "tc35815.c:v" DRV_VERSION "\n";
#define MODNAME "tc35815"
@@ -49,6 +49,7 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
#include <linux/pci.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -597,13 +598,46 @@ static int tc_mdio_read(struct net_device *dev, int phy_id, int location);
static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
int val);
-static void __devinit tc35815_init_dev_addr (struct net_device *dev)
+#ifdef CONFIG_CPU_TX49XX
+/*
+ * Find a platform_device providing a MAC address. The platform code
+ * should provide a "tc35815-mac" device with a MAC address in its
+ * platform_data.
+ */
+static int __devinit tc35815_mac_match(struct device *dev, void *data)
+{
+ struct platform_device *plat_dev = to_platform_device(dev);
+ struct pci_dev *pci_dev = data;
+ unsigned int id = (pci_dev->bus->number << 8) | pci_dev->devfn;
+ return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
+}
+
+static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+{
+ struct tc35815_local *lp = dev->priv;
+ struct device *pd = bus_find_device(&platform_bus_type, NULL,
+ lp->pci_dev, tc35815_mac_match);
+ if (pd) {
+ if (pd->platform_data)
+ memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN);
+ put_device(pd);
+ return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV;
+ }
+ return -ENODEV;
+}
+#else
+static int __devinit tc35815_read_plat_dev_addr(struct device *dev)
+{
+ return -ENODEV;
+}
+#endif
+
+static int __devinit tc35815_init_dev_addr (struct net_device *dev)
{
struct tc35815_regs __iomem *tr =
(struct tc35815_regs __iomem *)dev->base_addr;
int i;
- /* dev_addr will be overwritten on NETDEV_REGISTER event */
while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)
;
for (i = 0; i < 6; i += 2) {
@@ -615,6 +649,9 @@ static void __devinit tc35815_init_dev_addr (struct net_device *dev)
dev->dev_addr[i] = data & 0xff;
dev->dev_addr[i+1] = data >> 8;
}
+ if (!is_valid_ether_addr(dev->dev_addr))
+ return tc35815_read_plat_dev_addr(dev);
+ return 0;
}
static int __devinit tc35815_init_one (struct pci_dev *pdev,
@@ -724,7 +761,10 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
tc35815_chip_reset(dev);
/* Retrieve the ethernet address. */
- tc35815_init_dev_addr(dev);
+ if (tc35815_init_dev_addr(dev)) {
+ dev_warn(&pdev->dev, "not valid ether addr\n");
+ random_ether_addr(dev->dev_addr);
+ }
rc = register_netdev (dev);
if (rc)
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 8c9634a98c11..1c537d5a3062 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -2,17 +2,17 @@
# Tulip family network device configuration
#
-menu "Tulip family network device support"
- depends on NET_ETHERNET && (PCI || EISA || CARDBUS)
-
-config NET_TULIP
+menuconfig NET_TULIP
bool "\"Tulip\" family network device support"
+ depends on PCI || EISA || CARDBUS
help
This selects the "Tulip" family of EISA/PCI network cards.
+if NET_TULIP
+
config DE2104X
tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)"
- depends on NET_TULIP && PCI && EXPERIMENTAL
+ depends on PCI && EXPERIMENTAL
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
@@ -30,7 +30,7 @@ config DE2104X
config TULIP
tristate "DECchip Tulip (dc2114x) PCI support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
@@ -95,7 +95,7 @@ config TULIP_NAPI_HW_MITIGATION
config DE4X5
tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
- depends on NET_TULIP && (PCI || EISA)
+ depends on PCI || EISA
select CRC32
---help---
This is support for the DIGITAL series of PCI/EISA Ethernet cards.
@@ -112,7 +112,7 @@ config DE4X5
config WINBOND_840
tristate "Winbond W89c840 Ethernet support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
select MII
help
@@ -123,7 +123,7 @@ config WINBOND_840
config DM9102
tristate "Davicom DM910x/DM980x support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
@@ -137,7 +137,7 @@ config DM9102
config ULI526X
tristate "ULi M526x controller support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is for ULi M5261/M5263 10/100M Ethernet Controller
@@ -149,7 +149,7 @@ config ULI526X
config PCMCIA_XIRCOM
tristate "Xircom CardBus support (new driver)"
- depends on NET_TULIP && CARDBUS
+ depends on CARDBUS
---help---
This driver is for the Digital "Tulip" Ethernet CardBus adapters.
It should work with most DEC 21*4*-based chips/ethercards, as well
@@ -162,7 +162,7 @@ config PCMCIA_XIRCOM
config PCMCIA_XIRTULIP
tristate "Xircom Tulip-like CardBus support (old driver)"
- depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP
+ depends on CARDBUS && BROKEN_ON_SMP
select CRC32
---help---
This driver is for the Digital "Tulip" Ethernet CardBus adapters.
@@ -174,5 +174,4 @@ config PCMCIA_XIRTULIP
<file:Documentation/networking/net-modules.txt>. The module will
be called xircom_tulip_cb. If unsure, say N.
-endmenu
-
+endif # NET_TULIP
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 861729806dc1..d380e0b3f05a 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -785,7 +785,6 @@ static void __de_set_rx_mode (struct net_device *dev)
de->tx_head = NEXT_TX(entry);
- BUG_ON(TX_BUFFS_AVAIL(de) < 0);
if (TX_BUFFS_AVAIL(de) == 0)
netif_stop_queue(dev);
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 62143f92c231..42fca26afc50 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -597,7 +597,7 @@ static char *args;
#endif
struct parameters {
- int fdx;
+ bool fdx;
int autosense;
};
@@ -809,10 +809,10 @@ struct de4x5_private {
s32 irq_en; /* Summary interrupt bits */
int media; /* Media (eg TP), mode (eg 100B)*/
int c_media; /* Remember the last media conn */
- int fdx; /* media full duplex flag */
+ bool fdx; /* media full duplex flag */
int linkOK; /* Link is OK */
int autosense; /* Allow/disallow autosensing */
- int tx_enable; /* Enable descriptor polling */
+ bool tx_enable; /* Enable descriptor polling */
int setup_f; /* Setup frame filtering type */
int local_state; /* State within a 'media' state */
struct mii_phy phy[DE4X5_MAX_PHY]; /* List of attached PHY devices */
@@ -838,8 +838,8 @@ struct de4x5_private {
struct de4x5_srom srom; /* A copy of the SROM */
int cfrv; /* Card CFRV copy */
int rx_ovf; /* Check for 'RX overflow' tag */
- int useSROM; /* For non-DEC card use SROM */
- int useMII; /* Infoblock using the MII */
+ bool useSROM; /* For non-DEC card use SROM */
+ bool useMII; /* Infoblock using the MII */
int asBitValid; /* Autosense bits in GEP? */
int asPolarity; /* 0 => asserted high */
int asBit; /* Autosense bit number in GEP */
@@ -928,7 +928,7 @@ static int dc21040_state(struct net_device *dev, int csr13, int csr14, int c
static int test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
static int test_for_100Mb(struct net_device *dev, int msec);
static int wait_for_link(struct net_device *dev);
-static int test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec);
+static int test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec);
static int is_spd_100(struct net_device *dev);
static int is_100_up(struct net_device *dev);
static int is_10_up(struct net_device *dev);
@@ -1109,7 +1109,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
/*
** Now find out what kind of DC21040/DC21041/DC21140 board we have.
*/
- lp->useSROM = FALSE;
+ lp->useSROM = false;
if (lp->bus == PCI) {
PCI_signature(name, lp);
} else {
@@ -1137,7 +1137,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
lp->cache.gepc = GEP_INIT;
lp->asBit = GEP_SLNK;
lp->asPolarity = GEP_SLNK;
- lp->asBitValid = TRUE;
+ lp->asBitValid = ~0;
lp->timeout = -1;
lp->gendev = gendev;
spin_lock_init(&lp->lock);
@@ -1463,7 +1463,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
u_long flags = 0;
netif_stop_queue(dev);
- if (lp->tx_enable == NO) { /* Cannot send for now */
+ if (!lp->tx_enable) { /* Cannot send for now */
return -1;
}
@@ -2424,7 +2424,7 @@ dc21040_autoconf(struct net_device *dev)
switch (lp->media) {
case INIT:
DISABLE_IRQs;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
lp->timeout = -1;
de4x5_save_skbs(dev);
if ((lp->autosense == AUTO) || (lp->autosense == TP)) {
@@ -2477,7 +2477,7 @@ dc21040_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
break;
}
@@ -2578,7 +2578,7 @@ dc21041_autoconf(struct net_device *dev)
switch (lp->media) {
case INIT:
DISABLE_IRQs;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
lp->timeout = -1;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) {
@@ -2757,7 +2757,7 @@ dc21041_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
break;
}
@@ -2781,7 +2781,7 @@ dc21140m_autoconf(struct net_device *dev)
case INIT:
if (lp->timeout < 0) {
DISABLE_IRQs;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
lp->linkOK = 0;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
}
@@ -2830,7 +2830,7 @@ dc21140m_autoconf(struct net_device *dev)
if (lp->timeout < 0) {
mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
}
- cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+ cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
if (cr < 0) {
next_tick = cr & ~TIMER_CB;
} else {
@@ -2845,7 +2845,7 @@ dc21140m_autoconf(struct net_device *dev)
break;
case 1:
- if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+ if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) {
next_tick = sr & ~TIMER_CB;
} else {
lp->media = SPD_DET;
@@ -2857,10 +2857,10 @@ dc21140m_autoconf(struct net_device *dev)
if (!(anlpa & MII_ANLPA_RF) &&
(cap = anlpa & MII_ANLPA_TAF & ana)) {
if (cap & MII_ANA_100M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
lp->media = _100Mb;
} else if (cap & MII_ANA_10M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
lp->media = _10Mb;
}
@@ -2932,7 +2932,7 @@ dc21140m_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
break;
}
@@ -2965,7 +2965,7 @@ dc2114x_autoconf(struct net_device *dev)
case INIT:
if (lp->timeout < 0) {
DISABLE_IRQs;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
lp->linkOK = 0;
lp->timeout = -1;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
@@ -3013,7 +3013,7 @@ dc2114x_autoconf(struct net_device *dev)
if (lp->timeout < 0) {
mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
}
- cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+ cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
if (cr < 0) {
next_tick = cr & ~TIMER_CB;
} else {
@@ -3028,7 +3028,8 @@ dc2114x_autoconf(struct net_device *dev)
break;
case 1:
- if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+ sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000);
+ if (sr < 0) {
next_tick = sr & ~TIMER_CB;
} else {
lp->media = SPD_DET;
@@ -3040,10 +3041,10 @@ dc2114x_autoconf(struct net_device *dev)
if (!(anlpa & MII_ANLPA_RF) &&
(cap = anlpa & MII_ANLPA_TAF & ana)) {
if (cap & MII_ANA_100M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
lp->media = _100Mb;
} else if (cap & MII_ANA_10M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
lp->media = _10Mb;
}
}
@@ -3222,14 +3223,14 @@ srom_map_media(struct net_device *dev)
{
struct de4x5_private *lp = netdev_priv(dev);
- lp->fdx = 0;
+ lp->fdx = false;
if (lp->infoblock_media == lp->media)
return 0;
switch(lp->infoblock_media) {
case SROM_10BASETF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_10BASET:
if (lp->params.fdx && !lp->fdx) return -1;
if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) {
@@ -3249,7 +3250,7 @@ srom_map_media(struct net_device *dev)
case SROM_100BASETF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_100BASET:
if (lp->params.fdx && !lp->fdx) return -1;
lp->media = _100Mb;
@@ -3261,7 +3262,7 @@ srom_map_media(struct net_device *dev)
case SROM_100BASEFF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_100BASEF:
if (lp->params.fdx && !lp->fdx) return -1;
lp->media = _100Mb;
@@ -3297,7 +3298,7 @@ de4x5_init_connection(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
de4x5_rst_desc_ring(dev);
de4x5_setup_intr(dev);
- lp->tx_enable = YES;
+ lp->tx_enable = true;
spin_unlock_irqrestore(&lp->lock, flags);
outl(POLL_DEMAND, DE4X5_TPD);
@@ -3336,7 +3337,7 @@ de4x5_reset_phy(struct net_device *dev)
}
}
if (lp->useMII) {
- next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500);
+ next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500);
}
} else if (lp->chipset == DC21140) {
PHY_HARD_RESET;
@@ -3466,7 +3467,7 @@ wait_for_link(struct net_device *dev)
**
*/
static int
-test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
+test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec)
{
struct de4x5_private *lp = netdev_priv(dev);
int test;
@@ -3476,9 +3477,8 @@ test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
lp->timeout = msec/100;
}
- if (pol) pol = ~0;
reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
- test = (reg ^ pol) & mask;
+ test = (reg ^ (pol ? ~0 : 0)) & mask;
if (test && --lp->timeout) {
reg = 100 | TIMER_CB;
@@ -3992,10 +3992,10 @@ PCI_signature(char *name, struct de4x5_private *lp)
)))))));
}
if (lp->chipset != DC21041) {
- lp->useSROM = TRUE; /* card is not recognisably DEC */
+ lp->useSROM = true; /* card is not recognisably DEC */
}
} else if ((lp->chipset & ~0x00ff) == DC2114x) {
- lp->useSROM = TRUE;
+ lp->useSROM = true;
}
return status;
@@ -4216,7 +4216,7 @@ srom_repair(struct net_device *dev, int card)
memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom));
memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN);
memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100);
- lp->useSROM = TRUE;
+ lp->useSROM = true;
break;
}
@@ -4392,7 +4392,7 @@ srom_infoleaf_info(struct net_device *dev)
if (lp->chipset == infoleaf_array[i].chipset) break;
}
if (i == INFOLEAF_SIZE) {
- lp->useSROM = FALSE;
+ lp->useSROM = false;
printk("%s: Cannot find correct chipset for SROM decoding!\n",
dev->name);
return -ENXIO;
@@ -4409,7 +4409,7 @@ srom_infoleaf_info(struct net_device *dev)
if (lp->device == *p) break;
}
if (i == 0) {
- lp->useSROM = FALSE;
+ lp->useSROM = false;
printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
dev->name, lp->device);
return -ENXIO;
@@ -4542,7 +4542,7 @@ dc21140_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4577,7 +4577,7 @@ dc21142_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4611,7 +4611,7 @@ dc21143_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4650,7 +4650,7 @@ compact_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4691,7 +4691,7 @@ type0_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4731,7 +4731,7 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->ibn = 1;
lp->active = *p;
lp->infoblock_csr6 = OMR_MII_100;
- lp->useMII = TRUE;
+ lp->useMII = true;
lp->infoblock_media = ANS;
de4x5_switch_mac_port(dev);
@@ -4773,7 +4773,7 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
lp->cache.gep = ((s32)(TWIDDLE(p)) << 16);
lp->infoblock_csr6 = OMR_SIA;
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4814,7 +4814,7 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->active = *p;
if (MOTO_SROM_BUG) lp->active = 0;
lp->infoblock_csr6 = OMR_MII_100;
- lp->useMII = TRUE;
+ lp->useMII = true;
lp->infoblock_media = ANS;
de4x5_switch_mac_port(dev);
@@ -4856,7 +4856,7 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -5077,7 +5077,7 @@ mii_get_phy(struct net_device *dev)
int id;
lp->active = 0;
- lp->useMII = TRUE;
+ lp->useMII = true;
/* Search the MII address space for possible PHY devices */
for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
@@ -5127,7 +5127,7 @@ mii_get_phy(struct net_device *dev)
de4x5_dbg_mii(dev, k);
}
}
- if (!lp->mii_cnt) lp->useMII = FALSE;
+ if (!lp->mii_cnt) lp->useMII = false;
return lp->mii_cnt;
}
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index 57226e5eb8a6..12af0cc037fb 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -893,15 +893,6 @@
#define PHYS_ADDR_ONLY 1 /* Update the physical address only */
/*
-** Booleans
-*/
-#define NO 0
-#define FALSE 0
-
-#define YES ~0
-#define TRUE ~0
-
-/*
** Adapter state
*/
#define INITIALISED 0 /* After h/w initialised and mem alloc'd */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index a12f576391cf..86b690843362 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -192,7 +192,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
usb_pipeendpoint(pipe), maxp, period);
}
}
- return 0;
+ return 0;
}
/* Passes this packet up the stack, updating its accounting.
@@ -326,7 +326,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
if (netif_running (dev->net)
&& netif_device_present (dev->net)
&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
- switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
+ switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
case -EPIPE:
usbnet_defer_kevent (dev, EVENT_RX_HALT);
break;
@@ -393,8 +393,8 @@ static void rx_complete (struct urb *urb)
entry->urb = NULL;
switch (urb_status) {
- // success
- case 0:
+ /* success */
+ case 0:
if (skb->len < dev->net->hard_header_len) {
entry->state = rx_cleanup;
dev->stats.rx_errors++;
@@ -404,28 +404,30 @@ static void rx_complete (struct urb *urb)
}
break;
- // stalls need manual reset. this is rare ... except that
- // when going through USB 2.0 TTs, unplug appears this way.
- // we avoid the highspeed version of the ETIMEOUT/EILSEQ
- // storm, recovering as needed.
- case -EPIPE:
+ /* stalls need manual reset. this is rare ... except that
+ * when going through USB 2.0 TTs, unplug appears this way.
+ * we avoid the highspeed version of the ETIMEOUT/EILSEQ
+ * storm, recovering as needed.
+ */
+ case -EPIPE:
dev->stats.rx_errors++;
usbnet_defer_kevent (dev, EVENT_RX_HALT);
// FALLTHROUGH
- // software-driven interface shutdown
- case -ECONNRESET: // async unlink
- case -ESHUTDOWN: // hardware gone
+ /* software-driven interface shutdown */
+ case -ECONNRESET: /* async unlink */
+ case -ESHUTDOWN: /* hardware gone */
if (netif_msg_ifdown (dev))
devdbg (dev, "rx shutdown, code %d", urb_status);
goto block;
- // we get controller i/o faults during khubd disconnect() delays.
- // throttle down resubmits, to avoid log floods; just temporarily,
- // so we still recover when the fault isn't a khubd delay.
- case -EPROTO:
- case -ETIME:
- case -EILSEQ:
+ /* we get controller i/o faults during khubd disconnect() delays.
+ * throttle down resubmits, to avoid log floods; just temporarily,
+ * so we still recover when the fault isn't a khubd delay.
+ */
+ case -EPROTO:
+ case -ETIME:
+ case -EILSEQ:
dev->stats.rx_errors++;
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@@ -438,12 +440,12 @@ block:
urb = NULL;
break;
- // data overrun ... flush fifo?
- case -EOVERFLOW:
+ /* data overrun ... flush fifo? */
+ case -EOVERFLOW:
dev->stats.rx_over_errors++;
// FALLTHROUGH
- default:
+ default:
entry->state = rx_cleanup;
dev->stats.rx_errors++;
if (netif_msg_rx_err (dev))
@@ -471,22 +473,22 @@ static void intr_complete (struct urb *urb)
int status = urb->status;
switch (status) {
- /* success */
- case 0:
+ /* success */
+ case 0:
dev->driver_info->status(dev, urb);
break;
- /* software-driven interface shutdown */
- case -ENOENT: // urb killed
- case -ESHUTDOWN: // hardware gone
+ /* software-driven interface shutdown */
+ case -ENOENT: /* urb killed */
+ case -ESHUTDOWN: /* hardware gone */
if (netif_msg_ifdown (dev))
devdbg (dev, "intr shutdown, code %d", status);
return;
- /* NOTE: not throttling like RX/TX, since this endpoint
- * already polls infrequently
- */
- default:
+ /* NOTE: not throttling like RX/TX, since this endpoint
+ * already polls infrequently
+ */
+ default:
devdbg (dev, "intr status %d", status);
break;
}
@@ -569,9 +571,9 @@ static int usbnet_stop (struct net_device *net)
temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
// maybe wait for deletions to finish.
- while (!skb_queue_empty(&dev->rxq) &&
- !skb_queue_empty(&dev->txq) &&
- !skb_queue_empty(&dev->done)) {
+ while (!skb_queue_empty(&dev->rxq)
+ && !skb_queue_empty(&dev->txq)
+ && !skb_queue_empty(&dev->done)) {
msleep(UNLINK_TIMEOUT_MS);
if (netif_msg_ifdown (dev))
devdbg (dev, "waited for %d urb completions", temp);
@@ -1011,16 +1013,16 @@ static void usbnet_bh (unsigned long param)
while ((skb = skb_dequeue (&dev->done))) {
entry = (struct skb_data *) skb->cb;
switch (entry->state) {
- case rx_done:
+ case rx_done:
entry->state = rx_cleanup;
rx_process (dev, skb);
continue;
- case tx_done:
- case rx_cleanup:
+ case tx_done:
+ case rx_cleanup:
usb_free_urb (entry->urb);
dev_kfree_skb (skb);
continue;
- default:
+ default:
devdbg (dev, "bogus skb state %d", entry->state);
}
}
diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h
index a3f8b9e7bc00..a6c5820767de 100644
--- a/drivers/net/usb/usbnet.h
+++ b/drivers/net/usb/usbnet.h
@@ -47,7 +47,7 @@ struct usbnet {
unsigned long data [5];
u32 xid;
u32 hard_mtu; /* count any extra framing */
- size_t rx_urb_size; /* size for rx urbs */
+ size_t rx_urb_size; /* size for rx urbs */
struct mii_if_info mii;
/* various kinds of pending driver work */
@@ -85,7 +85,7 @@ struct driver_info {
#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
-#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
/* init device ... can sleep, or cause probe() failure */
int (*bind)(struct usbnet *, struct usb_interface *);
@@ -146,9 +146,9 @@ extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *);
/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
- |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
- |USB_CDC_PACKET_TYPE_PROMISCUOUS \
- |USB_CDC_PACKET_TYPE_DIRECTED)
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
/* we record the state for each of our queued skbs */
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fa2399cbd5ca..ae27af0141c0 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -546,6 +546,18 @@ config USB_ZD1201
To compile this driver as a module, choose M here: the
module will be called zd1201.
+config RTL8187
+ tristate "Realtek 8187 USB support"
+ depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
+ select EEPROM_93CX6
+ ---help---
+ This is a driver for RTL8187 based cards.
+ These are USB based chips found in cards such as:
+
+ Netgear WG111v2
+
+ Thanks to Realtek for their support!
+
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index d2124602263b..ef35bc6c4a22 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -44,3 +44,6 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
obj-$(CONFIG_LIBERTAS_USB) += libertas/
+
+rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
+obj-$(CONFIG_RTL8187) += rtl8187.o
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b37f1e348700..d779199c30d0 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1638,7 +1638,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
return;
}
- if (phy->analog > 1) {
+ if (phy->analog == 1) {
value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
value |= (baseband_attenuation << 2) & 0x003C;
} else {
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 5b3abd54d0e5..90900525379c 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -326,7 +326,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
char *p = page;
struct ap_data *ap = (struct ap_data *) data;
char *policy_txt;
- struct list_head *ptr;
struct mac_entry *entry;
if (off != 0) {
@@ -352,14 +351,12 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
p += sprintf(p, "MAC list:\n");
spin_lock_bh(&ap->mac_restrictions.lock);
- for (ptr = ap->mac_restrictions.mac_list.next;
- ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
+ list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
if (p - page > PAGE_SIZE - 80) {
p += sprintf(p, "All entries did not fit one page.\n");
break;
}
- entry = list_entry(ptr, struct mac_entry, list);
p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
}
spin_unlock_bh(&ap->mac_restrictions.lock);
@@ -413,7 +410,6 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
u8 *mac)
{
- struct list_head *ptr;
struct mac_entry *entry;
int found = 0;
@@ -421,10 +417,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
return 0;
spin_lock_bh(&mac_restrictions->lock);
- for (ptr = mac_restrictions->mac_list.next;
- ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
- entry = list_entry(ptr, struct mac_entry, list);
-
+ list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
found = 1;
break;
@@ -519,7 +512,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
{
char *p = page;
struct ap_data *ap = (struct ap_data *) data;
- struct list_head *ptr;
+ struct sta_info *sta;
int i;
if (off > PROC_LIMIT) {
@@ -529,9 +522,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
spin_lock_bh(&ap->sta_table_lock);
- for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
- struct sta_info *sta = (struct sta_info *) ptr;
-
+ list_for_each_entry(sta, &ap->sta_list, list) {
if (!sta->ap)
continue;
@@ -861,7 +852,7 @@ void hostap_init_ap_proc(local_info_t *local)
void hostap_free_data(struct ap_data *ap)
{
- struct list_head *n, *ptr;
+ struct sta_info *n, *sta;
if (ap == NULL || !ap->initialized) {
printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
@@ -875,8 +866,7 @@ void hostap_free_data(struct ap_data *ap)
ap->crypt = ap->crypt_priv = NULL;
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
- list_for_each_safe(ptr, n, &ap->sta_list) {
- struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry_safe(sta, n, &ap->sta_list, list) {
ap_sta_hash_del(ap, sta);
list_del(&sta->list);
if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
@@ -2704,6 +2694,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
if (hdr->addr1[0] & 0x01) {
/* broadcast/multicast frame - no AP related processing */
+ if (local->ap->num_sta <= 0)
+ ret = AP_TX_DROP;
goto out;
}
@@ -3198,15 +3190,14 @@ int hostap_update_rx_stats(struct ap_data *ap,
void hostap_update_rates(local_info_t *local)
{
- struct list_head *ptr;
+ struct sta_info *sta;
struct ap_data *ap = local->ap;
if (!ap)
return;
spin_lock_bh(&ap->sta_table_lock);
- for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
- struct sta_info *sta = (struct sta_info *) ptr;
+ list_for_each_entry(sta, &ap->sta_list, list) {
prism2_check_tx_rates(sta);
}
spin_unlock_bh(&ap->sta_table_lock);
@@ -3242,11 +3233,10 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
void hostap_add_wds_links(local_info_t *local)
{
struct ap_data *ap = local->ap;
- struct list_head *ptr;
+ struct sta_info *sta;
spin_lock_bh(&ap->sta_table_lock);
- list_for_each(ptr, &ap->sta_list) {
- struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry(sta, &ap->sta_list, list) {
if (sta->ap)
hostap_wds_link_oper(local, sta->addr, WDS_ADD);
}
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index c090a5aebb58..30acd39d76a2 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -1,8 +1,6 @@
#ifndef HOSTAP_CONFIG_H
#define HOSTAP_CONFIG_H
-#define PRISM2_VERSION "0.4.4-kernel"
-
/* In the previous versions of Host AP driver, support for user space version
* of IEEE 802.11 management (hostapd) used to be disabled in the default
* configuration. From now on, support for hostapd is always included and it is
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ee1532b62e42..30e723f65979 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -22,7 +22,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static dev_info_t dev_info = "hostap_cs";
MODULE_AUTHOR("Jouni Malinen");
@@ -30,7 +29,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PC Card).");
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
static int ignore_cis_vcc;
@@ -910,14 +908,12 @@ static struct pcmcia_driver hostap_driver = {
static int __init init_prism2_pccard(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
return pcmcia_register_driver(&hostap_driver);
}
static void __exit exit_prism2_pccard(void)
{
pcmcia_unregister_driver(&hostap_driver);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index cdea7f71b9eb..8c71077d653c 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3893,8 +3893,6 @@ static void prism2_get_drvinfo(struct net_device *dev,
local = iface->local;
strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
- strncpy(info->version, PRISM2_VERSION,
- sizeof(info->version) - 1);
snprintf(info->fw_version, sizeof(info->fw_version) - 1,
"%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
(local->sta_fw_ver >> 8) & 0xff,
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 4743426cf6ad..446de51bab74 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -37,7 +37,6 @@
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP common routines");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
#define TX_TIMEOUT (2 * HZ)
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index db4899ed4bb1..0cd48d151f5e 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -20,7 +20,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static char *dev_info = "hostap_pci";
@@ -29,7 +28,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
"PCI cards.");
MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
/* struct local_info::hw_priv */
@@ -462,8 +460,6 @@ static struct pci_driver prism2_pci_drv_id = {
static int __init init_prism2_pci(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
-
return pci_register_driver(&prism2_pci_drv_id);
}
@@ -471,7 +467,6 @@ static int __init init_prism2_pci(void)
static void __exit exit_prism2_pci(void)
{
pci_unregister_driver(&prism2_pci_drv_id);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index f0fd5ecdb24d..0183df757b3e 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -23,7 +23,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static char *dev_info = "hostap_plx";
@@ -32,7 +31,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PLX).");
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
static int ignore_cis;
@@ -623,8 +621,6 @@ static struct pci_driver prism2_plx_drv_id = {
static int __init init_prism2_plx(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
-
return pci_register_driver(&prism2_plx_drv_id);
}
@@ -632,7 +628,6 @@ static int __init init_prism2_plx(void)
static void __exit exit_prism2_plx(void)
{
pci_unregister_driver(&prism2_plx_drv_id);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
new file mode 100644
index 000000000000..6124e467b156
--- /dev/null
+++ b/drivers/net/wireless/rtl8187.h
@@ -0,0 +1,145 @@
+/*
+ * Definitions for RTL8187 hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL8187_H
+#define RTL8187_H
+
+#include "rtl818x.h"
+
+#define RTL8187_EEPROM_TXPWR_BASE 0x05
+#define RTL8187_EEPROM_MAC_ADDR 0x07
+#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */
+
+#define RTL8187_REQT_READ 0xC0
+#define RTL8187_REQT_WRITE 0x40
+#define RTL8187_REQ_GET_REG 0x05
+#define RTL8187_REQ_SET_REG 0x05
+
+#define RTL8187_MAX_RX 0x9C4
+
+struct rtl8187_rx_info {
+ struct urb *urb;
+ struct ieee80211_hw *dev;
+};
+
+struct rtl8187_rx_hdr {
+ __le16 len;
+ __le16 rate;
+ u8 noise;
+ u8 signal;
+ u8 agc;
+ u8 reserved;
+ __le64 mac_time;
+} __attribute__((packed));
+
+struct rtl8187_tx_info {
+ struct ieee80211_tx_control *control;
+ struct urb *urb;
+ struct ieee80211_hw *dev;
+};
+
+struct rtl8187_tx_hdr {
+ __le32 flags;
+#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15)
+#define RTL8187_TX_FLAG_MORE_FRAG (1 << 17)
+#define RTL8187_TX_FLAG_CTS (1 << 18)
+#define RTL8187_TX_FLAG_RTS (1 << 23)
+ __le16 rts_duration;
+ __le16 len;
+ __le32 retry;
+} __attribute__((packed));
+
+struct rtl8187_priv {
+ /* common between rtl818x drivers */
+ struct rtl818x_csr *map;
+ void (*rf_init)(struct ieee80211_hw *);
+ int mode;
+
+ /* rtl8187 specific */
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+ struct ieee80211_hw_mode modes[2];
+ struct usb_device *udev;
+ u8 *hwaddr;
+ u16 txpwr_base;
+ u8 asic_rev;
+ struct sk_buff_head rx_queue;
+};
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
+
+static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
+{
+ u8 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return val;
+}
+
+static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
+{
+ __le16 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return le16_to_cpu(val);
+}
+
+static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
+{
+ __le32 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return le32_to_cpu(val);
+}
+
+static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
+ u8 *addr, u8 val)
+{
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+}
+
+static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
+ __le16 *addr, u16 val)
+{
+ __le16 buf = cpu_to_le16(val);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
+ __le32 *addr, u32 val)
+{
+ __le32 buf = cpu_to_le32(val);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+#endif /* RTL8187_H */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
new file mode 100644
index 000000000000..cea85894b7f2
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -0,0 +1,731 @@
+/*
+ * Linux device driver for RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays and register offsets below are taken from the original
+ * r8187 driver sources. Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/eeprom_93cx6.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
+MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
+MODULE_DESCRIPTION("RTL8187 USB wireless driver");
+MODULE_LICENSE("GPL");
+
+static struct usb_device_id rtl8187_table[] __devinitdata = {
+ /* Realtek */
+ {USB_DEVICE(0x0bda, 0x8187)},
+ /* Netgear */
+ {USB_DEVICE(0x0846, 0x6100)},
+ {USB_DEVICE(0x0846, 0x6a00)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, rtl8187_table);
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ data <<= 8;
+ data |= addr | 0x80;
+
+ rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
+
+ msleep(1);
+}
+
+static void rtl8187_tx_cb(struct urb *urb)
+{
+ struct ieee80211_tx_status status = { {0} };
+ struct sk_buff *skb = (struct sk_buff *)urb->context;
+ struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
+
+ usb_free_urb(info->urb);
+ if (info->control)
+ memcpy(&status.control, info->control, sizeof(status.control));
+ kfree(info->control);
+ skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
+ status.flags |= IEEE80211_TX_STATUS_ACK;
+ ieee80211_tx_status_irqsafe(info->dev, skb, &status);
+}
+
+static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_tx_hdr *hdr;
+ struct rtl8187_tx_info *info;
+ struct urb *urb;
+ u32 tmp;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ tmp = skb->len - sizeof(*hdr);
+ tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
+ tmp |= control->rts_cts_rate << 19;
+ tmp |= control->tx_rate << 24;
+ if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
+ tmp |= RTL8187_TX_FLAG_MORE_FRAG;
+ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+ tmp |= RTL8187_TX_FLAG_RTS;
+ hdr->rts_duration =
+ ieee80211_rts_duration(dev, skb->len, control);
+ }
+ if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+ tmp |= RTL8187_TX_FLAG_CTS;
+ hdr->flags = cpu_to_le32(tmp);
+ hdr->len = 0;
+ tmp = control->retry_limit << 8;
+ hdr->retry = cpu_to_le32(tmp);
+
+ info = (struct rtl8187_tx_info *)skb->cb;
+ info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
+ info->urb = urb;
+ info->dev = dev;
+ usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
+ hdr, skb->len, rtl8187_tx_cb, skb);
+ usb_submit_urb(urb, GFP_ATOMIC);
+
+ return 0;
+}
+
+static void rtl8187_rx_cb(struct urb *urb)
+{
+ struct sk_buff *skb = (struct sk_buff *)urb->context;
+ struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
+ struct ieee80211_hw *dev = info->dev;
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_rx_hdr *hdr;
+ struct ieee80211_rx_status rx_status = { 0 };
+ int rate, signal;
+
+ spin_lock(&priv->rx_queue.lock);
+ if (skb->next)
+ __skb_unlink(skb, &priv->rx_queue);
+ else {
+ spin_unlock(&priv->rx_queue.lock);
+ return;
+ }
+ spin_unlock(&priv->rx_queue.lock);
+
+ if (unlikely(urb->status)) {
+ usb_free_urb(urb);
+ dev_kfree_skb_irq(skb);
+ return;
+ }
+
+ skb_put(skb, urb->actual_length);
+ hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
+ skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
+
+ signal = hdr->agc >> 1;
+ rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
+ if (rate > 3) { /* OFDM rate */
+ if (signal > 90)
+ signal = 90;
+ else if (signal < 25)
+ signal = 25;
+ signal = 90 - signal;
+ } else { /* CCK rate */
+ if (signal > 95)
+ signal = 95;
+ else if (signal < 30)
+ signal = 30;
+ signal = 95 - signal;
+ }
+
+ rx_status.antenna = (hdr->signal >> 7) & 1;
+ rx_status.signal = 64 - min(hdr->noise, (u8)64);
+ rx_status.ssi = signal;
+ rx_status.rate = rate;
+ rx_status.freq = dev->conf.freq;
+ rx_status.channel = dev->conf.channel;
+ rx_status.phymode = dev->conf.phymode;
+ rx_status.mactime = le64_to_cpu(hdr->mac_time);
+ ieee80211_rx_irqsafe(dev, skb, &rx_status);
+
+ skb = dev_alloc_skb(RTL8187_MAX_RX);
+ if (unlikely(!skb)) {
+ usb_free_urb(urb);
+ /* TODO check rx queue length and refill *somewhere* */
+ return;
+ }
+
+ info = (struct rtl8187_rx_info *)skb->cb;
+ info->urb = urb;
+ info->dev = dev;
+ urb->transfer_buffer = skb_tail_pointer(skb);
+ urb->context = skb;
+ skb_queue_tail(&priv->rx_queue, skb);
+
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl8187_init_urbs(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct urb *entry;
+ struct sk_buff *skb;
+ struct rtl8187_rx_info *info;
+
+ while (skb_queue_len(&priv->rx_queue) < 8) {
+ skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
+ if (!skb)
+ break;
+ entry = usb_alloc_urb(0, GFP_KERNEL);
+ if (!entry) {
+ kfree_skb(skb);
+ break;
+ }
+ usb_fill_bulk_urb(entry, priv->udev,
+ usb_rcvbulkpipe(priv->udev, 1),
+ skb_tail_pointer(skb),
+ RTL8187_MAX_RX, rtl8187_rx_cb, skb);
+ info = (struct rtl8187_rx_info *)skb->cb;
+ info->urb = entry;
+ info->dev = dev;
+ skb_queue_tail(&priv->rx_queue, skb);
+ usb_submit_urb(entry, GFP_KERNEL);
+ }
+
+ return 0;
+}
+
+static int rtl8187_init_hw(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg;
+ int i;
+
+ /* reset */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+ msleep(200);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
+ msleep(200);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= (1 << 1);
+ reg |= RTL818X_CMD_RESET;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ i = 10;
+ do {
+ msleep(2);
+ if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
+ RTL818X_CMD_RESET))
+ break;
+ } while (--i);
+
+ if (!i) {
+ printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
+ return -ETIMEDOUT;
+ }
+
+ /* reload registers from eeprom */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
+
+ i = 10;
+ do {
+ msleep(4);
+ if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
+ RTL818X_EEPROM_CMD_CONFIG))
+ break;
+ } while (--i);
+
+ if (!i) {
+ printk(KERN_ERR "%s: eeprom reset timeout!\n",
+ wiphy_name(dev->wiphy));
+ return -ETIMEDOUT;
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ /* setup card */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
+
+ rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
+ reg &= 0x3F;
+ reg |= 0x80;
+ rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+ rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
+ rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+
+ // TODO: set RESP_RATE and BRSR properly
+ rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+
+ /* host_usb_init */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+ reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
+ rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
+ msleep(100);
+
+ rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+ rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
+ msleep(100);
+
+ priv->rf_init(dev);
+
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+ reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
+ rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
+ rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
+ rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+
+ return 0;
+}
+
+static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
+{
+ u32 reg;
+ struct rtl8187_priv *priv = dev->priv;
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ /* Enable TX loopback on MAC level to avoid TX during channel
+ * changes, as this has be seen to causes problems and the
+ * card will stop work until next reset
+ */
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+ reg | RTL818X_TX_CONF_LOOPBACK_MAC);
+ msleep(10);
+ rtl8225_rf_set_channel(dev, channel);
+ msleep(10);
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+}
+
+static int rtl8187_open(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u32 reg;
+ int ret;
+
+ ret = rtl8187_init_hw(dev);
+ if (ret)
+ return ret;
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+
+ rtl8187_init_urbs(dev);
+
+ reg = RTL818X_RX_CONF_ONLYERLPKT |
+ RTL818X_RX_CONF_RX_AUTORESETPHY |
+ RTL818X_RX_CONF_BSSID |
+ RTL818X_RX_CONF_MGMT |
+ RTL818X_RX_CONF_CTRL |
+ RTL818X_RX_CONF_DATA |
+ (7 << 13 /* RX FIFO threshold NONE */) |
+ (7 << 10 /* MAX RX DMA */) |
+ RTL818X_RX_CONF_BROADCAST |
+ RTL818X_RX_CONF_MULTICAST |
+ RTL818X_RX_CONF_NICMAC;
+ if (priv->mode == IEEE80211_IF_TYPE_MNTR)
+ reg |= RTL818X_RX_CONF_MONITOR;
+
+ rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
+ reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
+ reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+ rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+ reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
+ rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
+
+ reg = RTL818X_TX_CONF_CW_MIN |
+ (7 << 21 /* MAX TX DMA */) |
+ RTL818X_TX_CONF_NO_ICV;
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg |= RTL818X_CMD_TX_ENABLE;
+ reg |= RTL818X_CMD_RX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ return 0;
+}
+
+static int rtl8187_stop(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_rx_info *info;
+ struct sk_buff *skb;
+ u32 reg;
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= ~RTL818X_CMD_TX_ENABLE;
+ reg &= ~RTL818X_CMD_RX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ rtl8225_rf_stop(dev);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ while ((skb = skb_dequeue(&priv->rx_queue))) {
+ info = (struct rtl8187_rx_info *)skb->cb;
+ usb_kill_urb(info->urb);
+ kfree_skb(skb);
+ }
+ return 0;
+}
+
+static int rtl8187_add_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
+ if (priv->mode != IEEE80211_IF_TYPE_MGMT)
+ return -1;
+
+ switch (conf->type) {
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_MNTR:
+ priv->mode = conf->type;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ priv->hwaddr = conf->mac_addr;
+
+ return 0;
+}
+
+static void rtl8187_remove_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ priv->mode = IEEE80211_IF_TYPE_MGMT;
+}
+
+static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ rtl8187_set_channel(dev, conf->channel);
+
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+
+ if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
+ rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
+ rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
+ rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
+ return 0;
+}
+
+static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
+ struct ieee80211_if_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
+
+ if (is_valid_ether_addr(conf->bssid))
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
+ else
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
+
+ return 0;
+}
+
+static const struct ieee80211_ops rtl8187_ops = {
+ .tx = rtl8187_tx,
+ .open = rtl8187_open,
+ .stop = rtl8187_stop,
+ .add_interface = rtl8187_add_interface,
+ .remove_interface = rtl8187_remove_interface,
+ .config = rtl8187_config,
+ .config_interface = rtl8187_config_interface,
+};
+
+static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+ struct ieee80211_hw *dev = eeprom->data;
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+
+ eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+ eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+ eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+ eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+ struct ieee80211_hw *dev = eeprom->data;
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
+
+ if (eeprom->reg_data_in)
+ reg |= RTL818X_EEPROM_CMD_WRITE;
+ if (eeprom->reg_data_out)
+ reg |= RTL818X_EEPROM_CMD_READ;
+ if (eeprom->reg_data_clock)
+ reg |= RTL818X_EEPROM_CMD_CK;
+ if (eeprom->reg_chip_select)
+ reg |= RTL818X_EEPROM_CMD_CS;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+ udelay(10);
+}
+
+static int __devinit rtl8187_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct ieee80211_hw *dev;
+ struct rtl8187_priv *priv;
+ struct eeprom_93cx6 eeprom;
+ struct ieee80211_channel *channel;
+ u16 txpwr, reg;
+ int err, i;
+
+ dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
+ if (!dev) {
+ printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
+ return -ENOMEM;
+ }
+
+ priv = dev->priv;
+
+ SET_IEEE80211_DEV(dev, &intf->dev);
+ usb_set_intfdata(intf, dev);
+ priv->udev = udev;
+
+ usb_get_dev(udev);
+
+ skb_queue_head_init(&priv->rx_queue);
+ memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+ memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+ priv->map = (struct rtl818x_csr *)0xFF00;
+ priv->modes[0].mode = MODE_IEEE80211G;
+ priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+ priv->modes[0].rates = priv->rates;
+ priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+ priv->modes[0].channels = priv->channels;
+ priv->modes[1].mode = MODE_IEEE80211B;
+ priv->modes[1].num_rates = 4;
+ priv->modes[1].rates = priv->rates;
+ priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+ priv->modes[1].channels = priv->channels;
+ priv->mode = IEEE80211_IF_TYPE_MGMT;
+ dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_WEP_INCLUDE_IV |
+ IEEE80211_HW_DATA_NULLFUNC_ACK;
+ dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
+ dev->queues = 1;
+ dev->max_rssi = 65;
+ dev->max_signal = 64;
+
+ for (i = 0; i < 2; i++)
+ if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
+ goto err_free_dev;
+
+ eeprom.data = dev;
+ eeprom.register_read = rtl8187_eeprom_register_read;
+ eeprom.register_write = rtl8187_eeprom_register_write;
+ if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
+ eeprom.width = PCI_EEPROM_WIDTH_93C66;
+ else
+ eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ udelay(10);
+
+ eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR,
+ (__le16 __force *)dev->wiphy->perm_addr, 3);
+ if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+ printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly "
+ "generated MAC address\n");
+ random_ether_addr(dev->wiphy->perm_addr);
+ }
+
+ channel = priv->channels;
+ for (i = 0; i < 3; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+ for (i = 0; i < 2; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+ for (i = 0; i < 2; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
+ &priv->txpwr_base);
+
+ reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
+ /* 0 means asic B-cut, we should use SW 3 wire
+ * bit-by-bit banging for radio. 1 means we can use
+ * USB specific request to write radio registers */
+ priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write(dev, 0, 0x1B7);
+
+ if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
+ priv->rf_init = rtl8225_rf_init;
+ else
+ priv->rf_init = rtl8225z2_rf_init;
+
+ rtl8225_write(dev, 0, 0x0B7);
+
+ err = ieee80211_register_hw(dev);
+ if (err) {
+ printk(KERN_ERR "rtl8187: Cannot register device\n");
+ goto err_free_dev;
+ }
+
+ printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
+ wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
+ priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
+ "rtl8225" : "rtl8225z2");
+
+ return 0;
+
+ err_free_dev:
+ ieee80211_free_hw(dev);
+ usb_set_intfdata(intf, NULL);
+ usb_put_dev(udev);
+ return err;
+}
+
+static void __devexit rtl8187_disconnect(struct usb_interface *intf)
+{
+ struct ieee80211_hw *dev = usb_get_intfdata(intf);
+ struct rtl8187_priv *priv;
+
+ if (!dev)
+ return;
+
+ ieee80211_unregister_hw(dev);
+
+ priv = dev->priv;
+ usb_put_dev(interface_to_usbdev(intf));
+ ieee80211_free_hw(dev);
+}
+
+static struct usb_driver rtl8187_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = rtl8187_table,
+ .probe = rtl8187_probe,
+ .disconnect = rtl8187_disconnect,
+};
+
+static int __init rtl8187_init(void)
+{
+ return usb_register(&rtl8187_driver);
+}
+
+static void __exit rtl8187_exit(void)
+{
+ usb_deregister(&rtl8187_driver);
+}
+
+module_init(rtl8187_init);
+module_exit(rtl8187_exit);
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
new file mode 100644
index 000000000000..e25a09f1b068
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -0,0 +1,745 @@
+/*
+ * Radio tuning for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays, register offsets, and phy value tables below are
+ * taken from the original r8187 driver sources. Thanks to Realtek
+ * for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg84, reg82;
+ u32 bangdata;
+ int i;
+
+ bangdata = (data << 4) | (addr & 0xf);
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
+
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(10);
+
+ for (i = 15; i >= 0; i--) {
+ u16 reg = reg80 | (bangdata & (1 << i)) >> i;
+
+ if (i & 1)
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+
+ if (!(i & 1))
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ msleep(2);
+}
+
+static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg82, reg84;
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+ reg80 &= ~(0x3 << 2);
+ reg84 &= ~0xF;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(10);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ addr, 0x8225, &data, sizeof(data), HZ / 2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ msleep(2);
+}
+
+void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ if (priv->asic_rev)
+ rtl8225_write_8051(dev, addr, data);
+ else
+ rtl8225_write_bitbang(dev, addr, data);
+}
+
+u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg82, reg84, out;
+ int i;
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+ reg80 &= ~0xF;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(4);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(5);
+
+ for (i = 4; i >= 0; i--) {
+ u16 reg = reg80 | ((addr >> i) & 1);
+
+ if (!(i & 1)) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ udelay(1);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ udelay(2);
+
+ if (i & 1) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ udelay(1);
+ }
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+
+ out = 0;
+ for (i = 11; i >= 0; i--) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(1);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+
+ if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
+ out |= 1 << i;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 2));
+ udelay(2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
+
+ return out;
+}
+
+static const u16 rtl8225bcd_rxgain[] = {
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static const u8 rtl8225_agc[] = {
+ 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
+ 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+ 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
+ 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+ 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
+ 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+ 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
+ 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+ 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+ 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
+ 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+ 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
+ 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const u8 rtl8225_gain[] = {
+ 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
+ 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
+ 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
+ 0x33, 0x80, 0x79, 0xc5, /* -78dBm */
+ 0x43, 0x78, 0x76, 0xc5, /* -74dBm */
+ 0x53, 0x60, 0x73, 0xc5, /* -70dBm */
+ 0x63, 0x58, 0x70, 0xc5, /* -66dBm */
+};
+
+static const u8 rtl8225_threshold[] = {
+ 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
+};
+
+static const u8 rtl8225_tx_gain_cck_ofdm[] = {
+ 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static const u8 rtl8225_tx_power_cck[] = {
+ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static const u8 rtl8225_tx_power_cck_ch14[] = {
+ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225_tx_power_ofdm[] = {
+ 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static const u32 rtl8225_chan[] = {
+ 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
+ 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
+};
+
+static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ u32 reg;
+ int i;
+
+ cck_power = priv->channels[channel - 1].val & 0xF;
+ ofdm_power = priv->channels[channel - 1].val >> 4;
+
+ cck_power = min(cck_power, (u8)11);
+ ofdm_power = min(ofdm_power, (u8)35);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+ rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
+
+ if (channel == 14)
+ tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
+ else
+ tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ msleep(1); // FIXME: optional?
+
+ /* anaparam2 on */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write_phy_ofdm(dev, 2, 0x42);
+ rtl8225_write_phy_ofdm(dev, 6, 0x00);
+ rtl8225_write_phy_ofdm(dev, 8, 0x00);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+ rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
+
+ tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
+
+ rtl8225_write_phy_ofdm(dev, 5, *tmp);
+ rtl8225_write_phy_ofdm(dev, 7, *tmp);
+
+ msleep(1);
+}
+
+void rtl8225_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ rtl8225_write(dev, 0x0, 0x067); msleep(1);
+ rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+ rtl8225_write(dev, 0x3, 0x441); msleep(1);
+ rtl8225_write(dev, 0x4, 0x486); msleep(1);
+ rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
+ rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
+ rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+ rtl8225_write(dev, 0x8, 0x01F); msleep(1);
+ rtl8225_write(dev, 0x9, 0x334); msleep(1);
+ rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
+ rtl8225_write(dev, 0xB, 0x391); msleep(1);
+ rtl8225_write(dev, 0xC, 0x050); msleep(1);
+ rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
+ rtl8225_write(dev, 0xE, 0x029); msleep(1);
+ rtl8225_write(dev, 0xF, 0x914); msleep(100);
+
+ rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(200);
+
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0c4d);
+ msleep(200);
+ rtl8225_write(dev, 0x02, 0x044d);
+ msleep(100);
+ if (!(rtl8225_read(dev, 6) & (1 << 7)))
+ printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+ wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+ }
+
+ rtl8225_write(dev, 0x0, 0x127);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x0, 0x027);
+ rtl8225_write(dev, 0x0, 0x22F);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ msleep(1);
+ }
+
+ msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+ rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+ rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
+
+ rtl8225_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ msleep(1);
+ rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+
+ /* set sensitivity */
+ rtl8225_write(dev, 0x0c, 0x50);
+ rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+ rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+ rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
+}
+
+static const u8 rtl8225z2_tx_power_cck_ch14[] = {
+ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225z2_tx_power_cck[] = {
+ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_ofdm[] = {
+ 0x42, 0x00, 0x40, 0x00, 0x40
+};
+
+static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
+};
+
+static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ u32 reg;
+ int i;
+
+ cck_power = priv->channels[channel - 1].val & 0xF;
+ ofdm_power = priv->channels[channel - 1].val >> 4;
+
+ cck_power = min(cck_power, (u8)15);
+ cck_power += priv->txpwr_base & 0xF;
+ cck_power = min(cck_power, (u8)35);
+
+ ofdm_power = min(ofdm_power, (u8)15);
+ ofdm_power += priv->txpwr_base >> 4;
+ ofdm_power = min(ofdm_power, (u8)35);
+
+ if (channel == 14)
+ tmp = rtl8225z2_tx_power_cck_ch14;
+ else
+ tmp = rtl8225z2_tx_power_cck;
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+ rtl8225z2_tx_gain_cck_ofdm[cck_power]);
+ msleep(1);
+
+ /* anaparam2 on */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write_phy_ofdm(dev, 2, 0x42);
+ rtl8225_write_phy_ofdm(dev, 5, 0x00);
+ rtl8225_write_phy_ofdm(dev, 6, 0x40);
+ rtl8225_write_phy_ofdm(dev, 7, 0x00);
+ rtl8225_write_phy_ofdm(dev, 8, 0x40);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+ rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
+ msleep(1);
+}
+
+static const u16 rtl8225z2_rxgain[] = {
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static const u8 rtl8225z2_gain_bg[] = {
+ 0x23, 0x15, 0xa5, /* -82-1dBm */
+ 0x23, 0x15, 0xb5, /* -82-2dBm */
+ 0x23, 0x15, 0xc5, /* -82-3dBm */
+ 0x33, 0x15, 0xc5, /* -78dBm */
+ 0x43, 0x15, 0xc5, /* -74dBm */
+ 0x53, 0x15, 0xc5, /* -70dBm */
+ 0x63, 0x15, 0xc5 /* -66dBm */
+};
+
+void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
+ rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+ rtl8225_write(dev, 0x3, 0x441); msleep(1);
+ rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
+ rtl8225_write(dev, 0x5, 0xC72); msleep(1);
+ rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
+ rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+ rtl8225_write(dev, 0x8, 0x03F); msleep(1);
+ rtl8225_write(dev, 0x9, 0x335); msleep(1);
+ rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
+ rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
+ rtl8225_write(dev, 0xc, 0x850); msleep(1);
+ rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
+ rtl8225_write(dev, 0xe, 0x02B); msleep(1);
+ rtl8225_write(dev, 0xf, 0x114); msleep(100);
+
+ rtl8225_write(dev, 0x0, 0x1B7);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x3, 0x080);
+ rtl8225_write(dev, 0x5, 0x004);
+ rtl8225_write(dev, 0x0, 0x0B7);
+ rtl8225_write(dev, 0x2, 0xc4D);
+
+ msleep(200);
+ rtl8225_write(dev, 0x2, 0x44D);
+ msleep(100);
+
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0C4D);
+ msleep(200);
+ rtl8225_write(dev, 0x02, 0x044D);
+ msleep(100);
+ if (!(rtl8225_read(dev, 6) & (1 << 7)))
+ printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+ wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+ }
+
+ msleep(200);
+
+ rtl8225_write(dev, 0x0, 0x2BF);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ msleep(1);
+ }
+
+ msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+ rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
+
+ rtl8225z2_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ msleep(1);
+ rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+}
+
+void rtl8225_rf_stop(struct ieee80211_hw *dev)
+{
+ u8 reg;
+ struct rtl8187_priv *priv = dev->priv;
+
+ rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ if (priv->rf_init == rtl8225_rf_init)
+ rtl8225_rf_set_tx_power(dev, channel);
+ else
+ rtl8225z2_rf_set_tx_power(dev, channel);
+
+ rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
+ msleep(10);
+}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
new file mode 100644
index 000000000000..798ba4a97376
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -0,0 +1,44 @@
+/*
+ * Radio tuning definitions for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL8187_RTL8225_H
+#define RTL8187_RTL8225_H
+
+#define RTL8225_ANAPARAM_ON 0xa0000a59
+#define RTL8225_ANAPARAM2_ON 0x860c7312
+#define RTL8225_ANAPARAM_OFF 0xa00beb59
+#define RTL8225_ANAPARAM2_OFF 0x840dec11
+
+void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
+u16 rtl8225_read(struct ieee80211_hw *, u8 addr);
+
+void rtl8225_rf_init(struct ieee80211_hw *);
+void rtl8225z2_rf_init(struct ieee80211_hw *);
+void rtl8225_rf_stop(struct ieee80211_hw *);
+void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
+
+
+static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
+ u8 addr, u32 data)
+{
+ rtl8187_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
+ u8 addr, u32 data)
+{
+ rtl8187_write_phy(dev, addr, data | 0x10000);
+}
+
+#endif /* RTL8187_RTL8225_H */
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
new file mode 100644
index 000000000000..283de30628e1
--- /dev/null
+++ b/drivers/net/wireless/rtl818x.h
@@ -0,0 +1,226 @@
+/*
+ * Definitions for RTL818x hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL818X_H
+#define RTL818X_H
+
+struct rtl818x_csr {
+ u8 MAC[6];
+ u8 reserved_0[2];
+ __le32 MAR[2];
+ u8 RX_FIFO_COUNT;
+ u8 reserved_1;
+ u8 TX_FIFO_COUNT;
+ u8 BQREQ;
+ u8 reserved_2[4];
+ __le32 TSFT[2];
+ __le32 TLPDA;
+ __le32 TNPDA;
+ __le32 THPDA;
+ __le16 BRSR;
+ u8 BSSID[6];
+ u8 RESP_RATE;
+ u8 EIFS;
+ u8 reserved_3[1];
+ u8 CMD;
+#define RTL818X_CMD_TX_ENABLE (1 << 2)
+#define RTL818X_CMD_RX_ENABLE (1 << 3)
+#define RTL818X_CMD_RESET (1 << 4)
+ u8 reserved_4[4];
+ __le16 INT_MASK;
+ __le16 INT_STATUS;
+#define RTL818X_INT_RX_OK (1 << 0)
+#define RTL818X_INT_RX_ERR (1 << 1)
+#define RTL818X_INT_TXL_OK (1 << 2)
+#define RTL818X_INT_TXL_ERR (1 << 3)
+#define RTL818X_INT_RX_DU (1 << 4)
+#define RTL818X_INT_RX_FO (1 << 5)
+#define RTL818X_INT_TXN_OK (1 << 6)
+#define RTL818X_INT_TXN_ERR (1 << 7)
+#define RTL818X_INT_TXH_OK (1 << 8)
+#define RTL818X_INT_TXH_ERR (1 << 9)
+#define RTL818X_INT_TXB_OK (1 << 10)
+#define RTL818X_INT_TXB_ERR (1 << 11)
+#define RTL818X_INT_ATIM (1 << 12)
+#define RTL818X_INT_BEACON (1 << 13)
+#define RTL818X_INT_TIME_OUT (1 << 14)
+#define RTL818X_INT_TX_FO (1 << 15)
+ __le32 TX_CONF;
+#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17)
+#define RTL818X_TX_CONF_NO_ICV (1 << 19)
+#define RTL818X_TX_CONF_DISCW (1 << 20)
+#define RTL818X_TX_CONF_R8180_ABCD (2 << 25)
+#define RTL818X_TX_CONF_R8180_F (3 << 25)
+#define RTL818X_TX_CONF_R8185_ABC (4 << 25)
+#define RTL818X_TX_CONF_R8185_D (5 << 25)
+#define RTL818X_TX_CONF_HWVER_MASK (7 << 25)
+#define RTL818X_TX_CONF_CW_MIN (1 << 31)
+ __le32 RX_CONF;
+#define RTL818X_RX_CONF_MONITOR (1 << 0)
+#define RTL818X_RX_CONF_NICMAC (1 << 1)
+#define RTL818X_RX_CONF_MULTICAST (1 << 2)
+#define RTL818X_RX_CONF_BROADCAST (1 << 3)
+#define RTL818X_RX_CONF_DATA (1 << 18)
+#define RTL818X_RX_CONF_CTRL (1 << 19)
+#define RTL818X_RX_CONF_MGMT (1 << 20)
+#define RTL818X_RX_CONF_BSSID (1 << 23)
+#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28)
+#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31)
+ __le32 INT_TIMEOUT;
+ __le32 TBDA;
+ u8 EEPROM_CMD;
+#define RTL818X_EEPROM_CMD_READ (1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
+#define RTL818X_EEPROM_CMD_CK (1 << 2)
+#define RTL818X_EEPROM_CMD_CS (1 << 3)
+#define RTL818X_EEPROM_CMD_NORMAL (0 << 6)
+#define RTL818X_EEPROM_CMD_LOAD (1 << 6)
+#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6)
+#define RTL818X_EEPROM_CMD_CONFIG (3 << 6)
+ u8 CONFIG0;
+ u8 CONFIG1;
+ u8 CONFIG2;
+ __le32 ANAPARAM;
+ u8 MSR;
+#define RTL818X_MSR_NO_LINK (0 << 2)
+#define RTL818X_MSR_ADHOC (1 << 2)
+#define RTL818X_MSR_INFRA (2 << 2)
+ u8 CONFIG3;
+#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6)
+ u8 CONFIG4;
+#define RTL818X_CONFIG4_POWEROFF (1 << 6)
+#define RTL818X_CONFIG4_VCOOFF (1 << 7)
+ u8 TESTR;
+ u8 reserved_9[2];
+ __le16 PGSELECT;
+ __le32 ANAPARAM2;
+ u8 reserved_10[12];
+ __le16 BEACON_INTERVAL;
+ __le16 ATIM_WND;
+ __le16 BEACON_INTERVAL_TIME;
+ __le16 ATIMTR_INTERVAL;
+ u8 reserved_11[4];
+ u8 PHY[4];
+ __le16 RFPinsOutput;
+ __le16 RFPinsEnable;
+ __le16 RFPinsSelect;
+ __le16 RFPinsInput;
+ __le32 RF_PARA;
+ __le32 RF_TIMING;
+ u8 GP_ENABLE;
+ u8 GPIO;
+ u8 reserved_12[10];
+ u8 TX_AGC_CTL;
+#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0)
+#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1)
+#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2)
+ u8 TX_GAIN_CCK;
+ u8 TX_GAIN_OFDM;
+ u8 TX_ANTENNA;
+ u8 reserved_13[16];
+ u8 WPA_CONF;
+ u8 reserved_14[3];
+ u8 SIFS;
+ u8 DIFS;
+ u8 SLOT;
+ u8 reserved_15[5];
+ u8 CW_CONF;
+#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0)
+#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1)
+ u8 CW_VAL;
+ u8 RATE_FALLBACK;
+ u8 reserved_16[25];
+ u8 CONFIG5;
+ u8 TX_DMA_POLLING;
+ u8 reserved_17[2];
+ __le16 CWR;
+ u8 RETRY_CTR;
+ u8 reserved_18[5];
+ __le32 RDSAR;
+ u8 reserved_19[18];
+ u16 TALLY_CNT;
+ u8 TALLY_SEL;
+} __attribute__((packed));
+
+static const struct ieee80211_rate rtl818x_rates[] = {
+ { .rate = 10,
+ .val = 0,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 20,
+ .val = 1,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 55,
+ .val = 2,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 110,
+ .val = 3,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 60,
+ .val = 4,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 90,
+ .val = 5,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 120,
+ .val = 6,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 180,
+ .val = 7,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 240,
+ .val = 8,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 360,
+ .val = 9,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 480,
+ .val = 10,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 540,
+ .val = 11,
+ .flags = IEEE80211_RATE_OFDM },
+};
+
+static const struct ieee80211_channel rtl818x_channels[] = {
+ { .chan = 1,
+ .freq = 2412},
+ { .chan = 2,
+ .freq = 2417},
+ { .chan = 3,
+ .freq = 2422},
+ { .chan = 4,
+ .freq = 2427},
+ { .chan = 5,
+ .freq = 2432},
+ { .chan = 6,
+ .freq = 2437},
+ { .chan = 7,
+ .freq = 2442},
+ { .chan = 8,
+ .freq = 2447},
+ { .chan = 9,
+ .freq = 2452},
+ { .chan = 10,
+ .freq = 2457},
+ { .chan = 11,
+ .freq = 2462},
+ { .chan = 12,
+ .freq = 2467},
+ { .chan = 13,
+ .freq = 2472},
+ { .chan = 14,
+ .freq = 2484}
+};
+
+#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 6603ad5be63d..4d505903352c 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o
zd1211rw-objs := zd_chip.o zd_ieee80211.o \
zd_mac.o zd_netdev.o \
zd_rf_al2230.o zd_rf_rf2959.o \
- zd_rf_al7230b.o \
+ zd_rf_al7230b.o zd_rf_uw2453.o \
zd_rf.o zd_usb.o zd_util.o
ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 95b4a2a26707..5b624bfc01a6 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1253,6 +1253,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
{
int r;
+ if (!zd_rf_should_update_pwr_int(&chip->rf))
+ return 0;
+
r = update_pwr_int(chip, channel);
if (r)
return r;
@@ -1283,7 +1286,7 @@ static int patch_cck_gain(struct zd_chip *chip)
int r;
u32 value;
- if (!chip->patch_cck_gain)
+ if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
return 0;
ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ce0a5f6da0d2..79d0288c193a 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -608,6 +608,9 @@ enum {
#define CR_ZD1211B_TXOP CTL_REG(0x0b20)
#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28)
+/* Used to detect PLL lock */
+#define UW2453_INTR_REG ((zd_addr_t)0x85c1)
+
#define CWIN_SIZE 0x007f043f
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 549c23bcd6cc..7407409b60b1 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -52,34 +52,38 @@ const char *zd_rf_name(u8 type)
void zd_rf_init(struct zd_rf *rf)
{
memset(rf, 0, sizeof(*rf));
+
+ /* default to update channel integration, as almost all RF's do want
+ * this */
+ rf->update_channel_int = 1;
}
void zd_rf_clear(struct zd_rf *rf)
{
+ if (rf->clear)
+ rf->clear(rf);
ZD_MEMCLEAR(rf, sizeof(*rf));
}
int zd_rf_init_hw(struct zd_rf *rf, u8 type)
{
- int r, t;
+ int r = 0;
+ int t;
struct zd_chip *chip = zd_rf_to_chip(rf);
ZD_ASSERT(mutex_is_locked(&chip->mutex));
switch (type) {
case RF2959_RF:
r = zd_rf_init_rf2959(rf);
- if (r)
- return r;
break;
case AL2230_RF:
r = zd_rf_init_al2230(rf);
- if (r)
- return r;
break;
case AL7230B_RF:
r = zd_rf_init_al7230b(rf);
- if (r)
- return r;
+ break;
+ case UW2453_RF:
+ r = zd_rf_init_uw2453(rf);
break;
default:
dev_err(zd_chip_dev(chip),
@@ -88,6 +92,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
return -ENODEV;
}
+ if (r)
+ return r;
+
rf->type = type;
r = zd_chip_lock_phy_regs(chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index aa9cc105ce60..c6dfd8227f6e 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -48,12 +48,26 @@ struct zd_rf {
u8 channel;
+ /* whether channel integration and calibration should be updated
+ * defaults to 1 (yes) */
+ u8 update_channel_int:1;
+
+ /* whether CR47 should be patched from the EEPROM, if the appropriate
+ * flag is set in the POD. The vendor driver suggests that this should
+ * be done for all RF's, but a bug in their code prevents but their
+ * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
+ u8 patch_cck_gain:1;
+
+ /* private RF driver data */
+ void *priv;
+
/* RF-specific functions */
int (*init_hw)(struct zd_rf *rf);
int (*set_channel)(struct zd_rf *rf, u8 channel);
int (*switch_radio_on)(struct zd_rf *rf);
int (*switch_radio_off)(struct zd_rf *rf);
int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
+ void (*clear)(struct zd_rf *rf);
};
const char *zd_rf_name(u8 type);
@@ -71,10 +85,24 @@ int zd_switch_radio_off(struct zd_rf *rf);
int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
+{
+ return rf->update_channel_int;
+}
+
+static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
+{
+ return rf->patch_cck_gain;
+}
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+
/* Functions for individual RF chips */
int zd_rf_init_rf2959(struct zd_rf *rf);
int zd_rf_init_al2230(struct zd_rf *rf);
int zd_rf_init_al7230b(struct zd_rf *rf);
+int zd_rf_init_uw2453(struct zd_rf *rf);
#endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 511392acfedf..e7a4ecf7b6e2 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -432,5 +432,6 @@ int zd_rf_init_al2230(struct zd_rf *rf)
rf->switch_radio_on = zd1211_al2230_switch_radio_on;
}
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->patch_cck_gain = 1;
return 0;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index 5e5e9ddc6a74..f4e8b6ada854 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -483,6 +483,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf)
rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
rf->set_channel = zd1211_al7230b_set_channel;
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->patch_cck_gain = 1;
}
rf->switch_radio_off = al7230b_switch_radio_off;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
new file mode 100644
index 000000000000..414e40d571ab
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -0,0 +1,534 @@
+/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+/* This RF programming code is based upon the code found in v2.16.0.0 of the
+ * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
+ * for this RF on their website, so we're able to understand more than
+ * usual as to what is going on. Thumbs up for Ubec for doing that. */
+
+/* The 3-wire serial interface provides access to 8 write-only registers.
+ * The data format is a 4 bit register address followed by a 20 bit value. */
+#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
+
+/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
+ * fractional divide ratio) and 3 (VCO config).
+ *
+ * We configure the RF to produce an interrupt when the PLL is locked onto
+ * the configured frequency. During initialization, we run through a variety
+ * of different VCO configurations on channel 1 until we detect a PLL lock.
+ * When this happens, we remember which VCO configuration produced the lock
+ * and use it later. Actually, we use the configuration *after* the one that
+ * produced the lock, which seems odd, but it works.
+ *
+ * If we do not see a PLL lock on any standard VCO config, we fall back on an
+ * autocal configuration, which has a fixed (as opposed to per-channel) VCO
+ * config and different synth values from the standard set (divide ratio
+ * is still shared with the standard set). */
+
+/* The per-channel synth values for all standard VCO configurations. These get
+ * written to register 1. */
+static const u8 uw2453_std_synth[] = {
+ RF_CHANNEL( 1) = 0x47,
+ RF_CHANNEL( 2) = 0x47,
+ RF_CHANNEL( 3) = 0x67,
+ RF_CHANNEL( 4) = 0x67,
+ RF_CHANNEL( 5) = 0x67,
+ RF_CHANNEL( 6) = 0x67,
+ RF_CHANNEL( 7) = 0x57,
+ RF_CHANNEL( 8) = 0x57,
+ RF_CHANNEL( 9) = 0x57,
+ RF_CHANNEL(10) = 0x57,
+ RF_CHANNEL(11) = 0x77,
+ RF_CHANNEL(12) = 0x77,
+ RF_CHANNEL(13) = 0x77,
+ RF_CHANNEL(14) = 0x4f,
+};
+
+/* This table stores the synthesizer fractional divide ratio for *all* VCO
+ * configurations (both standard and autocal). These get written to register 2.
+ */
+static const u16 uw2453_synth_divide[] = {
+ RF_CHANNEL( 1) = 0x999,
+ RF_CHANNEL( 2) = 0x99b,
+ RF_CHANNEL( 3) = 0x998,
+ RF_CHANNEL( 4) = 0x99a,
+ RF_CHANNEL( 5) = 0x999,
+ RF_CHANNEL( 6) = 0x99b,
+ RF_CHANNEL( 7) = 0x998,
+ RF_CHANNEL( 8) = 0x99a,
+ RF_CHANNEL( 9) = 0x999,
+ RF_CHANNEL(10) = 0x99b,
+ RF_CHANNEL(11) = 0x998,
+ RF_CHANNEL(12) = 0x99a,
+ RF_CHANNEL(13) = 0x999,
+ RF_CHANNEL(14) = 0xccc,
+};
+
+/* Here is the data for all the standard VCO configurations. We shrink our
+ * table a little by observing that both channels in a consecutive pair share
+ * the same value. We also observe that the high 4 bits ([0:3] in the specs)
+ * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
+ * below. */
+#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
+#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
+static const u16 uw2453_std_vco_cfg[][7] = {
+ { /* table 1 */
+ RF_CHANPAIR( 1, 2) = 0x664d,
+ RF_CHANPAIR( 3, 4) = 0x604d,
+ RF_CHANPAIR( 5, 6) = 0x6675,
+ RF_CHANPAIR( 7, 8) = 0x6475,
+ RF_CHANPAIR( 9, 10) = 0x6655,
+ RF_CHANPAIR(11, 12) = 0x6455,
+ RF_CHANPAIR(13, 14) = 0x6665,
+ },
+ { /* table 2 */
+ RF_CHANPAIR( 1, 2) = 0x666d,
+ RF_CHANPAIR( 3, 4) = 0x606d,
+ RF_CHANPAIR( 5, 6) = 0x664d,
+ RF_CHANPAIR( 7, 8) = 0x644d,
+ RF_CHANPAIR( 9, 10) = 0x6675,
+ RF_CHANPAIR(11, 12) = 0x6475,
+ RF_CHANPAIR(13, 14) = 0x6655,
+ },
+ { /* table 3 */
+ RF_CHANPAIR( 1, 2) = 0x665d,
+ RF_CHANPAIR( 3, 4) = 0x605d,
+ RF_CHANPAIR( 5, 6) = 0x666d,
+ RF_CHANPAIR( 7, 8) = 0x646d,
+ RF_CHANPAIR( 9, 10) = 0x664d,
+ RF_CHANPAIR(11, 12) = 0x644d,
+ RF_CHANPAIR(13, 14) = 0x6675,
+ },
+ { /* table 4 */
+ RF_CHANPAIR( 1, 2) = 0x667d,
+ RF_CHANPAIR( 3, 4) = 0x607d,
+ RF_CHANPAIR( 5, 6) = 0x665d,
+ RF_CHANPAIR( 7, 8) = 0x645d,
+ RF_CHANPAIR( 9, 10) = 0x666d,
+ RF_CHANPAIR(11, 12) = 0x646d,
+ RF_CHANPAIR(13, 14) = 0x664d,
+ },
+ { /* table 5 */
+ RF_CHANPAIR( 1, 2) = 0x6643,
+ RF_CHANPAIR( 3, 4) = 0x6043,
+ RF_CHANPAIR( 5, 6) = 0x667d,
+ RF_CHANPAIR( 7, 8) = 0x647d,
+ RF_CHANPAIR( 9, 10) = 0x665d,
+ RF_CHANPAIR(11, 12) = 0x645d,
+ RF_CHANPAIR(13, 14) = 0x666d,
+ },
+ { /* table 6 */
+ RF_CHANPAIR( 1, 2) = 0x6663,
+ RF_CHANPAIR( 3, 4) = 0x6063,
+ RF_CHANPAIR( 5, 6) = 0x6643,
+ RF_CHANPAIR( 7, 8) = 0x6443,
+ RF_CHANPAIR( 9, 10) = 0x667d,
+ RF_CHANPAIR(11, 12) = 0x647d,
+ RF_CHANPAIR(13, 14) = 0x665d,
+ },
+ { /* table 7 */
+ RF_CHANPAIR( 1, 2) = 0x6653,
+ RF_CHANPAIR( 3, 4) = 0x6053,
+ RF_CHANPAIR( 5, 6) = 0x6663,
+ RF_CHANPAIR( 7, 8) = 0x6463,
+ RF_CHANPAIR( 9, 10) = 0x6643,
+ RF_CHANPAIR(11, 12) = 0x6443,
+ RF_CHANPAIR(13, 14) = 0x667d,
+ },
+ { /* table 8 */
+ RF_CHANPAIR( 1, 2) = 0x6673,
+ RF_CHANPAIR( 3, 4) = 0x6073,
+ RF_CHANPAIR( 5, 6) = 0x6653,
+ RF_CHANPAIR( 7, 8) = 0x6453,
+ RF_CHANPAIR( 9, 10) = 0x6663,
+ RF_CHANPAIR(11, 12) = 0x6463,
+ RF_CHANPAIR(13, 14) = 0x6643,
+ },
+ { /* table 9 */
+ RF_CHANPAIR( 1, 2) = 0x664b,
+ RF_CHANPAIR( 3, 4) = 0x604b,
+ RF_CHANPAIR( 5, 6) = 0x6673,
+ RF_CHANPAIR( 7, 8) = 0x6473,
+ RF_CHANPAIR( 9, 10) = 0x6653,
+ RF_CHANPAIR(11, 12) = 0x6453,
+ RF_CHANPAIR(13, 14) = 0x6663,
+ },
+ { /* table 10 */
+ RF_CHANPAIR( 1, 2) = 0x666b,
+ RF_CHANPAIR( 3, 4) = 0x606b,
+ RF_CHANPAIR( 5, 6) = 0x664b,
+ RF_CHANPAIR( 7, 8) = 0x644b,
+ RF_CHANPAIR( 9, 10) = 0x6673,
+ RF_CHANPAIR(11, 12) = 0x6473,
+ RF_CHANPAIR(13, 14) = 0x6653,
+ },
+ { /* table 11 */
+ RF_CHANPAIR( 1, 2) = 0x665b,
+ RF_CHANPAIR( 3, 4) = 0x605b,
+ RF_CHANPAIR( 5, 6) = 0x666b,
+ RF_CHANPAIR( 7, 8) = 0x646b,
+ RF_CHANPAIR( 9, 10) = 0x664b,
+ RF_CHANPAIR(11, 12) = 0x644b,
+ RF_CHANPAIR(13, 14) = 0x6673,
+ },
+
+};
+
+/* The per-channel synth values for autocal. These get written to register 1. */
+static const u16 uw2453_autocal_synth[] = {
+ RF_CHANNEL( 1) = 0x6847,
+ RF_CHANNEL( 2) = 0x6847,
+ RF_CHANNEL( 3) = 0x6867,
+ RF_CHANNEL( 4) = 0x6867,
+ RF_CHANNEL( 5) = 0x6867,
+ RF_CHANNEL( 6) = 0x6867,
+ RF_CHANNEL( 7) = 0x6857,
+ RF_CHANNEL( 8) = 0x6857,
+ RF_CHANNEL( 9) = 0x6857,
+ RF_CHANNEL(10) = 0x6857,
+ RF_CHANNEL(11) = 0x6877,
+ RF_CHANNEL(12) = 0x6877,
+ RF_CHANNEL(13) = 0x6877,
+ RF_CHANNEL(14) = 0x684f,
+};
+
+/* The VCO configuration for autocal (all channels) */
+static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
+
+/* TX gain settings. The array index corresponds to the TX power integration
+ * values found in the EEPROM. The values get written to register 7. */
+static u32 uw2453_txgain[] = {
+ [0x00] = 0x0e313,
+ [0x01] = 0x0fb13,
+ [0x02] = 0x0e093,
+ [0x03] = 0x0f893,
+ [0x04] = 0x0ea93,
+ [0x05] = 0x1f093,
+ [0x06] = 0x1f493,
+ [0x07] = 0x1f693,
+ [0x08] = 0x1f393,
+ [0x09] = 0x1f35b,
+ [0x0a] = 0x1e6db,
+ [0x0b] = 0x1ff3f,
+ [0x0c] = 0x1ffff,
+ [0x0d] = 0x361d7,
+ [0x0e] = 0x37fbf,
+ [0x0f] = 0x3ff8b,
+ [0x10] = 0x3ff33,
+ [0x11] = 0x3fb3f,
+ [0x12] = 0x3ffff,
+};
+
+/* RF-specific structure */
+struct uw2453_priv {
+ /* index into synth/VCO config tables where PLL lock was found
+ * -1 means autocal */
+ int config;
+};
+
+#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
+
+static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
+ bool autocal)
+{
+ int r;
+ int idx = channel - 1;
+ u32 val;
+
+ if (autocal)
+ val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
+ else
+ val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
+
+ r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
+ if (r)
+ return r;
+
+ return zd_rfwrite_locked(chip,
+ UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
+}
+
+static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
+{
+ /* vendor driver always sets these upper bits even though the specs say
+ * they are reserved */
+ u32 val = 0x40000 | value;
+ return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
+}
+
+static int uw2453_init_mode(struct zd_chip *chip)
+{
+ static const u32 rv[] = {
+ UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
+ UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
+ UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
+ UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
+ };
+
+ return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
+{
+ u8 int_value = chip->pwr_int_values[channel - 1];
+
+ if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
+ dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
+ "int value %x on channel %d\n", int_value, channel);
+ return 0;
+ }
+
+ return zd_rfwrite_locked(chip,
+ UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
+}
+
+static int uw2453_init_hw(struct zd_rf *rf)
+{
+ int i, r;
+ int found_config = -1;
+ u16 intr_status;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR10, 0x89 }, { CR15, 0x20 },
+ { CR17, 0x28 }, /* 6112 no change */
+ { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 },
+ { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 },
+ { CR33, 0x28 }, { CR34, 0x30 },
+ { CR35, 0x43 }, /* 6112 3e->43 */
+ { CR41, 0x24 }, { CR44, 0x32 },
+ { CR46, 0x92 }, /* 6112 96->92 */
+ { CR47, 0x1e },
+ { CR48, 0x04 }, /* 5602 Roger */
+ { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 },
+ { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 },
+ { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d },
+ { CR99, 0x28 }, { CR100, 0x02 },
+ { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
+ { CR102, 0x27 },
+ { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
+ { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
+ { CR109, 0x13 },
+ { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
+ { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
+ { CR114, 0x23 }, /* 6221 27->23 */
+ { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
+ { CR116, 0x24 }, /* 6220 1c->24 */
+ { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
+ { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
+ { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
+ { CR120, 0x4f },
+ { CR121, 0x1f }, /* 6220 4f->1f */
+ { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
+ { CR126, 0x6c }, { CR127, 0x03 },
+ { CR128, 0x14 }, /* 6302 12->11 */
+ { CR129, 0x12 }, /* 6301 10->0f */
+ { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
+ { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
+ { CR253, 0xff },
+ };
+
+ static const u32 rv[] = {
+ UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */
+ UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
+ UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
+ UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
+
+ /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
+ * RSSI circuit powered down, reduced RSSI range */
+ UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
+
+ /* synthesizer configuration for channel 1 */
+ UW2453_REGWRITE(1, 0x47),
+ UW2453_REGWRITE(2, 0x999),
+
+ /* disable manual VCO band selection */
+ UW2453_REGWRITE(3, 0x7602),
+
+ /* enable manual VCO band selection, configure current level */
+ UW2453_REGWRITE(3, 0x46063),
+ };
+
+ r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+ if (r)
+ return r;
+
+ r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+ if (r)
+ return r;
+
+ r = uw2453_init_mode(chip);
+ if (r)
+ return r;
+
+ /* Try all standard VCO configuration settings on channel 1 */
+ for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
+ /* Configure synthesizer for channel 1 */
+ r = uw2453_synth_set_channel(chip, 1, false);
+ if (r)
+ return r;
+
+ /* Write VCO config */
+ r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
+ if (r)
+ return r;
+
+ /* ack interrupt event */
+ r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
+ if (r)
+ return r;
+
+ /* check interrupt status */
+ r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
+ if (r)
+ return r;
+
+ if (!intr_status & 0xf) {
+ dev_dbg_f(zd_chip_dev(chip),
+ "PLL locked on configuration %d\n", i);
+ found_config = i;
+ break;
+ }
+ }
+
+ if (found_config == -1) {
+ /* autocal */
+ dev_dbg_f(zd_chip_dev(chip),
+ "PLL did not lock, using autocal\n");
+
+ r = uw2453_synth_set_channel(chip, 1, true);
+ if (r)
+ return r;
+
+ r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
+ if (r)
+ return r;
+ }
+
+ /* To match the vendor driver behaviour, we use the configuration after
+ * the one that produced a lock. */
+ UW2453_PRIV(rf)->config = found_config + 1;
+
+ return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
+{
+ int r;
+ u16 vco_cfg;
+ int config = UW2453_PRIV(rf)->config;
+ bool autocal = (config == -1);
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 },
+ { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 },
+ };
+
+ r = uw2453_synth_set_channel(chip, channel, autocal);
+ if (r)
+ return r;
+
+ if (autocal)
+ vco_cfg = UW2453_AUTOCAL_VCO_CFG;
+ else
+ vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
+
+ r = uw2453_write_vco_cfg(chip, vco_cfg);
+ if (r)
+ return r;
+
+ r = uw2453_init_mode(chip);
+ if (r)
+ return r;
+
+ r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+ if (r)
+ return r;
+
+ r = uw2453_set_tx_gain_level(chip, channel);
+ if (r)
+ return r;
+
+ return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_switch_radio_on(struct zd_rf *rf)
+{
+ int r;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+ struct zd_ioreq16 ioreqs[] = {
+ { CR11, 0x00 }, { CR251, 0x3f },
+ };
+
+ /* enter RXTX mode */
+ r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
+ if (r)
+ return r;
+
+ if (chip->is_zd1211b)
+ ioreqs[1].value = 0x7f;
+
+ return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int uw2453_switch_radio_off(struct zd_rf *rf)
+{
+ int r;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR11, 0x04 }, { CR251, 0x2f },
+ };
+
+ /* enter IDLE mode */
+ /* FIXME: shouldn't we go to SLEEP? sent email to zydas */
+ r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
+ if (r)
+ return r;
+
+ return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static void uw2453_clear(struct zd_rf *rf)
+{
+ kfree(rf->priv);
+}
+
+int zd_rf_init_uw2453(struct zd_rf *rf)
+{
+ rf->init_hw = uw2453_init_hw;
+ rf->set_channel = uw2453_set_channel;
+ rf->switch_radio_on = uw2453_switch_radio_on;
+ rf->switch_radio_off = uw2453_switch_radio_off;
+ rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->clear = uw2453_clear;
+ /* we have our own TX integration code */
+ rf->update_channel_int = 0;
+
+ rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
+ if (rf->priv == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 8459549d0cee..740a2194fdde 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -54,6 +54,7 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
/* ZD1211B */
{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
new file mode 100644
index 000000000000..ab9c3e5a7c1d
--- /dev/null
+++ b/drivers/power/Kconfig
@@ -0,0 +1,51 @@
+menuconfig POWER_SUPPLY
+ tristate "Power supply class support"
+ help
+ Say Y here to enable power supply class support. This allows
+ power supply (batteries, AC, USB) monitoring by userspace
+ via sysfs and uevent (if available) and/or APM kernel interface
+ (if selected below).
+
+if POWER_SUPPLY
+
+config POWER_SUPPLY_DEBUG
+ bool "Power supply debug"
+ help
+ Say Y here to enable debugging messages for power supply class
+ and drivers.
+
+config PDA_POWER
+ tristate "Generic PDA/phone power driver"
+ help
+ Say Y here to enable generic power driver for PDAs and phones with
+ one or two external power supplies (AC/USB) connected to main and
+ backup batteries, and optional builtin charger.
+
+config APM_POWER
+ tristate "APM emulation for class batteries"
+ depends on APM_EMULATION
+ help
+ Say Y here to enable support APM status emulation using
+ battery class devices.
+
+config BATTERY_DS2760
+ tristate "DS2760 battery driver (HP iPAQ & others)"
+ select W1
+ select W1_SLAVE_DS2760
+ help
+ Say Y here to enable support for batteries with ds2760 chip.
+
+config BATTERY_PMU
+ tristate "Apple PMU battery"
+ depends on ADB_PMU
+ help
+ Say Y here to expose battery information on Apple machines
+ through the generic battery class.
+
+config BATTERY_OLPC
+ tristate "One Laptop Per Child battery"
+ depends on X86_32 && OLPC
+ help
+ Say Y to enable support for the battery on the OLPC laptop.
+
+endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
new file mode 100644
index 000000000000..6413ded5fe5f
--- /dev/null
+++ b/drivers/power/Makefile
@@ -0,0 +1,22 @@
+power_supply-objs := power_supply_core.o
+
+ifeq ($(CONFIG_SYSFS),y)
+power_supply-objs += power_supply_sysfs.o
+endif
+
+ifeq ($(CONFIG_LEDS_TRIGGERS),y)
+power_supply-objs += power_supply_leds.o
+endif
+
+ifeq ($(CONFIG_POWER_SUPPLY_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
+
+obj-$(CONFIG_PDA_POWER) += pda_power.o
+obj-$(CONFIG_APM_POWER) += apm_power.o
+
+obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
+obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
+obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
new file mode 100644
index 000000000000..042bd950d036
--- /dev/null
+++ b/drivers/power/apm_power.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2007 Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Author: Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ */
+
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/apm-emulation.h>
+
+#define PSY_PROP(psy, prop, val) psy->get_property(psy, \
+ POWER_SUPPLY_PROP_##prop, val)
+
+#define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \
+ prop, val)
+
+#define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
+
+static struct power_supply *main_battery;
+
+static void find_main_battery(void)
+{
+ struct device *dev;
+ struct power_supply *bat, *batm;
+ union power_supply_propval full;
+ int max_charge = 0;
+
+ main_battery = NULL;
+ batm = NULL;
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ bat = dev_get_drvdata(dev);
+ /* If none of battery devices cantains 'use_for_apm' flag,
+ choice one with maximum design charge */
+ if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full)) {
+ if (full.intval > max_charge) {
+ batm = bat;
+ max_charge = full.intval;
+ }
+ }
+
+ if (bat->use_for_apm)
+ main_battery = bat;
+ }
+ if (!main_battery)
+ main_battery = batm;
+
+ return;
+}
+
+static int calculate_time(int status)
+{
+ union power_supply_propval charge_full, charge_empty;
+ union power_supply_propval charge, I;
+
+ if (MPSY_PROP(CHARGE_FULL, &charge_full)) {
+ /* if battery can't report this property, use design value */
+ if (MPSY_PROP(CHARGE_FULL_DESIGN, &charge_full))
+ return -1;
+ }
+
+ if (MPSY_PROP(CHARGE_EMPTY, &charge_empty)) {
+ /* if battery can't report this property, use design value */
+ if (MPSY_PROP(CHARGE_EMPTY_DESIGN, &charge_empty))
+ charge_empty.intval = 0;
+ }
+
+ if (MPSY_PROP(CHARGE_AVG, &charge)) {
+ /* if battery can't report average value, use momentary */
+ if (MPSY_PROP(CHARGE_NOW, &charge))
+ return -1;
+ }
+
+ if (MPSY_PROP(CURRENT_AVG, &I)) {
+ /* if battery can't report average value, use momentary */
+ if (MPSY_PROP(CURRENT_NOW, &I))
+ return -1;
+ }
+
+ if (status == POWER_SUPPLY_STATUS_CHARGING)
+ return ((charge.intval - charge_full.intval) * 60L) /
+ I.intval;
+ else
+ return -((charge.intval - charge_empty.intval) * 60L) /
+ I.intval;
+}
+
+static int calculate_capacity(int using_charge)
+{
+ enum power_supply_property full_prop, empty_prop;
+ enum power_supply_property full_design_prop, empty_design_prop;
+ enum power_supply_property now_prop, avg_prop;
+ union power_supply_propval empty, full, cur;
+ int ret;
+
+ if (using_charge) {
+ full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
+ empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+ full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
+ empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
+ now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
+ avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
+ } else {
+ full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
+ empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
+ full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
+ empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
+ now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
+ avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+ }
+
+ if (_MPSY_PROP(full_prop, &full)) {
+ /* if battery can't report this property, use design value */
+ if (_MPSY_PROP(full_design_prop, &full))
+ return -1;
+ }
+
+ if (_MPSY_PROP(avg_prop, &cur)) {
+ /* if battery can't report average value, use momentary */
+ if (_MPSY_PROP(now_prop, &cur))
+ return -1;
+ }
+
+ if (_MPSY_PROP(empty_prop, &empty)) {
+ /* if battery can't report this property, use design value */
+ if (_MPSY_PROP(empty_design_prop, &empty))
+ empty.intval = 0;
+ }
+
+ if (full.intval - empty.intval)
+ ret = ((cur.intval - empty.intval) * 100L) /
+ (full.intval - empty.intval);
+ else
+ return -1;
+
+ if (ret > 100)
+ return 100;
+ else if (ret < 0)
+ return 0;
+
+ return ret;
+}
+
+static void apm_battery_apm_get_power_status(struct apm_power_info *info)
+{
+ union power_supply_propval status;
+ union power_supply_propval capacity, time_to_full, time_to_empty;
+
+ down(&power_supply_class->sem);
+ find_main_battery();
+ if (!main_battery) {
+ up(&power_supply_class->sem);
+ return;
+ }
+
+ /* status */
+
+ if (MPSY_PROP(STATUS, &status))
+ status.intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ /* ac line status */
+
+ if ((status.intval == POWER_SUPPLY_STATUS_CHARGING) ||
+ (status.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) ||
+ (status.intval == POWER_SUPPLY_STATUS_FULL))
+ info->ac_line_status = APM_AC_ONLINE;
+ else
+ info->ac_line_status = APM_AC_OFFLINE;
+
+ /* battery life (i.e. capacity, in percents) */
+
+ if (MPSY_PROP(CAPACITY, &capacity) == 0) {
+ info->battery_life = capacity.intval;
+ } else {
+ /* try calculate using energy */
+ info->battery_life = calculate_capacity(0);
+ /* if failed try calculate using charge instead */
+ if (info->battery_life == -1)
+ info->battery_life = calculate_capacity(1);
+ }
+
+ /* charging status */
+
+ if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+ info->battery_status = APM_BATTERY_STATUS_CHARGING;
+ } else {
+ if (info->battery_life > 50)
+ info->battery_status = APM_BATTERY_STATUS_HIGH;
+ else if (info->battery_life > 5)
+ info->battery_status = APM_BATTERY_STATUS_LOW;
+ else
+ info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+ }
+ info->battery_flag = info->battery_status;
+
+ /* time */
+
+ info->units = APM_UNITS_MINS;
+
+ if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+ if (MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full)) {
+ if (MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
+ info->time = calculate_time(status.intval);
+ else
+ info->time = time_to_full.intval / 60;
+ }
+ } else {
+ if (MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty)) {
+ if (MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
+ info->time = calculate_time(status.intval);
+ else
+ info->time = time_to_empty.intval / 60;
+ }
+ }
+
+ up(&power_supply_class->sem);
+ return;
+}
+
+static int __init apm_battery_init(void)
+{
+ printk(KERN_INFO "APM Battery Driver\n");
+
+ apm_get_power_status = apm_battery_apm_get_power_status;
+ return 0;
+}
+
+static void __exit apm_battery_exit(void)
+{
+ apm_get_power_status = NULL;
+ return;
+}
+
+module_init(apm_battery_init);
+module_exit(apm_battery_exit);
+
+MODULE_AUTHOR("Eugeny Boger <eugenyboger@dgap.mipt.ru>");
+MODULE_DESCRIPTION("APM emulation driver for battery monitoring class");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
new file mode 100644
index 000000000000..00e1ea6f1de2
--- /dev/null
+++ b/drivers/power/ds2760_battery.c
@@ -0,0 +1,470 @@
+/*
+ * Driver for batteries with DS2760 chips inside.
+ *
+ * Copyright © 2007 Anton Vorontsov
+ * 2004-2007 Matt Reimer
+ * 2004 Szabolcs Gyurko
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * Author: Anton Vorontsov <cbou@mail.ru>
+ * February 2007
+ *
+ * Matt Reimer <mreimer@vpop.net>
+ * April 2004, 2005, 2007
+ *
+ * Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ * September 2004
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include "../w1/w1.h"
+#include "../w1/slaves/w1_ds2760.h"
+
+struct ds2760_device_info {
+ struct device *dev;
+
+ /* DS2760 data, valid after calling ds2760_battery_read_status() */
+ unsigned long update_time; /* jiffies when data read */
+ char raw[DS2760_DATA_SIZE]; /* raw DS2760 data */
+ int voltage_raw; /* units of 4.88 mV */
+ int voltage_uV; /* units of µV */
+ int current_raw; /* units of 0.625 mA */
+ int current_uA; /* units of µA */
+ int accum_current_raw; /* units of 0.25 mAh */
+ int accum_current_uAh; /* units of µAh */
+ int temp_raw; /* units of 0.125 °C */
+ int temp_C; /* units of 0.1 °C */
+ int rated_capacity; /* units of µAh */
+ int rem_capacity; /* percentage */
+ int full_active_uAh; /* units of µAh */
+ int empty_uAh; /* units of µAh */
+ int life_sec; /* units of seconds */
+ int charge_status; /* POWER_SUPPLY_STATUS_* */
+
+ int full_counter;
+ struct power_supply bat;
+ struct device *w1_dev;
+ struct workqueue_struct *monitor_wqueue;
+ struct delayed_work monitor_work;
+};
+
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+
+/* Some batteries have their rated capacity stored a N * 10 mAh, while
+ * others use an index into this table. */
+static int rated_capacities[] = {
+ 0,
+ 920, /* Samsung */
+ 920, /* BYD */
+ 920, /* Lishen */
+ 920, /* NEC */
+ 1440, /* Samsung */
+ 1440, /* BYD */
+ 1440, /* Lishen */
+ 1440, /* NEC */
+ 2880, /* Samsung */
+ 2880, /* BYD */
+ 2880, /* Lishen */
+ 2880 /* NEC */
+};
+
+/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C
+ * temp is in Celsius */
+static int battery_interpolate(int array[], int temp)
+{
+ int index, dt;
+
+ if (temp <= 0)
+ return array[0];
+ if (temp >= 40)
+ return array[4];
+
+ index = temp / 10;
+ dt = temp % 10;
+
+ return array[index] + (((array[index + 1] - array[index]) * dt) / 10);
+}
+
+static int ds2760_battery_read_status(struct ds2760_device_info *di)
+{
+ int ret, i, start, count, scale[5];
+
+ if (di->update_time && time_before(jiffies, di->update_time +
+ msecs_to_jiffies(cache_time)))
+ return 0;
+
+ /* The first time we read the entire contents of SRAM/EEPROM,
+ * but after that we just read the interesting bits that change. */
+ if (di->update_time == 0) {
+ start = 0;
+ count = DS2760_DATA_SIZE;
+ } else {
+ start = DS2760_VOLTAGE_MSB;
+ count = DS2760_TEMP_LSB - start + 1;
+ }
+
+ ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);
+ if (ret != count) {
+ dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",
+ di->w1_dev);
+ return 1;
+ }
+
+ di->update_time = jiffies;
+
+ /* DS2760 reports voltage in units of 4.88mV, but the battery class
+ * reports in units of uV, so convert by multiplying by 4880. */
+ di->voltage_raw = (di->raw[DS2760_VOLTAGE_MSB] << 3) |
+ (di->raw[DS2760_VOLTAGE_LSB] >> 5);
+ di->voltage_uV = di->voltage_raw * 4880;
+
+ /* DS2760 reports current in signed units of 0.625mA, but the battery
+ * class reports in units of µA, so convert by multiplying by 625. */
+ di->current_raw =
+ (((signed char)di->raw[DS2760_CURRENT_MSB]) << 5) |
+ (di->raw[DS2760_CURRENT_LSB] >> 3);
+ di->current_uA = di->current_raw * 625;
+
+ /* DS2760 reports accumulated current in signed units of 0.25mAh. */
+ di->accum_current_raw =
+ (((signed char)di->raw[DS2760_CURRENT_ACCUM_MSB]) << 8) |
+ di->raw[DS2760_CURRENT_ACCUM_LSB];
+ di->accum_current_uAh = di->accum_current_raw * 250;
+
+ /* DS2760 reports temperature in signed units of 0.125°C, but the
+ * battery class reports in units of 1/10 °C, so we convert by
+ * multiplying by .125 * 10 = 1.25. */
+ di->temp_raw = (((signed char)di->raw[DS2760_TEMP_MSB]) << 3) |
+ (di->raw[DS2760_TEMP_LSB] >> 5);
+ di->temp_C = di->temp_raw + (di->temp_raw / 4);
+
+ /* At least some battery monitors (e.g. HP iPAQ) store the battery's
+ * maximum rated capacity. */
+ if (di->raw[DS2760_RATED_CAPACITY] < ARRAY_SIZE(rated_capacities))
+ di->rated_capacity = rated_capacities[
+ (unsigned int)di->raw[DS2760_RATED_CAPACITY]];
+ else
+ di->rated_capacity = di->raw[DS2760_RATED_CAPACITY] * 10;
+
+ di->rated_capacity *= 1000; /* convert to µAh */
+
+ /* Calculate the full level at the present temperature. */
+ di->full_active_uAh = di->raw[DS2760_ACTIVE_FULL] << 8 |
+ di->raw[DS2760_ACTIVE_FULL + 1];
+
+ scale[0] = di->raw[DS2760_ACTIVE_FULL] << 8 |
+ di->raw[DS2760_ACTIVE_FULL + 1];
+ for (i = 1; i < 5; i++)
+ scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];
+
+ di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10);
+ di->full_active_uAh *= 1000; /* convert to µAh */
+
+ /* Calculate the empty level at the present temperature. */
+ scale[4] = di->raw[DS2760_ACTIVE_EMPTY + 4];
+ for (i = 3; i >= 0; i--)
+ scale[i] = scale[i + 1] + di->raw[DS2760_ACTIVE_EMPTY + i];
+
+ di->empty_uAh = battery_interpolate(scale, di->temp_C / 10);
+ di->empty_uAh *= 1000; /* convert to µAh */
+
+ /* From Maxim Application Note 131: remaining capacity =
+ * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */
+ di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /
+ (di->full_active_uAh - di->empty_uAh);
+
+ if (di->rem_capacity < 0)
+ di->rem_capacity = 0;
+ if (di->rem_capacity > 100)
+ di->rem_capacity = 100;
+
+ if (di->current_uA)
+ di->life_sec = -((di->accum_current_uAh - di->empty_uAh) *
+ 3600L) / di->current_uA;
+ else
+ di->life_sec = 0;
+
+ return 0;
+}
+
+static void ds2760_battery_update_status(struct ds2760_device_info *di)
+{
+ int old_charge_status = di->charge_status;
+
+ ds2760_battery_read_status(di);
+
+ if (di->charge_status == POWER_SUPPLY_STATUS_UNKNOWN)
+ di->full_counter = 0;
+
+ if (power_supply_am_i_supplied(&di->bat)) {
+ if (di->current_uA > 10000) {
+ di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+ di->full_counter = 0;
+ } else if (di->current_uA < -5000) {
+ if (di->charge_status != POWER_SUPPLY_STATUS_NOT_CHARGING)
+ dev_notice(di->dev, "not enough power to "
+ "charge\n");
+ di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ di->full_counter = 0;
+ } else if (di->current_uA < 10000 &&
+ di->charge_status != POWER_SUPPLY_STATUS_FULL) {
+
+ /* Don't consider the battery to be full unless
+ * we've seen the current < 10 mA at least two
+ * consecutive times. */
+
+ di->full_counter++;
+
+ if (di->full_counter < 2) {
+ di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else {
+ unsigned char acr[2];
+ int acr_val;
+
+ /* acr is in units of 0.25 mAh */
+ acr_val = di->full_active_uAh * 4L / 1000;
+
+ acr[0] = acr_val >> 8;
+ acr[1] = acr_val & 0xff;
+
+ if (w1_ds2760_write(di->w1_dev, acr,
+ DS2760_CURRENT_ACCUM_MSB, 2) < 2)
+ dev_warn(di->dev,
+ "ACR reset failed\n");
+
+ di->charge_status = POWER_SUPPLY_STATUS_FULL;
+ }
+ }
+ } else {
+ di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
+ di->full_counter = 0;
+ }
+
+ if (di->charge_status != old_charge_status)
+ power_supply_changed(&di->bat);
+
+ return;
+}
+
+static void ds2760_battery_work(struct work_struct *work)
+{
+ struct ds2760_device_info *di = container_of(work,
+ struct ds2760_device_info, monitor_work.work);
+ const int interval = HZ * 60;
+
+ dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+ ds2760_battery_update_status(di);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
+
+ return;
+}
+
+#define to_ds2760_device_info(x) container_of((x), struct ds2760_device_info, \
+ bat);
+
+static void ds2760_battery_external_power_changed(struct power_supply *psy)
+{
+ struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+ dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+ cancel_delayed_work(&di->monitor_work);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
+
+ return;
+}
+
+static int ds2760_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = di->charge_status;
+ return 0;
+ default:
+ break;
+ }
+
+ ds2760_battery_read_status(di);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = di->voltage_uV;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = di->current_uA;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = di->rated_capacity;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = di->full_active_uAh;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_EMPTY:
+ val->intval = di->empty_uAh;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = di->accum_current_uAh;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = di->temp_C;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property ds2760_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_TEMP,
+};
+
+static int ds2760_battery_probe(struct platform_device *pdev)
+{
+ int retval = 0;
+ struct ds2760_device_info *di;
+ struct ds2760_platform_data *pdata;
+
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di) {
+ retval = -ENOMEM;
+ goto di_alloc_failed;
+ }
+
+ platform_set_drvdata(pdev, di);
+
+ pdata = pdev->dev.platform_data;
+ di->dev = &pdev->dev;
+ di->w1_dev = pdev->dev.parent;
+ di->bat.name = pdev->dev.bus_id;
+ di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat.properties = ds2760_battery_props;
+ di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
+ di->bat.get_property = ds2760_battery_get_property;
+ di->bat.external_power_changed =
+ ds2760_battery_external_power_changed;
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ retval = power_supply_register(&pdev->dev, &di->bat);
+ if (retval) {
+ dev_err(di->dev, "failed to register battery");
+ goto batt_failed;
+ }
+
+ INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
+ di->monitor_wqueue = create_singlethread_workqueue(pdev->dev.bus_id);
+ if (!di->monitor_wqueue) {
+ retval = -ESRCH;
+ goto workqueue_failed;
+ }
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
+
+ goto success;
+
+workqueue_failed:
+ power_supply_unregister(&di->bat);
+batt_failed:
+ kfree(di);
+di_alloc_failed:
+success:
+ return retval;
+}
+
+static int ds2760_battery_remove(struct platform_device *pdev)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ cancel_rearming_delayed_workqueue(di->monitor_wqueue,
+ &di->monitor_work);
+ destroy_workqueue(di->monitor_wqueue);
+ power_supply_unregister(&di->bat);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ds2760_battery_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ return 0;
+}
+
+static int ds2760_battery_resume(struct platform_device *pdev)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ power_supply_changed(&di->bat);
+
+ cancel_delayed_work(&di->monitor_work);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
+
+ return 0;
+}
+
+#else
+
+#define ds2760_battery_suspend NULL
+#define ds2760_battery_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct platform_driver ds2760_battery_driver = {
+ .driver = {
+ .name = "ds2760-battery",
+ },
+ .probe = ds2760_battery_probe,
+ .remove = ds2760_battery_remove,
+ .suspend = ds2760_battery_suspend,
+ .resume = ds2760_battery_resume,
+};
+
+static int __init ds2760_battery_init(void)
+{
+ return platform_driver_register(&ds2760_battery_driver);
+}
+
+static void __exit ds2760_battery_exit(void)
+{
+ platform_driver_unregister(&ds2760_battery_driver);
+ return;
+}
+
+module_init(ds2760_battery_init);
+module_exit(ds2760_battery_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
+ "Matt Reimer <mreimer@vpop.net>, "
+ "Anton Vorontsov <cbou@mail.ru>");
+MODULE_DESCRIPTION("ds2760 battery driver");
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
new file mode 100644
index 000000000000..878684df7667
--- /dev/null
+++ b/drivers/power/olpc_battery.c
@@ -0,0 +1,352 @@
+/*
+ * Battery driver for One Laptop Per Child board.
+ *
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <asm/olpc.h>
+
+
+#define EC_BAT_VOLTAGE 0x10 /* uint16_t, *9.76/32, mV */
+#define EC_BAT_CURRENT 0x11 /* int16_t, *15.625/120, mA */
+#define EC_BAT_ACR 0x12
+#define EC_BAT_TEMP 0x13 /* uint16_t, *100/256, °C */
+#define EC_AMB_TEMP 0x14 /* uint16_t, *100/256, °C */
+#define EC_BAT_STATUS 0x15 /* uint8_t, bitmask */
+#define EC_BAT_SOC 0x16 /* uint8_t, percentage */
+#define EC_BAT_SERIAL 0x17 /* uint8_t[6] */
+#define EC_BAT_EEPROM 0x18 /* uint8_t adr as input, uint8_t output */
+#define EC_BAT_ERRCODE 0x1f /* uint8_t, bitmask */
+
+#define BAT_STAT_PRESENT 0x01
+#define BAT_STAT_FULL 0x02
+#define BAT_STAT_LOW 0x04
+#define BAT_STAT_DESTROY 0x08
+#define BAT_STAT_AC 0x10
+#define BAT_STAT_CHARGING 0x20
+#define BAT_STAT_DISCHARGING 0x40
+
+#define BAT_ERR_INFOFAIL 0x02
+#define BAT_ERR_OVERVOLTAGE 0x04
+#define BAT_ERR_OVERTEMP 0x05
+#define BAT_ERR_GAUGESTOP 0x06
+#define BAT_ERR_OUT_OF_CONTROL 0x07
+#define BAT_ERR_ID_FAIL 0x09
+#define BAT_ERR_ACR_FAIL 0x10
+
+#define BAT_ADDR_MFR_TYPE 0x5F
+
+/*********************************************************************
+ * Power
+ *********************************************************************/
+
+static int olpc_ac_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret = 0;
+ uint8_t status;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+ if (ret)
+ return ret;
+
+ val->intval = !!(status & BAT_STAT_AC);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property olpc_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply olpc_ac = {
+ .name = "olpc-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = olpc_ac_props,
+ .num_properties = ARRAY_SIZE(olpc_ac_props),
+ .get_property = olpc_ac_get_prop,
+};
+
+/*********************************************************************
+ * Battery properties
+ *********************************************************************/
+static int olpc_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret = 0;
+ int16_t ec_word;
+ uint8_t ec_byte;
+
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ /* Theoretically there's a race here -- the battery could be
+ removed immediately after we check whether it's present, and
+ then we query for some other property of the now-absent battery.
+ It doesn't matter though -- the EC will return the last-known
+ information, and it's as if we just ran that _little_ bit faster
+ and managed to read it out before the battery went away. */
+ if (!(ec_byte & BAT_STAT_PRESENT) && psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (olpc_platform_info.ecver > 0x44) {
+ if (ec_byte & BAT_STAT_CHARGING)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (ec_byte & BAT_STAT_DISCHARGING)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else /* er,... */
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ /* Older EC didn't report charge/discharge bits */
+ if (!(ec_byte & BAT_STAT_AC)) /* No AC means discharging */
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else /* Not _necessarily_ true but EC doesn't tell all yet */
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ }
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(ec_byte & BAT_STAT_PRESENT);
+ break;
+
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (ec_byte & BAT_STAT_DESTROY)
+ val->intval = POWER_SUPPLY_HEALTH_DEAD;
+ else {
+ ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte) {
+ case 0:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+
+ case BAT_ERR_OVERTEMP:
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ break;
+
+ case BAT_ERR_OVERVOLTAGE:
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ break;
+
+ case BAT_ERR_INFOFAIL:
+ case BAT_ERR_OUT_OF_CONTROL:
+ case BAT_ERR_ID_FAIL:
+ case BAT_ERR_ACR_FAIL:
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ break;
+
+ default:
+ /* Eep. We don't know this failure code */
+ return -EIO;
+ }
+ }
+ break;
+
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ ec_byte = BAT_ADDR_MFR_TYPE;
+ ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte >> 4) {
+ case 1:
+ val->strval = "Gold Peak";
+ break;
+ case 2:
+ val->strval = "BYD";
+ break;
+ default:
+ val->strval = "Unknown";
+ break;
+ }
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ ec_byte = BAT_ADDR_MFR_TYPE;
+ ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte & 0xf) {
+ case 1:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
+ break;
+ case 2:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+ break;
+ }
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 9760L / 32;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 15625L / 120;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+ val->intval = ec_byte;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (ec_byte & BAT_STAT_LOW)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 100 / 256;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+ ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 100 / 256;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static enum power_supply_property olpc_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+/*********************************************************************
+ * Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static struct power_supply olpc_bat = {
+ .properties = olpc_bat_props,
+ .num_properties = ARRAY_SIZE(olpc_bat_props),
+ .get_property = olpc_bat_get_property,
+ .use_for_apm = 1,
+};
+
+void olpc_battery_trigger_uevent(unsigned long cause)
+{
+ if (cause & EC_SCI_SRC_ACPWR)
+ kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE);
+ if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY))
+ kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE);
+}
+
+static int __init olpc_bat_init(void)
+{
+ int ret = 0;
+ uint8_t status;
+
+ if (!olpc_platform_info.ecver)
+ return -ENXIO;
+ if (olpc_platform_info.ecver < 0x43) {
+ printk(KERN_NOTICE "OLPC EC version 0x%02x too old for battery driver.\n", olpc_platform_info.ecver);
+ return -ENXIO;
+ }
+
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+ if (ret)
+ return ret;
+
+ /* Ignore the status. It doesn't actually matter */
+
+ bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0);
+ if (IS_ERR(bat_pdev))
+ return PTR_ERR(bat_pdev);
+
+ ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
+ if (ret)
+ goto ac_failed;
+
+ olpc_bat.name = bat_pdev->name;
+
+ ret = power_supply_register(&bat_pdev->dev, &olpc_bat);
+ if (ret)
+ goto battery_failed;
+
+ olpc_register_battery_callback(&olpc_battery_trigger_uevent);
+ goto success;
+
+battery_failed:
+ power_supply_unregister(&olpc_ac);
+ac_failed:
+ platform_device_unregister(bat_pdev);
+success:
+ return ret;
+}
+
+static void __exit olpc_bat_exit(void)
+{
+ olpc_deregister_battery_callback();
+ power_supply_unregister(&olpc_bat);
+ power_supply_unregister(&olpc_ac);
+ platform_device_unregister(bat_pdev);
+ return;
+}
+
+module_init(olpc_bat_init);
+module_exit(olpc_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Battery driver for One Laptop Per Child 'XO' machine");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
new file mode 100644
index 000000000000..4e1eb040e148
--- /dev/null
+++ b/drivers/power/pda_power.c
@@ -0,0 +1,261 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/power_supply.h>
+#include <linux/pda_power.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+
+static inline unsigned int get_irq_flags(struct resource *res)
+{
+ unsigned int flags = IRQF_DISABLED | IRQF_SHARED;
+
+ flags |= res->flags & IRQF_TRIGGER_MASK;
+
+ return flags;
+}
+
+static struct device *dev;
+static struct pda_power_pdata *pdata;
+static struct resource *ac_irq, *usb_irq;
+static struct timer_list charger_timer;
+static struct timer_list supply_timer;
+
+static int pda_power_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ if (psy->type == POWER_SUPPLY_TYPE_MAINS)
+ val->intval = pdata->is_ac_online ?
+ pdata->is_ac_online() : 0;
+ else
+ val->intval = pdata->is_usb_online ?
+ pdata->is_usb_online() : 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static enum power_supply_property pda_power_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static char *pda_power_supplied_to[] = {
+ "main-battery",
+ "backup-battery",
+};
+
+static struct power_supply pda_power_supplies[] = {
+ {
+ .name = "ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .supplied_to = pda_power_supplied_to,
+ .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+ .properties = pda_power_props,
+ .num_properties = ARRAY_SIZE(pda_power_props),
+ .get_property = pda_power_get_property,
+ },
+ {
+ .name = "usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .supplied_to = pda_power_supplied_to,
+ .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+ .properties = pda_power_props,
+ .num_properties = ARRAY_SIZE(pda_power_props),
+ .get_property = pda_power_get_property,
+ },
+};
+
+static void update_charger(void)
+{
+ if (!pdata->set_charge)
+ return;
+
+ if (pdata->is_ac_online && pdata->is_ac_online()) {
+ dev_dbg(dev, "charger on (AC)\n");
+ pdata->set_charge(PDA_POWER_CHARGE_AC);
+ } else if (pdata->is_usb_online && pdata->is_usb_online()) {
+ dev_dbg(dev, "charger on (USB)\n");
+ pdata->set_charge(PDA_POWER_CHARGE_USB);
+ } else {
+ dev_dbg(dev, "charger off\n");
+ pdata->set_charge(0);
+ }
+
+ return;
+}
+
+static void supply_timer_func(unsigned long irq)
+{
+ if (ac_irq && irq == ac_irq->start)
+ power_supply_changed(&pda_power_supplies[0]);
+ else if (usb_irq && irq == usb_irq->start)
+ power_supply_changed(&pda_power_supplies[1]);
+ return;
+}
+
+static void charger_timer_func(unsigned long irq)
+{
+ update_charger();
+
+ /* Okay, charger set. Now wait a bit before notifying supplicants,
+ * charge power should stabilize. */
+ supply_timer.data = irq;
+ mod_timer(&supply_timer,
+ jiffies + msecs_to_jiffies(pdata->wait_for_charger));
+ return;
+}
+
+static irqreturn_t power_changed_isr(int irq, void *unused)
+{
+ /* Wait a bit before reading ac/usb line status and setting charger,
+ * because ac/usb status readings may lag from irq. */
+ charger_timer.data = irq;
+ mod_timer(&charger_timer,
+ jiffies + msecs_to_jiffies(pdata->wait_for_status));
+ return IRQ_HANDLED;
+}
+
+static int pda_power_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ dev = &pdev->dev;
+
+ if (pdev->id != -1) {
+ dev_err(dev, "it's meaningless to register several "
+ "pda_powers; use id = -1\n");
+ ret = -EINVAL;
+ goto wrongid;
+ }
+
+ pdata = pdev->dev.platform_data;
+
+ update_charger();
+
+ if (!pdata->wait_for_status)
+ pdata->wait_for_status = 500;
+
+ if (!pdata->wait_for_charger)
+ pdata->wait_for_charger = 500;
+
+ setup_timer(&charger_timer, charger_timer_func, 0);
+ setup_timer(&supply_timer, supply_timer_func, 0);
+
+ ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
+ usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
+ if (!ac_irq && !usb_irq) {
+ dev_err(dev, "no ac/usb irq specified\n");
+ ret = -ENODEV;
+ goto noirqs;
+ }
+
+ if (pdata->supplied_to) {
+ pda_power_supplies[0].supplied_to = pdata->supplied_to;
+ pda_power_supplies[1].supplied_to = pdata->supplied_to;
+ pda_power_supplies[0].num_supplicants = pdata->num_supplicants;
+ pda_power_supplies[1].num_supplicants = pdata->num_supplicants;
+ }
+
+ ret = power_supply_register(&pdev->dev, &pda_power_supplies[0]);
+ if (ret) {
+ dev_err(dev, "failed to register %s power supply\n",
+ pda_power_supplies[0].name);
+ goto supply0_failed;
+ }
+
+ ret = power_supply_register(&pdev->dev, &pda_power_supplies[1]);
+ if (ret) {
+ dev_err(dev, "failed to register %s power supply\n",
+ pda_power_supplies[1].name);
+ goto supply1_failed;
+ }
+
+ if (ac_irq) {
+ ret = request_irq(ac_irq->start, power_changed_isr,
+ get_irq_flags(ac_irq), ac_irq->name,
+ &pda_power_supplies[0]);
+ if (ret) {
+ dev_err(dev, "request ac irq failed\n");
+ goto ac_irq_failed;
+ }
+ }
+
+ if (usb_irq) {
+ ret = request_irq(usb_irq->start, power_changed_isr,
+ get_irq_flags(usb_irq), usb_irq->name,
+ &pda_power_supplies[1]);
+ if (ret) {
+ dev_err(dev, "request usb irq failed\n");
+ goto usb_irq_failed;
+ }
+ }
+
+ goto success;
+
+usb_irq_failed:
+ if (ac_irq)
+ free_irq(ac_irq->start, &pda_power_supplies[0]);
+ac_irq_failed:
+ power_supply_unregister(&pda_power_supplies[1]);
+supply1_failed:
+ power_supply_unregister(&pda_power_supplies[0]);
+supply0_failed:
+noirqs:
+wrongid:
+success:
+ return ret;
+}
+
+static int pda_power_remove(struct platform_device *pdev)
+{
+ if (usb_irq)
+ free_irq(usb_irq->start, &pda_power_supplies[1]);
+ if (ac_irq)
+ free_irq(ac_irq->start, &pda_power_supplies[0]);
+ del_timer_sync(&charger_timer);
+ del_timer_sync(&supply_timer);
+ power_supply_unregister(&pda_power_supplies[1]);
+ power_supply_unregister(&pda_power_supplies[0]);
+ return 0;
+}
+
+static struct platform_driver pda_power_pdrv = {
+ .driver = {
+ .name = "pda-power",
+ },
+ .probe = pda_power_probe,
+ .remove = pda_power_remove,
+};
+
+static int __init pda_power_init(void)
+{
+ return platform_driver_register(&pda_power_pdrv);
+}
+
+static void __exit pda_power_exit(void)
+{
+ platform_driver_unregister(&pda_power_pdrv);
+ return;
+}
+
+module_init(pda_power_init);
+module_exit(pda_power_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c
new file mode 100644
index 000000000000..2fea4af0e40a
--- /dev/null
+++ b/drivers/power/pmu_battery.c
@@ -0,0 +1,215 @@
+/*
+ * Battery class driver for Apple PMU
+ *
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+static struct pmu_battery_dev {
+ struct power_supply bat;
+ struct pmu_battery_info *pbi;
+ char name[16];
+ int propval;
+} *pbats[PMU_MAX_BATTERIES];
+
+#define to_pmu_battery_dev(x) container_of(x, struct pmu_battery_dev, bat)
+
+/*********************************************************************
+ * Power
+ *********************************************************************/
+
+static int pmu_get_ac_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = (!!(pmu_power_flags & PMU_PWR_AC_PRESENT)) ||
+ (pmu_battery_count == 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property pmu_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply pmu_ac = {
+ .name = "pmu-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = pmu_ac_props,
+ .num_properties = ARRAY_SIZE(pmu_ac_props),
+ .get_property = pmu_get_ac_prop,
+};
+
+/*********************************************************************
+ * Battery properties
+ *********************************************************************/
+
+static char *pmu_batt_types[] = {
+ "Smart", "Comet", "Hooper", "Unknown"
+};
+
+static char *pmu_bat_get_model_name(struct pmu_battery_info *pbi)
+{
+ switch (pbi->flags & PMU_BATT_TYPE_MASK) {
+ case PMU_BATT_TYPE_SMART:
+ return pmu_batt_types[0];
+ case PMU_BATT_TYPE_COMET:
+ return pmu_batt_types[1];
+ case PMU_BATT_TYPE_HOOPER:
+ return pmu_batt_types[2];
+ default: break;
+ }
+ return pmu_batt_types[3];
+}
+
+static int pmu_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pmu_battery_dev *pbat = to_pmu_battery_dev(psy);
+ struct pmu_battery_info *pbi = pbat->pbi;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (pbi->flags & PMU_BATT_CHARGING)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(pbi->flags & PMU_BATT_PRESENT);
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = pmu_bat_get_model_name(pbi);
+ break;
+ case POWER_SUPPLY_PROP_ENERGY_AVG:
+ val->intval = pbi->charge * 1000; /* mWh -> µWh */
+ break;
+ case POWER_SUPPLY_PROP_ENERGY_FULL:
+ val->intval = pbi->max_charge * 1000; /* mWh -> µWh */
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval = pbi->amperage * 1000; /* mA -> µA */
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ val->intval = pbi->voltage * 1000; /* mV -> µV */
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+ val->intval = pbi->time_remaining;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property pmu_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_ENERGY_AVG,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+};
+
+/*********************************************************************
+ * Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static int __init pmu_bat_init(void)
+{
+ int ret;
+ int i;
+
+ bat_pdev = platform_device_register_simple("pmu-battery",
+ 0, NULL, 0);
+ if (IS_ERR(bat_pdev)) {
+ ret = PTR_ERR(bat_pdev);
+ goto pdev_register_failed;
+ }
+
+ ret = power_supply_register(&bat_pdev->dev, &pmu_ac);
+ if (ret)
+ goto ac_register_failed;
+
+ for (i = 0; i < pmu_battery_count; i++) {
+ struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat),
+ GFP_KERNEL);
+ if (!pbat)
+ break;
+
+ sprintf(pbat->name, "PMU battery %d", i);
+ pbat->bat.name = pbat->name;
+ pbat->bat.properties = pmu_bat_props;
+ pbat->bat.num_properties = ARRAY_SIZE(pmu_bat_props);
+ pbat->bat.get_property = pmu_bat_get_property;
+ pbat->pbi = &pmu_batteries[i];
+
+ ret = power_supply_register(&bat_pdev->dev, &pbat->bat);
+ if (ret) {
+ kfree(pbat);
+ goto battery_register_failed;
+ }
+ pbats[i] = pbat;
+ }
+
+ goto success;
+
+battery_register_failed:
+ while (i--) {
+ if (!pbats[i])
+ continue;
+ power_supply_unregister(&pbats[i]->bat);
+ kfree(pbats[i]);
+ }
+ power_supply_unregister(&pmu_ac);
+ac_register_failed:
+ platform_device_unregister(bat_pdev);
+pdev_register_failed:
+success:
+ return ret;
+}
+
+static void __exit pmu_bat_exit(void)
+{
+ int i;
+
+ for (i = 0; i < PMU_MAX_BATTERIES; i++) {
+ if (!pbats[i])
+ continue;
+ power_supply_unregister(&pbats[i]->bat);
+ kfree(pbats[i]);
+ }
+ power_supply_unregister(&pmu_ac);
+ platform_device_unregister(bat_pdev);
+
+ return;
+}
+
+module_init(pmu_bat_init);
+module_exit(pmu_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PMU battery driver");
diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h
new file mode 100644
index 000000000000..a9880d468ee4
--- /dev/null
+++ b/drivers/power/power_supply.h
@@ -0,0 +1,42 @@
+/*
+ * Functions private to power supply class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#ifdef CONFIG_SYSFS
+
+extern int power_supply_create_attrs(struct power_supply *psy);
+extern void power_supply_remove_attrs(struct power_supply *psy);
+extern int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size);
+
+#else
+
+static inline int power_supply_create_attrs(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_attrs(struct power_supply *psy) {}
+#define power_supply_uevent NULL
+
+#endif /* CONFIG_SYSFS */
+
+#ifdef CONFIG_LEDS_TRIGGERS
+
+extern void power_supply_update_leds(struct power_supply *psy);
+extern int power_supply_create_triggers(struct power_supply *psy);
+extern void power_supply_remove_triggers(struct power_supply *psy);
+
+#else
+
+static inline void power_supply_update_leds(struct power_supply *psy) {}
+static inline int power_supply_create_triggers(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_triggers(struct power_supply *psy) {}
+
+#endif /* CONFIG_LEDS_TRIGGERS */
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
new file mode 100644
index 000000000000..e87ea5156755
--- /dev/null
+++ b/drivers/power/power_supply_core.c
@@ -0,0 +1,168 @@
+/*
+ * Universal power supply monitor class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include "power_supply.h"
+
+struct class *power_supply_class;
+
+static void power_supply_changed_work(struct work_struct *work)
+{
+ struct power_supply *psy = container_of(work, struct power_supply,
+ changed_work);
+ int i;
+
+ dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+ for (i = 0; i < psy->num_supplicants; i++) {
+ struct device *dev;
+
+ down(&power_supply_class->sem);
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ struct power_supply *pst = dev_get_drvdata(dev);
+
+ if (!strcmp(psy->supplied_to[i], pst->name)) {
+ if (pst->external_power_changed)
+ pst->external_power_changed(pst);
+ }
+ }
+ up(&power_supply_class->sem);
+ }
+
+ power_supply_update_leds(psy);
+
+ kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
+
+ return;
+}
+
+void power_supply_changed(struct power_supply *psy)
+{
+ dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+ schedule_work(&psy->changed_work);
+
+ return;
+}
+
+int power_supply_am_i_supplied(struct power_supply *psy)
+{
+ union power_supply_propval ret = {0,};
+ struct device *dev;
+
+ down(&power_supply_class->sem);
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ struct power_supply *epsy = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < epsy->num_supplicants; i++) {
+ if (!strcmp(epsy->supplied_to[i], psy->name)) {
+ if (epsy->get_property(epsy,
+ POWER_SUPPLY_PROP_ONLINE, &ret))
+ continue;
+ if (ret.intval)
+ goto out;
+ }
+ }
+ }
+out:
+ up(&power_supply_class->sem);
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, ret.intval);
+
+ return ret.intval;
+}
+
+int power_supply_register(struct device *parent, struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->dev = device_create(power_supply_class, parent, 0,
+ "%s", psy->name);
+ if (IS_ERR(psy->dev)) {
+ rc = PTR_ERR(psy->dev);
+ goto dev_create_failed;
+ }
+
+ dev_set_drvdata(psy->dev, psy);
+
+ INIT_WORK(&psy->changed_work, power_supply_changed_work);
+
+ rc = power_supply_create_attrs(psy);
+ if (rc)
+ goto create_attrs_failed;
+
+ rc = power_supply_create_triggers(psy);
+ if (rc)
+ goto create_triggers_failed;
+
+ power_supply_changed(psy);
+
+ goto success;
+
+create_triggers_failed:
+ power_supply_remove_attrs(psy);
+create_attrs_failed:
+ device_unregister(psy->dev);
+dev_create_failed:
+success:
+ return rc;
+}
+
+void power_supply_unregister(struct power_supply *psy)
+{
+ flush_scheduled_work();
+ power_supply_remove_triggers(psy);
+ power_supply_remove_attrs(psy);
+ device_unregister(psy->dev);
+ return;
+}
+
+static int __init power_supply_class_init(void)
+{
+ power_supply_class = class_create(THIS_MODULE, "power_supply");
+
+ if (IS_ERR(power_supply_class))
+ return PTR_ERR(power_supply_class);
+
+ power_supply_class->dev_uevent = power_supply_uevent;
+
+ return 0;
+}
+
+static void __exit power_supply_class_exit(void)
+{
+ class_destroy(power_supply_class);
+ return;
+}
+
+EXPORT_SYMBOL_GPL(power_supply_changed);
+EXPORT_SYMBOL_GPL(power_supply_am_i_supplied);
+EXPORT_SYMBOL_GPL(power_supply_register);
+EXPORT_SYMBOL_GPL(power_supply_unregister);
+
+/* exported for the APM Power driver, APM emulation */
+EXPORT_SYMBOL_GPL(power_supply_class);
+
+subsys_initcall(power_supply_class_init);
+module_exit(power_supply_class_exit);
+
+MODULE_DESCRIPTION("Universal power supply monitor class");
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, "
+ "Szabolcs Gyurko, "
+ "Anton Vorontsov <cbou@mail.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c
new file mode 100644
index 000000000000..7232490bb595
--- /dev/null
+++ b/drivers/power/power_supply_leds.c
@@ -0,0 +1,176 @@
+/*
+ * LEDs triggers for power supply class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/power_supply.h>
+
+/* Battery specific LEDs triggers. */
+
+static void power_supply_update_bat_leds(struct power_supply *psy)
+{
+ union power_supply_propval status;
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
+ return;
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, status.intval);
+
+ switch (status.intval) {
+ case POWER_SUPPLY_STATUS_FULL:
+ led_trigger_event(psy->charging_full_trig, LED_FULL);
+ led_trigger_event(psy->charging_trig, LED_OFF);
+ led_trigger_event(psy->full_trig, LED_FULL);
+ break;
+ case POWER_SUPPLY_STATUS_CHARGING:
+ led_trigger_event(psy->charging_full_trig, LED_FULL);
+ led_trigger_event(psy->charging_trig, LED_FULL);
+ led_trigger_event(psy->full_trig, LED_OFF);
+ break;
+ default:
+ led_trigger_event(psy->charging_full_trig, LED_OFF);
+ led_trigger_event(psy->charging_trig, LED_OFF);
+ led_trigger_event(psy->full_trig, LED_OFF);
+ break;
+ }
+
+ return;
+}
+
+static int power_supply_create_bat_triggers(struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->charging_full_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-charging-or-full"), GFP_KERNEL);
+ if (!psy->charging_full_trig_name)
+ goto charging_full_failed;
+
+ psy->charging_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-charging"), GFP_KERNEL);
+ if (!psy->charging_trig_name)
+ goto charging_failed;
+
+ psy->full_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-full"), GFP_KERNEL);
+ if (!psy->full_trig_name)
+ goto full_failed;
+
+ strcpy(psy->charging_full_trig_name, psy->name);
+ strcat(psy->charging_full_trig_name, "-charging-or-full");
+ strcpy(psy->charging_trig_name, psy->name);
+ strcat(psy->charging_trig_name, "-charging");
+ strcpy(psy->full_trig_name, psy->name);
+ strcat(psy->full_trig_name, "-full");
+
+ led_trigger_register_simple(psy->charging_full_trig_name,
+ &psy->charging_full_trig);
+ led_trigger_register_simple(psy->charging_trig_name,
+ &psy->charging_trig);
+ led_trigger_register_simple(psy->full_trig_name,
+ &psy->full_trig);
+
+ goto success;
+
+full_failed:
+ kfree(psy->charging_trig_name);
+charging_failed:
+ kfree(psy->charging_full_trig_name);
+charging_full_failed:
+ rc = -ENOMEM;
+success:
+ return rc;
+}
+
+static void power_supply_remove_bat_triggers(struct power_supply *psy)
+{
+ led_trigger_unregister_simple(psy->charging_full_trig);
+ led_trigger_unregister_simple(psy->charging_trig);
+ led_trigger_unregister_simple(psy->full_trig);
+ kfree(psy->full_trig_name);
+ kfree(psy->charging_trig_name);
+ kfree(psy->charging_full_trig_name);
+ return;
+}
+
+/* Generated power specific LEDs triggers. */
+
+static void power_supply_update_gen_leds(struct power_supply *psy)
+{
+ union power_supply_propval online;
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
+ return;
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, online.intval);
+
+ if (online.intval)
+ led_trigger_event(psy->online_trig, LED_FULL);
+ else
+ led_trigger_event(psy->online_trig, LED_OFF);
+
+ return;
+}
+
+static int power_supply_create_gen_triggers(struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->online_trig_name = kmalloc(strlen(psy->name) + sizeof("-online"),
+ GFP_KERNEL);
+ if (!psy->online_trig_name)
+ goto online_failed;
+
+ strcpy(psy->online_trig_name, psy->name);
+ strcat(psy->online_trig_name, "-online");
+
+ led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
+
+ goto success;
+
+online_failed:
+ rc = -ENOMEM;
+success:
+ return rc;
+}
+
+static void power_supply_remove_gen_triggers(struct power_supply *psy)
+{
+ led_trigger_unregister_simple(psy->online_trig);
+ kfree(psy->online_trig_name);
+ return;
+}
+
+/* Choice what triggers to create&update. */
+
+void power_supply_update_leds(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ power_supply_update_bat_leds(psy);
+ else
+ power_supply_update_gen_leds(psy);
+ return;
+}
+
+int power_supply_create_triggers(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ return power_supply_create_bat_triggers(psy);
+ return power_supply_create_gen_triggers(psy);
+}
+
+void power_supply_remove_triggers(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ power_supply_remove_bat_triggers(psy);
+ else
+ power_supply_remove_gen_triggers(psy);
+ return;
+}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
new file mode 100644
index 000000000000..c07d4258d347
--- /dev/null
+++ b/drivers/power/power_supply_sysfs.c
@@ -0,0 +1,299 @@
+/*
+ * Sysfs interface for the universal power supply monitor class
+ *
+ * Copyright © 2007 David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/ctype.h>
+#include <linux/power_supply.h>
+
+/*
+ * This is because the name "current" breaks the device attr macro.
+ * The "current" word resolves to "(get_current())" so instead of
+ * "current" "(get_current())" appears in the sysfs.
+ *
+ * The source of this definition is the device.h which calls __ATTR
+ * macro in sysfs.h which calls the __stringify macro.
+ *
+ * Only modification that the name is not tried to be resolved
+ * (as a macro let's say).
+ */
+
+#define POWER_SUPPLY_ATTR(_name) \
+{ \
+ .attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE }, \
+ .show = power_supply_show_property, \
+ .store = NULL, \
+}
+
+static struct device_attribute power_supply_attrs[];
+
+static ssize_t power_supply_show_property(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ static char *status_text[] = {
+ "Unknown", "Charging", "Discharging", "Not charging", "Full"
+ };
+ static char *health_text[] = {
+ "Unknown", "Good", "Overheat", "Dead", "Over voltage",
+ "Unspecified failure"
+ };
+ static char *technology_text[] = {
+ "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd"
+ };
+ static char *capacity_level_text[] = {
+ "Unknown", "Critical", "Low", "Normal", "High", "Full"
+ };
+ ssize_t ret;
+ struct power_supply *psy = dev_get_drvdata(dev);
+ const ptrdiff_t off = attr - power_supply_attrs;
+ union power_supply_propval value;
+
+ ret = psy->get_property(psy, off, &value);
+
+ if (ret < 0) {
+ if (ret != -ENODEV)
+ dev_err(dev, "driver failed to report `%s' property\n",
+ attr->attr.name);
+ return ret;
+ }
+
+ if (off == POWER_SUPPLY_PROP_STATUS)
+ return sprintf(buf, "%s\n", status_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_HEALTH)
+ return sprintf(buf, "%s\n", health_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)
+ return sprintf(buf, "%s\n", technology_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)
+ return sprintf(buf, "%s\n",
+ capacity_level_text[value.intval]);
+ else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
+ return sprintf(buf, "%s\n", value.strval);
+
+ return sprintf(buf, "%d\n", value.intval);
+}
+
+/* Must be in the same order as POWER_SUPPLY_PROP_* */
+static struct device_attribute power_supply_attrs[] = {
+ /* Properties of type `int' */
+ POWER_SUPPLY_ATTR(status),
+ POWER_SUPPLY_ATTR(health),
+ POWER_SUPPLY_ATTR(present),
+ POWER_SUPPLY_ATTR(online),
+ POWER_SUPPLY_ATTR(technology),
+ POWER_SUPPLY_ATTR(voltage_max_design),
+ POWER_SUPPLY_ATTR(voltage_min_design),
+ POWER_SUPPLY_ATTR(voltage_now),
+ POWER_SUPPLY_ATTR(voltage_avg),
+ POWER_SUPPLY_ATTR(current_now),
+ POWER_SUPPLY_ATTR(current_avg),
+ POWER_SUPPLY_ATTR(charge_full_design),
+ POWER_SUPPLY_ATTR(charge_empty_design),
+ POWER_SUPPLY_ATTR(charge_full),
+ POWER_SUPPLY_ATTR(charge_empty),
+ POWER_SUPPLY_ATTR(charge_now),
+ POWER_SUPPLY_ATTR(charge_avg),
+ POWER_SUPPLY_ATTR(energy_full_design),
+ POWER_SUPPLY_ATTR(energy_empty_design),
+ POWER_SUPPLY_ATTR(energy_full),
+ POWER_SUPPLY_ATTR(energy_empty),
+ POWER_SUPPLY_ATTR(energy_now),
+ POWER_SUPPLY_ATTR(energy_avg),
+ POWER_SUPPLY_ATTR(capacity),
+ POWER_SUPPLY_ATTR(capacity_level),
+ POWER_SUPPLY_ATTR(temp),
+ POWER_SUPPLY_ATTR(temp_ambient),
+ POWER_SUPPLY_ATTR(time_to_empty_now),
+ POWER_SUPPLY_ATTR(time_to_empty_avg),
+ POWER_SUPPLY_ATTR(time_to_full_now),
+ POWER_SUPPLY_ATTR(time_to_full_avg),
+ /* Properties of type `const char *' */
+ POWER_SUPPLY_ATTR(model_name),
+ POWER_SUPPLY_ATTR(manufacturer),
+};
+
+static ssize_t power_supply_show_static_attrs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ static char *type_text[] = { "Battery", "UPS", "Mains", "USB" };
+ struct power_supply *psy = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", type_text[psy->type]);
+}
+
+static struct device_attribute power_supply_static_attrs[] = {
+ __ATTR(type, 0444, power_supply_show_static_attrs, NULL),
+};
+
+int power_supply_create_attrs(struct power_supply *psy)
+{
+ int rc = 0;
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++) {
+ rc = device_create_file(psy->dev,
+ &power_supply_static_attrs[i]);
+ if (rc)
+ goto statics_failed;
+ }
+
+ for (j = 0; j < psy->num_properties; j++) {
+ rc = device_create_file(psy->dev,
+ &power_supply_attrs[psy->properties[j]]);
+ if (rc)
+ goto dynamics_failed;
+ }
+
+ goto succeed;
+
+dynamics_failed:
+ while (j--)
+ device_remove_file(psy->dev,
+ &power_supply_attrs[psy->properties[j]]);
+statics_failed:
+ while (i--)
+ device_remove_file(psy->dev,
+ &power_supply_static_attrs[psy->properties[i]]);
+succeed:
+ return rc;
+}
+
+void power_supply_remove_attrs(struct power_supply *psy)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++)
+ device_remove_file(psy->dev,
+ &power_supply_static_attrs[i]);
+
+ for (i = 0; i < psy->num_properties; i++)
+ device_remove_file(psy->dev,
+ &power_supply_attrs[psy->properties[i]]);
+
+ return;
+}
+
+static char *kstruprdup(const char *str, gfp_t gfp)
+{
+ char *ret, *ustr;
+
+ ustr = ret = kmalloc(strlen(str) + 1, gfp);
+
+ if (!ret)
+ return NULL;
+
+ while (*str)
+ *ustr++ = toupper(*str++);
+
+ *ustr = 0;
+
+ return ret;
+}
+
+int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ struct power_supply *psy = dev_get_drvdata(dev);
+ int i = 0, length = 0, ret = 0, j;
+ char *prop_buf;
+ char *attrname;
+
+ dev_dbg(dev, "uevent\n");
+
+ if (!psy) {
+ dev_dbg(dev, "No power supply yet\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_NAME=%s", psy->name);
+ if (ret)
+ return ret;
+
+ prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!prop_buf)
+ return -ENOMEM;
+
+ for (j = 0; j < ARRAY_SIZE(power_supply_static_attrs); j++) {
+ struct device_attribute *attr;
+ char *line;
+
+ attr = &power_supply_static_attrs[j];
+
+ ret = power_supply_show_static_attrs(dev, attr, prop_buf);
+ if (ret < 0)
+ goto out;
+
+ line = strchr(prop_buf, '\n');
+ if (line)
+ *line = 0;
+
+ attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+ if (!attrname) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_%s=%s",
+ attrname, prop_buf);
+ kfree(attrname);
+ if (ret)
+ goto out;
+ }
+
+ dev_dbg(dev, "%zd dynamic props\n", psy->num_properties);
+
+ for (j = 0; j < psy->num_properties; j++) {
+ struct device_attribute *attr;
+ char *line;
+
+ attr = &power_supply_attrs[psy->properties[j]];
+
+ ret = power_supply_show_property(dev, attr, prop_buf);
+ if (ret == -ENODEV) {
+ /* When a battery is absent, we expect -ENODEV. Don't abort;
+ send the uevent with at least the the PRESENT=0 property */
+ ret = 0;
+ continue;
+ }
+
+ if (ret < 0)
+ goto out;
+
+ line = strchr(prop_buf, '\n');
+ if (line)
+ *line = 0;
+
+ attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+ if (!attrname) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_%s=%s",
+ attrname, prop_buf);
+ kfree(attrname);
+ if (ret)
+ goto out;
+ }
+
+out:
+ free_page((unsigned long)prop_buf);
+
+ return ret;
+}
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 8b3b0f4a157c..ac7e8ef504cb 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -28,6 +28,7 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL;
static struct proc_dir_entry *dasd_devices_entry = NULL;
static struct proc_dir_entry *dasd_statistics_entry = NULL;
+#ifdef CONFIG_DASD_PROFILE
static char *
dasd_get_user_string(const char __user *user_buf, size_t user_len)
{
@@ -47,6 +48,7 @@ dasd_get_user_string(const char __user *user_buf, size_t user_len)
buffer[user_len] = 0;
return buffer;
}
+#endif /* CONFIG_DASD_PROFILE */
static int
dasd_devices_show(struct seq_file *m, void *v)
@@ -167,6 +169,7 @@ dasd_calc_metrics(char *page, char **start, off_t off,
return len;
}
+#ifdef CONFIG_DASD_PROFILE
static char *
dasd_statistics_array(char *str, unsigned int *array, int shift)
{
@@ -180,6 +183,7 @@ dasd_statistics_array(char *str, unsigned int *array, int shift)
str += sprintf(str,"\n");
return str;
}
+#endif /* CONFIG_DASD_PROFILE */
static int
dasd_statistics_read(char *page, char **start, off_t off,
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index dbb99d1b6f57..c7318a125852 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -72,6 +72,18 @@ typedef unsigned int sclp_cmdw_t;
typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
+struct sccb_header {
+ u16 length;
+ u8 function_code;
+ u8 control_mask[3];
+ u16 response_code;
+} __attribute__((packed));
+
+extern u64 sclp_facilities;
+
+#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL)
+#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL)
+
struct gds_subvector {
u8 length;
u8 key;
diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c
index a66b914519b5..c68f5e7e63a0 100644
--- a/drivers/s390/char/sclp_chp.c
+++ b/drivers/s390/char/sclp_chp.c
@@ -55,6 +55,8 @@ static int do_configure(sclp_cmdw_t cmd)
struct chp_cfg_data *data;
int rc;
+ if (!SCLP_HAS_CHP_RECONFIG)
+ return -EOPNOTSUPP;
/* Prepare sccb. */
data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!data)
@@ -152,6 +154,8 @@ int sclp_chp_read_info(struct sclp_chp_info *info)
struct chp_info_data *data;
int rc;
+ if (!SCLP_HAS_CHP_INFO)
+ return -EOPNOTSUPP;
/* Prepare sccb. */
data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!data)
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
index 7bcbe643b087..a1136e052750 100644
--- a/drivers/s390/char/sclp_info.c
+++ b/drivers/s390/char/sclp_info.c
@@ -11,47 +11,106 @@
#include <asm/sclp.h>
#include "sclp.h"
-struct sclp_readinfo_sccb s390_readinfo_sccb;
+struct sclp_readinfo_sccb {
+ struct sccb_header header; /* 0-7 */
+ u16 rnmax; /* 8-9 */
+ u8 rnsize; /* 10 */
+ u8 _reserved0[24 - 11]; /* 11-23 */
+ u8 loadparm[8]; /* 24-31 */
+ u8 _reserved1[48 - 32]; /* 32-47 */
+ u64 facilities; /* 48-55 */
+ u8 _reserved2[91 - 56]; /* 56-90 */
+ u8 flags; /* 91 */
+ u8 _reserved3[100 - 92]; /* 92-99 */
+ u32 rnsize2; /* 100-103 */
+ u64 rnmax2; /* 104-111 */
+ u8 _reserved4[4096 - 112]; /* 112-4095 */
+} __attribute__((packed, aligned(4096)));
+
+static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
+static int __initdata early_readinfo_sccb_valid;
+
+u64 sclp_facilities;
void __init sclp_readinfo_early(void)
{
- sclp_cmdw_t command;
- struct sccb_header *sccb;
int ret;
+ int i;
+ struct sclp_readinfo_sccb *sccb;
+ sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
+ SCLP_CMDW_READ_SCP_INFO};
- __ctl_set_bit(0, 9); /* enable service signal subclass mask */
-
- sccb = &s390_readinfo_sccb.header;
- command = SCLP_CMDW_READ_SCP_INFO_FORCED;
- while (1) {
- u16 response;
-
- memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
- sccb->length = sizeof(s390_readinfo_sccb);
- sccb->control_mask[2] = 0x80;
-
- ret = sclp_service_call(command, &s390_readinfo_sccb);
-
- if (ret == -EIO)
- goto out;
- if (ret == -EBUSY)
- continue;
+ /* Enable service signal subclass mask. */
+ __ctl_set_bit(0, 9);
+ sccb = &early_readinfo_sccb;
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ do {
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->header.length = sizeof(*sccb);
+ sccb->header.control_mask[2] = 0x80;
+ ret = sclp_service_call(commands[i], sccb);
+ } while (ret == -EBUSY);
+ if (ret)
+ break;
__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
PSW_MASK_WAIT | PSW_DEFAULT_KEY);
local_irq_disable();
+ /*
+ * Contents of the sccb might have changed
+ * therefore a barrier is needed.
+ */
barrier();
+ if (sccb->header.response_code == 0x10) {
+ early_readinfo_sccb_valid = 1;
+ break;
+ }
+ if (sccb->header.response_code != 0x1f0)
+ break;
+ }
+ /* Disable service signal subclass mask again. */
+ __ctl_clear_bit(0, 9);
+}
- response = sccb->response_code;
+void __init sclp_facilities_detect(void)
+{
+ if (!early_readinfo_sccb_valid)
+ return;
+ sclp_facilities = early_readinfo_sccb.facilities;
+}
- if (response == 0x10)
- break;
+unsigned long long __init sclp_memory_detect(void)
+{
+ unsigned long long memsize;
+ struct sclp_readinfo_sccb *sccb;
- if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
- break;
+ if (!early_readinfo_sccb_valid)
+ return 0;
+ sccb = &early_readinfo_sccb;
+ if (sccb->rnsize)
+ memsize = sccb->rnsize << 20;
+ else
+ memsize = sccb->rnsize2 << 20;
+ if (sccb->rnmax)
+ memsize *= sccb->rnmax;
+ else
+ memsize *= sccb->rnmax2;
+ return memsize;
+}
- command = SCLP_CMDW_READ_SCP_INFO;
- }
-out:
- __ctl_clear_bit(0, 9); /* disable service signal subclass mask */
+/*
+ * This function will be called after sclp_memory_detect(), which gets called
+ * early from early.c code. Therefore the sccb should have valid contents.
+ */
+void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
+{
+ struct sclp_readinfo_sccb *sccb;
+
+ if (!early_readinfo_sccb_valid)
+ return;
+ sccb = &early_readinfo_sccb;
+ info->is_valid = 1;
+ if (sccb->flags & 0x2)
+ info->has_dump = 1;
+ memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
}
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index fce3dac5cb3e..82e6a6b253eb 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -175,13 +175,12 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static const struct file_operations vmcp_fops = {
.owner = THIS_MODULE,
- .open = &vmcp_open,
- .release = &vmcp_release,
- .read = &vmcp_read,
- .llseek = &no_llseek,
- .write = &vmcp_write,
- .unlocked_ioctl = &vmcp_ioctl,
- .compat_ioctl = &vmcp_ioctl
+ .open = vmcp_open,
+ .release = vmcp_release,
+ .read = vmcp_read,
+ .write = vmcp_write,
+ .unlocked_ioctl = vmcp_ioctl,
+ .compat_ioctl = vmcp_ioctl
};
static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index a5a00e9ae4d0..12f7a4ce82c1 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -835,7 +835,7 @@ static void vmlogrdr_cleanup(void)
}
-static int vmlogrdr_init(void)
+static int __init vmlogrdr_init(void)
{
int rc;
int i;
@@ -885,7 +885,7 @@ cleanup:
}
-static void vmlogrdr_exit(void)
+static void __exit vmlogrdr_exit(void)
{
vmlogrdr_cleanup();
printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 4e711a985d59..3712ede16723 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -156,7 +156,7 @@ static int memcpy_real(void *dest, unsigned long src, size_t count)
return rc;
}
-static int memcpy_real_user(__user void *dest, unsigned long src, size_t count)
+static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
{
static char buf[4096];
int offs = 0, size;
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 997f46874537..60b9347f7c92 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -27,7 +27,6 @@
/*
* diag210 is used under VM to get information about a virtual device
*/
-#ifdef CONFIG_64BIT
int
diag210(struct diag210 * addr)
{
@@ -43,6 +42,7 @@ diag210(struct diag210 * addr)
spin_lock_irqsave(&diag210_lock, flags);
diag210_tmp = *addr;
+#ifdef CONFIG_64BIT
asm volatile(
" lhi %0,-1\n"
" sam31\n"
@@ -51,19 +51,8 @@ diag210(struct diag210 * addr)
" srl %0,28\n"
"1: sam64\n"
EX_TABLE(0b,1b)
- : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory");
-
- *addr = diag210_tmp;
- spin_unlock_irqrestore(&diag210_lock, flags);
-
- return ccode;
-}
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
#else
-int
-diag210(struct diag210 * addr)
-{
- int ccode;
-
asm volatile(
" lhi %0,-1\n"
" diag %1,0,0x210\n"
@@ -71,11 +60,14 @@ diag210(struct diag210 * addr)
" srl %0,28\n"
"1:\n"
EX_TABLE(0b,1b)
- : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory");
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#endif
+
+ *addr = diag210_tmp;
+ spin_unlock_irqrestore(&diag210_lock, flags);
return ccode;
}
-#endif
/*
* Input :
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 5aac0ec36368..90bd22014513 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -43,6 +43,7 @@ static void ap_poll_all(unsigned long);
static void ap_poll_timeout(unsigned long);
static int ap_poll_thread_start(void);
static void ap_poll_thread_stop(void);
+static void ap_request_timeout(unsigned long);
/**
* Module description.
@@ -189,6 +190,7 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
case AP_RESPONSE_NORMAL:
return 0;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
return -EBUSY;
default: /* Device is gone. */
return -ENODEV;
@@ -252,6 +254,8 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
if (status.queue_empty)
return -ENOENT;
return -EBUSY;
+ case AP_RESPONSE_RESET_IN_PROGRESS:
+ return -EBUSY;
default:
return -ENODEV;
}
@@ -326,11 +330,12 @@ static int ap_init_queue(ap_qid_t qid)
i = AP_MAX_RESET; /* return with -ENODEV */
break;
case AP_RESPONSE_RESET_IN_PROGRESS:
+ rc = -EBUSY;
case AP_RESPONSE_BUSY:
default:
break;
}
- if (rc != -ENODEV)
+ if (rc != -ENODEV && rc != -EBUSY)
break;
if (i < AP_MAX_RESET - 1) {
udelay(5);
@@ -341,6 +346,40 @@ static int ap_init_queue(ap_qid_t qid)
}
/**
+ * Arm request timeout if a AP device was idle and a new request is submitted.
+ */
+static void ap_increase_queue_count(struct ap_device *ap_dev)
+{
+ int timeout = ap_dev->drv->request_timeout;
+
+ ap_dev->queue_count++;
+ if (ap_dev->queue_count == 1) {
+ mod_timer(&ap_dev->timeout, jiffies + timeout);
+ ap_dev->reset = AP_RESET_ARMED;
+ }
+}
+
+/**
+ * AP device is still alive, re-schedule request timeout if there are still
+ * pending requests.
+ */
+static void ap_decrease_queue_count(struct ap_device *ap_dev)
+{
+ int timeout = ap_dev->drv->request_timeout;
+
+ ap_dev->queue_count--;
+ if (ap_dev->queue_count > 0)
+ mod_timer(&ap_dev->timeout, jiffies + timeout);
+ else
+ /**
+ * The timeout timer should to be disabled now - since
+ * del_timer_sync() is very expensive, we just tell via the
+ * reset flag to ignore the pending timeout timer.
+ */
+ ap_dev->reset = AP_RESET_IGNORE;
+}
+
+/**
* AP device related attributes.
*/
static ssize_t ap_hwtype_show(struct device *dev,
@@ -498,6 +537,7 @@ static int ap_device_remove(struct device *dev)
struct ap_driver *ap_drv = ap_dev->drv;
ap_flush_queue(ap_dev);
+ del_timer_sync(&ap_dev->timeout);
if (ap_drv->remove)
ap_drv->remove(ap_dev);
spin_lock_bh(&ap_device_lock);
@@ -759,17 +799,21 @@ static void ap_scan_bus(struct work_struct *unused)
__ap_scan_bus);
rc = ap_query_queue(qid, &queue_depth, &device_type);
if (dev) {
+ if (rc == -EBUSY) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(AP_RESET_TIMEOUT);
+ rc = ap_query_queue(qid, &queue_depth,
+ &device_type);
+ }
ap_dev = to_ap_dev(dev);
spin_lock_bh(&ap_dev->lock);
if (rc || ap_dev->unregistered) {
spin_unlock_bh(&ap_dev->lock);
- put_device(dev);
device_unregister(dev);
+ put_device(dev);
continue;
- } else
- spin_unlock_bh(&ap_dev->lock);
- }
- if (dev) {
+ }
+ spin_unlock_bh(&ap_dev->lock);
put_device(dev);
continue;
}
@@ -788,6 +832,8 @@ static void ap_scan_bus(struct work_struct *unused)
INIT_LIST_HEAD(&ap_dev->pendingq);
INIT_LIST_HEAD(&ap_dev->requestq);
INIT_LIST_HEAD(&ap_dev->list);
+ setup_timer(&ap_dev->timeout, ap_request_timeout,
+ (unsigned long) ap_dev);
if (device_type == 0)
ap_probe_device_type(ap_dev);
else
@@ -853,7 +899,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
atomic_dec(&ap_poll_requests);
- ap_dev->queue_count--;
+ ap_decrease_queue_count(ap_dev);
list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
if (ap_msg->psmid != ap_dev->reply->psmid)
continue;
@@ -904,7 +950,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
atomic_inc(&ap_poll_requests);
- ap_dev->queue_count++;
+ ap_increase_queue_count(ap_dev);
list_move_tail(&ap_msg->list, &ap_dev->pendingq);
ap_dev->requestq_count--;
ap_dev->pendingq_count++;
@@ -914,6 +960,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
*flags |= 2;
break;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
*flags |= 2;
break;
case AP_RESPONSE_MESSAGE_TOO_BIG:
@@ -960,10 +1007,11 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms
list_add_tail(&ap_msg->list, &ap_dev->pendingq);
atomic_inc(&ap_poll_requests);
ap_dev->pendingq_count++;
- ap_dev->queue_count++;
+ ap_increase_queue_count(ap_dev);
ap_dev->total_request_count++;
break;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
list_add_tail(&ap_msg->list, &ap_dev->requestq);
ap_dev->requestq_count++;
ap_dev->total_request_count++;
@@ -1046,6 +1094,25 @@ static void ap_poll_timeout(unsigned long unused)
}
/**
+ * Reset a not responding AP device and move all requests from the
+ * pending queue to the request queue.
+ */
+static void ap_reset(struct ap_device *ap_dev)
+{
+ int rc;
+
+ ap_dev->reset = AP_RESET_IGNORE;
+ atomic_sub(ap_dev->queue_count, &ap_poll_requests);
+ ap_dev->queue_count = 0;
+ list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
+ ap_dev->requestq_count += ap_dev->pendingq_count;
+ ap_dev->pendingq_count = 0;
+ rc = ap_init_queue(ap_dev->qid);
+ if (rc == -ENODEV)
+ ap_dev->unregistered = 1;
+}
+
+/**
* Poll all AP devices on the bus in a round robin fashion. Continue
* polling until bit 2^0 of the control flags is not set. If bit 2^1
* of the control flags has been set arm the poll timer.
@@ -1056,6 +1123,8 @@ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
if (!ap_dev->unregistered) {
if (ap_poll_queue(ap_dev, flags))
ap_dev->unregistered = 1;
+ if (ap_dev->reset == AP_RESET_DO)
+ ap_reset(ap_dev);
}
spin_unlock(&ap_dev->lock);
return 0;
@@ -1147,6 +1216,17 @@ static void ap_poll_thread_stop(void)
mutex_unlock(&ap_poll_thread_mutex);
}
+/**
+ * Handling of request timeouts
+ */
+static void ap_request_timeout(unsigned long data)
+{
+ struct ap_device *ap_dev = (struct ap_device *) data;
+
+ if (ap_dev->reset == AP_RESET_ARMED)
+ ap_dev->reset = AP_RESET_DO;
+}
+
static void ap_reset_domain(void)
{
int i;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 008559ea742b..87c2d6442875 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -33,6 +33,7 @@
#define AP_DEVICES 64 /* Number of AP devices. */
#define AP_DOMAINS 16 /* Number of AP domains. */
#define AP_MAX_RESET 90 /* Maximum number of resets. */
+#define AP_RESET_TIMEOUT (HZ/2) /* Time in ticks for reset timeouts. */
#define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */
#define AP_POLL_TIME 1 /* Time in ticks between receive polls. */
@@ -83,6 +84,13 @@ struct ap_queue_status {
#define AP_DEVICE_TYPE_CEX2A 6
#define AP_DEVICE_TYPE_CEX2C 7
+/**
+ * AP reset flag states
+ */
+#define AP_RESET_IGNORE 0 /* request timeout will be ignored */
+#define AP_RESET_ARMED 1 /* request timeout timer is active */
+#define AP_RESET_DO 2 /* AP reset required */
+
struct ap_device;
struct ap_message;
@@ -95,6 +103,7 @@ struct ap_driver {
/* receive is called from tasklet context */
void (*receive)(struct ap_device *, struct ap_message *,
struct ap_message *);
+ int request_timeout; /* request timeout in jiffies */
};
#define to_ap_drv(x) container_of((x), struct ap_driver, driver)
@@ -112,6 +121,8 @@ struct ap_device {
int queue_depth; /* AP queue depth.*/
int device_type; /* AP device type. */
int unregistered; /* marks AP device as unregistered */
+ struct timer_list timeout; /* Timer for request timeouts. */
+ int reset; /* Reset required after req. timeout. */
int queue_count; /* # messages currently on AP queue. */
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 5bb13a9d0898..08657f604b8c 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_cex2a_driver = {
.remove = zcrypt_cex2a_remove,
.receive = zcrypt_cex2a_receive,
.ids = zcrypt_cex2a_ids,
+ .request_timeout = CEX2A_CLEANUP_TIME,
};
/**
@@ -306,18 +307,13 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, CEX2A_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
@@ -348,18 +344,13 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, CEX2A_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 818ffe05ac00..6e93b4751782 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_pcica_driver = {
.remove = zcrypt_pcica_remove,
.receive = zcrypt_pcica_receive,
.ids = zcrypt_pcica_ids,
+ .request_timeout = PCICA_CLEANUP_TIME,
};
/**
@@ -290,18 +291,13 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICA_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
@@ -332,18 +328,13 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICA_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index f295a403b29a..d6d59bf9ac38 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -82,6 +82,7 @@ static struct ap_driver zcrypt_pcicc_driver = {
.remove = zcrypt_pcicc_remove,
.receive = zcrypt_pcicc_receive,
.ids = zcrypt_pcicc_ids,
+ .request_timeout = PCICC_CLEANUP_TIME,
};
/**
@@ -501,18 +502,13 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -544,18 +540,13 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 252443b6bd1b..64948788d301 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -93,6 +93,7 @@ static struct ap_driver zcrypt_pcixcc_driver = {
.remove = zcrypt_pcixcc_remove,
.receive = zcrypt_pcixcc_receive,
.ids = zcrypt_pcixcc_ids,
+ .request_timeout = PCIXCC_CLEANUP_TIME,
};
/**
@@ -641,18 +642,13 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -685,18 +681,13 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -729,17 +720,12 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
memset(ap_msg.message, 0x0, ap_msg.length);
kfree(ap_msg.message);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 6b76babc7fbf..a0ea43598515 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -842,12 +842,16 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 61de78a9f6ee..4fff61b32dcb 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -143,7 +143,7 @@ static struct console sercons;
static unsigned long break_pressed; /* break, really ... */
#endif
-static unsigned char zs_init_regs[16] __initdata = {
+static unsigned char zs_init_regs[16] = {
0, /* write 0 */
0, /* write 1 */
0, /* write 2 */
@@ -1581,7 +1581,7 @@ static void __init show_serial_version(void)
/* Initialize Z8530s zs_channels
*/
-static void __init probe_sccs(void)
+static void probe_sccs(void)
{
struct dec_serial **pp;
int i, n, n_chips = 0, n_channels, chip, channel;
@@ -1923,7 +1923,7 @@ static struct tty_driver *serial_console_device(struct console *c, int *index)
* - initialize the serial port
* Return non-zero if we didn't find a serial port.
*/
-static int __init serial_console_setup(struct console *co, char *options)
+static int serial_console_setup(struct console *co, char *options)
{
struct dec_serial *info;
int baud = 9600;
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 904e5aeb696c..df95d6c2cefa 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -35,4 +35,17 @@ config W1_SLAVE_DS2433_CRC
Each block has 30 bytes of data and a two byte CRC16.
Full block writes are only allowed if the CRC is valid.
+config W1_SLAVE_DS2760
+ tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
+ depends on W1
+ help
+ If you enable this you will have the DS2760 battery monitor
+ chip support.
+
+ The battery monitor chip is used in many batteries/devices
+ as the one who is responsible for charging/discharging/monitoring
+ Li+ batteries.
+
+ If you are unsure, say N.
+
endmenu
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index 725dcfdfddb4..a8eb7524df1d 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o
obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o
obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
+obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
new file mode 100644
index 000000000000..88a37fbccc3f
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -0,0 +1,213 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/idr.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+#include "w1_ds2760.h"
+
+static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
+ int io)
+{
+ struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+ if (!dev)
+ return 0;
+
+ mutex_lock(&sl->master->mutex);
+
+ if (addr > DS2760_DATA_SIZE || addr < 0) {
+ count = 0;
+ goto out;
+ }
+ if (addr + count > DS2760_DATA_SIZE)
+ count = DS2760_DATA_SIZE - addr;
+
+ if (!w1_reset_select_slave(sl)) {
+ if (!io) {
+ w1_write_8(sl->master, W1_DS2760_READ_DATA);
+ w1_write_8(sl->master, addr);
+ count = w1_read_block(sl->master, buf, count);
+ } else {
+ w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
+ w1_write_8(sl->master, addr);
+ w1_write_block(sl->master, buf, count);
+ /* XXX w1_write_block returns void, not n_written */
+ }
+ }
+
+out:
+ mutex_unlock(&sl->master->mutex);
+
+ return count;
+}
+
+int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count)
+{
+ return w1_ds2760_io(dev, buf, addr, count, 0);
+}
+
+int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count)
+{
+ return w1_ds2760_io(dev, buf, addr, count, 1);
+}
+
+static ssize_t w1_ds2760_read_bin(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ return w1_ds2760_read(dev, buf, off, count);
+}
+
+static struct bin_attribute w1_ds2760_bin_attr = {
+ .attr = {
+ .name = "w1_slave",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = DS2760_DATA_SIZE,
+ .read = w1_ds2760_read_bin,
+};
+
+static DEFINE_IDR(bat_idr);
+static DEFINE_MUTEX(bat_idr_lock);
+
+static int new_bat_id(void)
+{
+ int ret;
+
+ while (1) {
+ int id;
+
+ ret = idr_pre_get(&bat_idr, GFP_KERNEL);
+ if (ret == 0)
+ return -ENOMEM;
+
+ mutex_lock(&bat_idr_lock);
+ ret = idr_get_new(&bat_idr, NULL, &id);
+ mutex_unlock(&bat_idr_lock);
+
+ if (ret == 0) {
+ ret = id & MAX_ID_MASK;
+ break;
+ } else if (ret == -EAGAIN) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void release_bat_id(int id)
+{
+ mutex_lock(&bat_idr_lock);
+ idr_remove(&bat_idr, id);
+ mutex_unlock(&bat_idr_lock);
+
+ return;
+}
+
+static int w1_ds2760_add_slave(struct w1_slave *sl)
+{
+ int ret;
+ int id;
+ struct platform_device *pdev;
+
+ id = new_bat_id();
+ if (id < 0) {
+ ret = id;
+ goto noid;
+ }
+
+ pdev = platform_device_alloc("ds2760-battery", id);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto pdev_alloc_failed;
+ }
+ pdev->dev.parent = &sl->dev;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto pdev_add_failed;
+
+ ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+ if (ret)
+ goto bin_attr_failed;
+
+ dev_set_drvdata(&sl->dev, pdev);
+
+ goto success;
+
+bin_attr_failed:
+pdev_add_failed:
+ platform_device_unregister(pdev);
+pdev_alloc_failed:
+ release_bat_id(id);
+noid:
+success:
+ return ret;
+}
+
+static void w1_ds2760_remove_slave(struct w1_slave *sl)
+{
+ struct platform_device *pdev = dev_get_drvdata(&sl->dev);
+ int id = pdev->id;
+
+ platform_device_unregister(pdev);
+ release_bat_id(id);
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+
+ return;
+}
+
+static struct w1_family_ops w1_ds2760_fops = {
+ .add_slave = w1_ds2760_add_slave,
+ .remove_slave = w1_ds2760_remove_slave,
+};
+
+static struct w1_family w1_ds2760_family = {
+ .fid = W1_FAMILY_DS2760,
+ .fops = &w1_ds2760_fops,
+};
+
+static int __init w1_ds2760_init(void)
+{
+ printk(KERN_INFO "1-Wire driver for the DS2760 battery monitor "
+ " chip - (c) 2004-2005, Szabolcs Gyurko\n");
+ idr_init(&bat_idr);
+ return w1_register_family(&w1_ds2760_family);
+}
+
+static void __exit w1_ds2760_exit(void)
+{
+ w1_unregister_family(&w1_ds2760_family);
+ idr_destroy(&bat_idr);
+}
+
+EXPORT_SYMBOL(w1_ds2760_read);
+EXPORT_SYMBOL(w1_ds2760_write);
+
+module_init(w1_ds2760_init);
+module_exit(w1_ds2760_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>");
+MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
diff --git a/drivers/w1/slaves/w1_ds2760.h b/drivers/w1/slaves/w1_ds2760.h
new file mode 100644
index 000000000000..f1302429cb02
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.h
@@ -0,0 +1,50 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#ifndef __w1_ds2760_h__
+#define __w1_ds2760_h__
+
+/* Known commands to the DS2760 chip */
+#define W1_DS2760_SWAP 0xAA
+#define W1_DS2760_READ_DATA 0x69
+#define W1_DS2760_WRITE_DATA 0x6C
+#define W1_DS2760_COPY_DATA 0x48
+#define W1_DS2760_RECALL_DATA 0xB8
+#define W1_DS2760_LOCK 0x6A
+
+/* Number of valid register addresses */
+#define DS2760_DATA_SIZE 0x40
+
+#define DS2760_PROTECTION_REG 0x00
+#define DS2760_STATUS_REG 0x01
+#define DS2760_EEPROM_REG 0x07
+#define DS2760_SPECIAL_FEATURE_REG 0x08
+#define DS2760_VOLTAGE_MSB 0x0c
+#define DS2760_VOLTAGE_LSB 0x0d
+#define DS2760_CURRENT_MSB 0x0e
+#define DS2760_CURRENT_LSB 0x0f
+#define DS2760_CURRENT_ACCUM_MSB 0x10
+#define DS2760_CURRENT_ACCUM_LSB 0x11
+#define DS2760_TEMP_MSB 0x18
+#define DS2760_TEMP_LSB 0x19
+#define DS2760_EEPROM_BLOCK0 0x20
+#define DS2760_ACTIVE_FULL 0x20
+#define DS2760_EEPROM_BLOCK1 0x30
+#define DS2760_RATED_CAPACITY 0x32
+#define DS2760_CURRENT_OFFSET_BIAS 0x33
+#define DS2760_ACTIVE_EMPTY 0x3b
+
+extern int w1_ds2760_read(struct device *dev, char *buf, int addr,
+ size_t count);
+extern int w1_ds2760_write(struct device *dev, char *buf, int addr,
+ size_t count);
+
+#endif /* !__w1_ds2760_h__ */
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 1e2ac40c2c14..ef1e1dafa19a 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -33,6 +33,7 @@
#define W1_THERM_DS1822 0x22
#define W1_EEPROM_DS2433 0x23
#define W1_THERM_DS18B20 0x28
+#define W1_FAMILY_DS2760 0x30
#define MAXNAMELEN 32
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index f544a2855923..36e381c6a99a 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -33,7 +33,7 @@ const struct file_operations adfs_file_operations = {
.fsync = file_fsync,
.write = do_sync_write,
.aio_write = generic_file_aio_write,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations adfs_file_inode_operations = {
diff --git a/fs/affs/file.c b/fs/affs/file.c
index c8796906f584..c314a35f0918 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -35,7 +35,7 @@ const struct file_operations affs_file_operations = {
.open = affs_file_open,
.release = affs_file_release,
.fsync = file_fsync,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations affs_file_inode_operations = {
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 9c0e721d9fc2..aede7eb66dd4 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -32,7 +32,7 @@ const struct file_operations afs_file_operations = {
.aio_read = generic_file_aio_read,
.aio_write = afs_file_write,
.mmap = generic_file_readonly_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.fsync = afs_fsync,
};
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 329ee473eede..521ff7caadbd 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -114,12 +114,6 @@ static int bad_file_lock(struct file *file, int cmd, struct file_lock *fl)
return -EIO;
}
-static ssize_t bad_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
-{
- return -EIO;
-}
-
static ssize_t bad_file_sendpage(struct file *file, struct page *page,
int off, size_t len, loff_t *pos, int more)
{
@@ -182,7 +176,6 @@ static const struct file_operations bad_file_ops =
.aio_fsync = bad_file_aio_fsync,
.fasync = bad_file_fasync,
.lock = bad_file_lock,
- .sendfile = bad_file_sendfile,
.sendpage = bad_file_sendpage,
.get_unmapped_area = bad_file_get_unmapped_area,
.check_flags = bad_file_check_flags,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index ef4d1fa04e65..24310e9ee05a 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -24,7 +24,7 @@ const struct file_operations bfs_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
diff --git a/fs/bio.c b/fs/bio.c
index 093345f00128..33e46340a766 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1223,8 +1223,6 @@ EXPORT_SYMBOL(bio_hw_segments);
EXPORT_SYMBOL(bio_add_page);
EXPORT_SYMBOL(bio_add_pc_page);
EXPORT_SYMBOL(bio_get_nr_vecs);
-EXPORT_SYMBOL(bio_map_user);
-EXPORT_SYMBOL(bio_unmap_user);
EXPORT_SYMBOL(bio_map_kern);
EXPORT_SYMBOL(bio_pair_release);
EXPORT_SYMBOL(bio_split);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index ea1480a16f51..b3e9bfa748cf 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1346,7 +1346,6 @@ const struct file_operations def_blk_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_blkdev_ioctl,
#endif
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 7c04752b76cb..8b0cbf4a4ad0 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -616,7 +616,7 @@ const struct file_operations cifs_file_ops = {
.fsync = cifs_fsync,
.flush = cifs_flush,
.mmap = cifs_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
@@ -637,7 +637,7 @@ const struct file_operations cifs_file_direct_ops = {
.lock = cifs_lock,
.fsync = cifs_fsync,
.flush = cifs_flush,
- .sendfile = generic_file_sendfile, /* BB removeme BB */
+ .splice_read = generic_file_splice_read,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
@@ -656,7 +656,7 @@ const struct file_operations cifs_file_nobrl_ops = {
.fsync = cifs_fsync,
.flush = cifs_flush,
.mmap = cifs_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
@@ -676,7 +676,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
.release = cifs_close,
.fsync = cifs_fsync,
.flush = cifs_flush,
- .sendfile = generic_file_sendfile, /* BB removeme BB */
+ .splice_read = generic_file_splice_read,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 5ef2b609ec7d..99dbe866816d 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -47,8 +47,9 @@ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *p
}
static ssize_t
-coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
- read_actor_t actor, void *target)
+coda_file_splice_read(struct file *coda_file, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t count,
+ unsigned int flags)
{
struct coda_file_info *cfi;
struct file *host_file;
@@ -57,10 +58,10 @@ coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
- if (!host_file->f_op || !host_file->f_op->sendfile)
+ if (!host_file->f_op || !host_file->f_op->splice_read)
return -EINVAL;
- return host_file->f_op->sendfile(host_file, ppos, count, actor, target);
+ return host_file->f_op->splice_read(host_file, ppos, pipe, count,flags);
}
static ssize_t
@@ -295,6 +296,6 @@ const struct file_operations coda_file_operations = {
.flush = coda_flush,
.release = coda_release,
.fsync = coda_fsync,
- .sendfile = coda_file_sendfile,
+ .splice_read = coda_file_splice_read,
};
diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile
index 604cf7dc5f39..d248e60951ba 100644
--- a/fs/dlm/Makefile
+++ b/fs/dlm/Makefile
@@ -8,6 +8,7 @@ dlm-y := ast.o \
member.o \
memory.o \
midcomms.o \
+ netlink.o \
lowcomms.o \
rcom.o \
recover.o \
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 822abdcd1434..5069b2cb5a1f 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -90,6 +90,7 @@ struct cluster {
unsigned int cl_scan_secs;
unsigned int cl_log_debug;
unsigned int cl_protocol;
+ unsigned int cl_timewarn_cs;
};
enum {
@@ -103,6 +104,7 @@ enum {
CLUSTER_ATTR_SCAN_SECS,
CLUSTER_ATTR_LOG_DEBUG,
CLUSTER_ATTR_PROTOCOL,
+ CLUSTER_ATTR_TIMEWARN_CS,
};
struct cluster_attribute {
@@ -162,6 +164,7 @@ CLUSTER_ATTR(toss_secs, 1);
CLUSTER_ATTR(scan_secs, 1);
CLUSTER_ATTR(log_debug, 0);
CLUSTER_ATTR(protocol, 0);
+CLUSTER_ATTR(timewarn_cs, 1);
static struct configfs_attribute *cluster_attrs[] = {
[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
@@ -174,6 +177,7 @@ static struct configfs_attribute *cluster_attrs[] = {
[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
+ [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
NULL,
};
@@ -429,6 +433,8 @@ static struct config_group *make_cluster(struct config_group *g,
cl->cl_toss_secs = dlm_config.ci_toss_secs;
cl->cl_scan_secs = dlm_config.ci_scan_secs;
cl->cl_log_debug = dlm_config.ci_log_debug;
+ cl->cl_protocol = dlm_config.ci_protocol;
+ cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
space_list = &sps->ss_group;
comm_list = &cms->cs_group;
@@ -748,9 +754,16 @@ static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len)
static struct space *get_space(char *name)
{
+ struct config_item *i;
+
if (!space_list)
return NULL;
- return to_space(config_group_find_obj(space_list, name));
+
+ down(&space_list->cg_subsys->su_sem);
+ i = config_group_find_obj(space_list, name);
+ up(&space_list->cg_subsys->su_sem);
+
+ return to_space(i);
}
static void put_space(struct space *sp)
@@ -776,20 +789,20 @@ static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr)
if (cm->nodeid != nodeid)
continue;
found = 1;
+ config_item_get(i);
break;
} else {
if (!cm->addr_count ||
memcmp(cm->addr[0], addr, sizeof(*addr)))
continue;
found = 1;
+ config_item_get(i);
break;
}
}
up(&clusters_root.subsys.su_sem);
- if (found)
- config_item_get(i);
- else
+ if (!found)
cm = NULL;
return cm;
}
@@ -909,6 +922,7 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
#define DEFAULT_SCAN_SECS 5
#define DEFAULT_LOG_DEBUG 0
#define DEFAULT_PROTOCOL 0
+#define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */
struct dlm_config_info dlm_config = {
.ci_tcp_port = DEFAULT_TCP_PORT,
@@ -920,6 +934,7 @@ struct dlm_config_info dlm_config = {
.ci_toss_secs = DEFAULT_TOSS_SECS,
.ci_scan_secs = DEFAULT_SCAN_SECS,
.ci_log_debug = DEFAULT_LOG_DEBUG,
- .ci_protocol = DEFAULT_PROTOCOL
+ .ci_protocol = DEFAULT_PROTOCOL,
+ .ci_timewarn_cs = DEFAULT_TIMEWARN_CS
};
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index 967cc3d72e5e..a3170fe22090 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -27,6 +27,7 @@ struct dlm_config_info {
int ci_scan_secs;
int ci_log_debug;
int ci_protocol;
+ int ci_timewarn_cs;
};
extern struct dlm_config_info dlm_config;
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 61ba670b9e02..12c3bfd5e660 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -17,6 +17,7 @@
#include <linux/debugfs.h>
#include "dlm_internal.h"
+#include "lock.h"
#define DLM_DEBUG_BUF_LEN 4096
static char debug_buf[DLM_DEBUG_BUF_LEN];
@@ -26,6 +27,8 @@ static struct dentry *dlm_root;
struct rsb_iter {
int entry;
+ int locks;
+ int header;
struct dlm_ls *ls;
struct list_head *next;
struct dlm_rsb *rsb;
@@ -57,8 +60,8 @@ static char *print_lockmode(int mode)
}
}
-static void print_lock(struct seq_file *s, struct dlm_lkb *lkb,
- struct dlm_rsb *res)
+static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
+ struct dlm_rsb *res)
{
seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
@@ -85,6 +88,8 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
struct dlm_lkb *lkb;
int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
+ lock_rsb(res);
+
seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
for (i = 0; i < res->res_length; i++) {
if (isprint(res->res_name[i]))
@@ -129,15 +134,15 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
/* Print the locks attached to this resource */
seq_printf(s, "Granted Queue\n");
list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
- print_lock(s, lkb, res);
+ print_resource_lock(s, lkb, res);
seq_printf(s, "Conversion Queue\n");
list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
- print_lock(s, lkb, res);
+ print_resource_lock(s, lkb, res);
seq_printf(s, "Waiting Queue\n");
list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
- print_lock(s, lkb, res);
+ print_resource_lock(s, lkb, res);
if (list_empty(&res->res_lookup))
goto out;
@@ -151,6 +156,61 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
seq_printf(s, "\n");
}
out:
+ unlock_rsb(res);
+ return 0;
+}
+
+static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r)
+{
+ struct dlm_user_args *ua;
+ unsigned int waiting = 0;
+ uint64_t xid = 0;
+
+ if (lkb->lkb_flags & DLM_IFL_USER) {
+ ua = (struct dlm_user_args *) lkb->lkb_astparam;
+ if (ua)
+ xid = ua->xid;
+ }
+
+ if (lkb->lkb_timestamp)
+ waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp);
+
+ /* id nodeid remid pid xid exflags flags sts grmode rqmode time_ms
+ r_nodeid r_len r_name */
+
+ seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %u %u %d \"%s\"\n",
+ lkb->lkb_id,
+ lkb->lkb_nodeid,
+ lkb->lkb_remid,
+ lkb->lkb_ownpid,
+ (unsigned long long)xid,
+ lkb->lkb_exflags,
+ lkb->lkb_flags,
+ lkb->lkb_status,
+ lkb->lkb_grmode,
+ lkb->lkb_rqmode,
+ waiting,
+ r->res_nodeid,
+ r->res_length,
+ r->res_name);
+}
+
+static int print_locks(struct dlm_rsb *r, struct seq_file *s)
+{
+ struct dlm_lkb *lkb;
+
+ lock_rsb(r);
+
+ list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
+ print_lock(s, lkb, r);
+
+ list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
+ print_lock(s, lkb, r);
+
+ list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
+ print_lock(s, lkb, r);
+
+ unlock_rsb(r);
return 0;
}
@@ -166,6 +226,9 @@ static int rsb_iter_next(struct rsb_iter *ri)
read_lock(&ls->ls_rsbtbl[i].lock);
if (!list_empty(&ls->ls_rsbtbl[i].list)) {
ri->next = ls->ls_rsbtbl[i].list.next;
+ ri->rsb = list_entry(ri->next, struct dlm_rsb,
+ res_hashchain);
+ dlm_hold_rsb(ri->rsb);
read_unlock(&ls->ls_rsbtbl[i].lock);
break;
}
@@ -176,6 +239,7 @@ static int rsb_iter_next(struct rsb_iter *ri)
if (ri->entry >= ls->ls_rsbtbl_size)
return 1;
} else {
+ struct dlm_rsb *old = ri->rsb;
i = ri->entry;
read_lock(&ls->ls_rsbtbl[i].lock);
ri->next = ri->next->next;
@@ -184,11 +248,14 @@ static int rsb_iter_next(struct rsb_iter *ri)
ri->next = NULL;
ri->entry++;
read_unlock(&ls->ls_rsbtbl[i].lock);
+ dlm_put_rsb(old);
goto top;
}
+ ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
+ dlm_hold_rsb(ri->rsb);
read_unlock(&ls->ls_rsbtbl[i].lock);
+ dlm_put_rsb(old);
}
- ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
return 0;
}
@@ -202,7 +269,7 @@ static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
{
struct rsb_iter *ri;
- ri = kmalloc(sizeof *ri, GFP_KERNEL);
+ ri = kzalloc(sizeof *ri, GFP_KERNEL);
if (!ri)
return NULL;
@@ -260,7 +327,17 @@ static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
{
struct rsb_iter *ri = iter_ptr;
- print_resource(ri->rsb, file);
+ if (ri->locks) {
+ if (ri->header) {
+ seq_printf(file, "id nodeid remid pid xid exflags flags "
+ "sts grmode rqmode time_ms r_nodeid "
+ "r_len r_name\n");
+ ri->header = 0;
+ }
+ print_locks(ri->rsb, file);
+ } else {
+ print_resource(ri->rsb, file);
+ }
return 0;
}
@@ -296,6 +373,83 @@ static const struct file_operations rsb_fops = {
};
/*
+ * Dump state in compact per-lock listing
+ */
+
+static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
+{
+ struct rsb_iter *ri;
+
+ ri = kzalloc(sizeof *ri, GFP_KERNEL);
+ if (!ri)
+ return NULL;
+
+ ri->ls = ls;
+ ri->entry = 0;
+ ri->next = NULL;
+ ri->locks = 1;
+
+ if (*pos == 0)
+ ri->header = 1;
+
+ if (rsb_iter_next(ri)) {
+ rsb_iter_free(ri);
+ return NULL;
+ }
+
+ return ri;
+}
+
+static void *locks_seq_start(struct seq_file *file, loff_t *pos)
+{
+ struct rsb_iter *ri;
+ loff_t n = *pos;
+
+ ri = locks_iter_init(file->private, pos);
+ if (!ri)
+ return NULL;
+
+ while (n--) {
+ if (rsb_iter_next(ri)) {
+ rsb_iter_free(ri);
+ return NULL;
+ }
+ }
+
+ return ri;
+}
+
+static struct seq_operations locks_seq_ops = {
+ .start = locks_seq_start,
+ .next = rsb_seq_next,
+ .stop = rsb_seq_stop,
+ .show = rsb_seq_show,
+};
+
+static int locks_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int ret;
+
+ ret = seq_open(file, &locks_seq_ops);
+ if (ret)
+ return ret;
+
+ seq = file->private_data;
+ seq->private = inode->i_private;
+
+ return 0;
+}
+
+static const struct file_operations locks_fops = {
+ .owner = THIS_MODULE,
+ .open = locks_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/*
* dump lkb's on the ls_waiters list
*/
@@ -362,6 +516,20 @@ int dlm_create_debug_file(struct dlm_ls *ls)
return -ENOMEM;
}
+ memset(name, 0, sizeof(name));
+ snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
+
+ ls->ls_debug_locks_dentry = debugfs_create_file(name,
+ S_IFREG | S_IRUGO,
+ dlm_root,
+ ls,
+ &locks_fops);
+ if (!ls->ls_debug_locks_dentry) {
+ debugfs_remove(ls->ls_debug_waiters_dentry);
+ debugfs_remove(ls->ls_debug_rsb_dentry);
+ return -ENOMEM;
+ }
+
return 0;
}
@@ -371,6 +539,8 @@ void dlm_delete_debug_file(struct dlm_ls *ls)
debugfs_remove(ls->ls_debug_rsb_dentry);
if (ls->ls_debug_waiters_dentry)
debugfs_remove(ls->ls_debug_waiters_dentry);
+ if (ls->ls_debug_locks_dentry)
+ debugfs_remove(ls->ls_debug_locks_dentry);
}
int dlm_register_debugfs(void)
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 30994d68f6a0..74901e981e10 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -151,6 +151,7 @@ struct dlm_args {
void *bastaddr;
int mode;
struct dlm_lksb *lksb;
+ unsigned long timeout;
};
@@ -213,6 +214,9 @@ struct dlm_args {
#define DLM_IFL_OVERLAP_UNLOCK 0x00080000
#define DLM_IFL_OVERLAP_CANCEL 0x00100000
#define DLM_IFL_ENDOFLIFE 0x00200000
+#define DLM_IFL_WATCH_TIMEWARN 0x00400000
+#define DLM_IFL_TIMEOUT_CANCEL 0x00800000
+#define DLM_IFL_DEADLOCK_CANCEL 0x01000000
#define DLM_IFL_USER 0x00000001
#define DLM_IFL_ORPHAN 0x00000002
@@ -243,6 +247,9 @@ struct dlm_lkb {
struct list_head lkb_wait_reply; /* waiting for remote reply */
struct list_head lkb_astqueue; /* need ast to be sent */
struct list_head lkb_ownqueue; /* list of locks for a process */
+ struct list_head lkb_time_list;
+ unsigned long lkb_timestamp;
+ unsigned long lkb_timeout_cs;
char *lkb_lvbptr;
struct dlm_lksb *lkb_lksb; /* caller's status block */
@@ -447,12 +454,16 @@ struct dlm_ls {
struct mutex ls_orphans_mutex;
struct list_head ls_orphans;
+ struct mutex ls_timeout_mutex;
+ struct list_head ls_timeout;
+
struct list_head ls_nodes; /* current nodes in ls */
struct list_head ls_nodes_gone; /* dead node list, recovery */
int ls_num_nodes; /* number of nodes in ls */
int ls_low_nodeid;
int ls_total_weight;
int *ls_node_array;
+ gfp_t ls_allocation;
struct dlm_rsb ls_stub_rsb; /* for returning errors */
struct dlm_lkb ls_stub_lkb; /* for returning errors */
@@ -460,9 +471,12 @@ struct dlm_ls {
struct dentry *ls_debug_rsb_dentry; /* debugfs */
struct dentry *ls_debug_waiters_dentry; /* debugfs */
+ struct dentry *ls_debug_locks_dentry; /* debugfs */
wait_queue_head_t ls_uevent_wait; /* user part of join/leave */
int ls_uevent_result;
+ struct completion ls_members_done;
+ int ls_members_result;
struct miscdevice ls_device;
@@ -472,6 +486,7 @@ struct dlm_ls {
struct task_struct *ls_recoverd_task;
struct mutex ls_recoverd_active;
spinlock_t ls_recover_lock;
+ unsigned long ls_recover_begin; /* jiffies timestamp */
uint32_t ls_recover_status; /* DLM_RS_ */
uint64_t ls_recover_seq;
struct dlm_recover *ls_recover_args;
@@ -501,6 +516,7 @@ struct dlm_ls {
#define LSFL_RCOM_READY 3
#define LSFL_RCOM_WAIT 4
#define LSFL_UEVENT_WAIT 5
+#define LSFL_TIMEWARN 6
/* much of this is just saving user space pointers associated with the
lock that we pass back to the user lib with an ast */
@@ -518,6 +534,7 @@ struct dlm_user_args {
void __user *castaddr;
void __user *bastparam;
void __user *bastaddr;
+ uint64_t xid;
};
#define DLM_PROC_FLAGS_CLOSING 1
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index d8d6e729f96b..b455919c1998 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -82,10 +82,13 @@ static int send_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int mode);
static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb);
static int send_remove(struct dlm_rsb *r);
static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
+static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
struct dlm_message *ms);
static int receive_extralen(struct dlm_message *ms);
static void do_purge(struct dlm_ls *ls, int nodeid, int pid);
+static void del_timeout(struct dlm_lkb *lkb);
+void dlm_timeout_warn(struct dlm_lkb *lkb);
/*
* Lock compatibilty matrix - thanks Steve
@@ -194,17 +197,17 @@ void dlm_dump_rsb(struct dlm_rsb *r)
/* Threads cannot use the lockspace while it's being recovered */
-static inline void lock_recovery(struct dlm_ls *ls)
+static inline void dlm_lock_recovery(struct dlm_ls *ls)
{
down_read(&ls->ls_in_recovery);
}
-static inline void unlock_recovery(struct dlm_ls *ls)
+void dlm_unlock_recovery(struct dlm_ls *ls)
{
up_read(&ls->ls_in_recovery);
}
-static inline int lock_recovery_try(struct dlm_ls *ls)
+int dlm_lock_recovery_try(struct dlm_ls *ls)
{
return down_read_trylock(&ls->ls_in_recovery);
}
@@ -286,8 +289,22 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
if (is_master_copy(lkb))
return;
+ del_timeout(lkb);
+
DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb););
+ /* if the operation was a cancel, then return -DLM_ECANCEL, if a
+ timeout caused the cancel then return -ETIMEDOUT */
+ if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_TIMEOUT_CANCEL)) {
+ lkb->lkb_flags &= ~DLM_IFL_TIMEOUT_CANCEL;
+ rv = -ETIMEDOUT;
+ }
+
+ if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_DEADLOCK_CANCEL)) {
+ lkb->lkb_flags &= ~DLM_IFL_DEADLOCK_CANCEL;
+ rv = -EDEADLK;
+ }
+
lkb->lkb_lksb->sb_status = rv;
lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
@@ -581,6 +598,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
kref_init(&lkb->lkb_ref);
INIT_LIST_HEAD(&lkb->lkb_ownqueue);
INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
+ INIT_LIST_HEAD(&lkb->lkb_time_list);
get_random_bytes(&bucket, sizeof(bucket));
bucket &= (ls->ls_lkbtbl_size - 1);
@@ -985,15 +1003,136 @@ void dlm_scan_rsbs(struct dlm_ls *ls)
{
int i;
- if (dlm_locking_stopped(ls))
- return;
-
for (i = 0; i < ls->ls_rsbtbl_size; i++) {
shrink_bucket(ls, i);
+ if (dlm_locking_stopped(ls))
+ break;
cond_resched();
}
}
+static void add_timeout(struct dlm_lkb *lkb)
+{
+ struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+
+ if (is_master_copy(lkb)) {
+ lkb->lkb_timestamp = jiffies;
+ return;
+ }
+
+ if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) &&
+ !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
+ lkb->lkb_flags |= DLM_IFL_WATCH_TIMEWARN;
+ goto add_it;
+ }
+ if (lkb->lkb_exflags & DLM_LKF_TIMEOUT)
+ goto add_it;
+ return;
+
+ add_it:
+ DLM_ASSERT(list_empty(&lkb->lkb_time_list), dlm_print_lkb(lkb););
+ mutex_lock(&ls->ls_timeout_mutex);
+ hold_lkb(lkb);
+ lkb->lkb_timestamp = jiffies;
+ list_add_tail(&lkb->lkb_time_list, &ls->ls_timeout);
+ mutex_unlock(&ls->ls_timeout_mutex);
+}
+
+static void del_timeout(struct dlm_lkb *lkb)
+{
+ struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+
+ mutex_lock(&ls->ls_timeout_mutex);
+ if (!list_empty(&lkb->lkb_time_list)) {
+ list_del_init(&lkb->lkb_time_list);
+ unhold_lkb(lkb);
+ }
+ mutex_unlock(&ls->ls_timeout_mutex);
+}
+
+/* FIXME: is it safe to look at lkb_exflags, lkb_flags, lkb_timestamp, and
+ lkb_lksb_timeout without lock_rsb? Note: we can't lock timeout_mutex
+ and then lock rsb because of lock ordering in add_timeout. We may need
+ to specify some special timeout-related bits in the lkb that are just to
+ be accessed under the timeout_mutex. */
+
+void dlm_scan_timeout(struct dlm_ls *ls)
+{
+ struct dlm_rsb *r;
+ struct dlm_lkb *lkb;
+ int do_cancel, do_warn;
+
+ for (;;) {
+ if (dlm_locking_stopped(ls))
+ break;
+
+ do_cancel = 0;
+ do_warn = 0;
+ mutex_lock(&ls->ls_timeout_mutex);
+ list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) {
+
+ if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) &&
+ time_after_eq(jiffies, lkb->lkb_timestamp +
+ lkb->lkb_timeout_cs * HZ/100))
+ do_cancel = 1;
+
+ if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
+ time_after_eq(jiffies, lkb->lkb_timestamp +
+ dlm_config.ci_timewarn_cs * HZ/100))
+ do_warn = 1;
+
+ if (!do_cancel && !do_warn)
+ continue;
+ hold_lkb(lkb);
+ break;
+ }
+ mutex_unlock(&ls->ls_timeout_mutex);
+
+ if (!do_cancel && !do_warn)
+ break;
+
+ r = lkb->lkb_resource;
+ hold_rsb(r);
+ lock_rsb(r);
+
+ if (do_warn) {
+ /* clear flag so we only warn once */
+ lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
+ if (!(lkb->lkb_exflags & DLM_LKF_TIMEOUT))
+ del_timeout(lkb);
+ dlm_timeout_warn(lkb);
+ }
+
+ if (do_cancel) {
+ log_debug(ls, "timeout cancel %x node %d %s",
+ lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+ lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
+ lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
+ del_timeout(lkb);
+ _cancel_lock(r, lkb);
+ }
+
+ unlock_rsb(r);
+ unhold_rsb(r);
+ dlm_put_lkb(lkb);
+ }
+}
+
+/* This is only called by dlm_recoverd, and we rely on dlm_ls_stop() stopping
+ dlm_recoverd before checking/setting ls_recover_begin. */
+
+void dlm_adjust_timeouts(struct dlm_ls *ls)
+{
+ struct dlm_lkb *lkb;
+ long adj = jiffies - ls->ls_recover_begin;
+
+ ls->ls_recover_begin = 0;
+ mutex_lock(&ls->ls_timeout_mutex);
+ list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list)
+ lkb->lkb_timestamp += adj;
+ mutex_unlock(&ls->ls_timeout_mutex);
+}
+
/* lkb is master or local copy */
static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -1275,10 +1414,8 @@ static int queue_conflict(struct list_head *head, struct dlm_lkb *lkb)
* queue for one resource. The granted mode of each lock blocks the requested
* mode of the other lock."
*
- * Part 2: if the granted mode of lkb is preventing the first lkb in the
- * convert queue from being granted, then demote lkb (set grmode to NL).
- * This second form requires that we check for conv-deadlk even when
- * now == 0 in _can_be_granted().
+ * Part 2: if the granted mode of lkb is preventing an earlier lkb in the
+ * convert queue from being granted, then deadlk/demote lkb.
*
* Example:
* Granted Queue: empty
@@ -1287,41 +1424,52 @@ static int queue_conflict(struct list_head *head, struct dlm_lkb *lkb)
*
* The first lock can't be granted because of the granted mode of the second
* lock and the second lock can't be granted because it's not first in the
- * list. We demote the granted mode of the second lock (the lkb passed to this
- * function).
+ * list. We either cancel lkb's conversion (PR->EX) and return EDEADLK, or we
+ * demote the granted mode of lkb (from PR to NL) if it has the CONVDEADLK
+ * flag set and return DEMOTED in the lksb flags.
+ *
+ * Originally, this function detected conv-deadlk in a more limited scope:
+ * - if !modes_compat(lkb1, lkb2) && !modes_compat(lkb2, lkb1), or
+ * - if lkb1 was the first entry in the queue (not just earlier), and was
+ * blocked by the granted mode of lkb2, and there was nothing on the
+ * granted queue preventing lkb1 from being granted immediately, i.e.
+ * lkb2 was the only thing preventing lkb1 from being granted.
+ *
+ * That second condition meant we'd only say there was conv-deadlk if
+ * resolving it (by demotion) would lead to the first lock on the convert
+ * queue being granted right away. It allowed conversion deadlocks to exist
+ * between locks on the convert queue while they couldn't be granted anyway.
*
- * After the resolution, the "grant pending" function needs to go back and try
- * to grant locks on the convert queue again since the first lock can now be
- * granted.
+ * Now, we detect and take action on conversion deadlocks immediately when
+ * they're created, even if they may not be immediately consequential. If
+ * lkb1 exists anywhere in the convert queue and lkb2 comes in with a granted
+ * mode that would prevent lkb1's conversion from being granted, we do a
+ * deadlk/demote on lkb2 right away and don't let it onto the convert queue.
+ * I think this means that the lkb_is_ahead condition below should always
+ * be zero, i.e. there will never be conv-deadlk between two locks that are
+ * both already on the convert queue.
*/
-static int conversion_deadlock_detect(struct dlm_rsb *rsb, struct dlm_lkb *lkb)
+static int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2)
{
- struct dlm_lkb *this, *first = NULL, *self = NULL;
+ struct dlm_lkb *lkb1;
+ int lkb_is_ahead = 0;
- list_for_each_entry(this, &rsb->res_convertqueue, lkb_statequeue) {
- if (!first)
- first = this;
- if (this == lkb) {
- self = lkb;
+ list_for_each_entry(lkb1, &r->res_convertqueue, lkb_statequeue) {
+ if (lkb1 == lkb2) {
+ lkb_is_ahead = 1;
continue;
}
- if (!modes_compat(this, lkb) && !modes_compat(lkb, this))
- return 1;
- }
-
- /* if lkb is on the convert queue and is preventing the first
- from being granted, then there's deadlock and we demote lkb.
- multiple converting locks may need to do this before the first
- converting lock can be granted. */
-
- if (self && self != first) {
- if (!modes_compat(lkb, first) &&
- !queue_conflict(&rsb->res_grantqueue, first))
- return 1;
+ if (!lkb_is_ahead) {
+ if (!modes_compat(lkb2, lkb1))
+ return 1;
+ } else {
+ if (!modes_compat(lkb2, lkb1) &&
+ !modes_compat(lkb1, lkb2))
+ return 1;
+ }
}
-
return 0;
}
@@ -1450,42 +1598,57 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
if (!now && !conv && list_empty(&r->res_convertqueue) &&
first_in_list(lkb, &r->res_waitqueue))
return 1;
-
out:
- /*
- * The following, enabled by CONVDEADLK, departs from VMS.
- */
-
- if (conv && (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) &&
- conversion_deadlock_detect(r, lkb)) {
- lkb->lkb_grmode = DLM_LOCK_NL;
- lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
- }
-
return 0;
}
-/*
- * The ALTPR and ALTCW flags aren't traditional lock manager flags, but are a
- * simple way to provide a big optimization to applications that can use them.
- */
-
-static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
+static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
+ int *err)
{
- uint32_t flags = lkb->lkb_exflags;
int rv;
int8_t alt = 0, rqmode = lkb->lkb_rqmode;
+ int8_t is_convert = (lkb->lkb_grmode != DLM_LOCK_IV);
+
+ if (err)
+ *err = 0;
rv = _can_be_granted(r, lkb, now);
if (rv)
goto out;
- if (lkb->lkb_sbflags & DLM_SBF_DEMOTED)
+ /*
+ * The CONVDEADLK flag is non-standard and tells the dlm to resolve
+ * conversion deadlocks by demoting grmode to NL, otherwise the dlm
+ * cancels one of the locks.
+ */
+
+ if (is_convert && can_be_queued(lkb) &&
+ conversion_deadlock_detect(r, lkb)) {
+ if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) {
+ lkb->lkb_grmode = DLM_LOCK_NL;
+ lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
+ } else if (!(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
+ if (err)
+ *err = -EDEADLK;
+ else {
+ log_print("can_be_granted deadlock %x now %d",
+ lkb->lkb_id, now);
+ dlm_dump_rsb(r);
+ }
+ }
goto out;
+ }
- if (rqmode != DLM_LOCK_PR && flags & DLM_LKF_ALTPR)
+ /*
+ * The ALTPR and ALTCW flags are non-standard and tell the dlm to try
+ * to grant a request in a mode other than the normal rqmode. It's a
+ * simple way to provide a big optimization to applications that can
+ * use them.
+ */
+
+ if (rqmode != DLM_LOCK_PR && (lkb->lkb_exflags & DLM_LKF_ALTPR))
alt = DLM_LOCK_PR;
- else if (rqmode != DLM_LOCK_CW && flags & DLM_LKF_ALTCW)
+ else if (rqmode != DLM_LOCK_CW && (lkb->lkb_exflags & DLM_LKF_ALTCW))
alt = DLM_LOCK_CW;
if (alt) {
@@ -1500,10 +1663,20 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
return rv;
}
+/* FIXME: I don't think that can_be_granted() can/will demote or find deadlock
+ for locks pending on the convert list. Once verified (watch for these
+ log_prints), we should be able to just call _can_be_granted() and not
+ bother with the demote/deadlk cases here (and there's no easy way to deal
+ with a deadlk here, we'd have to generate something like grant_lock with
+ the deadlk error.) */
+
+/* returns the highest requested mode of all blocked conversions */
+
static int grant_pending_convert(struct dlm_rsb *r, int high)
{
struct dlm_lkb *lkb, *s;
int hi, demoted, quit, grant_restart, demote_restart;
+ int deadlk;
quit = 0;
restart:
@@ -1513,14 +1686,29 @@ static int grant_pending_convert(struct dlm_rsb *r, int high)
list_for_each_entry_safe(lkb, s, &r->res_convertqueue, lkb_statequeue) {
demoted = is_demoted(lkb);
- if (can_be_granted(r, lkb, 0)) {
+ deadlk = 0;
+
+ if (can_be_granted(r, lkb, 0, &deadlk)) {
grant_lock_pending(r, lkb);
grant_restart = 1;
- } else {
- hi = max_t(int, lkb->lkb_rqmode, hi);
- if (!demoted && is_demoted(lkb))
- demote_restart = 1;
+ continue;
}
+
+ if (!demoted && is_demoted(lkb)) {
+ log_print("WARN: pending demoted %x node %d %s",
+ lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+ demote_restart = 1;
+ continue;
+ }
+
+ if (deadlk) {
+ log_print("WARN: pending deadlock %x node %d %s",
+ lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+ dlm_dump_rsb(r);
+ continue;
+ }
+
+ hi = max_t(int, lkb->lkb_rqmode, hi);
}
if (grant_restart)
@@ -1538,7 +1726,7 @@ static int grant_pending_wait(struct dlm_rsb *r, int high)
struct dlm_lkb *lkb, *s;
list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
- if (can_be_granted(r, lkb, 0))
+ if (can_be_granted(r, lkb, 0, NULL))
grant_lock_pending(r, lkb);
else
high = max_t(int, lkb->lkb_rqmode, high);
@@ -1733,7 +1921,7 @@ static void confirm_master(struct dlm_rsb *r, int error)
}
static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
- int namelen, uint32_t parent_lkid, void *ast,
+ int namelen, unsigned long timeout_cs, void *ast,
void *astarg, void *bast, struct dlm_args *args)
{
int rv = -EINVAL;
@@ -1776,10 +1964,6 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr)
goto out;
- /* parent/child locks not yet supported */
- if (parent_lkid)
- goto out;
-
if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid)
goto out;
@@ -1791,6 +1975,7 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
args->astaddr = ast;
args->astparam = (long) astarg;
args->bastaddr = bast;
+ args->timeout = timeout_cs;
args->mode = mode;
args->lksb = lksb;
rv = 0;
@@ -1845,6 +2030,7 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
lkb->lkb_lksb = args->lksb;
lkb->lkb_lvbptr = args->lksb->sb_lvbptr;
lkb->lkb_ownpid = (int) current->pid;
+ lkb->lkb_timeout_cs = args->timeout;
rv = 0;
out:
return rv;
@@ -1903,6 +2089,9 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
if (is_overlap(lkb))
goto out;
+ /* don't let scand try to do a cancel */
+ del_timeout(lkb);
+
if (lkb->lkb_flags & DLM_IFL_RESEND) {
lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
rv = -EBUSY;
@@ -1934,6 +2123,9 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
if (is_overlap_unlock(lkb))
goto out;
+ /* don't let scand try to do a cancel */
+ del_timeout(lkb);
+
if (lkb->lkb_flags & DLM_IFL_RESEND) {
lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
rv = -EBUSY;
@@ -1984,7 +2176,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
{
int error = 0;
- if (can_be_granted(r, lkb, 1)) {
+ if (can_be_granted(r, lkb, 1, NULL)) {
grant_lock(r, lkb);
queue_cast(r, lkb, 0);
goto out;
@@ -1994,6 +2186,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
error = -EINPROGRESS;
add_lkb(r, lkb, DLM_LKSTS_WAITING);
send_blocking_asts(r, lkb);
+ add_timeout(lkb);
goto out;
}
@@ -2009,16 +2202,32 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
{
int error = 0;
+ int deadlk = 0;
/* changing an existing lock may allow others to be granted */
- if (can_be_granted(r, lkb, 1)) {
+ if (can_be_granted(r, lkb, 1, &deadlk)) {
grant_lock(r, lkb);
queue_cast(r, lkb, 0);
grant_pending_locks(r);
goto out;
}
+ /* can_be_granted() detected that this lock would block in a conversion
+ deadlock, so we leave it on the granted queue and return EDEADLK in
+ the ast for the convert. */
+
+ if (deadlk) {
+ /* it's left on the granted queue */
+ log_debug(r->res_ls, "deadlock %x node %d sts%d g%d r%d %s",
+ lkb->lkb_id, lkb->lkb_nodeid, lkb->lkb_status,
+ lkb->lkb_grmode, lkb->lkb_rqmode, r->res_name);
+ revert_lock(r, lkb);
+ queue_cast(r, lkb, -EDEADLK);
+ error = -EDEADLK;
+ goto out;
+ }
+
/* is_demoted() means the can_be_granted() above set the grmode
to NL, and left us on the granted queue. This auto-demotion
(due to CONVDEADLK) might mean other locks, and/or this lock, are
@@ -2041,6 +2250,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
del_lkb(r, lkb);
add_lkb(r, lkb, DLM_LKSTS_CONVERT);
send_blocking_asts(r, lkb);
+ add_timeout(lkb);
goto out;
}
@@ -2274,7 +2484,7 @@ int dlm_lock(dlm_lockspace_t *lockspace,
if (!ls)
return -EINVAL;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
if (convert)
error = find_lkb(ls, lksb->sb_lkid, &lkb);
@@ -2284,7 +2494,7 @@ int dlm_lock(dlm_lockspace_t *lockspace,
if (error)
goto out;
- error = set_lock_args(mode, lksb, flags, namelen, parent_lkid, ast,
+ error = set_lock_args(mode, lksb, flags, namelen, 0, ast,
astarg, bast, &args);
if (error)
goto out_put;
@@ -2299,10 +2509,10 @@ int dlm_lock(dlm_lockspace_t *lockspace,
out_put:
if (convert || error)
__put_lkb(ls, lkb);
- if (error == -EAGAIN)
+ if (error == -EAGAIN || error == -EDEADLK)
error = 0;
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
dlm_put_lockspace(ls);
return error;
}
@@ -2322,7 +2532,7 @@ int dlm_unlock(dlm_lockspace_t *lockspace,
if (!ls)
return -EINVAL;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = find_lkb(ls, lkid, &lkb);
if (error)
@@ -2344,7 +2554,7 @@ int dlm_unlock(dlm_lockspace_t *lockspace,
out_put:
dlm_put_lkb(lkb);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
dlm_put_lockspace(ls);
return error;
}
@@ -2384,7 +2594,7 @@ static int _create_message(struct dlm_ls *ls, int mb_len,
pass into lowcomms_commit and a message buffer (mb) that we
write our data into */
- mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb);
+ mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
if (!mh)
return -ENOBUFS;
@@ -3111,9 +3321,10 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
lkb->lkb_remid = ms->m_lkid;
if (is_altmode(lkb))
munge_altmode(lkb, ms);
- if (result)
+ if (result) {
add_lkb(r, lkb, DLM_LKSTS_WAITING);
- else {
+ add_timeout(lkb);
+ } else {
grant_lock_pc(r, lkb, ms);
queue_cast(r, lkb, 0);
}
@@ -3172,6 +3383,12 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
queue_cast(r, lkb, -EAGAIN);
break;
+ case -EDEADLK:
+ receive_flags_reply(lkb, ms);
+ revert_lock_pc(r, lkb);
+ queue_cast(r, lkb, -EDEADLK);
+ break;
+
case -EINPROGRESS:
/* convert was queued on remote master */
receive_flags_reply(lkb, ms);
@@ -3179,6 +3396,7 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
munge_demoted(lkb, ms);
del_lkb(r, lkb);
add_lkb(r, lkb, DLM_LKSTS_CONVERT);
+ add_timeout(lkb);
break;
case 0:
@@ -3298,8 +3516,7 @@ static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
case -DLM_ECANCEL:
receive_flags_reply(lkb, ms);
revert_lock_pc(r, lkb);
- if (ms->m_result)
- queue_cast(r, lkb, -DLM_ECANCEL);
+ queue_cast(r, lkb, -DLM_ECANCEL);
break;
case 0:
break;
@@ -3424,7 +3641,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery)
}
}
- if (lock_recovery_try(ls))
+ if (dlm_lock_recovery_try(ls))
break;
schedule();
}
@@ -3503,7 +3720,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery)
log_error(ls, "unknown message type %d", ms->m_type);
}
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
out:
dlm_put_lockspace(ls);
dlm_astd_wake();
@@ -4034,13 +4251,13 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
int mode, uint32_t flags, void *name, unsigned int namelen,
- uint32_t parent_lkid)
+ unsigned long timeout_cs)
{
struct dlm_lkb *lkb;
struct dlm_args args;
int error;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = create_lkb(ls, &lkb);
if (error) {
@@ -4062,7 +4279,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
When DLM_IFL_USER is set, the dlm knows that this is a userspace
lock and that lkb_astparam is the dlm_user_args structure. */
- error = set_lock_args(mode, &ua->lksb, flags, namelen, parent_lkid,
+ error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
lkb->lkb_flags |= DLM_IFL_USER;
ua->old_mode = DLM_LOCK_IV;
@@ -4094,19 +4311,20 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks);
spin_unlock(&ua->proc->locks_spin);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
return error;
}
int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- int mode, uint32_t flags, uint32_t lkid, char *lvb_in)
+ int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+ unsigned long timeout_cs)
{
struct dlm_lkb *lkb;
struct dlm_args args;
struct dlm_user_args *ua;
int error;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = find_lkb(ls, lkid, &lkb);
if (error)
@@ -4127,6 +4345,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
if (lvb_in && ua->lksb.sb_lvbptr)
memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
+ ua->xid = ua_tmp->xid;
ua->castparam = ua_tmp->castparam;
ua->castaddr = ua_tmp->castaddr;
ua->bastparam = ua_tmp->bastparam;
@@ -4134,19 +4353,19 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
ua->user_lksb = ua_tmp->user_lksb;
ua->old_mode = lkb->lkb_grmode;
- error = set_lock_args(mode, &ua->lksb, flags, 0, 0, DLM_FAKE_USER_AST,
- ua, DLM_FAKE_USER_AST, &args);
+ error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs,
+ DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
if (error)
goto out_put;
error = convert_lock(ls, lkb, &args);
- if (error == -EINPROGRESS || error == -EAGAIN)
+ if (error == -EINPROGRESS || error == -EAGAIN || error == -EDEADLK)
error = 0;
out_put:
dlm_put_lkb(lkb);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
kfree(ua_tmp);
return error;
}
@@ -4159,7 +4378,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
struct dlm_user_args *ua;
int error;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = find_lkb(ls, lkid, &lkb);
if (error)
@@ -4194,7 +4413,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
out_put:
dlm_put_lkb(lkb);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
kfree(ua_tmp);
return error;
}
@@ -4207,7 +4426,7 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
struct dlm_user_args *ua;
int error;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = find_lkb(ls, lkid, &lkb);
if (error)
@@ -4231,11 +4450,59 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
out_put:
dlm_put_lkb(lkb);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
kfree(ua_tmp);
return error;
}
+int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid)
+{
+ struct dlm_lkb *lkb;
+ struct dlm_args args;
+ struct dlm_user_args *ua;
+ struct dlm_rsb *r;
+ int error;
+
+ dlm_lock_recovery(ls);
+
+ error = find_lkb(ls, lkid, &lkb);
+ if (error)
+ goto out;
+
+ ua = (struct dlm_user_args *)lkb->lkb_astparam;
+
+ error = set_unlock_args(flags, ua, &args);
+ if (error)
+ goto out_put;
+
+ /* same as cancel_lock(), but set DEADLOCK_CANCEL after lock_rsb */
+
+ r = lkb->lkb_resource;
+ hold_rsb(r);
+ lock_rsb(r);
+
+ error = validate_unlock_args(lkb, &args);
+ if (error)
+ goto out_r;
+ lkb->lkb_flags |= DLM_IFL_DEADLOCK_CANCEL;
+
+ error = _cancel_lock(r, lkb);
+ out_r:
+ unlock_rsb(r);
+ put_rsb(r);
+
+ if (error == -DLM_ECANCEL)
+ error = 0;
+ /* from validate_unlock_args() */
+ if (error == -EBUSY)
+ error = 0;
+ out_put:
+ dlm_put_lkb(lkb);
+ out:
+ dlm_unlock_recovery(ls);
+ return error;
+}
+
/* lkb's that are removed from the waiters list by revert are just left on the
orphans list with the granted orphan locks, to be freed by purge */
@@ -4314,12 +4581,13 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
{
struct dlm_lkb *lkb, *safe;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
while (1) {
lkb = del_proc_lock(ls, proc);
if (!lkb)
break;
+ del_timeout(lkb);
if (lkb->lkb_exflags & DLM_LKF_PERSISTENT)
orphan_proc_lock(ls, lkb);
else
@@ -4347,7 +4615,7 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
}
mutex_unlock(&ls->ls_clear_proc_locks);
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
}
static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
@@ -4429,12 +4697,12 @@ int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
if (nodeid != dlm_our_nodeid()) {
error = send_purge(ls, nodeid, pid);
} else {
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
if (pid == current->pid)
purge_proc_locks(ls, proc);
else
do_purge(ls, nodeid, pid);
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
}
return error;
}
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
index 64fc4ec40668..1720313c22df 100644
--- a/fs/dlm/lock.h
+++ b/fs/dlm/lock.h
@@ -1,7 +1,7 @@
/******************************************************************************
*******************************************************************************
**
-** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -24,6 +24,10 @@ void dlm_put_rsb(struct dlm_rsb *r);
void dlm_hold_rsb(struct dlm_rsb *r);
int dlm_put_lkb(struct dlm_lkb *lkb);
void dlm_scan_rsbs(struct dlm_ls *ls);
+int dlm_lock_recovery_try(struct dlm_ls *ls);
+void dlm_unlock_recovery(struct dlm_ls *ls);
+void dlm_scan_timeout(struct dlm_ls *ls);
+void dlm_adjust_timeouts(struct dlm_ls *ls);
int dlm_purge_locks(struct dlm_ls *ls);
void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
@@ -34,15 +38,18 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode,
- uint32_t flags, void *name, unsigned int namelen, uint32_t parent_lkid);
+ uint32_t flags, void *name, unsigned int namelen,
+ unsigned long timeout_cs);
int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- int mode, uint32_t flags, uint32_t lkid, char *lvb_in);
+ int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+ unsigned long timeout_cs);
int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
uint32_t flags, uint32_t lkid, char *lvb_in);
int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
uint32_t flags, uint32_t lkid);
int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
int nodeid, int pid);
+int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid);
void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc);
static inline int is_master(struct dlm_rsb *r)
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a677b2a5eed4..1dc72105ab12 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -197,13 +197,24 @@ static int do_uevent(struct dlm_ls *ls, int in)
else
kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
+ log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
+
+ /* dlm_controld will see the uevent, do the necessary group management
+ and then write to sysfs to wake us */
+
error = wait_event_interruptible(ls->ls_uevent_wait,
test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
+
+ log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
+
if (error)
goto out;
error = ls->ls_uevent_result;
out:
+ if (error)
+ log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
+ error, ls->ls_uevent_result);
return error;
}
@@ -234,8 +245,13 @@ static int dlm_scand(void *data)
struct dlm_ls *ls;
while (!kthread_should_stop()) {
- list_for_each_entry(ls, &lslist, ls_list)
- dlm_scan_rsbs(ls);
+ list_for_each_entry(ls, &lslist, ls_list) {
+ if (dlm_lock_recovery_try(ls)) {
+ dlm_scan_rsbs(ls);
+ dlm_scan_timeout(ls);
+ dlm_unlock_recovery(ls);
+ }
+ }
schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
}
return 0;
@@ -395,6 +411,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
{
struct dlm_ls *ls;
int i, size, error = -ENOMEM;
+ int do_unreg = 0;
if (namelen > DLM_LOCKSPACE_LEN)
return -EINVAL;
@@ -417,11 +434,22 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
goto out;
memcpy(ls->ls_name, name, namelen);
ls->ls_namelen = namelen;
- ls->ls_exflags = flags;
ls->ls_lvblen = lvblen;
ls->ls_count = 0;
ls->ls_flags = 0;
+ if (flags & DLM_LSFL_TIMEWARN)
+ set_bit(LSFL_TIMEWARN, &ls->ls_flags);
+
+ if (flags & DLM_LSFL_FS)
+ ls->ls_allocation = GFP_NOFS;
+ else
+ ls->ls_allocation = GFP_KERNEL;
+
+ /* ls_exflags are forced to match among nodes, and we don't
+ need to require all nodes to have TIMEWARN or FS set */
+ ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
+
size = dlm_config.ci_rsbtbl_size;
ls->ls_rsbtbl_size = size;
@@ -461,6 +489,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
mutex_init(&ls->ls_waiters_mutex);
INIT_LIST_HEAD(&ls->ls_orphans);
mutex_init(&ls->ls_orphans_mutex);
+ INIT_LIST_HEAD(&ls->ls_timeout);
+ mutex_init(&ls->ls_timeout_mutex);
INIT_LIST_HEAD(&ls->ls_nodes);
INIT_LIST_HEAD(&ls->ls_nodes_gone);
@@ -477,6 +507,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
init_waitqueue_head(&ls->ls_uevent_wait);
ls->ls_uevent_result = 0;
+ init_completion(&ls->ls_members_done);
+ ls->ls_members_result = -1;
ls->ls_recoverd_task = NULL;
mutex_init(&ls->ls_recoverd_active);
@@ -513,32 +545,49 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
error = dlm_recoverd_start(ls);
if (error) {
log_error(ls, "can't start dlm_recoverd %d", error);
- goto out_rcomfree;
+ goto out_delist;
}
- dlm_create_debug_file(ls);
-
error = kobject_setup(ls);
if (error)
- goto out_del;
+ goto out_stop;
error = kobject_register(&ls->ls_kobj);
if (error)
- goto out_del;
+ goto out_stop;
+
+ /* let kobject handle freeing of ls if there's an error */
+ do_unreg = 1;
+
+ /* This uevent triggers dlm_controld in userspace to add us to the
+ group of nodes that are members of this lockspace (managed by the
+ cluster infrastructure.) Once it's done that, it tells us who the
+ current lockspace members are (via configfs) and then tells the
+ lockspace to start running (via sysfs) in dlm_ls_start(). */
error = do_uevent(ls, 1);
if (error)
- goto out_unreg;
+ goto out_stop;
+
+ wait_for_completion(&ls->ls_members_done);
+ error = ls->ls_members_result;
+ if (error)
+ goto out_members;
+
+ dlm_create_debug_file(ls);
+
+ log_debug(ls, "join complete");
*lockspace = ls;
return 0;
- out_unreg:
- kobject_unregister(&ls->ls_kobj);
- out_del:
- dlm_delete_debug_file(ls);
+ out_members:
+ do_uevent(ls, 0);
+ dlm_clear_members(ls);
+ kfree(ls->ls_node_array);
+ out_stop:
dlm_recoverd_stop(ls);
- out_rcomfree:
+ out_delist:
spin_lock(&lslist_lock);
list_del(&ls->ls_list);
spin_unlock(&lslist_lock);
@@ -550,7 +599,10 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
out_rsbfree:
kfree(ls->ls_rsbtbl);
out_lsfree:
- kfree(ls);
+ if (do_unreg)
+ kobject_unregister(&ls->ls_kobj);
+ else
+ kfree(ls);
out:
module_put(THIS_MODULE);
return error;
@@ -570,6 +622,8 @@ int dlm_new_lockspace(char *name, int namelen, void **lockspace,
error = new_lockspace(name, namelen, lockspace, flags, lvblen);
if (!error)
ls_count++;
+ else if (!ls_count)
+ threads_stop();
out:
mutex_unlock(&ls_lock);
return error;
@@ -696,7 +750,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
dlm_clear_members_gone(ls);
kfree(ls->ls_node_array);
kobject_unregister(&ls->ls_kobj);
- /* The ls structure will be freed when the kobject is done with */
+ /* The ls structure will be freed when the kobject is done with */
mutex_lock(&ls_lock);
ls_count--;
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 27970a58d29b..0553a6158dcb 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -260,7 +260,7 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
static void lowcomms_data_ready(struct sock *sk, int count_unused)
{
struct connection *con = sock2con(sk);
- if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
+ if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags))
queue_work(recv_workqueue, &con->rwork);
}
@@ -268,7 +268,7 @@ static void lowcomms_write_space(struct sock *sk)
{
struct connection *con = sock2con(sk);
- if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+ if (con && !test_and_set_bit(CF_WRITE_PENDING, &con->flags))
queue_work(send_workqueue, &con->swork);
}
@@ -720,11 +720,17 @@ static int tcp_accept_from_sock(struct connection *con)
INIT_WORK(&othercon->rwork, process_recv_sockets);
set_bit(CF_IS_OTHERCON, &othercon->flags);
newcon->othercon = othercon;
+ othercon->sock = newsock;
+ newsock->sk->sk_user_data = othercon;
+ add_sock(newsock, othercon);
+ addcon = othercon;
+ }
+ else {
+ printk("Extra connection from node %d attempted\n", nodeid);
+ result = -EAGAIN;
+ mutex_unlock(&newcon->sock_mutex);
+ goto accept_err;
}
- othercon->sock = newsock;
- newsock->sk->sk_user_data = othercon;
- add_sock(newsock, othercon);
- addcon = othercon;
}
else {
newsock->sk->sk_user_data = newcon;
@@ -1400,8 +1406,11 @@ void dlm_lowcomms_stop(void)
down(&connections_lock);
for (i = 0; i <= max_nodeid; i++) {
con = __nodeid2con(i, 0);
- if (con)
+ if (con) {
con->flags |= 0xFF;
+ if (con->sock)
+ con->sock->sk->sk_user_data = NULL;
+ }
}
up(&connections_lock);
diff --git a/fs/dlm/main.c b/fs/dlm/main.c
index 162fbae58fe5..eca2907f2386 100644
--- a/fs/dlm/main.c
+++ b/fs/dlm/main.c
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -25,6 +25,8 @@ void dlm_unregister_debugfs(void);
static inline int dlm_register_debugfs(void) { return 0; }
static inline void dlm_unregister_debugfs(void) { }
#endif
+int dlm_netlink_init(void);
+void dlm_netlink_exit(void);
static int __init init_dlm(void)
{
@@ -50,10 +52,16 @@ static int __init init_dlm(void)
if (error)
goto out_debug;
+ error = dlm_netlink_init();
+ if (error)
+ goto out_user;
+
printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
return 0;
+ out_user:
+ dlm_user_exit();
out_debug:
dlm_unregister_debugfs();
out_config:
@@ -68,6 +76,7 @@ static int __init init_dlm(void)
static void __exit exit_dlm(void)
{
+ dlm_netlink_exit();
dlm_user_exit();
dlm_config_exit();
dlm_memory_exit();
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 85e2897bd740..073599dced2a 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -1,7 +1,7 @@
/******************************************************************************
*******************************************************************************
**
-** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -233,6 +233,12 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
*neg_out = neg;
error = ping_members(ls);
+ if (!error || error == -EPROTO) {
+ /* new_lockspace() may be waiting to know if the config
+ is good or bad */
+ ls->ls_members_result = error;
+ complete(&ls->ls_members_done);
+ }
if (error)
goto out;
@@ -284,6 +290,9 @@ int dlm_ls_stop(struct dlm_ls *ls)
dlm_recoverd_suspend(ls);
ls->ls_recover_status = 0;
dlm_recoverd_resume(ls);
+
+ if (!ls->ls_recover_begin)
+ ls->ls_recover_begin = jiffies;
return 0;
}
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
new file mode 100644
index 000000000000..863b87d0dc71
--- /dev/null
+++ b/fs/dlm/netlink.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#include <net/genetlink.h>
+#include <linux/dlm.h>
+#include <linux/dlm_netlink.h>
+
+#include "dlm_internal.h"
+
+static uint32_t dlm_nl_seqnum;
+static uint32_t listener_nlpid;
+
+static struct genl_family family = {
+ .id = GENL_ID_GENERATE,
+ .name = DLM_GENL_NAME,
+ .version = DLM_GENL_VERSION,
+};
+
+static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
+{
+ struct sk_buff *skb;
+ void *data;
+
+ skb = genlmsg_new(size, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ /* add the message headers */
+ data = genlmsg_put(skb, 0, dlm_nl_seqnum++, &family, 0, cmd);
+ if (!data) {
+ nlmsg_free(skb);
+ return -EINVAL;
+ }
+
+ *skbp = skb;
+ return 0;
+}
+
+static struct dlm_lock_data *mk_data(struct sk_buff *skb)
+{
+ struct nlattr *ret;
+
+ ret = nla_reserve(skb, DLM_TYPE_LOCK, sizeof(struct dlm_lock_data));
+ if (!ret)
+ return NULL;
+ return nla_data(ret);
+}
+
+static int send_data(struct sk_buff *skb)
+{
+ struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
+ void *data = genlmsg_data(genlhdr);
+ int rv;
+
+ rv = genlmsg_end(skb, data);
+ if (rv < 0) {
+ nlmsg_free(skb);
+ return rv;
+ }
+
+ return genlmsg_unicast(skb, listener_nlpid);
+}
+
+static int user_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+ listener_nlpid = info->snd_pid;
+ printk("user_cmd nlpid %u\n", listener_nlpid);
+ return 0;
+}
+
+static struct genl_ops dlm_nl_ops = {
+ .cmd = DLM_CMD_HELLO,
+ .doit = user_cmd,
+};
+
+int dlm_netlink_init(void)
+{
+ int rv;
+
+ rv = genl_register_family(&family);
+ if (rv)
+ return rv;
+
+ rv = genl_register_ops(&family, &dlm_nl_ops);
+ if (rv < 0)
+ goto err;
+ return 0;
+ err:
+ genl_unregister_family(&family);
+ return rv;
+}
+
+void dlm_netlink_exit(void)
+{
+ genl_unregister_ops(&family, &dlm_nl_ops);
+ genl_unregister_family(&family);
+}
+
+static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
+{
+ struct dlm_rsb *r = lkb->lkb_resource;
+ struct dlm_user_args *ua = (struct dlm_user_args *) lkb->lkb_astparam;
+
+ memset(data, 0, sizeof(struct dlm_lock_data));
+
+ data->version = DLM_LOCK_DATA_VERSION;
+ data->nodeid = lkb->lkb_nodeid;
+ data->ownpid = lkb->lkb_ownpid;
+ data->id = lkb->lkb_id;
+ data->remid = lkb->lkb_remid;
+ data->status = lkb->lkb_status;
+ data->grmode = lkb->lkb_grmode;
+ data->rqmode = lkb->lkb_rqmode;
+ data->timestamp = lkb->lkb_timestamp;
+ if (ua)
+ data->xid = ua->xid;
+ if (r) {
+ data->lockspace_id = r->res_ls->ls_global_id;
+ data->resource_namelen = r->res_length;
+ memcpy(data->resource_name, r->res_name, r->res_length);
+ }
+}
+
+void dlm_timeout_warn(struct dlm_lkb *lkb)
+{
+ struct dlm_lock_data *data;
+ struct sk_buff *send_skb;
+ size_t size;
+ int rv;
+
+ size = nla_total_size(sizeof(struct dlm_lock_data)) +
+ nla_total_size(0); /* why this? */
+
+ rv = prepare_data(DLM_CMD_TIMEOUT, &send_skb, size);
+ if (rv < 0)
+ return;
+
+ data = mk_data(send_skb);
+ if (!data) {
+ nlmsg_free(send_skb);
+ return;
+ }
+
+ fill_data(data, lkb);
+
+ send_data(send_skb);
+}
+
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 6bfbd6153809..e3a1527cbdbe 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -38,7 +38,7 @@ static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len,
char *mb;
int mb_len = sizeof(struct dlm_rcom) + len;
- mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb);
+ mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
if (!mh) {
log_print("create_rcom to %d type %d len %d ENOBUFS",
to_nodeid, type, len);
@@ -90,7 +90,7 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
log_error(ls, "version mismatch: %x nodeid %d: %x",
DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid,
rc->rc_header.h_version);
- return -EINVAL;
+ return -EPROTO;
}
if (rf->rf_lvblen != ls->ls_lvblen ||
@@ -98,7 +98,7 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
ls->ls_lvblen, ls->ls_exflags,
nodeid, rf->rf_lvblen, rf->rf_lsflags);
- return -EINVAL;
+ return -EPROTO;
}
return 0;
}
@@ -386,7 +386,8 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
dlm_recover_process_copy(ls, rc_in);
}
-static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
+static int send_ls_not_ready(struct dlm_ls *ls, int nodeid,
+ struct dlm_rcom *rc_in)
{
struct dlm_rcom *rc;
struct rcom_config *rf;
@@ -394,7 +395,7 @@ static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
char *mb;
int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
- mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb);
+ mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb);
if (!mh)
return -ENOBUFS;
memset(mb, 0, mb_len);
@@ -464,7 +465,7 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid)
log_print("lockspace %x from %d type %x not found",
hd->h_lockspace, nodeid, rc->rc_type);
if (rc->rc_type == DLM_RCOM_STATUS)
- send_ls_not_ready(nodeid, rc);
+ send_ls_not_ready(ls, nodeid, rc);
return;
}
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 3cb636d60249..66575997861c 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -190,6 +190,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
dlm_clear_members_gone(ls);
+ dlm_adjust_timeouts(ls);
+
error = enable_locking(ls, rv->seq);
if (error) {
log_debug(ls, "enable_locking failed %d", error);
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index b0201ec325a7..6438941ab1f8 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -33,16 +33,17 @@ static const struct file_operations device_fops;
struct dlm_lock_params32 {
__u8 mode;
__u8 namelen;
- __u16 flags;
+ __u16 unused;
+ __u32 flags;
__u32 lkid;
__u32 parent;
-
+ __u64 xid;
+ __u64 timeout;
__u32 castparam;
__u32 castaddr;
__u32 bastparam;
__u32 bastaddr;
__u32 lksb;
-
char lvb[DLM_USER_LVB_LEN];
char name[0];
};
@@ -68,6 +69,7 @@ struct dlm_lksb32 {
};
struct dlm_lock_result32 {
+ __u32 version[3];
__u32 length;
__u32 user_astaddr;
__u32 user_astparam;
@@ -102,6 +104,8 @@ static void compat_input(struct dlm_write_request *kb,
kb->i.lock.flags = kb32->i.lock.flags;
kb->i.lock.lkid = kb32->i.lock.lkid;
kb->i.lock.parent = kb32->i.lock.parent;
+ kb->i.lock.xid = kb32->i.lock.xid;
+ kb->i.lock.timeout = kb32->i.lock.timeout;
kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
@@ -115,6 +119,10 @@ static void compat_input(struct dlm_write_request *kb,
static void compat_output(struct dlm_lock_result *res,
struct dlm_lock_result32 *res32)
{
+ res32->version[0] = res->version[0];
+ res32->version[1] = res->version[1];
+ res32->version[2] = res->version[2];
+
res32->user_astaddr = (__u32)(long)res->user_astaddr;
res32->user_astparam = (__u32)(long)res->user_astparam;
res32->user_lksb = (__u32)(long)res->user_lksb;
@@ -130,6 +138,36 @@ static void compat_output(struct dlm_lock_result *res,
}
#endif
+/* Figure out if this lock is at the end of its life and no longer
+ available for the application to use. The lkb still exists until
+ the final ast is read. A lock becomes EOL in three situations:
+ 1. a noqueue request fails with EAGAIN
+ 2. an unlock completes with EUNLOCK
+ 3. a cancel of a waiting request completes with ECANCEL/EDEADLK
+ An EOL lock needs to be removed from the process's list of locks.
+ And we can't allow any new operation on an EOL lock. This is
+ not related to the lifetime of the lkb struct which is managed
+ entirely by refcount. */
+
+static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
+{
+ switch (sb_status) {
+ case -DLM_EUNLOCK:
+ return 1;
+ case -DLM_ECANCEL:
+ case -ETIMEDOUT:
+ case -EDEADLK:
+ if (lkb->lkb_grmode == DLM_LOCK_IV)
+ return 1;
+ break;
+ case -EAGAIN:
+ if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
/* we could possibly check if the cancel of an orphan has resulted in the lkb
being removed and then remove that lkb from the orphans list and free it */
@@ -176,25 +214,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
log_debug(ls, "ast overlap %x status %x %x",
lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
- /* Figure out if this lock is at the end of its life and no longer
- available for the application to use. The lkb still exists until
- the final ast is read. A lock becomes EOL in three situations:
- 1. a noqueue request fails with EAGAIN
- 2. an unlock completes with EUNLOCK
- 3. a cancel of a waiting request completes with ECANCEL
- An EOL lock needs to be removed from the process's list of locks.
- And we can't allow any new operation on an EOL lock. This is
- not related to the lifetime of the lkb struct which is managed
- entirely by refcount. */
-
- if (type == AST_COMP &&
- lkb->lkb_grmode == DLM_LOCK_IV &&
- ua->lksb.sb_status == -EAGAIN)
- eol = 1;
- else if (ua->lksb.sb_status == -DLM_EUNLOCK ||
- (ua->lksb.sb_status == -DLM_ECANCEL &&
- lkb->lkb_grmode == DLM_LOCK_IV))
- eol = 1;
+ eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type);
if (eol) {
lkb->lkb_ast_type &= ~AST_BAST;
lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
@@ -252,16 +272,18 @@ static int device_user_lock(struct dlm_user_proc *proc,
ua->castaddr = params->castaddr;
ua->bastparam = params->bastparam;
ua->bastaddr = params->bastaddr;
+ ua->xid = params->xid;
if (params->flags & DLM_LKF_CONVERT)
error = dlm_user_convert(ls, ua,
params->mode, params->flags,
- params->lkid, params->lvb);
+ params->lkid, params->lvb,
+ (unsigned long) params->timeout);
else {
error = dlm_user_request(ls, ua,
params->mode, params->flags,
params->name, params->namelen,
- params->parent);
+ (unsigned long) params->timeout);
if (!error)
error = ua->lksb.sb_lkid;
}
@@ -299,6 +321,22 @@ static int device_user_unlock(struct dlm_user_proc *proc,
return error;
}
+static int device_user_deadlock(struct dlm_user_proc *proc,
+ struct dlm_lock_params *params)
+{
+ struct dlm_ls *ls;
+ int error;
+
+ ls = dlm_find_lockspace_local(proc->lockspace);
+ if (!ls)
+ return -ENOENT;
+
+ error = dlm_user_deadlock(ls, params->flags, params->lkid);
+
+ dlm_put_lockspace(ls);
+ return error;
+}
+
static int create_misc_device(struct dlm_ls *ls, char *name)
{
int error, len;
@@ -348,7 +386,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params)
return -EPERM;
error = dlm_new_lockspace(params->name, strlen(params->name),
- &lockspace, 0, DLM_USER_LVB_LEN);
+ &lockspace, params->flags, DLM_USER_LVB_LEN);
if (error)
return error;
@@ -524,6 +562,14 @@ static ssize_t device_write(struct file *file, const char __user *buf,
error = device_user_unlock(proc, &kbuf->i.lock);
break;
+ case DLM_USER_DEADLOCK:
+ if (!proc) {
+ log_print("no locking on control device");
+ goto out_sig;
+ }
+ error = device_user_deadlock(proc, &kbuf->i.lock);
+ break;
+
case DLM_USER_CREATE_LOCKSPACE:
if (proc) {
log_print("create/remove only on control device");
@@ -641,6 +687,9 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
int struct_len;
memset(&result, 0, sizeof(struct dlm_lock_result));
+ result.version[0] = DLM_DEVICE_VERSION_MAJOR;
+ result.version[1] = DLM_DEVICE_VERSION_MINOR;
+ result.version[2] = DLM_DEVICE_VERSION_PATCH;
memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
result.user_lksb = ua->user_lksb;
@@ -699,6 +748,20 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
return error;
}
+static int copy_version_to_user(char __user *buf, size_t count)
+{
+ struct dlm_device_version ver;
+
+ memset(&ver, 0, sizeof(struct dlm_device_version));
+ ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
+ ver.version[1] = DLM_DEVICE_VERSION_MINOR;
+ ver.version[2] = DLM_DEVICE_VERSION_PATCH;
+
+ if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
+ return -EFAULT;
+ return sizeof(struct dlm_device_version);
+}
+
/* a read returns a single ast described in a struct dlm_lock_result */
static ssize_t device_read(struct file *file, char __user *buf, size_t count,
@@ -710,6 +773,16 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
DECLARE_WAITQUEUE(wait, current);
int error, type=0, bmode=0, removed = 0;
+ if (count == sizeof(struct dlm_device_version)) {
+ error = copy_version_to_user(buf, count);
+ return error;
+ }
+
+ if (!proc) {
+ log_print("non-version read from control device %zu", count);
+ return -EINVAL;
+ }
+
#ifdef CONFIG_COMPAT
if (count < sizeof(struct dlm_lock_result32))
#else
@@ -747,11 +820,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
}
}
- if (list_empty(&proc->asts)) {
- spin_unlock(&proc->asts_spin);
- return -EAGAIN;
- }
-
/* there may be both completion and blocking asts to return for
the lkb, don't remove lkb from asts list unless no asts remain */
@@ -823,6 +891,7 @@ static const struct file_operations device_fops = {
static const struct file_operations ctl_device_fops = {
.open = ctl_device_open,
.release = ctl_device_close,
+ .read = device_read,
.write = device_write,
.owner = THIS_MODULE,
};
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 59288d817078..94f456fe4d9b 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -338,16 +338,17 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag)
return rc;
}
-static ssize_t ecryptfs_sendfile(struct file *file, loff_t * ppos,
- size_t count, read_actor_t actor, void *target)
+static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos,
+ struct pipe_inode_info *pipe, size_t count,
+ unsigned int flags)
{
struct file *lower_file = NULL;
int rc = -EINVAL;
lower_file = ecryptfs_file_to_lower(file);
- if (lower_file->f_op && lower_file->f_op->sendfile)
- rc = lower_file->f_op->sendfile(lower_file, ppos, count,
- actor, target);
+ if (lower_file->f_op && lower_file->f_op->splice_read)
+ rc = lower_file->f_op->splice_read(lower_file, ppos, pipe,
+ count, flags);
return rc;
}
@@ -364,7 +365,7 @@ const struct file_operations ecryptfs_dir_fops = {
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
- .sendfile = ecryptfs_sendfile,
+ .splice_read = ecryptfs_splice_read,
};
const struct file_operations ecryptfs_main_fops = {
@@ -381,7 +382,7 @@ const struct file_operations ecryptfs_main_fops = {
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
- .sendfile = ecryptfs_sendfile,
+ .splice_read = ecryptfs_splice_read,
};
static int
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 566d4e2d3852..04afeecaaef3 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -53,7 +53,6 @@ const struct file_operations ext2_file_operations = {
.open = generic_file_open,
.release = ext2_release_file,
.fsync = ext2_sync_file,
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
@@ -71,7 +70,6 @@ const struct file_operations ext2_xip_file_operations = {
.open = generic_file_open,
.release = ext2_release_file,
.fsync = ext2_sync_file,
- .sendfile = xip_file_sendfile,
};
#endif
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 1e6f13864536..acc4913d3019 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -120,7 +120,6 @@ const struct file_operations ext3_file_operations = {
.open = generic_file_open,
.release = ext3_release_file,
.fsync = ext3_sync_file,
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 3c6c1fd2be90..d4c8186aed64 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -120,7 +120,6 @@ const struct file_operations ext4_file_operations = {
.open = generic_file_open,
.release = ext4_release_file,
.fsync = ext4_sync_file,
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 55d3c7461c5b..69a83b59dce8 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -134,7 +134,7 @@ const struct file_operations fat_file_operations = {
.release = fat_file_release,
.ioctl = fat_generic_ioctl,
.fsync = file_fsync,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
static int fat_cont_expand(struct inode *inode, loff_t size)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index adf7995232b8..f79de7c8cdfa 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -802,7 +802,7 @@ static const struct file_operations fuse_file_operations = {
.release = fuse_release,
.fsync = fuse_fsync,
.lock = fuse_file_lock,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
static const struct file_operations fuse_direct_io_file_operations = {
@@ -814,7 +814,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
.release = fuse_release,
.fsync = fuse_fsync,
.lock = fuse_file_lock,
- /* no mmap and sendfile */
+ /* no mmap and splice_read */
};
static const struct address_space_operations fuse_file_aops = {
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index e3f1ada643ac..04ad0caebedb 100644
--- a/fs/gfs2/Makefile
+++ b/fs/gfs2/Makefile
@@ -1,7 +1,7 @@
obj-$(CONFIG_GFS2_FS) += gfs2.o
gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \
- mount.o ondisk.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
+ mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
ops_fstype.o ops_inode.o ops_super.o ops_vm.o quota.o \
recovery.o rgrp.o super.o sys.o trans.o util.o
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index c53a5d2d0590..cd805a66880d 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -718,7 +718,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
for (x = 0; x < rlist.rl_rgrps; x++) {
struct gfs2_rgrpd *rgd;
rgd = rlist.rl_ghs[x].gh_gl->gl_object;
- rg_blocks += rgd->rd_ri.ri_length;
+ rg_blocks += rgd->rd_length;
}
error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
@@ -772,7 +772,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
gfs2_free_data(ip, bstart, blen);
}
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, dibh->b_data);
@@ -824,7 +824,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
goto out_gunlock_q;
error = gfs2_trans_begin(sdp,
- sdp->sd_max_height + al->al_rgd->rd_ri.ri_length +
+ sdp->sd_max_height + al->al_rgd->rd_length +
RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
if (error)
goto out_ipres;
@@ -847,7 +847,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
}
ip->i_di.di_size = size;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
error = gfs2_meta_inode_buffer(ip, &dibh);
if (error)
@@ -885,7 +885,6 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
unsigned blocksize, iblock, length, pos;
struct buffer_head *bh;
struct page *page;
- void *kaddr;
int err;
page = grab_cache_page(mapping, index);
@@ -928,15 +927,13 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
/* Uhhuh. Read error. Complain and punt. */
if (!buffer_uptodate(bh))
goto unlock;
+ err = 0;
}
if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
gfs2_trans_add_bh(ip->i_gl, bh, 0);
- kaddr = kmap_atomic(page, KM_USER0);
- memset(kaddr + offset, 0, length);
- flush_dcache_page(page);
- kunmap_atomic(kaddr, KM_USER0);
+ zero_user_page(page, offset, length, KM_USER0);
unlock:
unlock_page(page);
@@ -962,7 +959,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
if (gfs2_is_stuffed(ip)) {
ip->i_di.di_size = size;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
@@ -974,7 +971,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
if (!error) {
ip->i_di.di_size = size;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1044,10 +1041,10 @@ static int trunc_end(struct gfs2_inode *ip)
ip->i_di.di_height = 0;
ip->i_di.di_goal_meta =
ip->i_di.di_goal_data =
- ip->i_num.no_addr;
+ ip->i_no_addr;
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
}
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c
index 683cb5bda870..3548d9f31e0d 100644
--- a/fs/gfs2/daemon.c
+++ b/fs/gfs2/daemon.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>
+#include <linux/freezer.h>
#include "gfs2.h"
#include "incore.h"
@@ -49,6 +50,8 @@ int gfs2_scand(void *data)
while (!kthread_should_stop()) {
gfs2_scand_internal(sdp);
t = gfs2_tune_get(sdp, gt_scand_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
schedule_timeout_interruptible(t);
}
@@ -74,6 +77,8 @@ int gfs2_glockd(void *data)
wait_event_interruptible(sdp->sd_reclaim_wq,
(atomic_read(&sdp->sd_reclaim_count) ||
kthread_should_stop()));
+ if (freezing(current))
+ refrigerator();
}
return 0;
@@ -93,6 +98,8 @@ int gfs2_recoverd(void *data)
while (!kthread_should_stop()) {
gfs2_check_journals(sdp);
t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
schedule_timeout_interruptible(t);
}
@@ -141,6 +148,8 @@ int gfs2_logd(void *data)
}
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
schedule_timeout_interruptible(t);
}
@@ -191,6 +200,8 @@ int gfs2_quotad(void *data)
gfs2_quota_scan(sdp);
t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
schedule_timeout_interruptible(t);
}
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index a96fa07b3f3b..2beb2f401aa2 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -130,7 +130,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
if (ip->i_di.di_size < offset + size)
ip->i_di.di_size = offset + size;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -228,7 +228,7 @@ out:
if (ip->i_di.di_size < offset + copied)
ip->i_di.di_size = offset + copied;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1456,7 +1456,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
if (dip->i_di.di_entries != g.offset) {
fs_warn(sdp, "Number of entries corrupt in dir %llu, "
"ip->i_di.di_entries (%u) != g.offset (%u)\n",
- (unsigned long long)dip->i_num.no_addr,
+ (unsigned long long)dip->i_no_addr,
dip->i_di.di_entries,
g.offset);
error = -EIO;
@@ -1488,24 +1488,55 @@ out:
* Returns: errno
*/
-int gfs2_dir_search(struct inode *dir, const struct qstr *name,
- struct gfs2_inum_host *inum, unsigned int *type)
+struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
+ struct inode *inode;
+
+ dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
+ if (dent) {
+ if (IS_ERR(dent))
+ return ERR_PTR(PTR_ERR(dent));
+ inode = gfs2_inode_lookup(dir->i_sb,
+ be16_to_cpu(dent->de_type),
+ be64_to_cpu(dent->de_inum.no_addr),
+ be64_to_cpu(dent->de_inum.no_formal_ino));
+ brelse(bh);
+ return inode;
+ }
+ return ERR_PTR(-ENOENT);
+}
+
+int gfs2_dir_check(struct inode *dir, const struct qstr *name,
+ const struct gfs2_inode *ip)
+{
+ struct buffer_head *bh;
+ struct gfs2_dirent *dent;
+ int ret = -ENOENT;
dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
if (dent) {
if (IS_ERR(dent))
return PTR_ERR(dent);
- if (inum)
- gfs2_inum_in(inum, (char *)&dent->de_inum);
- if (type)
- *type = be16_to_cpu(dent->de_type);
+ if (ip) {
+ if (be64_to_cpu(dent->de_inum.no_addr) != ip->i_no_addr)
+ goto out;
+ if (be64_to_cpu(dent->de_inum.no_formal_ino) !=
+ ip->i_no_formal_ino)
+ goto out;
+ if (unlikely(IF2DT(ip->i_inode.i_mode) !=
+ be16_to_cpu(dent->de_type))) {
+ gfs2_consist_inode(GFS2_I(dir));
+ ret = -EIO;
+ goto out;
+ }
+ }
+ ret = 0;
+out:
brelse(bh);
- return 0;
}
- return -ENOENT;
+ return ret;
}
static int dir_new_leaf(struct inode *inode, const struct qstr *name)
@@ -1565,7 +1596,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
*/
int gfs2_dir_add(struct inode *inode, const struct qstr *name,
- const struct gfs2_inum_host *inum, unsigned type)
+ const struct gfs2_inode *nip, unsigned type)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
@@ -1580,7 +1611,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
if (IS_ERR(dent))
return PTR_ERR(dent);
dent = gfs2_init_dirent(inode, dent, name, bh);
- gfs2_inum_out(inum, (char *)&dent->de_inum);
+ gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(type);
if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
leaf = (struct gfs2_leaf *)bh->b_data;
@@ -1592,7 +1623,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
break;
gfs2_trans_add_bh(ip->i_gl, bh, 1);
ip->i_di.di_entries++;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
error = 0;
@@ -1678,7 +1709,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
gfs2_consist_inode(dip);
gfs2_trans_add_bh(dip->i_gl, bh, 1);
dip->i_di.di_entries--;
- dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
mark_inode_dirty(&dip->i_inode);
@@ -1700,7 +1731,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
*/
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
- struct gfs2_inum_host *inum, unsigned int new_type)
+ const struct gfs2_inode *nip, unsigned int new_type)
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
@@ -1715,7 +1746,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
return PTR_ERR(dent);
gfs2_trans_add_bh(dip->i_gl, bh, 1);
- gfs2_inum_out(inum, (char *)&dent->de_inum);
+ gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(new_type);
if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
@@ -1726,7 +1757,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
gfs2_trans_add_bh(dip->i_gl, bh, 1);
}
- dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
return 0;
@@ -1867,7 +1898,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
for (x = 0; x < rlist.rl_rgrps; x++) {
struct gfs2_rgrpd *rgd;
rgd = rlist.rl_ghs[x].gh_gl->gl_object;
- rg_blocks += rgd->rd_ri.ri_length;
+ rg_blocks += rgd->rd_length;
}
error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index 48fe89046bba..8a468cac9328 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -16,15 +16,16 @@ struct inode;
struct gfs2_inode;
struct gfs2_inum;
-int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
- struct gfs2_inum_host *inum, unsigned int *type);
+struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename);
+int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
+ const struct gfs2_inode *ip);
int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
- const struct gfs2_inum_host *inum, unsigned int type);
+ const struct gfs2_inode *ip, unsigned int type);
int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir);
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
- struct gfs2_inum_host *new_inum, unsigned int new_type);
+ const struct gfs2_inode *nip, unsigned int new_type);
int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index 5b83ca6acab1..2a7435b5c4dc 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -254,7 +254,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
if (error)
return error;
- error = gfs2_trans_begin(sdp, rgd->rd_ri.ri_length + RES_DINODE +
+ error = gfs2_trans_begin(sdp, rgd->rd_length + RES_DINODE +
RES_EATTR + RES_STATFS + RES_QUOTA, blks);
if (error)
goto out_gunlock;
@@ -300,7 +300,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -700,7 +700,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
goto out_gunlock_q;
error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
- blks + al->al_rgd->rd_ri.ri_length +
+ blks + al->al_rgd->rd_length +
RES_DINODE + RES_STATFS + RES_QUOTA, 0);
if (error)
goto out_ipres;
@@ -717,7 +717,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
(er->er_mode & S_IFMT));
ip->i_inode.i_mode = er->er_mode;
}
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -852,7 +852,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
(ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));
ip->i_inode.i_mode = er->er_mode;
}
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -1133,7 +1133,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -1352,7 +1352,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
for (x = 0; x < rlist.rl_rgrps; x++) {
struct gfs2_rgrpd *rgd;
rgd = rlist.rl_ghs[x].gh_gl->gl_object;
- rg_blocks += rgd->rd_ri.ri_length;
+ rg_blocks += rgd->rd_length;
}
error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 1815429a2978..3f0974e1afef 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -422,11 +422,11 @@ void gfs2_holder_uninit(struct gfs2_holder *gh)
static void gfs2_holder_wake(struct gfs2_holder *gh)
{
clear_bit(HIF_WAIT, &gh->gh_iflags);
- smp_mb();
+ smp_mb__after_clear_bit();
wake_up_bit(&gh->gh_iflags, HIF_WAIT);
}
-static int holder_wait(void *word)
+static int just_schedule(void *word)
{
schedule();
return 0;
@@ -435,7 +435,20 @@ static int holder_wait(void *word)
static void wait_on_holder(struct gfs2_holder *gh)
{
might_sleep();
- wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE);
+ wait_on_bit(&gh->gh_iflags, HIF_WAIT, just_schedule, TASK_UNINTERRUPTIBLE);
+}
+
+static void gfs2_demote_wake(struct gfs2_glock *gl)
+{
+ clear_bit(GLF_DEMOTE, &gl->gl_flags);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&gl->gl_flags, GLF_DEMOTE);
+}
+
+static void wait_on_demote(struct gfs2_glock *gl)
+{
+ might_sleep();
+ wait_on_bit(&gl->gl_flags, GLF_DEMOTE, just_schedule, TASK_UNINTERRUPTIBLE);
}
/**
@@ -528,7 +541,7 @@ static int rq_demote(struct gfs2_glock *gl)
if (gl->gl_state == gl->gl_demote_state ||
gl->gl_state == LM_ST_UNLOCKED) {
- clear_bit(GLF_DEMOTE, &gl->gl_flags);
+ gfs2_demote_wake(gl);
return 0;
}
set_bit(GLF_LOCK, &gl->gl_flags);
@@ -666,12 +679,22 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl)
* practise: LM_ST_SHARED and LM_ST_UNLOCKED
*/
-static void handle_callback(struct gfs2_glock *gl, unsigned int state)
+static void handle_callback(struct gfs2_glock *gl, unsigned int state, int remote)
{
spin_lock(&gl->gl_spin);
if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) {
gl->gl_demote_state = state;
gl->gl_demote_time = jiffies;
+ if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN &&
+ gl->gl_object) {
+ struct inode *inode = igrab(gl->gl_object);
+ spin_unlock(&gl->gl_spin);
+ if (inode) {
+ d_prune_aliases(inode);
+ iput(inode);
+ }
+ return;
+ }
} else if (gl->gl_demote_state != LM_ST_UNLOCKED) {
gl->gl_demote_state = state;
}
@@ -740,7 +763,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
if (ret & LM_OUT_CANCELED)
op_done = 0;
else
- clear_bit(GLF_DEMOTE, &gl->gl_flags);
+ gfs2_demote_wake(gl);
} else {
spin_lock(&gl->gl_spin);
list_del_init(&gh->gh_list);
@@ -848,7 +871,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
gfs2_assert_warn(sdp, !ret);
state_change(gl, LM_ST_UNLOCKED);
- clear_bit(GLF_DEMOTE, &gl->gl_flags);
+ gfs2_demote_wake(gl);
if (glops->go_inval)
glops->go_inval(gl, DIO_METADATA);
@@ -1174,7 +1197,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
const struct gfs2_glock_operations *glops = gl->gl_ops;
if (gh->gh_flags & GL_NOCACHE)
- handle_callback(gl, LM_ST_UNLOCKED);
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
gfs2_glmutex_lock(gl);
@@ -1196,6 +1219,13 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
spin_unlock(&gl->gl_spin);
}
+void gfs2_glock_dq_wait(struct gfs2_holder *gh)
+{
+ struct gfs2_glock *gl = gh->gh_gl;
+ gfs2_glock_dq(gh);
+ wait_on_demote(gl);
+}
+
/**
* gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it
* @gh: the holder structure
@@ -1297,10 +1327,6 @@ static int nq_m_sync(unsigned int num_gh, struct gfs2_holder *ghs,
* @num_gh: the number of structures
* @ghs: an array of struct gfs2_holder structures
*
- * Figure out how big an impact this function has. Either:
- * 1) Replace this code with code that calls gfs2_glock_prefetch()
- * 2) Forget async stuff and just call nq_m_sync()
- * 3) Leave it like it is
*
* Returns: 0 on success (all glocks acquired),
* errno on failure (no glocks acquired)
@@ -1308,62 +1334,28 @@ static int nq_m_sync(unsigned int num_gh, struct gfs2_holder *ghs,
int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs)
{
- int *e;
- unsigned int x;
- int borked = 0, serious = 0;
+ struct gfs2_holder *tmp[4];
+ struct gfs2_holder **pph = tmp;
int error = 0;
- if (!num_gh)
+ switch(num_gh) {
+ case 0:
return 0;
-
- if (num_gh == 1) {
+ case 1:
ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
return gfs2_glock_nq(ghs);
- }
-
- e = kcalloc(num_gh, sizeof(struct gfs2_holder *), GFP_KERNEL);
- if (!e)
- return -ENOMEM;
-
- for (x = 0; x < num_gh; x++) {
- ghs[x].gh_flags |= LM_FLAG_TRY | GL_ASYNC;
- error = gfs2_glock_nq(&ghs[x]);
- if (error) {
- borked = 1;
- serious = error;
- num_gh = x;
+ default:
+ if (num_gh <= 4)
break;
- }
- }
-
- for (x = 0; x < num_gh; x++) {
- error = e[x] = glock_wait_internal(&ghs[x]);
- if (error) {
- borked = 1;
- if (error != GLR_TRYFAILED && error != GLR_CANCELED)
- serious = error;
- }
+ pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS);
+ if (!pph)
+ return -ENOMEM;
}
- if (!borked) {
- kfree(e);
- return 0;
- }
-
- for (x = 0; x < num_gh; x++)
- if (!e[x])
- gfs2_glock_dq(&ghs[x]);
-
- if (serious)
- error = serious;
- else {
- for (x = 0; x < num_gh; x++)
- gfs2_holder_reinit(ghs[x].gh_state, ghs[x].gh_flags,
- &ghs[x]);
- error = nq_m_sync(num_gh, ghs, (struct gfs2_holder **)e);
- }
+ error = nq_m_sync(num_gh, ghs, pph);
- kfree(e);
+ if (pph != tmp)
+ kfree(pph);
return error;
}
@@ -1456,7 +1448,7 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name,
if (!gl)
return;
- handle_callback(gl, state);
+ handle_callback(gl, state, 1);
spin_lock(&gl->gl_spin);
run_queue(gl);
@@ -1596,7 +1588,7 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp)
if (gfs2_glmutex_trylock(gl)) {
if (list_empty(&gl->gl_holders) &&
gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl))
- handle_callback(gl, LM_ST_UNLOCKED);
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
gfs2_glmutex_unlock(gl);
}
@@ -1709,7 +1701,7 @@ static void clear_glock(struct gfs2_glock *gl)
if (gfs2_glmutex_trylock(gl)) {
if (list_empty(&gl->gl_holders) &&
gl->gl_state != LM_ST_UNLOCKED)
- handle_callback(gl, LM_ST_UNLOCKED);
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
gfs2_glmutex_unlock(gl);
}
}
@@ -1823,7 +1815,8 @@ static int dump_inode(struct glock_iter *gi, struct gfs2_inode *ip)
print_dbg(gi, " Inode:\n");
print_dbg(gi, " num = %llu/%llu\n",
- ip->i_num.no_formal_ino, ip->i_num.no_addr);
+ (unsigned long long)ip->i_no_formal_ino,
+ (unsigned long long)ip->i_no_addr);
print_dbg(gi, " type = %u\n", IF2DT(ip->i_inode.i_mode));
print_dbg(gi, " i_flags =");
for (x = 0; x < 32; x++)
@@ -1909,8 +1902,8 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
}
if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
print_dbg(gi, " Demotion req to state %u (%llu uS ago)\n",
- gl->gl_demote_state,
- (u64)(jiffies - gl->gl_demote_time)*(1000000/HZ));
+ gl->gl_demote_state, (unsigned long long)
+ (jiffies - gl->gl_demote_time)*(1000000/HZ));
}
if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) {
if (!test_bit(GLF_LOCK, &gl->gl_flags) &&
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index b3e152db70c8..7721ca3fff9e 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -87,6 +87,7 @@ int gfs2_glock_nq(struct gfs2_holder *gh);
int gfs2_glock_poll(struct gfs2_holder *gh);
int gfs2_glock_wait(struct gfs2_holder *gh);
void gfs2_glock_dq(struct gfs2_holder *gh);
+void gfs2_glock_dq_wait(struct gfs2_holder *gh);
void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 7b82657a9910..777ca46010e8 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -156,9 +156,9 @@ static void inode_go_sync(struct gfs2_glock *gl)
ip = NULL;
if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
- gfs2_log_flush(gl->gl_sbd, gl);
if (ip)
filemap_fdatawrite(ip->i_inode.i_mapping);
+ gfs2_log_flush(gl->gl_sbd, gl);
gfs2_meta_sync(gl);
if (ip) {
struct address_space *mapping = ip->i_inode.i_mapping;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index d995441373ab..170ba93829c0 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -28,6 +28,14 @@ struct gfs2_sbd;
typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret);
+struct gfs2_log_header_host {
+ u64 lh_sequence; /* Sequence number of this transaction */
+ u32 lh_flags; /* GFS2_LOG_HEAD_... */
+ u32 lh_tail; /* Block number of log tail */
+ u32 lh_blkno;
+ u32 lh_hash;
+};
+
/*
* Structure of operations that are associated with each
* type of element in the log.
@@ -60,12 +68,23 @@ struct gfs2_bitmap {
u32 bi_len;
};
+struct gfs2_rgrp_host {
+ u32 rg_flags;
+ u32 rg_free;
+ u32 rg_dinodes;
+ u64 rg_igeneration;
+};
+
struct gfs2_rgrpd {
struct list_head rd_list; /* Link with superblock */
struct list_head rd_list_mru;
struct list_head rd_recent; /* Recently used rgrps */
struct gfs2_glock *rd_gl; /* Glock for this rgrp */
- struct gfs2_rindex_host rd_ri;
+ u64 rd_addr; /* grp block disk address */
+ u64 rd_data0; /* first data location */
+ u32 rd_length; /* length of rgrp header in fs blocks */
+ u32 rd_data; /* num of data blocks in rgrp */
+ u32 rd_bitbytes; /* number of bytes in data bitmaps */
struct gfs2_rgrp_host rd_rg;
u64 rd_rg_vn;
struct gfs2_bitmap *rd_bits;
@@ -76,6 +95,8 @@ struct gfs2_rgrpd {
u32 rd_last_alloc_data;
u32 rd_last_alloc_meta;
struct gfs2_sbd *rd_sbd;
+ unsigned long rd_flags;
+#define GFS2_RDF_CHECK 0x0001 /* Need to check for unlinked inodes */
};
enum gfs2_state_bits {
@@ -211,10 +232,24 @@ enum {
GIF_SW_PAGED = 3,
};
+struct gfs2_dinode_host {
+ u64 di_size; /* number of bytes in file */
+ u64 di_blocks; /* number of blocks in file */
+ u64 di_goal_meta; /* rgrp to alloc from next */
+ u64 di_goal_data; /* data block goal */
+ u64 di_generation; /* generation number for NFS */
+ u32 di_flags; /* GFS2_DIF_... */
+ u16 di_height; /* height of metadata */
+ /* These only apply to directories */
+ u16 di_depth; /* Number of bits in the table */
+ u32 di_entries; /* The number of entries in the directory */
+ u64 di_eattr; /* extended attribute block number */
+};
+
struct gfs2_inode {
struct inode i_inode;
- struct gfs2_inum_host i_num;
-
+ u64 i_no_addr;
+ u64 i_no_formal_ino;
unsigned long i_flags; /* GIF_... */
struct gfs2_dinode_host i_di; /* To be replaced by ref to block */
@@ -275,14 +310,6 @@ enum {
QDF_LOCKED = 2,
};
-struct gfs2_quota_lvb {
- __be32 qb_magic;
- u32 __pad;
- __be64 qb_limit; /* Hard limit of # blocks to alloc */
- __be64 qb_warn; /* Warn user when alloc is above this # */
- __be64 qb_value; /* Current # blocks allocated */
-};
-
struct gfs2_quota_data {
struct list_head qd_list;
unsigned int qd_count;
@@ -327,7 +354,9 @@ struct gfs2_trans {
unsigned int tr_num_buf;
unsigned int tr_num_buf_new;
+ unsigned int tr_num_databuf_new;
unsigned int tr_num_buf_rm;
+ unsigned int tr_num_databuf_rm;
struct list_head tr_list_buf;
unsigned int tr_num_revoke;
@@ -354,6 +383,12 @@ struct gfs2_jdesc {
unsigned int jd_blocks;
};
+struct gfs2_statfs_change_host {
+ s64 sc_total;
+ s64 sc_free;
+ s64 sc_dinodes;
+};
+
#define GFS2_GLOCKD_DEFAULT 1
#define GFS2_GLOCKD_MAX 16
@@ -426,6 +461,28 @@ enum {
#define GFS2_FSNAME_LEN 256
+struct gfs2_inum_host {
+ u64 no_formal_ino;
+ u64 no_addr;
+};
+
+struct gfs2_sb_host {
+ u32 sb_magic;
+ u32 sb_type;
+ u32 sb_format;
+
+ u32 sb_fs_format;
+ u32 sb_multihost_format;
+ u32 sb_bsize;
+ u32 sb_bsize_shift;
+
+ struct gfs2_inum_host sb_master_dir;
+ struct gfs2_inum_host sb_root_dir;
+
+ char sb_lockproto[GFS2_LOCKNAME_LEN];
+ char sb_locktable[GFS2_LOCKNAME_LEN];
+};
+
struct gfs2_sbd {
struct super_block *sd_vfs;
struct super_block *sd_vfs_meta;
@@ -544,6 +601,7 @@ struct gfs2_sbd {
unsigned int sd_log_blks_reserved;
unsigned int sd_log_commited_buf;
+ unsigned int sd_log_commited_databuf;
unsigned int sd_log_commited_revoke;
unsigned int sd_log_num_gl;
@@ -552,7 +610,6 @@ struct gfs2_sbd {
unsigned int sd_log_num_rg;
unsigned int sd_log_num_databuf;
unsigned int sd_log_num_jdata;
- unsigned int sd_log_num_hdrs;
struct list_head sd_log_le_gl;
struct list_head sd_log_le_buf;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index df0b8b3018b9..34f7bcdea1e9 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -38,12 +38,17 @@
#include "trans.h"
#include "util.h"
+struct gfs2_inum_range_host {
+ u64 ir_start;
+ u64 ir_length;
+};
+
static int iget_test(struct inode *inode, void *opaque)
{
struct gfs2_inode *ip = GFS2_I(inode);
- struct gfs2_inum_host *inum = opaque;
+ u64 *no_addr = opaque;
- if (ip->i_num.no_addr == inum->no_addr &&
+ if (ip->i_no_addr == *no_addr &&
inode->i_private != NULL)
return 1;
@@ -53,37 +58,70 @@ static int iget_test(struct inode *inode, void *opaque)
static int iget_set(struct inode *inode, void *opaque)
{
struct gfs2_inode *ip = GFS2_I(inode);
- struct gfs2_inum_host *inum = opaque;
+ u64 *no_addr = opaque;
- ip->i_num = *inum;
- inode->i_ino = inum->no_addr;
+ inode->i_ino = (unsigned long)*no_addr;
+ ip->i_no_addr = *no_addr;
return 0;
}
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum)
+struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr)
+{
+ unsigned long hash = (unsigned long)no_addr;
+ return ilookup5(sb, hash, iget_test, &no_addr);
+}
+
+static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
{
- return ilookup5(sb, (unsigned long)inum->no_addr,
- iget_test, inum);
+ unsigned long hash = (unsigned long)no_addr;
+ return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
}
-static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum)
+/**
+ * GFS2 lookup code fills in vfs inode contents based on info obtained
+ * from directory entry inside gfs2_inode_lookup(). This has caused issues
+ * with NFS code path since its get_dentry routine doesn't have the relevant
+ * directory entry when gfs2_inode_lookup() is invoked. Part of the code
+ * segment inside gfs2_inode_lookup code needs to get moved around.
+ *
+ * Clean up I_LOCK and I_NEW as well.
+ **/
+
+void gfs2_set_iop(struct inode *inode)
{
- return iget5_locked(sb, (unsigned long)inum->no_addr,
- iget_test, iget_set, inum);
+ umode_t mode = inode->i_mode;
+
+ if (S_ISREG(mode)) {
+ inode->i_op = &gfs2_file_iops;
+ inode->i_fop = &gfs2_file_fops;
+ inode->i_mapping->a_ops = &gfs2_file_aops;
+ } else if (S_ISDIR(mode)) {
+ inode->i_op = &gfs2_dir_iops;
+ inode->i_fop = &gfs2_dir_fops;
+ } else if (S_ISLNK(mode)) {
+ inode->i_op = &gfs2_symlink_iops;
+ } else {
+ inode->i_op = &gfs2_dev_iops;
+ }
+
+ unlock_new_inode(inode);
}
/**
* gfs2_inode_lookup - Lookup an inode
* @sb: The super block
- * @inum: The inode number
+ * @no_addr: The inode number
* @type: The type of the inode
*
* Returns: A VFS inode, or an error
*/
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type)
+struct inode *gfs2_inode_lookup(struct super_block *sb,
+ unsigned int type,
+ u64 no_addr,
+ u64 no_formal_ino)
{
- struct inode *inode = gfs2_iget(sb, inum);
+ struct inode *inode = gfs2_iget(sb, no_addr);
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_glock *io_gl;
int error;
@@ -93,29 +131,15 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *i
if (inode->i_state & I_NEW) {
struct gfs2_sbd *sdp = GFS2_SB(inode);
- umode_t mode = DT2IF(type);
inode->i_private = ip;
- inode->i_mode = mode;
-
- if (S_ISREG(mode)) {
- inode->i_op = &gfs2_file_iops;
- inode->i_fop = &gfs2_file_fops;
- inode->i_mapping->a_ops = &gfs2_file_aops;
- } else if (S_ISDIR(mode)) {
- inode->i_op = &gfs2_dir_iops;
- inode->i_fop = &gfs2_dir_fops;
- } else if (S_ISLNK(mode)) {
- inode->i_op = &gfs2_symlink_iops;
- } else {
- inode->i_op = &gfs2_dev_iops;
- }
+ ip->i_no_formal_ino = no_formal_ino;
- error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
+ error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
if (unlikely(error))
goto fail;
ip->i_gl->gl_object = ip;
- error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
+ error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
if (unlikely(error))
goto fail_put;
@@ -123,12 +147,38 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *i
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
if (unlikely(error))
goto fail_iopen;
+ ip->i_iopen_gh.gh_gl->gl_object = ip;
gfs2_glock_put(io_gl);
- unlock_new_inode(inode);
+
+ if ((type == DT_UNKNOWN) && (no_formal_ino == 0))
+ goto gfs2_nfsbypass;
+
+ inode->i_mode = DT2IF(type);
+
+ /*
+ * We must read the inode in order to work out its type in
+ * this case. Note that this doesn't happen often as we normally
+ * know the type beforehand. This code path only occurs during
+ * unlinked inode recovery (where it is safe to do this glock,
+ * which is not true in the general case).
+ */
+ if (type == DT_UNKNOWN) {
+ struct gfs2_holder gh;
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+ if (unlikely(error))
+ goto fail_glock;
+ /* Inode is now uptodate */
+ gfs2_glock_dq_uninit(&gh);
+ }
+
+ gfs2_set_iop(inode);
}
+gfs2_nfsbypass:
return inode;
+fail_glock:
+ gfs2_glock_dq(&ip->i_iopen_gh);
fail_iopen:
gfs2_glock_put(io_gl);
fail_put:
@@ -144,14 +194,12 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
struct gfs2_dinode_host *di = &ip->i_di;
const struct gfs2_dinode *str = buf;
- if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) {
+ if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) {
if (gfs2_consist_inode(ip))
gfs2_dinode_print(ip);
return -EIO;
}
- if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino))
- return -ESTALE;
-
+ ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
ip->i_inode.i_rdev = 0;
switch (ip->i_inode.i_mode & S_IFMT) {
@@ -175,11 +223,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
di->di_blocks = be64_to_cpu(str->di_blocks);
gfs2_set_inode_blocks(&ip->i_inode);
ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
- ip->i_inode.i_atime.tv_nsec = 0;
+ ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
- ip->i_inode.i_mtime.tv_nsec = 0;
+ ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
- ip->i_inode.i_ctime.tv_nsec = 0;
+ ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
di->di_goal_data = be64_to_cpu(str->di_goal_data);
@@ -247,7 +295,7 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
if (error)
goto out_qs;
- rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+ rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
if (!rgd) {
gfs2_consist_inode(ip);
error = -EIO;
@@ -314,7 +362,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
else
drop_nlink(&ip->i_inode);
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -366,9 +414,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
struct super_block *sb = dir->i_sb;
struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_holder d_gh;
- struct gfs2_inum_host inum;
- unsigned int type;
- int error;
+ int error = 0;
struct inode *inode = NULL;
int unlock = 0;
@@ -395,12 +441,9 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
goto out;
}
- error = gfs2_dir_search(dir, name, &inum, &type);
- if (error)
- goto out;
-
- inode = gfs2_inode_lookup(sb, &inum, type);
-
+ inode = gfs2_dir_search(dir, name);
+ if (IS_ERR(inode))
+ error = PTR_ERR(inode);
out:
if (unlock)
gfs2_glock_dq_uninit(&d_gh);
@@ -409,6 +452,22 @@ out:
return inode ? inode : ERR_PTR(error);
}
+static void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
+{
+ const struct gfs2_inum_range *str = buf;
+
+ ir->ir_start = be64_to_cpu(str->ir_start);
+ ir->ir_length = be64_to_cpu(str->ir_length);
+}
+
+static void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
+{
+ struct gfs2_inum_range *str = buf;
+
+ str->ir_start = cpu_to_be64(ir->ir_start);
+ str->ir_length = cpu_to_be64(ir->ir_length);
+}
+
static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino)
{
struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);
@@ -548,7 +607,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
if (!dip->i_inode.i_nlink)
return -EPERM;
- error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL);
+ error = gfs2_dir_check(&dip->i_inode, name, NULL);
switch (error) {
case -ENOENT:
error = 0;
@@ -588,8 +647,7 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
*gid = current->fsgid;
}
-static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum,
- u64 *generation)
+static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
{
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
int error;
@@ -605,7 +663,7 @@ static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum,
if (error)
goto out_ipreserv;
- inum->no_addr = gfs2_alloc_di(dip, generation);
+ *no_addr = gfs2_alloc_di(dip, generation);
gfs2_trans_end(sdp);
@@ -635,6 +693,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_dinode *di;
struct buffer_head *dibh;
+ struct timespec tv = CURRENT_TIME;
dibh = gfs2_meta_new(gl, inum->no_addr);
gfs2_trans_add_bh(gl, dibh, 1);
@@ -650,7 +709,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
di->di_nlink = 0;
di->di_size = 0;
di->di_blocks = cpu_to_be64(1);
- di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds());
+ di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
di->di_major = cpu_to_be32(MAJOR(dev));
di->di_minor = cpu_to_be32(MINOR(dev));
di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
@@ -680,6 +739,9 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
di->di_entries = 0;
memset(&di->__pad4, 0, sizeof(di->__pad4));
di->di_eattr = 0;
+ di->di_atime_nsec = cpu_to_be32(tv.tv_nsec);
+ di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
+ di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
memset(&di->di_reserved, 0, sizeof(di->di_reserved));
brelse(dibh);
@@ -749,7 +811,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
goto fail_quota_locks;
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
- al->al_rgd->rd_ri.ri_length +
+ al->al_rgd->rd_length +
2 * RES_DINODE +
RES_STATFS + RES_QUOTA, 0);
if (error)
@@ -760,7 +822,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
goto fail_quota_locks;
}
- error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode));
+ error = gfs2_dir_add(&dip->i_inode, name, ip, IF2DT(ip->i_inode.i_mode));
if (error)
goto fail_end_trans;
@@ -840,11 +902,11 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip)
struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
unsigned int mode, dev_t dev)
{
- struct inode *inode;
+ struct inode *inode = NULL;
struct gfs2_inode *dip = ghs->gh_gl->gl_object;
struct inode *dir = &dip->i_inode;
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
- struct gfs2_inum_host inum;
+ struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
int error;
u64 generation;
@@ -864,7 +926,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock;
- error = alloc_dinode(dip, &inum, &generation);
+ error = alloc_dinode(dip, &inum.no_addr, &generation);
if (error)
goto fail_gunlock;
@@ -877,34 +939,36 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock2;
- inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode));
+ inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode),
+ inum.no_addr,
+ inum.no_formal_ino);
if (IS_ERR(inode))
goto fail_gunlock2;
error = gfs2_inode_refresh(GFS2_I(inode));
if (error)
- goto fail_iput;
+ goto fail_gunlock2;
error = gfs2_acl_create(dip, GFS2_I(inode));
if (error)
- goto fail_iput;
+ goto fail_gunlock2;
error = gfs2_security_init(dip, GFS2_I(inode));
if (error)
- goto fail_iput;
+ goto fail_gunlock2;
error = link_dinode(dip, name, GFS2_I(inode));
if (error)
- goto fail_iput;
+ goto fail_gunlock2;
if (!inode)
return ERR_PTR(-ENOMEM);
return inode;
-fail_iput:
- iput(inode);
fail_gunlock2:
gfs2_glock_dq_uninit(ghs + 1);
+ if (inode)
+ iput(inode);
fail_gunlock:
gfs2_glock_dq(ghs);
fail:
@@ -976,10 +1040,8 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
*/
int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
- struct gfs2_inode *ip)
+ const struct gfs2_inode *ip)
{
- struct gfs2_inum_host inum;
- unsigned int type;
int error;
if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
@@ -997,18 +1059,10 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
if (error)
return error;
- error = gfs2_dir_search(&dip->i_inode, name, &inum, &type);
+ error = gfs2_dir_check(&dip->i_inode, name, ip);
if (error)
return error;
- if (!gfs2_inum_equal(&inum, &ip->i_num))
- return -ENOENT;
-
- if (IF2DT(ip->i_inode.i_mode) != type) {
- gfs2_consist_inode(dip);
- return -EIO;
- }
-
return 0;
}
@@ -1132,10 +1186,11 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
struct gfs2_glock *gl = gh->gh_gl;
struct gfs2_sbd *sdp = gl->gl_sbd;
struct gfs2_inode *ip = gl->gl_object;
- s64 curtime, quantum = gfs2_tune_get(sdp, gt_atime_quantum);
+ s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
unsigned int state;
int flags;
int error;
+ struct timespec tv = CURRENT_TIME;
if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
@@ -1153,8 +1208,7 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
(sdp->sd_vfs->s_flags & MS_RDONLY))
return 0;
- curtime = get_seconds();
- if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+ if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
gfs2_glock_dq(gh);
gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
gh);
@@ -1165,8 +1219,8 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
/* Verify that atime hasn't been updated while we were
trying to get exclusive lock. */
- curtime = get_seconds();
- if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+ tv = CURRENT_TIME;
+ if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
struct buffer_head *dibh;
struct gfs2_dinode *di;
@@ -1180,11 +1234,12 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
if (error)
goto fail_end_trans;
- ip->i_inode.i_atime.tv_sec = curtime;
+ ip->i_inode.i_atime = tv;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
di = (struct gfs2_dinode *)dibh->b_data;
di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+ di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
brelse(dibh);
gfs2_trans_end(sdp);
@@ -1252,3 +1307,66 @@ int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
return error;
}
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
+{
+ const struct gfs2_dinode_host *di = &ip->i_di;
+ struct gfs2_dinode *str = buf;
+
+ str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
+ str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
+ str->di_header.__pad0 = 0;
+ str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
+ str->di_header.__pad1 = 0;
+ str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
+ str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+ str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
+ str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
+ str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+ str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
+ str->di_size = cpu_to_be64(di->di_size);
+ str->di_blocks = cpu_to_be64(di->di_blocks);
+ str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+ str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
+ str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
+
+ str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
+ str->di_goal_data = cpu_to_be64(di->di_goal_data);
+ str->di_generation = cpu_to_be64(di->di_generation);
+
+ str->di_flags = cpu_to_be32(di->di_flags);
+ str->di_height = cpu_to_be16(di->di_height);
+ str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
+ !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
+ GFS2_FORMAT_DE : 0);
+ str->di_depth = cpu_to_be16(di->di_depth);
+ str->di_entries = cpu_to_be32(di->di_entries);
+
+ str->di_eattr = cpu_to_be64(di->di_eattr);
+ str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
+ str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec);
+ str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec);
+}
+
+void gfs2_dinode_print(const struct gfs2_inode *ip)
+{
+ const struct gfs2_dinode_host *di = &ip->i_di;
+
+ printk(KERN_INFO " no_formal_ino = %llu\n",
+ (unsigned long long)ip->i_no_formal_ino);
+ printk(KERN_INFO " no_addr = %llu\n",
+ (unsigned long long)ip->i_no_addr);
+ printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size);
+ printk(KERN_INFO " di_blocks = %llu\n",
+ (unsigned long long)di->di_blocks);
+ printk(KERN_INFO " di_goal_meta = %llu\n",
+ (unsigned long long)di->di_goal_meta);
+ printk(KERN_INFO " di_goal_data = %llu\n",
+ (unsigned long long)di->di_goal_data);
+ printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags);
+ printk(KERN_INFO " di_height = %u\n", di->di_height);
+ printk(KERN_INFO " di_depth = %u\n", di->di_depth);
+ printk(KERN_INFO " di_entries = %u\n", di->di_entries);
+ printk(KERN_INFO " di_eattr = %llu\n",
+ (unsigned long long)di->di_eattr);
+}
+
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index b57f448b15bc..4517ac82c01c 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -10,17 +10,17 @@
#ifndef __INODE_DOT_H__
#define __INODE_DOT_H__
-static inline int gfs2_is_stuffed(struct gfs2_inode *ip)
+static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
{
return !ip->i_di.di_height;
}
-static inline int gfs2_is_jdata(struct gfs2_inode *ip)
+static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
{
return ip->i_di.di_flags & GFS2_DIF_JDATA;
}
-static inline int gfs2_is_dir(struct gfs2_inode *ip)
+static inline int gfs2_is_dir(const struct gfs2_inode *ip)
{
return S_ISDIR(ip->i_inode.i_mode);
}
@@ -32,9 +32,25 @@ static inline void gfs2_set_inode_blocks(struct inode *inode)
(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
}
+static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr,
+ u64 no_formal_ino)
+{
+ return ip->i_no_addr == no_addr && ip->i_no_formal_ino == no_formal_ino;
+}
+
+static inline void gfs2_inum_out(const struct gfs2_inode *ip,
+ struct gfs2_dirent *dent)
+{
+ dent->de_inum.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+ dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr);
+}
+
+
void gfs2_inode_attr_in(struct gfs2_inode *ip);
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type);
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum);
+void gfs2_set_iop(struct inode *inode);
+struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
+ u64 no_addr, u64 no_formal_ino);
+struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
int gfs2_inode_refresh(struct gfs2_inode *ip);
@@ -47,12 +63,14 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
struct gfs2_inode *ip);
int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
- struct gfs2_inode *ip);
+ const struct gfs2_inode *ip);
int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to);
int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
int gfs2_glock_nq_atime(struct gfs2_holder *gh);
int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
+void gfs2_dinode_print(const struct gfs2_inode *ip);
#endif /* __INODE_DOT_H__ */
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c
index c305255bfe8a..542a797ac89a 100644
--- a/fs/gfs2/locking/dlm/lock.c
+++ b/fs/gfs2/locking/dlm/lock.c
@@ -174,7 +174,6 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
lp->cur = DLM_LOCK_IV;
lp->lvb = NULL;
lp->hold_null = NULL;
- init_completion(&lp->ast_wait);
INIT_LIST_HEAD(&lp->clist);
INIT_LIST_HEAD(&lp->blist);
INIT_LIST_HEAD(&lp->delay_list);
@@ -399,6 +398,12 @@ static void gdlm_del_lvb(struct gdlm_lock *lp)
lp->lksb.sb_lvbptr = NULL;
}
+static int gdlm_ast_wait(void *word)
+{
+ schedule();
+ return 0;
+}
+
/* This can do a synchronous dlm request (requiring a lock_dlm thread to get
the completion) because gfs won't call hold_lvb() during a callback (from
the context of a lock_dlm thread). */
@@ -424,10 +429,10 @@ static int hold_null_lock(struct gdlm_lock *lp)
lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE;
set_bit(LFL_NOBAST, &lpn->flags);
set_bit(LFL_INLOCK, &lpn->flags);
+ set_bit(LFL_AST_WAIT, &lpn->flags);
- init_completion(&lpn->ast_wait);
gdlm_do_lock(lpn);
- wait_for_completion(&lpn->ast_wait);
+ wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE);
error = lpn->lksb.sb_status;
if (error) {
printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n",
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h
index d074c6e6f9bf..24d70f73b651 100644
--- a/fs/gfs2/locking/dlm/lock_dlm.h
+++ b/fs/gfs2/locking/dlm/lock_dlm.h
@@ -101,6 +101,7 @@ enum {
LFL_NOBAST = 10,
LFL_HEADQUE = 11,
LFL_UNLOCK_DELETE = 12,
+ LFL_AST_WAIT = 13,
};
struct gdlm_lock {
@@ -117,7 +118,6 @@ struct gdlm_lock {
unsigned long flags; /* lock_dlm flags LFL_ */
int bast_mode; /* protected by async_lock */
- struct completion ast_wait;
struct list_head clist; /* complete */
struct list_head blist; /* blocking */
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
index 1d8faa3da8af..41c5b04caaba 100644
--- a/fs/gfs2/locking/dlm/mount.c
+++ b/fs/gfs2/locking/dlm/mount.c
@@ -147,7 +147,7 @@ static int gdlm_mount(char *table_name, char *host_data,
error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
&ls->dlm_lockspace,
- nodir ? DLM_LSFL_NODIR : 0,
+ DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
GDLM_LVB_SIZE);
if (error) {
log_error("dlm_new_lockspace error %d", error);
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
index f82495e18c2d..fba1f1d87e4f 100644
--- a/fs/gfs2/locking/dlm/plock.c
+++ b/fs/gfs2/locking/dlm/plock.c
@@ -242,7 +242,7 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
op->info.number = name->ln_number;
op->info.start = fl->fl_start;
op->info.end = fl->fl_end;
-
+ op->info.owner = (__u64)(long) fl->fl_owner;
send_op(op);
wait_event(recv_wq, (op->done != 0));
@@ -254,16 +254,20 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
}
spin_unlock(&ops_lock);
+ /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
+ -ENOENT if there are no locks on the file */
+
rv = op->info.rv;
fl->fl_type = F_UNLCK;
if (rv == -ENOENT)
rv = 0;
- else if (rv == 0 && op->info.pid != fl->fl_pid) {
+ else if (rv > 0) {
fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
fl->fl_pid = op->info.pid;
fl->fl_start = op->info.start;
fl->fl_end = op->info.end;
+ rv = 0;
}
kfree(op);
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
index 9cf1f168eaf8..1aca51e45092 100644
--- a/fs/gfs2/locking/dlm/thread.c
+++ b/fs/gfs2/locking/dlm/thread.c
@@ -44,6 +44,13 @@ static void process_blocking(struct gdlm_lock *lp, int bast_mode)
ls->fscb(ls->sdp, cb, &lp->lockname);
}
+static void wake_up_ast(struct gdlm_lock *lp)
+{
+ clear_bit(LFL_AST_WAIT, &lp->flags);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&lp->flags, LFL_AST_WAIT);
+}
+
static void process_complete(struct gdlm_lock *lp)
{
struct gdlm_ls *ls = lp->ls;
@@ -136,7 +143,7 @@ static void process_complete(struct gdlm_lock *lp)
*/
if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) {
- complete(&lp->ast_wait);
+ wake_up_ast(lp);
return;
}
@@ -214,7 +221,7 @@ out:
if (test_bit(LFL_INLOCK, &lp->flags)) {
clear_bit(LFL_NOBLOCK, &lp->flags);
lp->cur = lp->req;
- complete(&lp->ast_wait);
+ wake_up_ast(lp);
return;
}
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 291415ddfe51..f49a12e24086 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -83,6 +83,11 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
gfs2_assert(sdp, bd->bd_ail == ai);
+ if (!bh){
+ list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+ continue;
+ }
+
if (!buffer_busy(bh)) {
if (!buffer_uptodate(bh)) {
gfs2_log_unlock(sdp);
@@ -125,6 +130,11 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl
bd_ail_st_list) {
bh = bd->bd_bh;
+ if (!bh){
+ list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+ continue;
+ }
+
gfs2_assert(sdp, bd->bd_ail == ai);
if (buffer_busy(bh)) {
@@ -262,8 +272,8 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
* @sdp: The GFS2 superblock
* @blks: The number of blocks to reserve
*
- * Note that we never give out the last 6 blocks of the journal. Thats
- * due to the fact that there is are a small number of header blocks
+ * Note that we never give out the last few blocks of the journal. Thats
+ * due to the fact that there is a small number of header blocks
* associated with each log flush. The exact number can't be known until
* flush time, so we ensure that we have just enough free blocks at all
* times to avoid running out during a log flush.
@@ -274,6 +284,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
{
unsigned int try = 0;
+ unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize);
if (gfs2_assert_warn(sdp, blks) ||
gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks))
@@ -281,7 +292,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
mutex_lock(&sdp->sd_log_reserve_mutex);
gfs2_log_lock(sdp);
- while(sdp->sd_log_blks_free <= (blks + 6)) {
+ while(sdp->sd_log_blks_free <= (blks + reserved_blks)) {
gfs2_log_unlock(sdp);
gfs2_ail1_empty(sdp, 0);
gfs2_log_flush(sdp, NULL);
@@ -357,6 +368,58 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer
return dist;
}
+/**
+ * calc_reserved - Calculate the number of blocks to reserve when
+ * refunding a transaction's unused buffers.
+ * @sdp: The GFS2 superblock
+ *
+ * This is complex. We need to reserve room for all our currently used
+ * metadata buffers (e.g. normal file I/O rewriting file time stamps) and
+ * all our journaled data buffers for journaled files (e.g. files in the
+ * meta_fs like rindex, or files for which chattr +j was done.)
+ * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush
+ * will count it as free space (sd_log_blks_free) and corruption will follow.
+ *
+ * We can have metadata bufs and jdata bufs in the same journal. So each
+ * type gets its own log header, for which we need to reserve a block.
+ * In fact, each type has the potential for needing more than one header
+ * in cases where we have more buffers than will fit on a journal page.
+ * Metadata journal entries take up half the space of journaled buffer entries.
+ * Thus, metadata entries have buf_limit (502) and journaled buffers have
+ * databuf_limit (251) before they cause a wrap around.
+ *
+ * Also, we need to reserve blocks for revoke journal entries and one for an
+ * overall header for the lot.
+ *
+ * Returns: the number of blocks reserved
+ */
+static unsigned int calc_reserved(struct gfs2_sbd *sdp)
+{
+ unsigned int reserved = 0;
+ unsigned int mbuf_limit, metabufhdrs_needed;
+ unsigned int dbuf_limit, databufhdrs_needed;
+ unsigned int revokes = 0;
+
+ mbuf_limit = buf_limit(sdp);
+ metabufhdrs_needed = (sdp->sd_log_commited_buf +
+ (mbuf_limit - 1)) / mbuf_limit;
+ dbuf_limit = databuf_limit(sdp);
+ databufhdrs_needed = (sdp->sd_log_commited_databuf +
+ (dbuf_limit - 1)) / dbuf_limit;
+
+ if (sdp->sd_log_commited_revoke)
+ revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
+ sizeof(u64));
+
+ reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
+ sdp->sd_log_commited_databuf + databufhdrs_needed +
+ revokes;
+ /* One for the overall header */
+ if (reserved)
+ reserved++;
+ return reserved;
+}
+
static unsigned int current_tail(struct gfs2_sbd *sdp)
{
struct gfs2_ail *ai;
@@ -447,14 +510,14 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
return bh;
}
-static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull)
+static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
{
unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
ail2_empty(sdp, new_tail);
gfs2_log_lock(sdp);
- sdp->sd_log_blks_free += dist - (pull ? 1 : 0);
+ sdp->sd_log_blks_free += dist;
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
gfs2_log_unlock(sdp);
@@ -504,7 +567,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
brelse(bh);
if (sdp->sd_log_tail != tail)
- log_pull_tail(sdp, tail, pull);
+ log_pull_tail(sdp, tail);
else
gfs2_assert_withdraw(sdp, !pull);
@@ -517,6 +580,7 @@ static void log_flush_commit(struct gfs2_sbd *sdp)
struct list_head *head = &sdp->sd_log_flush_list;
struct gfs2_log_buf *lb;
struct buffer_head *bh;
+ int flushcount = 0;
while (!list_empty(head)) {
lb = list_entry(head->next, struct gfs2_log_buf, lb_list);
@@ -533,9 +597,20 @@ static void log_flush_commit(struct gfs2_sbd *sdp)
} else
brelse(bh);
kfree(lb);
+ flushcount++;
}
- log_write_header(sdp, 0, 0);
+ /* If nothing was journaled, the header is unplanned and unwanted. */
+ if (flushcount) {
+ log_write_header(sdp, 0, 0);
+ } else {
+ unsigned int tail;
+ tail = current_tail(sdp);
+
+ gfs2_ail1_empty(sdp, 0);
+ if (sdp->sd_log_tail != tail)
+ log_pull_tail(sdp, tail);
+ }
}
/**
@@ -565,7 +640,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
INIT_LIST_HEAD(&ai->ai_ail1_list);
INIT_LIST_HEAD(&ai->ai_ail2_list);
- gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf == sdp->sd_log_commited_buf);
+ gfs2_assert_withdraw(sdp,
+ sdp->sd_log_num_buf + sdp->sd_log_num_jdata ==
+ sdp->sd_log_commited_buf +
+ sdp->sd_log_commited_databuf);
gfs2_assert_withdraw(sdp,
sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
@@ -576,16 +654,19 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
lops_before_commit(sdp);
if (!list_empty(&sdp->sd_log_flush_list))
log_flush_commit(sdp);
- else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle)
+ else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
+ gfs2_log_lock(sdp);
+ sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */
+ gfs2_log_unlock(sdp);
log_write_header(sdp, 0, PULL);
+ }
lops_after_commit(sdp, ai);
gfs2_log_lock(sdp);
sdp->sd_log_head = sdp->sd_log_flush_head;
- sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs;
sdp->sd_log_blks_reserved = 0;
sdp->sd_log_commited_buf = 0;
- sdp->sd_log_num_hdrs = 0;
+ sdp->sd_log_commited_databuf = 0;
sdp->sd_log_commited_revoke = 0;
if (!list_empty(&ai->ai_ail1_list)) {
@@ -602,32 +683,26 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{
- unsigned int reserved = 0;
+ unsigned int reserved;
unsigned int old;
gfs2_log_lock(sdp);
sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
- gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 0);
+ sdp->sd_log_commited_databuf += tr->tr_num_databuf_new -
+ tr->tr_num_databuf_rm;
+ gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
+ (((int)sdp->sd_log_commited_databuf) >= 0));
sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
-
- if (sdp->sd_log_commited_buf)
- reserved += sdp->sd_log_commited_buf;
- if (sdp->sd_log_commited_revoke)
- reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
- sizeof(u64));
- if (reserved)
- reserved++;
-
+ reserved = calc_reserved(sdp);
old = sdp->sd_log_blks_free;
sdp->sd_log_blks_free += tr->tr_reserved -
(reserved - sdp->sd_log_blks_reserved);
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
- gfs2_assert_withdraw(sdp,
- sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks +
- sdp->sd_log_num_hdrs);
+ gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
+ sdp->sd_jdesc->jd_blocks);
sdp->sd_log_blks_reserved = reserved;
@@ -673,13 +748,13 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
- gfs2_assert_withdraw(sdp, !sdp->sd_log_num_hdrs);
gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
sdp->sd_log_flush_head = sdp->sd_log_head;
sdp->sd_log_flush_wrapped = 0;
- log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0);
+ log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
+ (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks);
gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index f82d84d05d23..aff70f0698fd 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -17,6 +17,7 @@
#include "gfs2.h"
#include "incore.h"
+#include "inode.h"
#include "glock.h"
#include "log.h"
#include "lops.h"
@@ -117,15 +118,13 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
struct gfs2_log_descriptor *ld;
struct gfs2_bufdata *bd1 = NULL, *bd2;
unsigned int total = sdp->sd_log_num_buf;
- unsigned int offset = sizeof(struct gfs2_log_descriptor);
+ unsigned int offset = BUF_OFFSET;
unsigned int limit;
unsigned int num;
unsigned n;
__be64 *ptr;
- offset += sizeof(__be64) - 1;
- offset &= ~(sizeof(__be64) - 1);
- limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
+ limit = buf_limit(sdp);
/* for 4k blocks, limit = 503 */
bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
@@ -134,7 +133,6 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
if (total > limit)
num = limit;
bh = gfs2_log_get_buf(sdp);
- sdp->sd_log_num_hdrs++;
ld = (struct gfs2_log_descriptor *)bh->b_data;
ptr = (__be64 *)(bh->b_data + offset);
ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
@@ -469,25 +467,28 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
struct gfs2_inode *ip = GFS2_I(mapping->host);
gfs2_log_lock(sdp);
+ if (!list_empty(&bd->bd_list_tr)) {
+ gfs2_log_unlock(sdp);
+ return;
+ }
tr->tr_touched = 1;
- if (list_empty(&bd->bd_list_tr) &&
- (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
+ if (gfs2_is_jdata(ip)) {
tr->tr_num_buf++;
list_add(&bd->bd_list_tr, &tr->tr_list_buf);
- gfs2_log_unlock(sdp);
- gfs2_pin(sdp, bd->bd_bh);
- tr->tr_num_buf_new++;
- } else {
- gfs2_log_unlock(sdp);
}
+ gfs2_log_unlock(sdp);
+ if (!list_empty(&le->le_list))
+ return;
+
gfs2_trans_add_gl(bd->bd_gl);
- gfs2_log_lock(sdp);
- if (list_empty(&le->le_list)) {
- if (ip->i_di.di_flags & GFS2_DIF_JDATA)
- sdp->sd_log_num_jdata++;
- sdp->sd_log_num_databuf++;
- list_add(&le->le_list, &sdp->sd_log_le_databuf);
+ if (gfs2_is_jdata(ip)) {
+ sdp->sd_log_num_jdata++;
+ gfs2_pin(sdp, bd->bd_bh);
+ tr->tr_num_databuf_new++;
}
+ sdp->sd_log_num_databuf++;
+ gfs2_log_lock(sdp);
+ list_add(&le->le_list, &sdp->sd_log_le_databuf);
gfs2_log_unlock(sdp);
}
@@ -520,7 +521,6 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
LIST_HEAD(started);
struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
struct buffer_head *bh = NULL,*bh1 = NULL;
- unsigned int offset = sizeof(struct gfs2_log_descriptor);
struct gfs2_log_descriptor *ld;
unsigned int limit;
unsigned int total_dbuf = sdp->sd_log_num_databuf;
@@ -528,9 +528,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
unsigned int num, n;
__be64 *ptr = NULL;
- offset += 2*sizeof(__be64) - 1;
- offset &= ~(2*sizeof(__be64) - 1);
- limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
+ limit = databuf_limit(sdp);
/*
* Start writing ordered buffers, write journaled buffers
@@ -581,10 +579,10 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
gfs2_log_unlock(sdp);
if (!bh) {
bh = gfs2_log_get_buf(sdp);
- sdp->sd_log_num_hdrs++;
ld = (struct gfs2_log_descriptor *)
bh->b_data;
- ptr = (__be64 *)(bh->b_data + offset);
+ ptr = (__be64 *)(bh->b_data +
+ DATABUF_OFFSET);
ld->ld_header.mh_magic =
cpu_to_be32(GFS2_MAGIC);
ld->ld_header.mh_type =
@@ -605,7 +603,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
if (unlikely(magic != 0))
set_buffer_escaped(bh1);
gfs2_log_lock(sdp);
- if (n++ > num)
+ if (++n >= num)
break;
} else if (!bh1) {
total_dbuf--;
@@ -622,6 +620,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
}
gfs2_log_unlock(sdp);
if (bh) {
+ set_buffer_mapped(bh);
set_buffer_dirty(bh);
ll_rw_block(WRITE, 1, &bh);
bh = NULL;
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 965bc65c7c64..41a00df75587 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -13,6 +13,13 @@
#include <linux/list.h>
#include "incore.h"
+#define BUF_OFFSET \
+ ((sizeof(struct gfs2_log_descriptor) + sizeof(__be64) - 1) & \
+ ~(sizeof(__be64) - 1))
+#define DATABUF_OFFSET \
+ ((sizeof(struct gfs2_log_descriptor) + (2 * sizeof(__be64) - 1)) & \
+ ~(2 * sizeof(__be64) - 1))
+
extern const struct gfs2_log_operations gfs2_glock_lops;
extern const struct gfs2_log_operations gfs2_buf_lops;
extern const struct gfs2_log_operations gfs2_revoke_lops;
@@ -21,6 +28,22 @@ extern const struct gfs2_log_operations gfs2_databuf_lops;
extern const struct gfs2_log_operations *gfs2_log_ops[];
+static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
+{
+ unsigned int limit;
+
+ limit = (sdp->sd_sb.sb_bsize - BUF_OFFSET) / sizeof(__be64);
+ return limit;
+}
+
+static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
+{
+ unsigned int limit;
+
+ limit = (sdp->sd_sb.sb_bsize - DATABUF_OFFSET) / (2 * sizeof(__be64));
+ return limit;
+}
+
static inline void lops_init_le(struct gfs2_log_element *le,
const struct gfs2_log_operations *lops)
{
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index e62d4f620c58..8da343b34ae7 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -387,12 +387,18 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
if (test_clear_buffer_pinned(bh)) {
struct gfs2_trans *tr = current->journal_info;
+ struct gfs2_inode *bh_ip =
+ GFS2_I(bh->b_page->mapping->host);
+
gfs2_log_lock(sdp);
list_del_init(&bd->bd_le.le_list);
gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
sdp->sd_log_num_buf--;
gfs2_log_unlock(sdp);
- tr->tr_num_buf_rm++;
+ if (bh_ip->i_inode.i_private != NULL)
+ tr->tr_num_databuf_rm++;
+ else
+ tr->tr_num_buf_rm++;
brelse(bh);
}
if (bd) {
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index e037425bc042..527bf19d9690 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -63,7 +63,7 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
struct buffer_head **bhp)
{
- return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp);
+ return gfs2_meta_indirect_buffer(ip, 0, ip->i_no_addr, 0, bhp);
}
struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c
index 4864659555d4..6f006a804db3 100644
--- a/fs/gfs2/mount.c
+++ b/fs/gfs2/mount.c
@@ -82,20 +82,19 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
char *options, *o, *v;
int error = 0;
- if (!remount) {
- /* If someone preloaded options, use those instead */
- spin_lock(&gfs2_sys_margs_lock);
- if (gfs2_sys_margs) {
- data = gfs2_sys_margs;
- gfs2_sys_margs = NULL;
- }
- spin_unlock(&gfs2_sys_margs_lock);
-
- /* Set some defaults */
- args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
- args->ar_quota = GFS2_QUOTA_DEFAULT;
- args->ar_data = GFS2_DATA_DEFAULT;
+ /* If someone preloaded options, use those instead */
+ spin_lock(&gfs2_sys_margs_lock);
+ if (!remount && gfs2_sys_margs) {
+ data = gfs2_sys_margs;
+ gfs2_sys_margs = NULL;
}
+ spin_unlock(&gfs2_sys_margs_lock);
+
+ /* Set some defaults */
+ memset(args, 0, sizeof(struct gfs2_args));
+ args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
+ args->ar_quota = GFS2_QUOTA_DEFAULT;
+ args->ar_data = GFS2_DATA_DEFAULT;
/* Split the options into tokens with the "," character and
process them */
diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c
deleted file mode 100644
index d9ecfd23a49e..000000000000
--- a/fs/gfs2/ondisk.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs2.h"
-#include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
-#include "incore.h"
-
-#define pv(struct, member, fmt) printk(KERN_INFO " "#member" = "fmt"\n", \
- struct->member);
-
-/*
- * gfs2_xxx_in - read in an xxx struct
- * first arg: the cpu-order structure
- * buf: the disk-order buffer
- *
- * gfs2_xxx_out - write out an xxx struct
- * first arg: the cpu-order structure
- * buf: the disk-order buffer
- *
- * gfs2_xxx_print - print out an xxx struct
- * first arg: the cpu-order structure
- */
-
-void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf)
-{
- const struct gfs2_inum *str = buf;
-
- no->no_formal_ino = be64_to_cpu(str->no_formal_ino);
- no->no_addr = be64_to_cpu(str->no_addr);
-}
-
-void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf)
-{
- struct gfs2_inum *str = buf;
-
- str->no_formal_ino = cpu_to_be64(no->no_formal_ino);
- str->no_addr = cpu_to_be64(no->no_addr);
-}
-
-static void gfs2_inum_print(const struct gfs2_inum_host *no)
-{
- printk(KERN_INFO " no_formal_ino = %llu\n", (unsigned long long)no->no_formal_ino);
- printk(KERN_INFO " no_addr = %llu\n", (unsigned long long)no->no_addr);
-}
-
-static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf)
-{
- const struct gfs2_meta_header *str = buf;
-
- mh->mh_magic = be32_to_cpu(str->mh_magic);
- mh->mh_type = be32_to_cpu(str->mh_type);
- mh->mh_format = be32_to_cpu(str->mh_format);
-}
-
-void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
-{
- const struct gfs2_sb *str = buf;
-
- gfs2_meta_header_in(&sb->sb_header, buf);
-
- sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
- sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
- sb->sb_bsize = be32_to_cpu(str->sb_bsize);
- sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
-
- gfs2_inum_in(&sb->sb_master_dir, (char *)&str->sb_master_dir);
- gfs2_inum_in(&sb->sb_root_dir, (char *)&str->sb_root_dir);
-
- memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
- memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
-}
-
-void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf)
-{
- const struct gfs2_rindex *str = buf;
-
- ri->ri_addr = be64_to_cpu(str->ri_addr);
- ri->ri_length = be32_to_cpu(str->ri_length);
- ri->ri_data0 = be64_to_cpu(str->ri_data0);
- ri->ri_data = be32_to_cpu(str->ri_data);
- ri->ri_bitbytes = be32_to_cpu(str->ri_bitbytes);
-
-}
-
-void gfs2_rindex_print(const struct gfs2_rindex_host *ri)
-{
- printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)ri->ri_addr);
- pv(ri, ri_length, "%u");
-
- printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)ri->ri_data0);
- pv(ri, ri_data, "%u");
-
- pv(ri, ri_bitbytes, "%u");
-}
-
-void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
-{
- const struct gfs2_rgrp *str = buf;
-
- rg->rg_flags = be32_to_cpu(str->rg_flags);
- rg->rg_free = be32_to_cpu(str->rg_free);
- rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
- rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
-}
-
-void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
-{
- struct gfs2_rgrp *str = buf;
-
- str->rg_flags = cpu_to_be32(rg->rg_flags);
- str->rg_free = cpu_to_be32(rg->rg_free);
- str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
- str->__pad = cpu_to_be32(0);
- str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
- memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
-}
-
-void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
-{
- const struct gfs2_quota *str = buf;
-
- qu->qu_limit = be64_to_cpu(str->qu_limit);
- qu->qu_warn = be64_to_cpu(str->qu_warn);
- qu->qu_value = be64_to_cpu(str->qu_value);
-}
-
-void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
-{
- const struct gfs2_dinode_host *di = &ip->i_di;
- struct gfs2_dinode *str = buf;
-
- str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
- str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
- str->di_header.__pad0 = 0;
- str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
- str->di_header.__pad1 = 0;
-
- gfs2_inum_out(&ip->i_num, &str->di_num);
-
- str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
- str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
- str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
- str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
- str->di_size = cpu_to_be64(di->di_size);
- str->di_blocks = cpu_to_be64(di->di_blocks);
- str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
- str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
- str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
-
- str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
- str->di_goal_data = cpu_to_be64(di->di_goal_data);
- str->di_generation = cpu_to_be64(di->di_generation);
-
- str->di_flags = cpu_to_be32(di->di_flags);
- str->di_height = cpu_to_be16(di->di_height);
- str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
- !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
- GFS2_FORMAT_DE : 0);
- str->di_depth = cpu_to_be16(di->di_depth);
- str->di_entries = cpu_to_be32(di->di_entries);
-
- str->di_eattr = cpu_to_be64(di->di_eattr);
-}
-
-void gfs2_dinode_print(const struct gfs2_inode *ip)
-{
- const struct gfs2_dinode_host *di = &ip->i_di;
-
- gfs2_inum_print(&ip->i_num);
-
- printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size);
- printk(KERN_INFO " di_blocks = %llu\n", (unsigned long long)di->di_blocks);
- printk(KERN_INFO " di_goal_meta = %llu\n", (unsigned long long)di->di_goal_meta);
- printk(KERN_INFO " di_goal_data = %llu\n", (unsigned long long)di->di_goal_data);
-
- pv(di, di_flags, "0x%.8X");
- pv(di, di_height, "%u");
-
- pv(di, di_depth, "%u");
- pv(di, di_entries, "%u");
-
- printk(KERN_INFO " di_eattr = %llu\n", (unsigned long long)di->di_eattr);
-}
-
-void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
-{
- const struct gfs2_log_header *str = buf;
-
- gfs2_meta_header_in(&lh->lh_header, buf);
- lh->lh_sequence = be64_to_cpu(str->lh_sequence);
- lh->lh_flags = be32_to_cpu(str->lh_flags);
- lh->lh_tail = be32_to_cpu(str->lh_tail);
- lh->lh_blkno = be32_to_cpu(str->lh_blkno);
- lh->lh_hash = be32_to_cpu(str->lh_hash);
-}
-
-void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
-{
- const struct gfs2_inum_range *str = buf;
-
- ir->ir_start = be64_to_cpu(str->ir_start);
- ir->ir_length = be64_to_cpu(str->ir_length);
-}
-
-void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
-{
- struct gfs2_inum_range *str = buf;
-
- str->ir_start = cpu_to_be64(ir->ir_start);
- str->ir_length = cpu_to_be64(ir->ir_length);
-}
-
-void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
-{
- const struct gfs2_statfs_change *str = buf;
-
- sc->sc_total = be64_to_cpu(str->sc_total);
- sc->sc_free = be64_to_cpu(str->sc_free);
- sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
-}
-
-void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
-{
- struct gfs2_statfs_change *str = buf;
-
- str->sc_total = cpu_to_be64(sc->sc_total);
- str->sc_free = cpu_to_be64(sc->sc_free);
- str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
-}
-
-void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
-{
- const struct gfs2_quota_change *str = buf;
-
- qc->qc_change = be64_to_cpu(str->qc_change);
- qc->qc_flags = be32_to_cpu(str->qc_flags);
- qc->qc_id = be32_to_cpu(str->qc_id);
-}
-
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 30c15622174f..26c888890c24 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
@@ -32,6 +32,7 @@
#include "trans.h"
#include "rgrp.h"
#include "ops_file.h"
+#include "super.h"
#include "util.h"
#include "glops.h"
@@ -49,6 +50,8 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
end = start + bsize;
if (end <= from || start >= to)
continue;
+ if (gfs2_is_jdata(ip))
+ set_buffer_uptodate(bh);
gfs2_trans_add_bh(ip->i_gl, bh, 0);
}
}
@@ -134,7 +137,9 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
return 0; /* don't care */
}
- if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) {
+ if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) &&
+ PageChecked(page)) {
+ ClearPageChecked(page);
error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0);
if (error)
goto out_ignore;
@@ -203,11 +208,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
* so we need to supply one here. It doesn't happen often.
*/
if (unlikely(page->index)) {
- kaddr = kmap_atomic(page, KM_USER0);
- memset(kaddr, 0, PAGE_CACHE_SIZE);
- kunmap_atomic(kaddr, KM_USER0);
- flush_dcache_page(page);
- SetPageUptodate(page);
+ zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
return 0;
}
@@ -450,6 +451,31 @@ out_uninit:
}
/**
+ * adjust_fs_space - Adjusts the free space available due to gfs2_grow
+ * @inode: the rindex inode
+ */
+static void adjust_fs_space(struct inode *inode)
+{
+ struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+ struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+ struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+ u64 fs_total, new_free;
+
+ /* Total up the file system space, according to the latest rindex. */
+ fs_total = gfs2_ri_total(sdp);
+
+ spin_lock(&sdp->sd_statfs_spin);
+ if (fs_total > (m_sc->sc_total + l_sc->sc_total))
+ new_free = fs_total - (m_sc->sc_total + l_sc->sc_total);
+ else
+ new_free = 0;
+ spin_unlock(&sdp->sd_statfs_spin);
+ fs_warn(sdp, "File system extended by %llu blocks.\n",
+ (unsigned long long)new_free);
+ gfs2_statfs_change(sdp, new_free, new_free, 0);
+}
+
+/**
* gfs2_commit_write - Commit write to a file
* @file: The file to write to
* @page: The page containing the data
@@ -511,6 +537,9 @@ static int gfs2_commit_write(struct file *file, struct page *page,
di->di_size = cpu_to_be64(inode->i_size);
}
+ if (inode == sdp->sd_rindex)
+ adjust_fs_space(inode);
+
brelse(dibh);
gfs2_trans_end(sdp);
if (al->al_requested) {
@@ -543,6 +572,23 @@ fail_nounlock:
}
/**
+ * gfs2_set_page_dirty - Page dirtying function
+ * @page: The page to dirty
+ *
+ * Returns: 1 if it dirtyed the page, or 0 otherwise
+ */
+
+static int gfs2_set_page_dirty(struct page *page)
+{
+ struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+ struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
+
+ if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
+ SetPageChecked(page);
+ return __set_page_dirty_buffers(page);
+}
+
+/**
* gfs2_bmap - Block map function
* @mapping: Address space info
* @lblock: The block to map
@@ -578,6 +624,8 @@ static void discard_buffer(struct gfs2_sbd *sdp, struct buffer_head *bh)
if (bd) {
bd->bd_bh = NULL;
bh->b_private = NULL;
+ if (!bd->bd_ail && list_empty(&bd->bd_le.le_list))
+ kmem_cache_free(gfs2_bufdata_cachep, bd);
}
gfs2_log_unlock(sdp);
@@ -598,6 +646,8 @@ static void gfs2_invalidatepage(struct page *page, unsigned long offset)
unsigned int curr_off = 0;
BUG_ON(!PageLocked(page));
+ if (offset == 0)
+ ClearPageChecked(page);
if (!page_has_buffers(page))
return;
@@ -728,8 +778,8 @@ static unsigned limit = 0;
return;
fs_warn(sdp, "ip = %llu %llu\n",
- (unsigned long long)ip->i_num.no_formal_ino,
- (unsigned long long)ip->i_num.no_addr);
+ (unsigned long long)ip->i_no_formal_ino,
+ (unsigned long long)ip->i_no_addr);
for (x = 0; x < GFS2_MAX_META_HEIGHT; x++)
fs_warn(sdp, "ip->i_cache[%u] = %s\n",
@@ -810,6 +860,7 @@ const struct address_space_operations gfs2_file_aops = {
.sync_page = block_sync_page,
.prepare_write = gfs2_prepare_write,
.commit_write = gfs2_commit_write,
+ .set_page_dirty = gfs2_set_page_dirty,
.bmap = gfs2_bmap,
.invalidatepage = gfs2_invalidatepage,
.releasepage = gfs2_releasepage,
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h
index 35aaee4aa7e1..fa1b5b3d28b9 100644
--- a/fs/gfs2/ops_address.h
+++ b/fs/gfs2/ops_address.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index a6fdc52f554a..793e334d098e 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -21,6 +21,7 @@
#include "glock.h"
#include "ops_dentry.h"
#include "util.h"
+#include "inode.h"
/**
* gfs2_drevalidate - Check directory lookup consistency
@@ -40,14 +41,15 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
struct gfs2_inode *dip = GFS2_I(parent->d_inode);
struct inode *inode = dentry->d_inode;
struct gfs2_holder d_gh;
- struct gfs2_inode *ip;
- struct gfs2_inum_host inum;
- unsigned int type;
+ struct gfs2_inode *ip = NULL;
int error;
int had_lock=0;
- if (inode && is_bad_inode(inode))
- goto invalid;
+ if (inode) {
+ if (is_bad_inode(inode))
+ goto invalid;
+ ip = GFS2_I(inode);
+ }
if (sdp->sd_args.ar_localcaching)
goto valid;
@@ -59,7 +61,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
goto fail;
}
- error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type);
+ error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip);
switch (error) {
case 0:
if (!inode)
@@ -73,16 +75,6 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
goto fail_gunlock;
}
- ip = GFS2_I(inode);
-
- if (!gfs2_inum_equal(&ip->i_num, &inum))
- goto invalid_gunlock;
-
- if (IF2DT(ip->i_inode.i_mode) != type) {
- gfs2_consist_inode(dip);
- goto fail_gunlock;
- }
-
valid_gunlock:
if (!had_lock)
gfs2_glock_dq_uninit(&d_gh);
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index aad918337a46..99ea5659bc2c 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -22,10 +22,14 @@
#include "glops.h"
#include "inode.h"
#include "ops_dentry.h"
-#include "ops_export.h"
+#include "ops_fstype.h"
#include "rgrp.h"
#include "util.h"
+#define GFS2_SMALL_FH_SIZE 4
+#define GFS2_LARGE_FH_SIZE 8
+#define GFS2_OLD_FH_SIZE 10
+
static struct dentry *gfs2_decode_fh(struct super_block *sb,
__u32 *p,
int fh_len,
@@ -35,31 +39,28 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb,
void *context)
{
__be32 *fh = (__force __be32 *)p;
- struct gfs2_fh_obj fh_obj;
- struct gfs2_inum_host *this, parent;
+ struct gfs2_inum_host inum, parent;
- this = &fh_obj.this;
- fh_obj.imode = DT_UNKNOWN;
memset(&parent, 0, sizeof(struct gfs2_inum));
switch (fh_len) {
case GFS2_LARGE_FH_SIZE:
+ case GFS2_OLD_FH_SIZE:
parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
parent.no_formal_ino |= be32_to_cpu(fh[5]);
parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
parent.no_addr |= be32_to_cpu(fh[7]);
- fh_obj.imode = be32_to_cpu(fh[8]);
case GFS2_SMALL_FH_SIZE:
- this->no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
- this->no_formal_ino |= be32_to_cpu(fh[1]);
- this->no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
- this->no_addr |= be32_to_cpu(fh[3]);
+ inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
+ inum.no_formal_ino |= be32_to_cpu(fh[1]);
+ inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
+ inum.no_addr |= be32_to_cpu(fh[3]);
break;
default:
return NULL;
}
- return gfs2_export_ops.find_exported_dentry(sb, &fh_obj, &parent,
+ return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent,
acceptable, context);
}
@@ -75,10 +76,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
(connectable && *len < GFS2_LARGE_FH_SIZE))
return 255;
- fh[0] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
- fh[1] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
- fh[2] = cpu_to_be32(ip->i_num.no_addr >> 32);
- fh[3] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
+ fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
+ fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+ fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
+ fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
*len = GFS2_SMALL_FH_SIZE;
if (!connectable || inode == sb->s_root->d_inode)
@@ -90,13 +91,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
igrab(inode);
spin_unlock(&dentry->d_lock);
- fh[4] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
- fh[5] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
- fh[6] = cpu_to_be32(ip->i_num.no_addr >> 32);
- fh[7] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
-
- fh[8] = cpu_to_be32(inode->i_mode);
- fh[9] = 0; /* pad to double word */
+ fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
+ fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+ fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
+ fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
*len = GFS2_LARGE_FH_SIZE;
iput(inode);
@@ -144,7 +142,8 @@ static int gfs2_get_name(struct dentry *parent, char *name,
ip = GFS2_I(inode);
*name = 0;
- gnfd.inum = ip->i_num;
+ gnfd.inum.no_addr = ip->i_no_addr;
+ gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
gnfd.name = name;
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
@@ -192,8 +191,7 @@ static struct dentry *gfs2_get_parent(struct dentry *child)
static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
- struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj;
- struct gfs2_inum_host *inum = &fh_obj->this;
+ struct gfs2_inum_host *inum = inum_obj;
struct gfs2_holder i_gh, ri_gh, rgd_gh;
struct gfs2_rgrpd *rgd;
struct inode *inode;
@@ -202,9 +200,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
/* System files? */
- inode = gfs2_ilookup(sb, inum);
+ inode = gfs2_ilookup(sb, inum->no_addr);
if (inode) {
- if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) {
+ if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
iput(inode);
return ERR_PTR(-ESTALE);
}
@@ -236,7 +234,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
gfs2_glock_dq_uninit(&rgd_gh);
gfs2_glock_dq_uninit(&ri_gh);
- inode = gfs2_inode_lookup(sb, inum, fh_obj->imode);
+ inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
+ inum->no_addr,
+ 0);
if (!inode)
goto fail;
if (IS_ERR(inode)) {
@@ -250,6 +250,15 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
goto fail;
}
+ /* Pick up the works we bypass in gfs2_inode_lookup */
+ if (inode->i_state & I_NEW)
+ gfs2_set_iop(inode);
+
+ if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
+ iput(inode);
+ goto fail;
+ }
+
error = -EIO;
if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
iput(inode);
diff --git a/fs/gfs2/ops_export.h b/fs/gfs2/ops_export.h
deleted file mode 100644
index f925a955b3b8..000000000000
--- a/fs/gfs2/ops_export.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __OPS_EXPORT_DOT_H__
-#define __OPS_EXPORT_DOT_H__
-
-#define GFS2_SMALL_FH_SIZE 4
-#define GFS2_LARGE_FH_SIZE 10
-
-extern struct export_operations gfs2_export_ops;
-struct gfs2_fh_obj {
- struct gfs2_inum_host this;
- __u32 imode;
-};
-
-#endif /* __OPS_EXPORT_DOT_H__ */
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 064df8804582..196d83266e34 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -502,7 +502,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
struct lm_lockname name =
- { .ln_number = ip->i_num.no_addr,
+ { .ln_number = ip->i_no_addr,
.ln_type = LM_TYPE_PLOCK };
if (!(fl->fl_flags & FL_POSIX))
@@ -557,7 +557,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
gfs2_glock_dq_uninit(fl_gh);
} else {
error = gfs2_glock_get(GFS2_SB(&ip->i_inode),
- ip->i_num.no_addr, &gfs2_flock_glops,
+ ip->i_no_addr, &gfs2_flock_glops,
CREATE, &gl);
if (error)
goto out;
@@ -635,7 +635,6 @@ const struct file_operations gfs2_file_fops = {
.release = gfs2_close,
.fsync = gfs2_fsync,
.lock = gfs2_lock,
- .sendfile = generic_file_sendfile,
.flock = gfs2_flock,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 2c5f8e7def0d..cf5aa5050548 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -27,7 +27,6 @@
#include "inode.h"
#include "lm.h"
#include "mount.h"
-#include "ops_export.h"
#include "ops_fstype.h"
#include "ops_super.h"
#include "recovery.h"
@@ -105,6 +104,7 @@ static void init_vfs(struct super_block *sb, unsigned noatime)
sb->s_magic = GFS2_MAGIC;
sb->s_op = &gfs2_super_ops;
sb->s_export_op = &gfs2_export_ops;
+ sb->s_time_gran = 1;
sb->s_maxbytes = MAX_LFS_FILESIZE;
if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME))
@@ -116,7 +116,6 @@ static void init_vfs(struct super_block *sb, unsigned noatime)
static int init_names(struct gfs2_sbd *sdp, int silent)
{
- struct page *page;
char *proto, *table;
int error = 0;
@@ -126,14 +125,9 @@ static int init_names(struct gfs2_sbd *sdp, int silent)
/* Try to autodetect */
if (!proto[0] || !table[0]) {
- struct gfs2_sb *sb;
- page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
- if (!page)
- return -ENOBUFS;
- sb = kmap(page);
- gfs2_sb_in(&sdp->sd_sb, sb);
- kunmap(page);
- __free_page(page);
+ error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+ if (error)
+ return error;
error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
if (error)
@@ -151,6 +145,9 @@ static int init_names(struct gfs2_sbd *sdp, int silent)
snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto);
snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table);
+ while ((table = strchr(sdp->sd_table_name, '/')))
+ *table = '_';
+
out:
return error;
}
@@ -236,17 +233,17 @@ fail:
return error;
}
-static struct inode *gfs2_lookup_root(struct super_block *sb,
- struct gfs2_inum_host *inum)
+static inline struct inode *gfs2_lookup_root(struct super_block *sb,
+ u64 no_addr)
{
- return gfs2_inode_lookup(sb, inum, DT_DIR);
+ return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0);
}
static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
{
struct super_block *sb = sdp->sd_vfs;
struct gfs2_holder sb_gh;
- struct gfs2_inum_host *inum;
+ u64 no_addr;
struct inode *inode;
int error = 0;
@@ -289,10 +286,10 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
sb_set_blocksize(sb, sdp->sd_sb.sb_bsize);
/* Get the root inode */
- inum = &sdp->sd_sb.sb_root_dir;
+ no_addr = sdp->sd_sb.sb_root_dir.no_addr;
if (sb->s_type == &gfs2meta_fs_type)
- inum = &sdp->sd_sb.sb_master_dir;
- inode = gfs2_lookup_root(sb, inum);
+ no_addr = sdp->sd_sb.sb_master_dir.no_addr;
+ inode = gfs2_lookup_root(sb, no_addr);
if (IS_ERR(inode)) {
error = PTR_ERR(inode);
fs_err(sdp, "can't read in root inode: %d\n", error);
@@ -449,7 +446,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
if (undo)
goto fail_qinode;
- inode = gfs2_lookup_root(sdp->sd_vfs, &sdp->sd_sb.sb_master_dir);
+ inode = gfs2_lookup_root(sdp->sd_vfs, sdp->sd_sb.sb_master_dir.no_addr);
if (IS_ERR(inode)) {
error = PTR_ERR(inode);
fs_err(sdp, "can't read in master directory: %d\n", error);
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h
index 7cc2c296271b..407029b3b2b3 100644
--- a/fs/gfs2/ops_fstype.h
+++ b/fs/gfs2/ops_fstype.h
@@ -14,5 +14,6 @@
extern struct file_system_type gfs2_fs_type;
extern struct file_system_type gfs2meta_fs_type;
+extern struct export_operations gfs2_export_ops;
#endif /* __OPS_FSTYPE_DOT_H__ */
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index d85f6e05cb95..911c115b5c6c 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -157,7 +157,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
if (error)
goto out_gunlock;
- error = gfs2_dir_search(dir, &dentry->d_name, NULL, NULL);
+ error = gfs2_dir_check(dir, &dentry->d_name, NULL);
switch (error) {
case -ENOENT:
break;
@@ -206,7 +206,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
goto out_gunlock_q;
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
- al->al_rgd->rd_ri.ri_length +
+ al->al_rgd->rd_length +
2 * RES_DINODE + RES_STATFS +
RES_QUOTA, 0);
if (error)
@@ -217,8 +217,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
goto out_ipres;
}
- error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num,
- IF2DT(inode->i_mode));
+ error = gfs2_dir_add(dir, &dentry->d_name, ip, IF2DT(inode->i_mode));
if (error)
goto out_end_trans;
@@ -275,7 +274,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
- rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+ rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
@@ -420,7 +419,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
- gfs2_inum_out(&dip->i_num, &dent->de_inum);
+ gfs2_inum_out(dip, dent);
dent->de_type = cpu_to_be16(DT_DIR);
gfs2_dinode_out(ip, di);
@@ -472,7 +471,7 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
- rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+ rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
error = gfs2_glock_nq_m(3, ghs);
@@ -614,7 +613,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
* this is the case of the target file already existing
* so we unlink before doing the rename
*/
- nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr);
+ nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr);
if (nrgd)
gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
}
@@ -653,7 +652,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
if (error)
goto out_gunlock;
- error = gfs2_dir_search(ndir, &ndentry->d_name, NULL, NULL);
+ error = gfs2_dir_check(ndir, &ndentry->d_name, NULL);
switch (error) {
case -ENOENT:
error = 0;
@@ -712,7 +711,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
goto out_gunlock_q;
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
- al->al_rgd->rd_ri.ri_length +
+ al->al_rgd->rd_length +
4 * RES_DINODE + 4 * RES_LEAF +
RES_STATFS + RES_QUOTA + 4, 0);
if (error)
@@ -750,7 +749,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
if (error)
goto out_end_trans;
- error = gfs2_dir_mvino(ip, &name, &ndip->i_num, DT_DIR);
+ error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR);
if (error)
goto out_end_trans;
} else {
@@ -758,7 +757,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (error)
goto out_end_trans;
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -768,8 +767,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
if (error)
goto out_end_trans;
- error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num,
- IF2DT(ip->i_inode.i_mode));
+ error = gfs2_dir_add(ndir, &ndentry->d_name, ip, IF2DT(ip->i_inode.i_mode));
if (error)
goto out_end_trans;
@@ -905,8 +903,8 @@ static int setattr_size(struct inode *inode, struct iattr *attr)
}
error = gfs2_truncatei(ip, attr->ia_size);
- if (error)
- return error;
+ if (error && (inode->i_size != ip->i_di.di_size))
+ i_size_write(inode, ip->i_di.di_size);
return error;
}
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 485ce3d49923..603d940f1159 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -326,8 +326,10 @@ static void gfs2_clear_inode(struct inode *inode)
gfs2_glock_schedule_for_reclaim(ip->i_gl);
gfs2_glock_put(ip->i_gl);
ip->i_gl = NULL;
- if (ip->i_iopen_gh.gh_gl)
+ if (ip->i_iopen_gh.gh_gl) {
+ ip->i_iopen_gh.gh_gl->gl_object = NULL;
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
+ }
}
}
@@ -422,13 +424,13 @@ static void gfs2_delete_inode(struct inode *inode)
if (!inode->i_private)
goto out;
- error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh);
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
if (unlikely(error)) {
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
goto out;
}
- gfs2_glock_dq(&ip->i_iopen_gh);
+ gfs2_glock_dq_wait(&ip->i_iopen_gh);
gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
error = gfs2_glock_nq(&ip->i_iopen_gh);
if (error)
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
index aa0dbd2aac1b..404b7cc9f8c4 100644
--- a/fs/gfs2/ops_vm.c
+++ b/fs/gfs2/ops_vm.c
@@ -66,7 +66,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
if (error)
goto out_gunlock_q;
- error = gfs2_trans_begin(sdp, al->al_rgd->rd_ri.ri_length +
+ error = gfs2_trans_begin(sdp, al->al_rgd->rd_length +
ind_blocks + RES_DINODE +
RES_STATFS + RES_QUOTA, 0);
if (error)
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c186857e48a8..6e546ee8f3d4 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -66,6 +66,18 @@
#define QUOTA_USER 1
#define QUOTA_GROUP 0
+struct gfs2_quota_host {
+ u64 qu_limit;
+ u64 qu_warn;
+ s64 qu_value;
+};
+
+struct gfs2_quota_change_host {
+ u64 qc_change;
+ u32 qc_flags; /* GFS2_QCF_... */
+ u32 qc_id;
+};
+
static u64 qd2offset(struct gfs2_quota_data *qd)
{
u64 offset;
@@ -561,6 +573,25 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
mutex_unlock(&sdp->sd_quota_mutex);
}
+static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
+{
+ const struct gfs2_quota *str = buf;
+
+ qu->qu_limit = be64_to_cpu(str->qu_limit);
+ qu->qu_warn = be64_to_cpu(str->qu_warn);
+ qu->qu_value = be64_to_cpu(str->qu_value);
+}
+
+static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf)
+{
+ struct gfs2_quota *str = buf;
+
+ str->qu_limit = cpu_to_be64(qu->qu_limit);
+ str->qu_warn = cpu_to_be64(qu->qu_warn);
+ str->qu_value = cpu_to_be64(qu->qu_value);
+ memset(&str->qu_reserved, 0, sizeof(str->qu_reserved));
+}
+
/**
* gfs2_adjust_quota
*
@@ -573,12 +604,13 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
struct inode *inode = &ip->i_inode;
struct address_space *mapping = inode->i_mapping;
unsigned long index = loc >> PAGE_CACHE_SHIFT;
- unsigned offset = loc & (PAGE_CACHE_SHIFT - 1);
+ unsigned offset = loc & (PAGE_CACHE_SIZE - 1);
unsigned blocksize, iblock, pos;
struct buffer_head *bh;
struct page *page;
void *kaddr;
- __be64 *ptr;
+ char *ptr;
+ struct gfs2_quota_host qp;
s64 value;
int err = -EIO;
@@ -620,13 +652,17 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
kaddr = kmap_atomic(page, KM_USER0);
ptr = kaddr + offset;
- value = (s64)be64_to_cpu(*ptr) + change;
- *ptr = cpu_to_be64(value);
+ gfs2_quota_in(&qp, ptr);
+ qp.qu_value += change;
+ value = qp.qu_value;
+ gfs2_quota_out(&qp, ptr);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
err = 0;
qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC);
qd->qd_qb.qb_value = cpu_to_be64(value);
+ ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC);
+ ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value);
unlock:
unlock_page(page);
page_cache_release(page);
@@ -689,7 +725,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
goto out_alloc;
error = gfs2_trans_begin(sdp,
- al->al_rgd->rd_ri.ri_length +
+ al->al_rgd->rd_length +
num_qd * data_blocks +
nalloc * ind_blocks +
RES_DINODE + num_qd +
@@ -709,7 +745,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
offset = qd2offset(qd);
error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync,
(struct gfs2_quota_data *)
- qd->qd_gl->gl_lvb);
+ qd);
if (error)
goto out_end_trans;
@@ -1050,6 +1086,15 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
return error;
}
+static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
+{
+ const struct gfs2_quota_change *str = buf;
+
+ qc->qc_change = be64_to_cpu(str->qc_change);
+ qc->qc_flags = be32_to_cpu(str->qc_flags);
+ qc->qc_id = be32_to_cpu(str->qc_id);
+}
+
int gfs2_quota_init(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 8bc182c7e2ef..5ada38c99a2c 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -116,6 +116,22 @@ void gfs2_revoke_clean(struct gfs2_sbd *sdp)
}
}
+static int gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
+{
+ const struct gfs2_log_header *str = buf;
+
+ if (str->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
+ str->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH))
+ return 1;
+
+ lh->lh_sequence = be64_to_cpu(str->lh_sequence);
+ lh->lh_flags = be32_to_cpu(str->lh_flags);
+ lh->lh_tail = be32_to_cpu(str->lh_tail);
+ lh->lh_blkno = be32_to_cpu(str->lh_blkno);
+ lh->lh_hash = be32_to_cpu(str->lh_hash);
+ return 0;
+}
+
/**
* get_log_header - read the log header for a given segment
* @jd: the journal
@@ -147,12 +163,10 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
sizeof(u32));
hash = crc32_le(hash, (unsigned char const *)&nothing, sizeof(nothing));
hash ^= (u32)~0;
- gfs2_log_header_in(&lh, bh->b_data);
+ error = gfs2_log_header_in(&lh, bh->b_data);
brelse(bh);
- if (lh.lh_header.mh_magic != GFS2_MAGIC ||
- lh.lh_header.mh_type != GFS2_METATYPE_LH ||
- lh.lh_blkno != blk || lh.lh_hash != hash)
+ if (error || lh.lh_blkno != blk || lh.lh_hash != hash)
return 1;
*head = lh;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 1727f5012efe..e4e040625153 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
@@ -28,6 +28,7 @@
#include "ops_file.h"
#include "util.h"
#include "log.h"
+#include "inode.h"
#define BFITNOENT ((u32)~0)
@@ -50,6 +51,9 @@ static const char valid_change[16] = {
1, 0, 0, 0
};
+static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+ unsigned char old_state, unsigned char new_state);
+
/**
* gfs2_setbit - Set a bit in the bitmaps
* @buffer: the buffer that holds the bitmaps
@@ -204,7 +208,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
struct gfs2_bitmap *bi = NULL;
- u32 length = rgd->rd_ri.ri_length;
+ u32 length = rgd->rd_length;
u32 count[4], tmp;
int buf, x;
@@ -227,7 +231,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
return;
}
- tmp = rgd->rd_ri.ri_data -
+ tmp = rgd->rd_data -
rgd->rd_rg.rg_free -
rgd->rd_rg.rg_dinodes;
if (count[1] + count[2] != tmp) {
@@ -253,10 +257,10 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
}
-static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block)
+static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
{
- u64 first = ri->ri_data0;
- u64 last = first + ri->ri_data;
+ u64 first = rgd->rd_data0;
+ u64 last = first + rgd->rd_data;
return first <= block && block < last;
}
@@ -275,7 +279,7 @@ struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk)
spin_lock(&sdp->sd_rindex_spin);
list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) {
- if (rgrp_contains_block(&rgd->rd_ri, blk)) {
+ if (rgrp_contains_block(rgd, blk)) {
list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
spin_unlock(&sdp->sd_rindex_spin);
return rgd;
@@ -354,6 +358,15 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
mutex_unlock(&sdp->sd_rindex_mutex);
}
+static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd)
+{
+ printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)rgd->rd_addr);
+ printk(KERN_INFO " ri_length = %u\n", rgd->rd_length);
+ printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0);
+ printk(KERN_INFO " ri_data = %u\n", rgd->rd_data);
+ printk(KERN_INFO " ri_bitbytes = %u\n", rgd->rd_bitbytes);
+}
+
/**
* gfs2_compute_bitstructs - Compute the bitmap sizes
* @rgd: The resource group descriptor
@@ -367,7 +380,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
struct gfs2_bitmap *bi;
- u32 length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */
+ u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */
u32 bytes_left, bytes;
int x;
@@ -378,7 +391,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
if (!rgd->rd_bits)
return -ENOMEM;
- bytes_left = rgd->rd_ri.ri_bitbytes;
+ bytes_left = rgd->rd_bitbytes;
for (x = 0; x < length; x++) {
bi = rgd->rd_bits + x;
@@ -399,14 +412,14 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
} else if (x + 1 == length) {
bytes = bytes_left;
bi->bi_offset = sizeof(struct gfs2_meta_header);
- bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
+ bi->bi_start = rgd->rd_bitbytes - bytes_left;
bi->bi_len = bytes;
/* other blocks */
} else {
bytes = sdp->sd_sb.sb_bsize -
sizeof(struct gfs2_meta_header);
bi->bi_offset = sizeof(struct gfs2_meta_header);
- bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
+ bi->bi_start = rgd->rd_bitbytes - bytes_left;
bi->bi_len = bytes;
}
@@ -418,9 +431,9 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
return -EIO;
}
bi = rgd->rd_bits + (length - 1);
- if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_ri.ri_data) {
+ if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_data) {
if (gfs2_consist_rgrpd(rgd)) {
- gfs2_rindex_print(&rgd->rd_ri);
+ gfs2_rindex_print(rgd);
fs_err(sdp, "start=%u len=%u offset=%u\n",
bi->bi_start, bi->bi_len, bi->bi_offset);
}
@@ -431,9 +444,104 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
}
/**
- * gfs2_ri_update - Pull in a new resource index from the disk
+ * gfs2_ri_total - Total up the file system space, according to the rindex.
+ *
+ */
+u64 gfs2_ri_total(struct gfs2_sbd *sdp)
+{
+ u64 total_data = 0;
+ struct inode *inode = sdp->sd_rindex;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ char buf[sizeof(struct gfs2_rindex)];
+ struct file_ra_state ra_state;
+ int error, rgrps;
+
+ mutex_lock(&sdp->sd_rindex_mutex);
+ file_ra_state_init(&ra_state, inode->i_mapping);
+ for (rgrps = 0;; rgrps++) {
+ loff_t pos = rgrps * sizeof(struct gfs2_rindex);
+
+ if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size)
+ break;
+ error = gfs2_internal_read(ip, &ra_state, buf, &pos,
+ sizeof(struct gfs2_rindex));
+ if (error != sizeof(struct gfs2_rindex))
+ break;
+ total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data);
+ }
+ mutex_unlock(&sdp->sd_rindex_mutex);
+ return total_data;
+}
+
+static void gfs2_rindex_in(struct gfs2_rgrpd *rgd, const void *buf)
+{
+ const struct gfs2_rindex *str = buf;
+
+ rgd->rd_addr = be64_to_cpu(str->ri_addr);
+ rgd->rd_length = be32_to_cpu(str->ri_length);
+ rgd->rd_data0 = be64_to_cpu(str->ri_data0);
+ rgd->rd_data = be32_to_cpu(str->ri_data);
+ rgd->rd_bitbytes = be32_to_cpu(str->ri_bitbytes);
+}
+
+/**
+ * read_rindex_entry - Pull in a new resource index entry from the disk
* @gl: The glock covering the rindex inode
*
+ * Returns: 0 on success, error code otherwise
+ */
+
+static int read_rindex_entry(struct gfs2_inode *ip,
+ struct file_ra_state *ra_state)
+{
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
+ char buf[sizeof(struct gfs2_rindex)];
+ int error;
+ struct gfs2_rgrpd *rgd;
+
+ error = gfs2_internal_read(ip, ra_state, buf, &pos,
+ sizeof(struct gfs2_rindex));
+ if (!error)
+ return 0;
+ if (error != sizeof(struct gfs2_rindex)) {
+ if (error > 0)
+ error = -EIO;
+ return error;
+ }
+
+ rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
+ error = -ENOMEM;
+ if (!rgd)
+ return error;
+
+ mutex_init(&rgd->rd_mutex);
+ lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
+ rgd->rd_sbd = sdp;
+
+ list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
+ list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
+
+ gfs2_rindex_in(rgd, buf);
+ error = compute_bitstructs(rgd);
+ if (error)
+ return error;
+
+ error = gfs2_glock_get(sdp, rgd->rd_addr,
+ &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
+ if (error)
+ return error;
+
+ rgd->rd_gl->gl_object = rgd;
+ rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
+ rgd->rd_flags |= GFS2_RDF_CHECK;
+ return error;
+}
+
+/**
+ * gfs2_ri_update - Pull in a new resource index from the disk
+ * @ip: pointer to the rindex inode
+ *
* Returns: 0 on successful update, error code otherwise
*/
@@ -441,13 +549,11 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode;
- struct gfs2_rgrpd *rgd;
- char buf[sizeof(struct gfs2_rindex)];
struct file_ra_state ra_state;
- u64 junk = ip->i_di.di_size;
+ u64 rgrp_count = ip->i_di.di_size;
int error;
- if (do_div(junk, sizeof(struct gfs2_rindex))) {
+ if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) {
gfs2_consist_inode(ip);
return -EIO;
}
@@ -455,50 +561,50 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
clear_rgrpdi(sdp);
file_ra_state_init(&ra_state, inode->i_mapping);
- for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
- loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
- error = gfs2_internal_read(ip, &ra_state, buf, &pos,
- sizeof(struct gfs2_rindex));
- if (!error)
- break;
- if (error != sizeof(struct gfs2_rindex)) {
- if (error > 0)
- error = -EIO;
- goto fail;
+ for (sdp->sd_rgrps = 0; sdp->sd_rgrps < rgrp_count; sdp->sd_rgrps++) {
+ error = read_rindex_entry(ip, &ra_state);
+ if (error) {
+ clear_rgrpdi(sdp);
+ return error;
}
+ }
- rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
- error = -ENOMEM;
- if (!rgd)
- goto fail;
-
- mutex_init(&rgd->rd_mutex);
- lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
- rgd->rd_sbd = sdp;
-
- list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
- list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
-
- gfs2_rindex_in(&rgd->rd_ri, buf);
- error = compute_bitstructs(rgd);
- if (error)
- goto fail;
+ sdp->sd_rindex_vn = ip->i_gl->gl_vn;
+ return 0;
+}
- error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr,
- &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
- if (error)
- goto fail;
+/**
+ * gfs2_ri_update_special - Pull in a new resource index from the disk
+ *
+ * This is a special version that's safe to call from gfs2_inplace_reserve_i.
+ * In this case we know that we don't have any resource groups in memory yet.
+ *
+ * @ip: pointer to the rindex inode
+ *
+ * Returns: 0 on successful update, error code otherwise
+ */
+static int gfs2_ri_update_special(struct gfs2_inode *ip)
+{
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct inode *inode = &ip->i_inode;
+ struct file_ra_state ra_state;
+ int error;
- rgd->rd_gl->gl_object = rgd;
- rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
+ file_ra_state_init(&ra_state, inode->i_mapping);
+ for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
+ /* Ignore partials */
+ if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
+ ip->i_di.di_size)
+ break;
+ error = read_rindex_entry(ip, &ra_state);
+ if (error) {
+ clear_rgrpdi(sdp);
+ return error;
+ }
}
sdp->sd_rindex_vn = ip->i_gl->gl_vn;
return 0;
-
-fail:
- clear_rgrpdi(sdp);
- return error;
}
/**
@@ -543,6 +649,28 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
return error;
}
+static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
+{
+ const struct gfs2_rgrp *str = buf;
+
+ rg->rg_flags = be32_to_cpu(str->rg_flags);
+ rg->rg_free = be32_to_cpu(str->rg_free);
+ rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
+ rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
+}
+
+static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
+{
+ struct gfs2_rgrp *str = buf;
+
+ str->rg_flags = cpu_to_be32(rg->rg_flags);
+ str->rg_free = cpu_to_be32(rg->rg_free);
+ str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
+ str->__pad = cpu_to_be32(0);
+ str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
+ memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
+}
+
/**
* gfs2_rgrp_bh_get - Read in a RG's header and bitmaps
* @rgd: the struct gfs2_rgrpd describing the RG to read in
@@ -557,7 +685,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
struct gfs2_glock *gl = rgd->rd_gl;
- unsigned int length = rgd->rd_ri.ri_length;
+ unsigned int length = rgd->rd_length;
struct gfs2_bitmap *bi;
unsigned int x, y;
int error;
@@ -575,7 +703,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
for (x = 0; x < length; x++) {
bi = rgd->rd_bits + x;
- error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh);
+ error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh);
if (error)
goto fail;
}
@@ -637,7 +765,7 @@ void gfs2_rgrp_bh_hold(struct gfs2_rgrpd *rgd)
void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
- int x, length = rgd->rd_ri.ri_length;
+ int x, length = rgd->rd_length;
spin_lock(&sdp->sd_rindex_spin);
gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count);
@@ -660,7 +788,7 @@ void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd)
void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
- unsigned int length = rgd->rd_ri.ri_length;
+ unsigned int length = rgd->rd_length;
unsigned int x;
for (x = 0; x < length; x++) {
@@ -722,6 +850,38 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
}
/**
+ * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
+ * @rgd: The rgrp
+ *
+ * Returns: The inode, if one has been found
+ */
+
+static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+{
+ struct inode *inode;
+ u32 goal = 0;
+ u64 no_addr;
+
+ for(;;) {
+ goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
+ GFS2_BLKST_UNLINKED);
+ if (goal == 0)
+ return 0;
+ no_addr = goal + rgd->rd_data0;
+ if (no_addr <= *last_unlinked)
+ continue;
+ *last_unlinked = no_addr;
+ inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
+ no_addr, -1);
+ if (!IS_ERR(inode))
+ return inode;
+ }
+
+ rgd->rd_flags &= ~GFS2_RDF_CHECK;
+ return NULL;
+}
+
+/**
* recent_rgrp_first - get first RG from "recent" list
* @sdp: The GFS2 superblock
* @rglast: address of the rgrp used last
@@ -743,7 +903,7 @@ static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp,
goto first;
list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
- if (rgd->rd_ri.ri_addr == rglast)
+ if (rgd->rd_addr == rglast)
goto out;
}
@@ -882,8 +1042,9 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd)
* Returns: errno
*/
-static int get_local_rgrp(struct gfs2_inode *ip)
+static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
{
+ struct inode *inode = NULL;
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd, *begin = NULL;
struct gfs2_alloc *al = &ip->i_alloc;
@@ -903,7 +1064,11 @@ static int get_local_rgrp(struct gfs2_inode *ip)
case 0:
if (try_rgrp_fit(rgd, al))
goto out;
+ if (rgd->rd_flags & GFS2_RDF_CHECK)
+ inode = try_rgrp_unlink(rgd, last_unlinked);
gfs2_glock_dq_uninit(&al->al_rgd_gh);
+ if (inode)
+ return inode;
rgd = recent_rgrp_next(rgd, 1);
break;
@@ -912,7 +1077,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
break;
default:
- return error;
+ return ERR_PTR(error);
}
}
@@ -927,7 +1092,11 @@ static int get_local_rgrp(struct gfs2_inode *ip)
case 0:
if (try_rgrp_fit(rgd, al))
goto out;
+ if (rgd->rd_flags & GFS2_RDF_CHECK)
+ inode = try_rgrp_unlink(rgd, last_unlinked);
gfs2_glock_dq_uninit(&al->al_rgd_gh);
+ if (inode)
+ return inode;
break;
case GLR_TRYFAILED:
@@ -935,7 +1104,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
break;
default:
- return error;
+ return ERR_PTR(error);
}
rgd = gfs2_rgrpd_get_next(rgd);
@@ -944,7 +1113,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
if (rgd == begin) {
if (++loops >= 3)
- return -ENOSPC;
+ return ERR_PTR(-ENOSPC);
if (!skipped)
loops++;
flags = 0;
@@ -954,7 +1123,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
}
out:
- ip->i_last_rg_alloc = rgd->rd_ri.ri_addr;
+ ip->i_last_rg_alloc = rgd->rd_addr;
if (begin) {
recent_rgrp_add(rgd);
@@ -964,7 +1133,7 @@ out:
forward_rgrp_set(sdp, rgd);
}
- return 0;
+ return NULL;
}
/**
@@ -978,19 +1147,33 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
- int error;
+ struct inode *inode;
+ int error = 0;
+ u64 last_unlinked = 0;
if (gfs2_assert_warn(sdp, al->al_requested))
return -EINVAL;
- error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+try_again:
+ /* We need to hold the rindex unless the inode we're using is
+ the rindex itself, in which case it's already held. */
+ if (ip != GFS2_I(sdp->sd_rindex))
+ error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+ else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */
+ error = gfs2_ri_update_special(ip);
+
if (error)
return error;
- error = get_local_rgrp(ip);
- if (error) {
- gfs2_glock_dq_uninit(&al->al_ri_gh);
- return error;
+ inode = get_local_rgrp(ip, &last_unlinked);
+ if (inode) {
+ if (ip != GFS2_I(sdp->sd_rindex))
+ gfs2_glock_dq_uninit(&al->al_ri_gh);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+ iput(inode);
+ gfs2_log_flush(sdp, NULL);
+ goto try_again;
}
al->al_file = file;
@@ -1019,7 +1202,8 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
al->al_rgd = NULL;
gfs2_glock_dq_uninit(&al->al_rgd_gh);
- gfs2_glock_dq_uninit(&al->al_ri_gh);
+ if (ip != GFS2_I(sdp->sd_rindex))
+ gfs2_glock_dq_uninit(&al->al_ri_gh);
}
/**
@@ -1037,8 +1221,8 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
unsigned int buf;
unsigned char type;
- length = rgd->rd_ri.ri_length;
- rgrp_block = block - rgd->rd_ri.ri_data0;
+ length = rgd->rd_length;
+ rgrp_block = block - rgd->rd_data0;
for (buf = 0; buf < length; buf++) {
bi = rgd->rd_bits + buf;
@@ -1077,10 +1261,10 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
*/
static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
- unsigned char old_state, unsigned char new_state)
+ unsigned char old_state, unsigned char new_state)
{
struct gfs2_bitmap *bi = NULL;
- u32 length = rgd->rd_ri.ri_length;
+ u32 length = rgd->rd_length;
u32 blk = 0;
unsigned int buf, x;
@@ -1118,17 +1302,18 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
goal = 0;
}
- if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length))
- blk = 0;
+ if (old_state != new_state) {
+ gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT);
- gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
- gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
- bi->bi_len, blk, new_state);
- if (bi->bi_clone)
- gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+ gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+ gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
bi->bi_len, blk, new_state);
+ if (bi->bi_clone)
+ gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+ bi->bi_len, blk, new_state);
+ }
- return bi->bi_start * GFS2_NBBY + blk;
+ return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk;
}
/**
@@ -1156,9 +1341,9 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
return NULL;
}
- length = rgd->rd_ri.ri_length;
+ length = rgd->rd_length;
- rgrp_blk = bstart - rgd->rd_ri.ri_data0;
+ rgrp_blk = bstart - rgd->rd_data0;
while (blen--) {
for (buf = 0; buf < length; buf++) {
@@ -1202,15 +1387,15 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip)
u32 goal, blk;
u64 block;
- if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_data))
- goal = ip->i_di.di_goal_data - rgd->rd_ri.ri_data0;
+ if (rgrp_contains_block(rgd, ip->i_di.di_goal_data))
+ goal = ip->i_di.di_goal_data - rgd->rd_data0;
else
goal = rgd->rd_last_alloc_data;
blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
rgd->rd_last_alloc_data = blk;
- block = rgd->rd_ri.ri_data0 + blk;
+ block = rgd->rd_data0 + blk;
ip->i_di.di_goal_data = block;
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
@@ -1246,15 +1431,15 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip)
u32 goal, blk;
u64 block;
- if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_meta))
- goal = ip->i_di.di_goal_meta - rgd->rd_ri.ri_data0;
+ if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta))
+ goal = ip->i_di.di_goal_meta - rgd->rd_data0;
else
goal = rgd->rd_last_alloc_meta;
blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
rgd->rd_last_alloc_meta = blk;
- block = rgd->rd_ri.ri_data0 + blk;
+ block = rgd->rd_data0 + blk;
ip->i_di.di_goal_meta = block;
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
@@ -1296,7 +1481,7 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
rgd->rd_last_alloc_meta = blk;
- block = rgd->rd_ri.ri_data0 + blk;
+ block = rgd->rd_data0 + blk;
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
rgd->rd_rg.rg_free--;
@@ -1379,7 +1564,7 @@ void gfs2_unlink_di(struct inode *inode)
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_rgrpd *rgd;
- u64 blkno = ip->i_num.no_addr;
+ u64 blkno = ip->i_no_addr;
rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED);
if (!rgd)
@@ -1414,9 +1599,9 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
{
- gfs2_free_uninit_di(rgd, ip->i_num.no_addr);
+ gfs2_free_uninit_di(rgd, ip->i_no_addr);
gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid);
- gfs2_meta_wipe(ip, ip->i_num.no_addr, 1);
+ gfs2_meta_wipe(ip, ip->i_no_addr, 1);
}
/**
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index b01e0cfc99b5..b4c6adfc6f2e 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -65,5 +65,6 @@ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
int flags);
void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
+u64 gfs2_ri_total(struct gfs2_sbd *sdp);
#endif /* __RGRP_DOT_H__ */
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 4fdda974dc83..f916b9740c75 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -95,8 +95,8 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent)
{
unsigned int x;
- if (sb->sb_header.mh_magic != GFS2_MAGIC ||
- sb->sb_header.mh_type != GFS2_METATYPE_SB) {
+ if (sb->sb_magic != GFS2_MAGIC ||
+ sb->sb_type != GFS2_METATYPE_SB) {
if (!silent)
printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n");
return -EINVAL;
@@ -174,10 +174,31 @@ static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error)
return 0;
}
+static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
+{
+ const struct gfs2_sb *str = buf;
+
+ sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic);
+ sb->sb_type = be32_to_cpu(str->sb_header.mh_type);
+ sb->sb_format = be32_to_cpu(str->sb_header.mh_format);
+ sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
+ sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
+ sb->sb_bsize = be32_to_cpu(str->sb_bsize);
+ sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
+ sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr);
+ sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino);
+ sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr);
+ sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino);
+
+ memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
+ memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
+}
+
/**
* gfs2_read_super - Read the gfs2 super block from disk
- * @sb: The VFS super block
+ * @sdp: The GFS2 super block
* @sector: The location of the super block
+ * @error: The error code to return
*
* This uses the bio functions to read the super block from disk
* because we want to be 100% sure that we never read cached data.
@@ -189,17 +210,19 @@ static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error)
* the master directory (contains pointers to journals etc) and the
* root directory.
*
- * Returns: A page containing the sb or NULL
+ * Returns: 0 on success or error
*/
-struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
+int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
{
+ struct super_block *sb = sdp->sd_vfs;
+ struct gfs2_sb *p;
struct page *page;
struct bio *bio;
page = alloc_page(GFP_KERNEL);
if (unlikely(!page))
- return NULL;
+ return -ENOBUFS;
ClearPageUptodate(page);
ClearPageDirty(page);
@@ -208,7 +231,7 @@ struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
bio = bio_alloc(GFP_KERNEL, 1);
if (unlikely(!bio)) {
__free_page(page);
- return NULL;
+ return -ENOBUFS;
}
bio->bi_sector = sector * (sb->s_blocksize >> 9);
@@ -222,9 +245,13 @@ struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
bio_put(bio);
if (!PageUptodate(page)) {
__free_page(page);
- return NULL;
+ return -EIO;
}
- return page;
+ p = kmap(page);
+ gfs2_sb_in(&sdp->sd_sb, p);
+ kunmap(page);
+ __free_page(page);
+ return 0;
}
/**
@@ -241,19 +268,13 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
u32 tmp_blocks;
unsigned int x;
int error;
- struct page *page;
- char *sb;
- page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
- if (!page) {
+ error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+ if (error) {
if (!silent)
fs_err(sdp, "can't read superblock\n");
- return -EIO;
+ return error;
}
- sb = kmap(page);
- gfs2_sb_in(&sdp->sd_sb, sb);
- kunmap(page);
- __free_page(page);
error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
if (error)
@@ -360,7 +381,7 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
name.len = sprintf(buf, "journal%u", sdp->sd_journals);
name.hash = gfs2_disk_hash(name.name, name.len);
- error = gfs2_dir_search(sdp->sd_jindex, &name, NULL, NULL);
+ error = gfs2_dir_check(sdp->sd_jindex, &name, NULL);
if (error == -ENOENT) {
error = 0;
break;
@@ -593,6 +614,24 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
return error;
}
+static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
+{
+ const struct gfs2_statfs_change *str = buf;
+
+ sc->sc_total = be64_to_cpu(str->sc_total);
+ sc->sc_free = be64_to_cpu(str->sc_free);
+ sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
+}
+
+static void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
+{
+ struct gfs2_statfs_change *str = buf;
+
+ str->sc_total = cpu_to_be64(sc->sc_total);
+ str->sc_free = cpu_to_be64(sc->sc_free);
+ str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
+}
+
int gfs2_statfs_init(struct gfs2_sbd *sdp)
{
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
@@ -772,7 +811,7 @@ static int statfs_slow_fill(struct gfs2_rgrpd *rgd,
struct gfs2_statfs_change_host *sc)
{
gfs2_rgrp_verify(rgd);
- sc->sc_total += rgd->rd_ri.ri_data;
+ sc->sc_total += rgd->rd_data;
sc->sc_free += rgd->rd_rg.rg_free;
sc->sc_dinodes += rgd->rd_rg.rg_dinodes;
return 0;
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
index e590b2df11dc..60a870e430be 100644
--- a/fs/gfs2/super.h
+++ b/fs/gfs2/super.h
@@ -16,7 +16,7 @@ void gfs2_tune_init(struct gfs2_tune *gt);
int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
-struct page *gfs2_read_super(struct super_block *sb, sector_t sector);
+int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector);
static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
{
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 601eaa1b9ed6..424a0774eda8 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -115,8 +115,8 @@ int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide,
"GFS2: fsid=%s: inode = %llu %llu\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n",
sdp->sd_fsname,
- sdp->sd_fsname, (unsigned long long)ip->i_num.no_formal_ino,
- (unsigned long long)ip->i_num.no_addr,
+ sdp->sd_fsname, (unsigned long long)ip->i_no_formal_ino,
+ (unsigned long long)ip->i_no_addr,
sdp->sd_fsname, function, file, line);
return rv;
}
@@ -137,7 +137,7 @@ int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide,
"GFS2: fsid=%s: RG = %llu\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n",
sdp->sd_fsname,
- sdp->sd_fsname, (unsigned long long)rgd->rd_ri.ri_addr,
+ sdp->sd_fsname, (unsigned long long)rgd->rd_addr,
sdp->sd_fsname, function, file, line);
return rv;
}
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 9a934db0bd8a..bc835f272a6e 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -607,7 +607,7 @@ static const struct file_operations hfs_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.fsync = file_fsync,
.open = hfs_file_open,
.release = hfs_file_release,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 45dab5d6cc10..409ce5429c91 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -288,7 +288,7 @@ static const struct file_operations hfsplus_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.fsync = file_fsync,
.open = hfsplus_file_open,
.release = hfsplus_file_release,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 8286491dbf31..c77862032e84 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -390,7 +390,7 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
static const struct file_operations hostfs_file_fops = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.write = do_sync_write,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index b4eafc0f1e54..5b53e5c5d8df 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -129,7 +129,7 @@ const struct file_operations hpfs_file_ops =
.mmap = generic_file_mmap,
.release = hpfs_file_release,
.fsync = hpfs_file_fsync,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations hpfs_file_iops =
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 99871279a1ed..c2530197be0c 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -47,7 +47,7 @@ const struct file_operations jffs2_file_operations =
.ioctl = jffs2_ioctl,
.mmap = generic_file_readonly_mmap,
.fsync = jffs2_fsync,
- .sendfile = generic_file_sendfile
+ .splice_read = generic_file_splice_read,
};
/* jffs2_file_inode_operations */
diff --git a/fs/jfs/endian24.h b/fs/jfs/endian24.h
index 79494c4f2b10..fa92f7f1d0d0 100644
--- a/fs/jfs/endian24.h
+++ b/fs/jfs/endian24.h
@@ -29,7 +29,7 @@
__u32 __x = (x); \
((__u32)( \
((__x & (__u32)0x000000ffUL) << 16) | \
- (__x & (__u32)0x0000ff00UL) | \
+ (__x & (__u32)0x0000ff00UL) | \
((__x & (__u32)0x00ff0000UL) >> 16) )); \
})
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index f7f8eff19b7b..87eb93694af7 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -108,7 +108,6 @@ const struct file_operations jfs_file_operations = {
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
.fsync = jfs_fsync,
diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
index 9c5d59632aac..887f5759e536 100644
--- a/fs/jfs/jfs_debug.c
+++ b/fs/jfs/jfs_debug.c
@@ -26,34 +26,6 @@
#include "jfs_filsys.h"
#include "jfs_debug.h"
-#ifdef CONFIG_JFS_DEBUG
-void dump_mem(char *label, void *data, int length)
-{
- int i, j;
- int *intptr = data;
- char *charptr = data;
- char buf[10], line[80];
-
- printk("%s: dump of %d bytes of data at 0x%p\n\n", label, length,
- data);
- for (i = 0; i < length; i += 16) {
- line[0] = 0;
- for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
- sprintf(buf, " %08x", intptr[i / 4 + j]);
- strcat(line, buf);
- }
- buf[0] = ' ';
- buf[2] = 0;
- for (j = 0; (j < 16) && (i + j < length); j++) {
- buf[1] =
- isprint(charptr[i + j]) ? charptr[i + j] : '.';
- strcat(line, buf);
- }
- printk("%s\n", line);
- }
-}
-#endif
-
#ifdef PROC_FS_JFS /* see jfs_debug.h */
static struct proc_dir_entry *base;
diff --git a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
index 7378798f0b21..044c1e654cc0 100644
--- a/fs/jfs/jfs_debug.h
+++ b/fs/jfs/jfs_debug.h
@@ -62,7 +62,6 @@ extern void jfs_proc_clean(void);
extern int jfsloglevel;
-extern void dump_mem(char *label, void *data, int length);
extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
/* information message: e.g., configuration, major event */
@@ -94,7 +93,6 @@ extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
* ---------
*/
#else /* CONFIG_JFS_DEBUG */
-#define dump_mem(label,data,length) do {} while (0)
#define ASSERT(p) do {} while (0)
#define jfs_info(fmt, arg...) do {} while (0)
#define jfs_debug(fmt, arg...) do {} while (0)
diff --git a/fs/jfs/jfs_dinode.h b/fs/jfs/jfs_dinode.h
index 40b20111383c..c387540d3425 100644
--- a/fs/jfs/jfs_dinode.h
+++ b/fs/jfs/jfs_dinode.h
@@ -19,23 +19,23 @@
#define _H_JFS_DINODE
/*
- * jfs_dinode.h: on-disk inode manager
+ * jfs_dinode.h: on-disk inode manager
*/
-#define INODESLOTSIZE 128
-#define L2INODESLOTSIZE 7
-#define log2INODESIZE 9 /* log2(bytes per dinode) */
+#define INODESLOTSIZE 128
+#define L2INODESLOTSIZE 7
+#define log2INODESIZE 9 /* log2(bytes per dinode) */
/*
- * on-disk inode : 512 bytes
+ * on-disk inode : 512 bytes
*
* note: align 64-bit fields on 8-byte boundary.
*/
struct dinode {
/*
- * I. base area (128 bytes)
- * ------------------------
+ * I. base area (128 bytes)
+ * ------------------------
*
* define generic/POSIX attributes
*/
@@ -70,16 +70,16 @@ struct dinode {
__le32 di_acltype; /* 4: Type of ACL */
/*
- * Extension Areas.
+ * Extension Areas.
*
- * Historically, the inode was partitioned into 4 128-byte areas,
- * the last 3 being defined as unions which could have multiple
- * uses. The first 96 bytes had been completely unused until
- * an index table was added to the directory. It is now more
- * useful to describe the last 3/4 of the inode as a single
- * union. We would probably be better off redesigning the
- * entire structure from scratch, but we don't want to break
- * commonality with OS/2's JFS at this time.
+ * Historically, the inode was partitioned into 4 128-byte areas,
+ * the last 3 being defined as unions which could have multiple
+ * uses. The first 96 bytes had been completely unused until
+ * an index table was added to the directory. It is now more
+ * useful to describe the last 3/4 of the inode as a single
+ * union. We would probably be better off redesigning the
+ * entire structure from scratch, but we don't want to break
+ * commonality with OS/2's JFS at this time.
*/
union {
struct {
@@ -95,7 +95,7 @@ struct dinode {
} _dir; /* (384) */
#define di_dirtable u._dir._table
#define di_dtroot u._dir._dtroot
-#define di_parent di_dtroot.header.idotdot
+#define di_parent di_dtroot.header.idotdot
#define di_DASD di_dtroot.header.DASD
struct {
@@ -127,14 +127,14 @@ struct dinode {
#define di_inlinedata u._file._u2._special._u
#define di_rdev u._file._u2._special._u._rdev
#define di_fastsymlink u._file._u2._special._u._fastsymlink
-#define di_inlineea u._file._u2._special._inlineea
+#define di_inlineea u._file._u2._special._inlineea
} u;
};
/* extended mode bits (on-disk inode di_mode) */
-#define IFJOURNAL 0x00010000 /* journalled file */
-#define ISPARSE 0x00020000 /* sparse file enabled */
-#define INLINEEA 0x00040000 /* inline EA area free */
+#define IFJOURNAL 0x00010000 /* journalled file */
+#define ISPARSE 0x00020000 /* sparse file enabled */
+#define INLINEEA 0x00040000 /* inline EA area free */
#define ISWAPFILE 0x00800000 /* file open for pager swap space */
/* more extended mode bits: attributes for OS/2 */
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index f3b1ebb22280..e1985066b1c6 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -154,12 +154,12 @@ static const s8 budtab[256] = {
* the in-core descriptor is initialized from disk.
*
* PARAMETERS:
- * ipbmap - pointer to in-core inode for the block map.
+ * ipbmap - pointer to in-core inode for the block map.
*
* RETURN VALUES:
- * 0 - success
- * -ENOMEM - insufficient memory
- * -EIO - i/o error
+ * 0 - success
+ * -ENOMEM - insufficient memory
+ * -EIO - i/o error
*/
int dbMount(struct inode *ipbmap)
{
@@ -232,11 +232,11 @@ int dbMount(struct inode *ipbmap)
* the memory for this descriptor is freed.
*
* PARAMETERS:
- * ipbmap - pointer to in-core inode for the block map.
+ * ipbmap - pointer to in-core inode for the block map.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*/
int dbUnmount(struct inode *ipbmap, int mounterror)
{
@@ -320,13 +320,13 @@ int dbSync(struct inode *ipbmap)
* at a time.
*
* PARAMETERS:
- * ip - pointer to in-core inode;
- * blkno - starting block number to be freed.
- * nblocks - number of blocks to be freed.
+ * ip - pointer to in-core inode;
+ * blkno - starting block number to be freed.
+ * nblocks - number of blocks to be freed.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*/
int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
{
@@ -395,23 +395,23 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
/*
* NAME: dbUpdatePMap()
*
- * FUNCTION: update the allocation state (free or allocate) of the
+ * FUNCTION: update the allocation state (free or allocate) of the
* specified block range in the persistent block allocation map.
*
* the blocks will be updated in the persistent map one
* dmap at a time.
*
* PARAMETERS:
- * ipbmap - pointer to in-core inode for the block map.
- * free - 'true' if block range is to be freed from the persistent
- * map; 'false' if it is to be allocated.
- * blkno - starting block number of the range.
- * nblocks - number of contiguous blocks in the range.
- * tblk - transaction block;
+ * ipbmap - pointer to in-core inode for the block map.
+ * free - 'true' if block range is to be freed from the persistent
+ * map; 'false' if it is to be allocated.
+ * blkno - starting block number of the range.
+ * nblocks - number of contiguous blocks in the range.
+ * tblk - transaction block;
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*/
int
dbUpdatePMap(struct inode *ipbmap,
@@ -573,7 +573,7 @@ dbUpdatePMap(struct inode *ipbmap,
/*
* NAME: dbNextAG()
*
- * FUNCTION: find the preferred allocation group for new allocations.
+ * FUNCTION: find the preferred allocation group for new allocations.
*
* Within the allocation groups, we maintain a preferred
* allocation group which consists of a group with at least
@@ -589,10 +589,10 @@ dbUpdatePMap(struct inode *ipbmap,
* empty ags around for large allocations.
*
* PARAMETERS:
- * ipbmap - pointer to in-core inode for the block map.
+ * ipbmap - pointer to in-core inode for the block map.
*
* RETURN VALUES:
- * the preferred allocation group number.
+ * the preferred allocation group number.
*/
int dbNextAG(struct inode *ipbmap)
{
@@ -656,7 +656,7 @@ unlock:
/*
* NAME: dbAlloc()
*
- * FUNCTION: attempt to allocate a specified number of contiguous free
+ * FUNCTION: attempt to allocate a specified number of contiguous free
* blocks from the working allocation block map.
*
* the block allocation policy uses hints and a multi-step
@@ -680,16 +680,16 @@ unlock:
* size or requests that specify no hint value.
*
* PARAMETERS:
- * ip - pointer to in-core inode;
- * hint - allocation hint.
- * nblocks - number of contiguous blocks in the range.
- * results - on successful return, set to the starting block number
+ * ip - pointer to in-core inode;
+ * hint - allocation hint.
+ * nblocks - number of contiguous blocks in the range.
+ * results - on successful return, set to the starting block number
* of the newly allocated contiguous range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*/
int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
{
@@ -706,12 +706,6 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
/* assert that nblocks is valid */
assert(nblocks > 0);
-#ifdef _STILL_TO_PORT
- /* DASD limit check F226941 */
- if (OVER_LIMIT(ip, nblocks))
- return -ENOSPC;
-#endif /* _STILL_TO_PORT */
-
/* get the log2 number of blocks to be allocated.
* if the number of blocks is not a log2 multiple,
* it will be rounded up to the next log2 multiple.
@@ -720,7 +714,6 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
bmp = JFS_SBI(ip->i_sb)->bmap;
-//retry: /* serialize w.r.t.extendfs() */
mapSize = bmp->db_mapsize;
/* the hint should be within the map */
@@ -879,17 +872,17 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
/*
* NAME: dbAllocExact()
*
- * FUNCTION: try to allocate the requested extent;
+ * FUNCTION: try to allocate the requested extent;
*
* PARAMETERS:
- * ip - pointer to in-core inode;
- * blkno - extent address;
- * nblocks - extent length;
+ * ip - pointer to in-core inode;
+ * blkno - extent address;
+ * nblocks - extent length;
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*/
int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
{
@@ -946,7 +939,7 @@ int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
/*
* NAME: dbReAlloc()
*
- * FUNCTION: attempt to extend a current allocation by a specified
+ * FUNCTION: attempt to extend a current allocation by a specified
* number of blocks.
*
* this routine attempts to satisfy the allocation request
@@ -959,21 +952,21 @@ int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
* number of blocks required.
*
* PARAMETERS:
- * ip - pointer to in-core inode requiring allocation.
- * blkno - starting block of the current allocation.
- * nblocks - number of contiguous blocks within the current
+ * ip - pointer to in-core inode requiring allocation.
+ * blkno - starting block of the current allocation.
+ * nblocks - number of contiguous blocks within the current
* allocation.
- * addnblocks - number of blocks to add to the allocation.
- * results - on successful return, set to the starting block number
+ * addnblocks - number of blocks to add to the allocation.
+ * results - on successful return, set to the starting block number
* of the existing allocation if the existing allocation
* was extended in place or to a newly allocated contiguous
* range if the existing allocation could not be extended
* in place.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*/
int
dbReAlloc(struct inode *ip,
@@ -1004,7 +997,7 @@ dbReAlloc(struct inode *ip,
/*
* NAME: dbExtend()
*
- * FUNCTION: attempt to extend a current allocation by a specified
+ * FUNCTION: attempt to extend a current allocation by a specified
* number of blocks.
*
* this routine attempts to satisfy the allocation request
@@ -1013,16 +1006,16 @@ dbReAlloc(struct inode *ip,
* immediately following the current allocation.
*
* PARAMETERS:
- * ip - pointer to in-core inode requiring allocation.
- * blkno - starting block of the current allocation.
- * nblocks - number of contiguous blocks within the current
+ * ip - pointer to in-core inode requiring allocation.
+ * blkno - starting block of the current allocation.
+ * nblocks - number of contiguous blocks within the current
* allocation.
- * addnblocks - number of blocks to add to the allocation.
+ * addnblocks - number of blocks to add to the allocation.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*/
static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
{
@@ -1109,19 +1102,19 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
/*
* NAME: dbAllocNext()
*
- * FUNCTION: attempt to allocate the blocks of the specified block
+ * FUNCTION: attempt to allocate the blocks of the specified block
* range within a dmap.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap.
- * blkno - starting block number of the range.
- * nblocks - number of contiguous free blocks of the range.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap.
+ * blkno - starting block number of the range.
+ * nblocks - number of contiguous free blocks of the range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) held on entry/exit;
*/
@@ -1233,7 +1226,7 @@ static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno,
/*
* NAME: dbAllocNear()
*
- * FUNCTION: attempt to allocate a number of contiguous free blocks near
+ * FUNCTION: attempt to allocate a number of contiguous free blocks near
* a specified block (hint) within a dmap.
*
* starting with the dmap leaf that covers the hint, we'll
@@ -1242,18 +1235,18 @@ static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno,
* the desired free space.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap.
- * blkno - block number to allocate near.
- * nblocks - actual number of contiguous free blocks desired.
- * l2nb - log2 number of contiguous free blocks desired.
- * results - on successful return, set to the starting block number
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap.
+ * blkno - block number to allocate near.
+ * nblocks - actual number of contiguous free blocks desired.
+ * l2nb - log2 number of contiguous free blocks desired.
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) held on entry/exit;
*/
@@ -1316,7 +1309,7 @@ dbAllocNear(struct bmap * bmp,
/*
* NAME: dbAllocAG()
*
- * FUNCTION: attempt to allocate the specified number of contiguous
+ * FUNCTION: attempt to allocate the specified number of contiguous
* free blocks within the specified allocation group.
*
* unless the allocation group size is equal to the number
@@ -1353,17 +1346,17 @@ dbAllocNear(struct bmap * bmp,
* the allocation group.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
+ * bmp - pointer to bmap descriptor
* agno - allocation group number.
- * nblocks - actual number of contiguous free blocks desired.
- * l2nb - log2 number of contiguous free blocks desired.
- * results - on successful return, set to the starting block number
+ * nblocks - actual number of contiguous free blocks desired.
+ * l2nb - log2 number of contiguous free blocks desired.
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* note: IWRITE_LOCK(ipmap) held on entry/exit;
*/
@@ -1546,7 +1539,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
/*
* NAME: dbAllocAny()
*
- * FUNCTION: attempt to allocate the specified number of contiguous
+ * FUNCTION: attempt to allocate the specified number of contiguous
* free blocks anywhere in the file system.
*
* dbAllocAny() attempts to find the sufficient free space by
@@ -1556,16 +1549,16 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
* desired free space is allocated.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * nblocks - actual number of contiguous free blocks desired.
- * l2nb - log2 number of contiguous free blocks desired.
- * results - on successful return, set to the starting block number
+ * bmp - pointer to bmap descriptor
+ * nblocks - actual number of contiguous free blocks desired.
+ * l2nb - log2 number of contiguous free blocks desired.
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -1598,9 +1591,9 @@ static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results)
/*
* NAME: dbFindCtl()
*
- * FUNCTION: starting at a specified dmap control page level and block
+ * FUNCTION: starting at a specified dmap control page level and block
* number, search down the dmap control levels for a range of
- * contiguous free blocks large enough to satisfy an allocation
+ * contiguous free blocks large enough to satisfy an allocation
* request for the specified number of free blocks.
*
* if sufficient contiguous free blocks are found, this routine
@@ -1609,17 +1602,17 @@ static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results)
* is sufficient in size.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * level - starting dmap control page level.
- * l2nb - log2 number of contiguous free blocks desired.
- * *blkno - on entry, starting block number for conducting the search.
+ * bmp - pointer to bmap descriptor
+ * level - starting dmap control page level.
+ * l2nb - log2 number of contiguous free blocks desired.
+ * *blkno - on entry, starting block number for conducting the search.
* on successful return, the first block within a dmap page
* that contains or starts a range of contiguous free blocks.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -1699,7 +1692,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
/*
* NAME: dbAllocCtl()
*
- * FUNCTION: attempt to allocate a specified number of contiguous
+ * FUNCTION: attempt to allocate a specified number of contiguous
* blocks starting within a specific dmap.
*
* this routine is called by higher level routines that search
@@ -1726,18 +1719,18 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
* first dmap (i.e. blkno).
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * nblocks - actual number of contiguous free blocks to allocate.
- * l2nb - log2 number of contiguous free blocks to allocate.
- * blkno - starting block number of the dmap to start the allocation
+ * bmp - pointer to bmap descriptor
+ * nblocks - actual number of contiguous free blocks to allocate.
+ * l2nb - log2 number of contiguous free blocks to allocate.
+ * blkno - starting block number of the dmap to start the allocation
* from.
- * results - on successful return, set to the starting block number
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -1870,7 +1863,7 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
/*
* NAME: dbAllocDmapLev()
*
- * FUNCTION: attempt to allocate a specified number of contiguous blocks
+ * FUNCTION: attempt to allocate a specified number of contiguous blocks
* from a specified dmap.
*
* this routine checks if the contiguous blocks are available.
@@ -1878,17 +1871,17 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
* returned.
*
* PARAMETERS:
- * mp - pointer to bmap descriptor
- * dp - pointer to dmap to attempt to allocate blocks from.
- * l2nb - log2 number of contiguous block desired.
- * nblocks - actual number of contiguous block desired.
- * results - on successful return, set to the starting block number
+ * mp - pointer to bmap descriptor
+ * dp - pointer to dmap to attempt to allocate blocks from.
+ * l2nb - log2 number of contiguous block desired.
+ * nblocks - actual number of contiguous block desired.
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap), e.g., from dbAlloc(), or
* IWRITE_LOCK(ipbmap), e.g., dbAllocCtl(), held on entry/exit;
@@ -1933,7 +1926,7 @@ dbAllocDmapLev(struct bmap * bmp,
/*
* NAME: dbAllocDmap()
*
- * FUNCTION: adjust the disk allocation map to reflect the allocation
+ * FUNCTION: adjust the disk allocation map to reflect the allocation
* of a specified block range within a dmap.
*
* this routine allocates the specified blocks from the dmap
@@ -1946,14 +1939,14 @@ dbAllocDmapLev(struct bmap * bmp,
* covers this dmap.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap to allocate the block range from.
- * blkno - starting block number of the block to be allocated.
- * nblocks - number of blocks to be allocated.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap to allocate the block range from.
+ * blkno - starting block number of the block to be allocated.
+ * nblocks - number of blocks to be allocated.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -1989,7 +1982,7 @@ static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
/*
* NAME: dbFreeDmap()
*
- * FUNCTION: adjust the disk allocation map to reflect the allocation
+ * FUNCTION: adjust the disk allocation map to reflect the allocation
* of a specified block range within a dmap.
*
* this routine frees the specified blocks from the dmap through
@@ -1997,18 +1990,18 @@ static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
* causes the maximum string of free blocks within the dmap to
* change (i.e. the value of the root of the dmap's dmtree), this
* routine will cause this change to be reflected up through the
- * appropriate levels of the dmap control pages by a call to
+ * appropriate levels of the dmap control pages by a call to
* dbAdjCtl() for the L0 dmap control page that covers this dmap.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap to free the block range from.
- * blkno - starting block number of the block to be freed.
- * nblocks - number of blocks to be freed.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap to free the block range from.
+ * blkno - starting block number of the block to be freed.
+ * nblocks - number of blocks to be freed.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -2055,7 +2048,7 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
/*
* NAME: dbAllocBits()
*
- * FUNCTION: allocate a specified block range from a dmap.
+ * FUNCTION: allocate a specified block range from a dmap.
*
* this routine updates the dmap to reflect the working
* state allocation of the specified block range. it directly
@@ -2065,10 +2058,10 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
* dmap's dmtree, as a whole, to reflect the allocated range.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap to allocate bits from.
- * blkno - starting block number of the bits to be allocated.
- * nblocks - number of bits to be allocated.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap to allocate bits from.
+ * blkno - starting block number of the bits to be allocated.
+ * nblocks - number of bits to be allocated.
*
* RETURN VALUES: none
*
@@ -2149,7 +2142,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
* the allocated words.
*/
for (; nwords > 0; nwords -= nw) {
- if (leaf[word] < BUDMIN) {
+ if (leaf[word] < BUDMIN) {
jfs_error(bmp->db_ipbmap->i_sb,
"dbAllocBits: leaf page "
"corrupt");
@@ -2202,7 +2195,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
/*
* NAME: dbFreeBits()
*
- * FUNCTION: free a specified block range from a dmap.
+ * FUNCTION: free a specified block range from a dmap.
*
* this routine updates the dmap to reflect the working
* state allocation of the specified block range. it directly
@@ -2212,10 +2205,10 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
* dmtree, as a whole, to reflect the deallocated range.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap to free bits from.
- * blkno - starting block number of the bits to be freed.
- * nblocks - number of bits to be freed.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap to free bits from.
+ * blkno - starting block number of the bits to be freed.
+ * nblocks - number of bits to be freed.
*
* RETURN VALUES: 0 for success
*
@@ -2388,19 +2381,19 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
* the new root value and the next dmap control page level to
* be adjusted.
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * blkno - the first block of a block range within a dmap. it is
+ * bmp - pointer to bmap descriptor
+ * blkno - the first block of a block range within a dmap. it is
* the allocation or deallocation of this block range that
* requires the dmap control page to be adjusted.
- * newval - the new value of the lower level dmap or dmap control
+ * newval - the new value of the lower level dmap or dmap control
* page root.
- * alloc - 'true' if adjustment is due to an allocation.
- * level - current level of dmap control page (i.e. L0, L1, L2) to
+ * alloc - 'true' if adjustment is due to an allocation.
+ * level - current level of dmap control page (i.e. L0, L1, L2) to
* be adjusted.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -2544,16 +2537,16 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
/*
* NAME: dbSplit()
*
- * FUNCTION: update the leaf of a dmtree with a new value, splitting
+ * FUNCTION: update the leaf of a dmtree with a new value, splitting
* the leaf from the binary buddy system of the dmtree's
* leaves, as required.
*
* PARAMETERS:
- * tp - pointer to the tree containing the leaf.
- * leafno - the number of the leaf to be updated.
- * splitsz - the size the binary buddy system starting at the leaf
+ * tp - pointer to the tree containing the leaf.
+ * leafno - the number of the leaf to be updated.
+ * splitsz - the size the binary buddy system starting at the leaf
* must be split to, specified as the log2 number of blocks.
- * newval - the new value for the leaf.
+ * newval - the new value for the leaf.
*
* RETURN VALUES: none
*
@@ -2600,7 +2593,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
/*
* NAME: dbBackSplit()
*
- * FUNCTION: back split the binary buddy system of dmtree leaves
+ * FUNCTION: back split the binary buddy system of dmtree leaves
* that hold a specified leaf until the specified leaf
* starts its own binary buddy system.
*
@@ -2617,8 +2610,8 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
* in which a previous join operation must be backed out.
*
* PARAMETERS:
- * tp - pointer to the tree containing the leaf.
- * leafno - the number of the leaf to be updated.
+ * tp - pointer to the tree containing the leaf.
+ * leafno - the number of the leaf to be updated.
*
* RETURN VALUES: none
*
@@ -2692,14 +2685,14 @@ static int dbBackSplit(dmtree_t * tp, int leafno)
/*
* NAME: dbJoin()
*
- * FUNCTION: update the leaf of a dmtree with a new value, joining
+ * FUNCTION: update the leaf of a dmtree with a new value, joining
* the leaf with other leaves of the dmtree into a multi-leaf
* binary buddy system, as required.
*
* PARAMETERS:
- * tp - pointer to the tree containing the leaf.
- * leafno - the number of the leaf to be updated.
- * newval - the new value for the leaf.
+ * tp - pointer to the tree containing the leaf.
+ * leafno - the number of the leaf to be updated.
+ * newval - the new value for the leaf.
*
* RETURN VALUES: none
*/
@@ -2785,15 +2778,15 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
/*
* NAME: dbAdjTree()
*
- * FUNCTION: update a leaf of a dmtree with a new value, adjusting
+ * FUNCTION: update a leaf of a dmtree with a new value, adjusting
* the dmtree, as required, to reflect the new leaf value.
* the combination of any buddies must already be done before
* this is called.
*
* PARAMETERS:
- * tp - pointer to the tree to be adjusted.
- * leafno - the number of the leaf to be updated.
- * newval - the new value for the leaf.
+ * tp - pointer to the tree to be adjusted.
+ * leafno - the number of the leaf to be updated.
+ * newval - the new value for the leaf.
*
* RETURN VALUES: none
*/
@@ -2852,7 +2845,7 @@ static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
/*
* NAME: dbFindLeaf()
*
- * FUNCTION: search a dmtree_t for sufficient free blocks, returning
+ * FUNCTION: search a dmtree_t for sufficient free blocks, returning
* the index of a leaf describing the free blocks if
* sufficient free blocks are found.
*
@@ -2861,15 +2854,15 @@ static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
* free space.
*
* PARAMETERS:
- * tp - pointer to the tree to be searched.
- * l2nb - log2 number of free blocks to search for.
+ * tp - pointer to the tree to be searched.
+ * l2nb - log2 number of free blocks to search for.
* leafidx - return pointer to be set to the index of the leaf
* describing at least l2nb free blocks if sufficient
* free blocks are found.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient free blocks.
+ * 0 - success
+ * -ENOSPC - insufficient free blocks.
*/
static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
{
@@ -2916,18 +2909,18 @@ static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
/*
* NAME: dbFindBits()
*
- * FUNCTION: find a specified number of binary buddy free bits within a
+ * FUNCTION: find a specified number of binary buddy free bits within a
* dmap bitmap word value.
*
* this routine searches the bitmap value for (1 << l2nb) free
* bits at (1 << l2nb) alignments within the value.
*
* PARAMETERS:
- * word - dmap bitmap word value.
- * l2nb - number of free bits specified as a log2 number.
+ * word - dmap bitmap word value.
+ * l2nb - number of free bits specified as a log2 number.
*
* RETURN VALUES:
- * starting bit number of free bits.
+ * starting bit number of free bits.
*/
static int dbFindBits(u32 word, int l2nb)
{
@@ -2963,14 +2956,14 @@ static int dbFindBits(u32 word, int l2nb)
/*
* NAME: dbMaxBud(u8 *cp)
*
- * FUNCTION: determine the largest binary buddy string of free
+ * FUNCTION: determine the largest binary buddy string of free
* bits within 32-bits of the map.
*
* PARAMETERS:
- * cp - pointer to the 32-bit value.
+ * cp - pointer to the 32-bit value.
*
* RETURN VALUES:
- * largest binary buddy of free bits within a dmap word.
+ * largest binary buddy of free bits within a dmap word.
*/
static int dbMaxBud(u8 * cp)
{
@@ -3000,14 +2993,14 @@ static int dbMaxBud(u8 * cp)
/*
* NAME: cnttz(uint word)
*
- * FUNCTION: determine the number of trailing zeros within a 32-bit
+ * FUNCTION: determine the number of trailing zeros within a 32-bit
* value.
*
* PARAMETERS:
- * value - 32-bit value to be examined.
+ * value - 32-bit value to be examined.
*
* RETURN VALUES:
- * count of trailing zeros
+ * count of trailing zeros
*/
static int cnttz(u32 word)
{
@@ -3025,14 +3018,14 @@ static int cnttz(u32 word)
/*
* NAME: cntlz(u32 value)
*
- * FUNCTION: determine the number of leading zeros within a 32-bit
+ * FUNCTION: determine the number of leading zeros within a 32-bit
* value.
*
* PARAMETERS:
- * value - 32-bit value to be examined.
+ * value - 32-bit value to be examined.
*
* RETURN VALUES:
- * count of leading zeros
+ * count of leading zeros
*/
static int cntlz(u32 value)
{
@@ -3050,14 +3043,14 @@ static int cntlz(u32 value)
* NAME: blkstol2(s64 nb)
*
* FUNCTION: convert a block count to its log2 value. if the block
- * count is not a l2 multiple, it is rounded up to the next
+ * count is not a l2 multiple, it is rounded up to the next
* larger l2 multiple.
*
* PARAMETERS:
- * nb - number of blocks
+ * nb - number of blocks
*
* RETURN VALUES:
- * log2 number of blocks
+ * log2 number of blocks
*/
static int blkstol2(s64 nb)
{
@@ -3099,13 +3092,13 @@ static int blkstol2(s64 nb)
* at a time.
*
* PARAMETERS:
- * ip - pointer to in-core inode;
- * blkno - starting block number to be freed.
- * nblocks - number of blocks to be freed.
+ * ip - pointer to in-core inode;
+ * blkno - starting block number to be freed.
+ * nblocks - number of blocks to be freed.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*/
int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks)
{
@@ -3278,10 +3271,10 @@ static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
* L2
* |
* L1---------------------------------L1
- * | |
- * L0---------L0---------L0 L0---------L0---------L0
- * | | | | | |
- * d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,.,dm;
+ * | |
+ * L0---------L0---------L0 L0---------L0---------L0
+ * | | | | | |
+ * d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,.,dm;
* L2L1L0d0,...,dnL0d0,...,dnL0d0,...,dnL1L0d0,...,dnL0d0,...,dnL0d0,..dm
*
* <---old---><----------------------------extend----------------------->
@@ -3307,7 +3300,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
(long long) blkno, (long long) nblocks, (long long) newsize);
/*
- * initialize bmap control page.
+ * initialize bmap control page.
*
* all the data in bmap control page should exclude
* the mkfs hidden dmap page.
@@ -3330,7 +3323,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
bmp->db_numag += ((u32) newsize % (u32) bmp->db_agsize) ? 1 : 0;
/*
- * reconfigure db_agfree[]
+ * reconfigure db_agfree[]
* from old AG configuration to new AG configuration;
*
* coalesce contiguous k (newAGSize/oldAGSize) AGs;
@@ -3362,7 +3355,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
bmp->db_maxag = bmp->db_maxag / k;
/*
- * extend bmap
+ * extend bmap
*
* update bit maps and corresponding level control pages;
* global control page db_nfree, db_agfree[agno], db_maxfreebud;
@@ -3410,7 +3403,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
/* compute start L0 */
j = 0;
l1leaf = l1dcp->stree + CTLLEAFIND;
- p += nbperpage; /* 1st L0 of L1.k */
+ p += nbperpage; /* 1st L0 of L1.k */
}
/*
@@ -3548,7 +3541,7 @@ errout:
return -EIO;
/*
- * finalize bmap control page
+ * finalize bmap control page
*/
finalize:
@@ -3567,7 +3560,7 @@ void dbFinalizeBmap(struct inode *ipbmap)
int i, n;
/*
- * finalize bmap control page
+ * finalize bmap control page
*/
//finalize:
/*
@@ -3953,8 +3946,8 @@ static int dbGetL2AGSize(s64 nblocks)
* convert number of map pages to the zero origin top dmapctl level
*/
#define BMAPPGTOLEV(npages) \
- (((npages) <= 3 + MAXL0PAGES) ? 0 \
- : ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
+ (((npages) <= 3 + MAXL0PAGES) ? 0 : \
+ ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
s64 dbMapFileSizeToMapSize(struct inode * ipbmap)
{
@@ -3981,8 +3974,8 @@ s64 dbMapFileSizeToMapSize(struct inode * ipbmap)
factor =
(i == 2) ? MAXL1PAGES : ((i == 1) ? MAXL0PAGES : 1);
complete = (u32) npages / factor;
- ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL
- : ((i == 1) ? LPERCTL : 1));
+ ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL :
+ ((i == 1) ? LPERCTL : 1));
/* pages in last/incomplete child */
npages = (u32) npages % factor;
diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
index 45ea454c74bd..11e6d471b364 100644
--- a/fs/jfs/jfs_dmap.h
+++ b/fs/jfs/jfs_dmap.h
@@ -83,7 +83,7 @@ static __inline signed char TREEMAX(signed char *cp)
* - 1 is added to account for the control page of the map.
*/
#define BLKTODMAP(b,s) \
- ((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
+ ((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
/*
* convert disk block number to the logical block number of the LEVEL 0
@@ -98,7 +98,7 @@ static __inline signed char TREEMAX(signed char *cp)
* - 1 is added to account for the control page of the map.
*/
#define BLKTOL0(b,s) \
- (((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
+ (((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
/*
* convert disk block number to the logical block number of the LEVEL 1
@@ -120,7 +120,7 @@ static __inline signed char TREEMAX(signed char *cp)
* at the specified level which describes the disk block.
*/
#define BLKTOCTL(b,s,l) \
- (((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
+ (((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
/*
* convert aggregate map size to the zero origin dmapctl level of the
@@ -145,27 +145,27 @@ static __inline signed char TREEMAX(signed char *cp)
* dmaptree must be consistent with dmapctl.
*/
struct dmaptree {
- __le32 nleafs; /* 4: number of tree leafs */
- __le32 l2nleafs; /* 4: l2 number of tree leafs */
- __le32 leafidx; /* 4: index of first tree leaf */
- __le32 height; /* 4: height of the tree */
+ __le32 nleafs; /* 4: number of tree leafs */
+ __le32 l2nleafs; /* 4: l2 number of tree leafs */
+ __le32 leafidx; /* 4: index of first tree leaf */
+ __le32 height; /* 4: height of the tree */
s8 budmin; /* 1: min l2 tree leaf value to combine */
- s8 stree[TREESIZE]; /* TREESIZE: tree */
- u8 pad[2]; /* 2: pad to word boundary */
-}; /* - 360 - */
+ s8 stree[TREESIZE]; /* TREESIZE: tree */
+ u8 pad[2]; /* 2: pad to word boundary */
+}; /* - 360 - */
/*
* dmap page per 8K blocks bitmap
*/
struct dmap {
- __le32 nblocks; /* 4: num blks covered by this dmap */
- __le32 nfree; /* 4: num of free blks in this dmap */
- __le64 start; /* 8: starting blkno for this dmap */
- struct dmaptree tree; /* 360: dmap tree */
- u8 pad[1672]; /* 1672: pad to 2048 bytes */
- __le32 wmap[LPERDMAP]; /* 1024: bits of the working map */
- __le32 pmap[LPERDMAP]; /* 1024: bits of the persistent map */
-}; /* - 4096 - */
+ __le32 nblocks; /* 4: num blks covered by this dmap */
+ __le32 nfree; /* 4: num of free blks in this dmap */
+ __le64 start; /* 8: starting blkno for this dmap */
+ struct dmaptree tree; /* 360: dmap tree */
+ u8 pad[1672]; /* 1672: pad to 2048 bytes */
+ __le32 wmap[LPERDMAP]; /* 1024: bits of the working map */
+ __le32 pmap[LPERDMAP]; /* 1024: bits of the persistent map */
+}; /* - 4096 - */
/*
* disk map control page per level.
@@ -173,14 +173,14 @@ struct dmap {
* dmapctl must be consistent with dmaptree.
*/
struct dmapctl {
- __le32 nleafs; /* 4: number of tree leafs */
- __le32 l2nleafs; /* 4: l2 number of tree leafs */
- __le32 leafidx; /* 4: index of the first tree leaf */
- __le32 height; /* 4: height of tree */
- s8 budmin; /* 1: minimum l2 tree leaf value */
- s8 stree[CTLTREESIZE]; /* CTLTREESIZE: dmapctl tree */
- u8 pad[2714]; /* 2714: pad to 4096 */
-}; /* - 4096 - */
+ __le32 nleafs; /* 4: number of tree leafs */
+ __le32 l2nleafs; /* 4: l2 number of tree leafs */
+ __le32 leafidx; /* 4: index of the first tree leaf */
+ __le32 height; /* 4: height of tree */
+ s8 budmin; /* 1: minimum l2 tree leaf value */
+ s8 stree[CTLTREESIZE]; /* CTLTREESIZE: dmapctl tree */
+ u8 pad[2714]; /* 2714: pad to 4096 */
+}; /* - 4096 - */
/*
* common definition for dmaptree within dmap and dmapctl
@@ -202,41 +202,41 @@ typedef union dmtree {
* on-disk aggregate disk allocation map descriptor.
*/
struct dbmap_disk {
- __le64 dn_mapsize; /* 8: number of blocks in aggregate */
- __le64 dn_nfree; /* 8: num free blks in aggregate map */
- __le32 dn_l2nbperpage; /* 4: number of blks per page */
- __le32 dn_numag; /* 4: total number of ags */
- __le32 dn_maxlevel; /* 4: number of active ags */
- __le32 dn_maxag; /* 4: max active alloc group number */
- __le32 dn_agpref; /* 4: preferred alloc group (hint) */
- __le32 dn_aglevel; /* 4: dmapctl level holding the AG */
- __le32 dn_agheigth; /* 4: height in dmapctl of the AG */
- __le32 dn_agwidth; /* 4: width in dmapctl of the AG */
- __le32 dn_agstart; /* 4: start tree index at AG height */
- __le32 dn_agl2size; /* 4: l2 num of blks per alloc group */
- __le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count */
- __le64 dn_agsize; /* 8: num of blks per alloc group */
- s8 dn_maxfreebud; /* 1: max free buddy system */
- u8 pad[3007]; /* 3007: pad to 4096 */
-}; /* - 4096 - */
+ __le64 dn_mapsize; /* 8: number of blocks in aggregate */
+ __le64 dn_nfree; /* 8: num free blks in aggregate map */
+ __le32 dn_l2nbperpage; /* 4: number of blks per page */
+ __le32 dn_numag; /* 4: total number of ags */
+ __le32 dn_maxlevel; /* 4: number of active ags */
+ __le32 dn_maxag; /* 4: max active alloc group number */
+ __le32 dn_agpref; /* 4: preferred alloc group (hint) */
+ __le32 dn_aglevel; /* 4: dmapctl level holding the AG */
+ __le32 dn_agheigth; /* 4: height in dmapctl of the AG */
+ __le32 dn_agwidth; /* 4: width in dmapctl of the AG */
+ __le32 dn_agstart; /* 4: start tree index at AG height */
+ __le32 dn_agl2size; /* 4: l2 num of blks per alloc group */
+ __le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count */
+ __le64 dn_agsize; /* 8: num of blks per alloc group */
+ s8 dn_maxfreebud; /* 1: max free buddy system */
+ u8 pad[3007]; /* 3007: pad to 4096 */
+}; /* - 4096 - */
struct dbmap {
- s64 dn_mapsize; /* number of blocks in aggregate */
- s64 dn_nfree; /* num free blks in aggregate map */
- int dn_l2nbperpage; /* number of blks per page */
- int dn_numag; /* total number of ags */
- int dn_maxlevel; /* number of active ags */
- int dn_maxag; /* max active alloc group number */
- int dn_agpref; /* preferred alloc group (hint) */
- int dn_aglevel; /* dmapctl level holding the AG */
- int dn_agheigth; /* height in dmapctl of the AG */
- int dn_agwidth; /* width in dmapctl of the AG */
- int dn_agstart; /* start tree index at AG height */
- int dn_agl2size; /* l2 num of blks per alloc group */
- s64 dn_agfree[MAXAG]; /* per AG free count */
- s64 dn_agsize; /* num of blks per alloc group */
- signed char dn_maxfreebud; /* max free buddy system */
-}; /* - 4096 - */
+ s64 dn_mapsize; /* number of blocks in aggregate */
+ s64 dn_nfree; /* num free blks in aggregate map */
+ int dn_l2nbperpage; /* number of blks per page */
+ int dn_numag; /* total number of ags */
+ int dn_maxlevel; /* number of active ags */
+ int dn_maxag; /* max active alloc group number */
+ int dn_agpref; /* preferred alloc group (hint) */
+ int dn_aglevel; /* dmapctl level holding the AG */
+ int dn_agheigth; /* height in dmapctl of the AG */
+ int dn_agwidth; /* width in dmapctl of the AG */
+ int dn_agstart; /* start tree index at AG height */
+ int dn_agl2size; /* l2 num of blks per alloc group */
+ s64 dn_agfree[MAXAG]; /* per AG free count */
+ s64 dn_agsize; /* num of blks per alloc group */
+ signed char dn_maxfreebud; /* max free buddy system */
+}; /* - 4096 - */
/*
* in-memory aggregate disk allocation map descriptor.
*/
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 6d62f3222892..c14ba3cfa818 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -315,8 +315,8 @@ static inline void lock_index(tid_t tid, struct inode *ip, struct metapage * mp,
lv = &llck->lv[llck->index];
/*
- * Linelock slot size is twice the size of directory table
- * slot size. 512 entries per page.
+ * Linelock slot size is twice the size of directory table
+ * slot size. 512 entries per page.
*/
lv->offset = ((index - 2) & 511) >> 1;
lv->length = 1;
@@ -615,7 +615,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
btstack->nsplit = 1;
/*
- * search down tree from root:
+ * search down tree from root:
*
* between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
* internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -659,7 +659,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
}
if (cmp == 0) {
/*
- * search hit
+ * search hit
*/
/* search hit - leaf page:
* return the entry found
@@ -723,7 +723,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
}
/*
- * search miss
+ * search miss
*
* base is the smallest index with key (Kj) greater than
* search key (K) and may be zero or (maxindex + 1) index.
@@ -834,7 +834,7 @@ int dtInsert(tid_t tid, struct inode *ip,
struct lv *lv;
/*
- * retrieve search result
+ * retrieve search result
*
* dtSearch() returns (leaf page pinned, index at which to insert).
* n.b. dtSearch() may return index of (maxindex + 1) of
@@ -843,7 +843,7 @@ int dtInsert(tid_t tid, struct inode *ip,
DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
/*
- * insert entry for new key
+ * insert entry for new key
*/
if (DO_INDEX(ip)) {
if (JFS_IP(ip)->next_index == DIREND) {
@@ -860,9 +860,9 @@ int dtInsert(tid_t tid, struct inode *ip,
data.leaf.ino = *fsn;
/*
- * leaf page does not have enough room for new entry:
+ * leaf page does not have enough room for new entry:
*
- * extend/split the leaf page;
+ * extend/split the leaf page;
*
* dtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -877,9 +877,9 @@ int dtInsert(tid_t tid, struct inode *ip,
}
/*
- * leaf page does have enough room for new entry:
+ * leaf page does have enough room for new entry:
*
- * insert the new data entry into the leaf page;
+ * insert the new data entry into the leaf page;
*/
BT_MARK_DIRTY(mp, ip);
/*
@@ -967,13 +967,13 @@ static int dtSplitUp(tid_t tid,
}
/*
- * split leaf page
+ * split leaf page
*
* The split routines insert the new entry, and
* acquire txLock as appropriate.
*/
/*
- * split root leaf page:
+ * split root leaf page:
*/
if (sp->header.flag & BT_ROOT) {
/*
@@ -1012,7 +1012,7 @@ static int dtSplitUp(tid_t tid,
}
/*
- * extend first leaf page
+ * extend first leaf page
*
* extend the 1st extent if less than buffer page size
* (dtExtendPage() reurns leaf page unpinned)
@@ -1068,7 +1068,7 @@ static int dtSplitUp(tid_t tid,
}
/*
- * split leaf page <sp> into <sp> and a new right page <rp>.
+ * split leaf page <sp> into <sp> and a new right page <rp>.
*
* return <rp> pinned and its extent descriptor <rpxd>
*/
@@ -1433,7 +1433,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
rp->header.freecnt = rp->header.maxslot - fsi;
/*
- * sequential append at tail: append without split
+ * sequential append at tail: append without split
*
* If splitting the last page on a level because of appending
* a entry to it (skip is maxentry), it's likely that the access is
@@ -1467,7 +1467,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
}
/*
- * non-sequential insert (at possibly middle page)
+ * non-sequential insert (at possibly middle page)
*/
/*
@@ -1508,7 +1508,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
left = 0;
/*
- * compute fill factor for split pages
+ * compute fill factor for split pages
*
* <nxt> traces the next entry to move to rp
* <off> traces the next entry to stay in sp
@@ -1551,7 +1551,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
/* <nxt> poins to the 1st entry to move */
/*
- * move entries to right page
+ * move entries to right page
*
* dtMoveEntry() initializes rp and reserves entry for insertion
*
@@ -1677,7 +1677,7 @@ static int dtExtendPage(tid_t tid,
return (rc);
/*
- * extend the extent
+ * extend the extent
*/
pxdlist = split->pxdlist;
pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1722,7 +1722,7 @@ static int dtExtendPage(tid_t tid,
}
/*
- * extend the page
+ * extend the page
*/
sp->header.self = *pxd;
@@ -1739,9 +1739,6 @@ static int dtExtendPage(tid_t tid,
/* update buffer extent descriptor of extended page */
xlen = lengthPXD(pxd);
xsize = xlen << JFS_SBI(sb)->l2bsize;
-#ifdef _STILL_TO_PORT
- bmSetXD(smp, xaddr, xsize);
-#endif /* _STILL_TO_PORT */
/*
* copy old stbl to new stbl at start of extended area
@@ -1836,7 +1833,7 @@ static int dtExtendPage(tid_t tid,
}
/*
- * update parent entry on the parent/root page
+ * update parent entry on the parent/root page
*/
/*
* acquire a transaction lock on the parent/root page
@@ -1904,7 +1901,7 @@ static int dtSplitRoot(tid_t tid,
sp = &JFS_IP(ip)->i_dtroot;
/*
- * allocate/initialize a single (right) child page
+ * allocate/initialize a single (right) child page
*
* N.B. at first split, a one (or two) block to fit new entry
* is allocated; at subsequent split, a full page is allocated;
@@ -1943,7 +1940,7 @@ static int dtSplitRoot(tid_t tid,
rp->header.prev = 0;
/*
- * move in-line root page into new right page extent
+ * move in-line root page into new right page extent
*/
/* linelock header + copied entries + new stbl (1st slot) in new page */
ASSERT(dtlck->index == 0);
@@ -2016,7 +2013,7 @@ static int dtSplitRoot(tid_t tid,
dtInsertEntry(rp, split->index, split->key, split->data, &dtlck);
/*
- * reset parent/root page
+ * reset parent/root page
*
* set the 1st entry offset to 0, which force the left-most key
* at any level of the tree to be less than any search key.
@@ -2102,7 +2099,7 @@ int dtDelete(tid_t tid,
dtpage_t *np;
/*
- * search for the entry to delete:
+ * search for the entry to delete:
*
* dtSearch() returns (leaf page pinned, index at which to delete).
*/
@@ -2253,7 +2250,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
int i;
/*
- * keep the root leaf page which has become empty
+ * keep the root leaf page which has become empty
*/
if (BT_IS_ROOT(fmp)) {
/*
@@ -2269,7 +2266,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
}
/*
- * free the non-root leaf page
+ * free the non-root leaf page
*/
/*
* acquire a transaction lock on the page
@@ -2299,7 +2296,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
discard_metapage(fmp);
/*
- * propagate page deletion up the directory tree
+ * propagate page deletion up the directory tree
*
* If the delete from the parent page makes it empty,
* continue all the way up the tree.
@@ -2440,10 +2437,10 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
#ifdef _NOTYET
/*
- * NAME: dtRelocate()
+ * NAME: dtRelocate()
*
- * FUNCTION: relocate dtpage (internal or leaf) of directory;
- * This function is mainly used by defragfs utility.
+ * FUNCTION: relocate dtpage (internal or leaf) of directory;
+ * This function is mainly used by defragfs utility.
*/
int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
s64 nxaddr)
@@ -2471,8 +2468,8 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
xlen);
/*
- * 1. get the internal parent dtpage covering
- * router entry for the tartget page to be relocated;
+ * 1. get the internal parent dtpage covering
+ * router entry for the tartget page to be relocated;
*/
rc = dtSearchNode(ip, lmxaddr, opxd, &btstack);
if (rc)
@@ -2483,7 +2480,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
jfs_info("dtRelocate: parent router entry validated.");
/*
- * 2. relocate the target dtpage
+ * 2. relocate the target dtpage
*/
/* read in the target page from src extent */
DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
@@ -2581,9 +2578,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
/* update the buffer extent descriptor of the dtpage */
xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
-#ifdef _STILL_TO_PORT
- bmSetXD(mp, nxaddr, xsize);
-#endif /* _STILL_TO_PORT */
+
/* unpin the relocated page */
DT_PUTPAGE(mp);
jfs_info("dtRelocate: target dtpage relocated.");
@@ -2594,7 +2589,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
*/
/*
- * 3. acquire maplock for the source extent to be freed;
+ * 3. acquire maplock for the source extent to be freed;
*/
/* for dtpage relocation, write a LOG_NOREDOPAGE record
* for the source dtpage (logredo() will init NoRedoPage
@@ -2609,7 +2604,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
pxdlock->index = 1;
/*
- * 4. update the parent router entry for relocation;
+ * 4. update the parent router entry for relocation;
*
* acquire tlck for the parent entry covering the target dtpage;
* write LOG_REDOPAGE to apply after image only;
@@ -2637,7 +2632,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
* NAME: dtSearchNode()
*
* FUNCTION: Search for an dtpage containing a specified address
- * This function is mainly used by defragfs utility.
+ * This function is mainly used by defragfs utility.
*
* NOTE: Search result on stack, the found page is pinned at exit.
* The result page must be an internal dtpage.
@@ -2660,7 +2655,7 @@ static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
BT_CLR(btstack); /* reset stack */
/*
- * descend tree to the level with specified leftmost page
+ * descend tree to the level with specified leftmost page
*
* by convention, root bn = 0.
*/
@@ -2699,7 +2694,7 @@ static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
}
/*
- * search each page at the current levevl
+ * search each page at the current levevl
*/
loop:
stbl = DT_GETSTBL(p);
@@ -3044,9 +3039,9 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (DO_INDEX(ip)) {
/*
* persistent index is stored in directory entries.
- * Special cases: 0 = .
- * 1 = ..
- * -1 = End of directory
+ * Special cases: 0 = .
+ * 1 = ..
+ * -1 = End of directory
*/
do_index = 1;
@@ -3128,10 +3123,10 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/*
* Legacy filesystem - OS/2 & Linux JFS < 0.3.6
*
- * pn = index = 0: First entry "."
- * pn = 0; index = 1: Second entry ".."
- * pn > 0: Real entries, pn=1 -> leftmost page
- * pn = index = -1: No more entries
+ * pn = index = 0: First entry "."
+ * pn = 0; index = 1: Second entry ".."
+ * pn > 0: Real entries, pn=1 -> leftmost page
+ * pn = index = -1: No more entries
*/
dtpos = filp->f_pos;
if (dtpos == 0) {
@@ -3351,7 +3346,7 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack)
BT_CLR(btstack); /* reset stack */
/*
- * descend leftmost path of the tree
+ * descend leftmost path of the tree
*
* by convention, root bn = 0.
*/
@@ -4531,7 +4526,7 @@ int dtModify(tid_t tid, struct inode *ip,
struct ldtentry *entry;
/*
- * search for the entry to modify:
+ * search for the entry to modify:
*
* dtSearch() returns (leaf page pinned, index at which to modify).
*/
diff --git a/fs/jfs/jfs_dtree.h b/fs/jfs/jfs_dtree.h
index af8513f78648..8561c6ecece0 100644
--- a/fs/jfs/jfs_dtree.h
+++ b/fs/jfs/jfs_dtree.h
@@ -35,7 +35,7 @@ typedef union {
/*
- * entry segment/slot
+ * entry segment/slot
*
* an entry consists of type dependent head/only segment/slot and
* additional segments/slots linked vi next field;
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index a35bdca6a805..7ae1e3281de9 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -34,8 +34,8 @@ static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *);
#endif
static s64 extRoundDown(s64 nb);
-#define DPD(a) (printk("(a): %d\n",(a)))
-#define DPC(a) (printk("(a): %c\n",(a)))
+#define DPD(a) (printk("(a): %d\n",(a)))
+#define DPC(a) (printk("(a): %c\n",(a)))
#define DPL1(a) \
{ \
if ((a) >> 32) \
@@ -51,19 +51,19 @@ static s64 extRoundDown(s64 nb);
printk("(a): %x\n",(a) << 32); \
}
-#define DPD1(a) (printk("(a): %d ",(a)))
-#define DPX(a) (printk("(a): %08x\n",(a)))
-#define DPX1(a) (printk("(a): %08x ",(a)))
-#define DPS(a) (printk("%s\n",(a)))
-#define DPE(a) (printk("\nENTERING: %s\n",(a)))
-#define DPE1(a) (printk("\nENTERING: %s",(a)))
-#define DPS1(a) (printk(" %s ",(a)))
+#define DPD1(a) (printk("(a): %d ",(a)))
+#define DPX(a) (printk("(a): %08x\n",(a)))
+#define DPX1(a) (printk("(a): %08x ",(a)))
+#define DPS(a) (printk("%s\n",(a)))
+#define DPE(a) (printk("\nENTERING: %s\n",(a)))
+#define DPE1(a) (printk("\nENTERING: %s",(a)))
+#define DPS1(a) (printk(" %s ",(a)))
/*
* NAME: extAlloc()
*
- * FUNCTION: allocate an extent for a specified page range within a
+ * FUNCTION: allocate an extent for a specified page range within a
* file.
*
* PARAMETERS:
@@ -78,9 +78,9 @@ static s64 extRoundDown(s64 nb);
* should be marked as allocated but not recorded.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
int
extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
@@ -192,9 +192,9 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
#ifdef _NOTYET
/*
- * NAME: extRealloc()
+ * NAME: extRealloc()
*
- * FUNCTION: extend the allocation of a file extent containing a
+ * FUNCTION: extend the allocation of a file extent containing a
* partial back last page.
*
* PARAMETERS:
@@ -207,9 +207,9 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
* should be marked as allocated but not recorded.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr)
{
@@ -345,9 +345,9 @@ exit:
/*
- * NAME: extHint()
+ * NAME: extHint()
*
- * FUNCTION: produce an extent allocation hint for a file offset.
+ * FUNCTION: produce an extent allocation hint for a file offset.
*
* PARAMETERS:
* ip - the inode of the file.
@@ -356,8 +356,8 @@ exit:
* the hint.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
+ * 0 - success
+ * -EIO - i/o error.
*/
int extHint(struct inode *ip, s64 offset, xad_t * xp)
{
@@ -387,7 +387,7 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp)
lxdl.nlxd = 1;
lxdl.lxd = &lxd;
LXDoffset(&lxd, prev)
- LXDlength(&lxd, nbperpage);
+ LXDlength(&lxd, nbperpage);
xadl.maxnxad = 1;
xadl.nxad = 0;
@@ -397,11 +397,11 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp)
if ((rc = xtLookupList(ip, &lxdl, &xadl, 0)))
return (rc);
- /* check if not extent exists for the previous page.
+ /* check if no extent exists for the previous page.
* this is possible for sparse files.
*/
if (xadl.nxad == 0) {
-// assert(ISSPARSE(ip));
+// assert(ISSPARSE(ip));
return (0);
}
@@ -410,28 +410,28 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp)
*/
xp->flag &= XAD_NOTRECORDED;
- if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
+ if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
jfs_error(ip->i_sb, "extHint: corrupt xtree");
return -EIO;
- }
+ }
return (0);
}
/*
- * NAME: extRecord()
+ * NAME: extRecord()
*
- * FUNCTION: change a page with a file from not recorded to recorded.
+ * FUNCTION: change a page with a file from not recorded to recorded.
*
* PARAMETERS:
* ip - inode of the file.
* cp - cbuf of the file page.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
int extRecord(struct inode *ip, xad_t * xp)
{
@@ -451,9 +451,9 @@ int extRecord(struct inode *ip, xad_t * xp)
#ifdef _NOTYET
/*
- * NAME: extFill()
+ * NAME: extFill()
*
- * FUNCTION: allocate disk space for a file page that represents
+ * FUNCTION: allocate disk space for a file page that represents
* a file hole.
*
* PARAMETERS:
@@ -461,16 +461,16 @@ int extRecord(struct inode *ip, xad_t * xp)
* cp - cbuf of the file page represent the hole.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
int extFill(struct inode *ip, xad_t * xp)
{
int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
s64 blkno = offsetXAD(xp) >> ip->i_blkbits;
-// assert(ISSPARSE(ip));
+// assert(ISSPARSE(ip));
/* initialize the extent allocation hint */
XADaddress(xp, 0);
@@ -489,7 +489,7 @@ int extFill(struct inode *ip, xad_t * xp)
/*
* NAME: extBalloc()
*
- * FUNCTION: allocate disk blocks to form an extent.
+ * FUNCTION: allocate disk blocks to form an extent.
*
* initially, we will try to allocate disk blocks for the
* requested size (nblocks). if this fails (nblocks
@@ -513,9 +513,9 @@ int extFill(struct inode *ip, xad_t * xp)
* allocated block range.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
static int
extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
@@ -580,7 +580,7 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
/*
* NAME: extBrealloc()
*
- * FUNCTION: attempt to extend an extent's allocation.
+ * FUNCTION: attempt to extend an extent's allocation.
*
* Initially, we will try to extend the extent's allocation
* in place. If this fails, we'll try to move the extent
@@ -597,8 +597,8 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
*
* PARAMETERS:
* ip - the inode of the file.
- * blkno - starting block number of the extents current allocation.
- * nblks - number of blocks within the extents current allocation.
+ * blkno - starting block number of the extents current allocation.
+ * nblks - number of blocks within the extents current allocation.
* newnblks - pointer to a s64 value. on entry, this value is the
* the new desired extent size (number of blocks). on
* successful exit, this value is set to the extent's actual
@@ -606,9 +606,9 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
* newblkno - the starting block number of the extents new allocation.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
static int
extBrealloc(struct inode *ip,
@@ -634,16 +634,16 @@ extBrealloc(struct inode *ip,
/*
- * NAME: extRoundDown()
+ * NAME: extRoundDown()
*
- * FUNCTION: round down a specified number of blocks to the next
+ * FUNCTION: round down a specified number of blocks to the next
* smallest power of 2 number.
*
* PARAMETERS:
* nb - the inode of the file.
*
* RETURN VALUES:
- * next smallest power of 2 number.
+ * next smallest power of 2 number.
*/
static s64 extRoundDown(s64 nb)
{
diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
index 38f70ac03bec..b3f5463fbe52 100644
--- a/fs/jfs/jfs_filsys.h
+++ b/fs/jfs/jfs_filsys.h
@@ -34,9 +34,9 @@
#define JFS_UNICODE 0x00000001 /* unicode name */
/* mount time flags for error handling */
-#define JFS_ERR_REMOUNT_RO 0x00000002 /* remount read-only */
-#define JFS_ERR_CONTINUE 0x00000004 /* continue */
-#define JFS_ERR_PANIC 0x00000008 /* panic */
+#define JFS_ERR_REMOUNT_RO 0x00000002 /* remount read-only */
+#define JFS_ERR_CONTINUE 0x00000004 /* continue */
+#define JFS_ERR_PANIC 0x00000008 /* panic */
/* Quota support */
#define JFS_USRQUOTA 0x00000010
@@ -83,7 +83,6 @@
/* case-insensitive name/directory support */
#define JFS_AIX 0x80000000 /* AIX support */
-/* POSIX name/directory support - Never implemented*/
/*
* buffer cache configuration
@@ -113,10 +112,10 @@
#define IDATASIZE 256 /* inode inline data size */
#define IXATTRSIZE 128 /* inode inline extended attribute size */
-#define XTPAGE_SIZE 4096
-#define log2_PAGESIZE 12
+#define XTPAGE_SIZE 4096
+#define log2_PAGESIZE 12
-#define IAG_SIZE 4096
+#define IAG_SIZE 4096
#define IAG_EXTENT_SIZE 4096
#define INOSPERIAG 4096 /* number of disk inodes per iag */
#define L2INOSPERIAG 12 /* l2 number of disk inodes per iag */
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index c6530227cda6..3870ba8b9086 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -93,21 +93,21 @@ static int copy_from_dinode(struct dinode *, struct inode *);
static void copy_to_dinode(struct dinode *, struct inode *);
/*
- * NAME: diMount()
+ * NAME: diMount()
*
- * FUNCTION: initialize the incore inode map control structures for
+ * FUNCTION: initialize the incore inode map control structures for
* a fileset or aggregate init time.
*
- * the inode map's control structure (dinomap) is
- * brought in from disk and placed in virtual memory.
+ * the inode map's control structure (dinomap) is
+ * brought in from disk and placed in virtual memory.
*
* PARAMETERS:
- * ipimap - pointer to inode map inode for the aggregate or fileset.
+ * ipimap - pointer to inode map inode for the aggregate or fileset.
*
* RETURN VALUES:
- * 0 - success
- * -ENOMEM - insufficient free virtual memory.
- * -EIO - i/o error.
+ * 0 - success
+ * -ENOMEM - insufficient free virtual memory.
+ * -EIO - i/o error.
*/
int diMount(struct inode *ipimap)
{
@@ -180,18 +180,18 @@ int diMount(struct inode *ipimap)
/*
- * NAME: diUnmount()
+ * NAME: diUnmount()
*
- * FUNCTION: write to disk the incore inode map control structures for
+ * FUNCTION: write to disk the incore inode map control structures for
* a fileset or aggregate at unmount time.
*
* PARAMETERS:
- * ipimap - pointer to inode map inode for the aggregate or fileset.
+ * ipimap - pointer to inode map inode for the aggregate or fileset.
*
* RETURN VALUES:
- * 0 - success
- * -ENOMEM - insufficient free virtual memory.
- * -EIO - i/o error.
+ * 0 - success
+ * -ENOMEM - insufficient free virtual memory.
+ * -EIO - i/o error.
*/
int diUnmount(struct inode *ipimap, int mounterror)
{
@@ -274,9 +274,9 @@ int diSync(struct inode *ipimap)
/*
- * NAME: diRead()
+ * NAME: diRead()
*
- * FUNCTION: initialize an incore inode from disk.
+ * FUNCTION: initialize an incore inode from disk.
*
* on entry, the specifed incore inode should itself
* specify the disk inode number corresponding to the
@@ -285,7 +285,7 @@ int diSync(struct inode *ipimap)
* this routine handles incore inode initialization for
* both "special" and "regular" inodes. special inodes
* are those required early in the mount process and
- * require special handling since much of the file system
+ * require special handling since much of the file system
* is not yet initialized. these "special" inodes are
* identified by a NULL inode map inode pointer and are
* actually initialized by a call to diReadSpecial().
@@ -298,12 +298,12 @@ int diSync(struct inode *ipimap)
* incore inode.
*
* PARAMETERS:
- * ip - pointer to incore inode to be initialized from disk.
+ * ip - pointer to incore inode to be initialized from disk.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOMEM - insufficient memory
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOMEM - insufficient memory
*
*/
int diRead(struct inode *ip)
@@ -410,26 +410,26 @@ int diRead(struct inode *ip)
/*
- * NAME: diReadSpecial()
+ * NAME: diReadSpecial()
*
- * FUNCTION: initialize a 'special' inode from disk.
+ * FUNCTION: initialize a 'special' inode from disk.
*
* this routines handles aggregate level inodes. The
* inode cache cannot differentiate between the
* aggregate inodes and the filesystem inodes, so we
* handle these here. We don't actually use the aggregate
- * inode map, since these inodes are at a fixed location
+ * inode map, since these inodes are at a fixed location
* and in some cases the aggregate inode map isn't initialized
* yet.
*
* PARAMETERS:
- * sb - filesystem superblock
+ * sb - filesystem superblock
* inum - aggregate inode number
* secondary - 1 if secondary aggregate inode table
*
* RETURN VALUES:
- * new inode - success
- * NULL - i/o error.
+ * new inode - success
+ * NULL - i/o error.
*/
struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
{
@@ -502,12 +502,12 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
}
/*
- * NAME: diWriteSpecial()
+ * NAME: diWriteSpecial()
*
- * FUNCTION: Write the special inode to disk
+ * FUNCTION: Write the special inode to disk
*
* PARAMETERS:
- * ip - special inode
+ * ip - special inode
* secondary - 1 if secondary aggregate inode table
*
* RETURN VALUES: none
@@ -554,9 +554,9 @@ void diWriteSpecial(struct inode *ip, int secondary)
}
/*
- * NAME: diFreeSpecial()
+ * NAME: diFreeSpecial()
*
- * FUNCTION: Free allocated space for special inode
+ * FUNCTION: Free allocated space for special inode
*/
void diFreeSpecial(struct inode *ip)
{
@@ -572,9 +572,9 @@ void diFreeSpecial(struct inode *ip)
/*
- * NAME: diWrite()
+ * NAME: diWrite()
*
- * FUNCTION: write the on-disk inode portion of the in-memory inode
+ * FUNCTION: write the on-disk inode portion of the in-memory inode
* to its corresponding on-disk inode.
*
* on entry, the specifed incore inode should itself
@@ -589,11 +589,11 @@ void diFreeSpecial(struct inode *ip)
*
* PARAMETERS:
* tid - transacation id
- * ip - pointer to incore inode to be written to the inode extent.
+ * ip - pointer to incore inode to be written to the inode extent.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
+ * 0 - success
+ * -EIO - i/o error.
*/
int diWrite(tid_t tid, struct inode *ip)
{
@@ -730,7 +730,7 @@ int diWrite(tid_t tid, struct inode *ip)
ilinelock = (struct linelock *) & tlck->lock;
/*
- * regular file: 16 byte (XAD slot) granularity
+ * regular file: 16 byte (XAD slot) granularity
*/
if (type & tlckXTREE) {
xtpage_t *p, *xp;
@@ -755,7 +755,7 @@ int diWrite(tid_t tid, struct inode *ip)
xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
}
/*
- * directory: 32 byte (directory entry slot) granularity
+ * directory: 32 byte (directory entry slot) granularity
*/
else if (type & tlckDTREE) {
dtpage_t *p, *xp;
@@ -800,9 +800,8 @@ int diWrite(tid_t tid, struct inode *ip)
}
/*
- * lock/copy inode base: 128 byte slot granularity
+ * lock/copy inode base: 128 byte slot granularity
*/
-// baseDinode:
lv = & dilinelock->lv[dilinelock->index];
lv->offset = dioffset >> L2INODESLOTSIZE;
copy_to_dinode(dp, ip);
@@ -813,17 +812,6 @@ int diWrite(tid_t tid, struct inode *ip)
lv->length = 1;
dilinelock->index++;
-#ifdef _JFS_FASTDASD
- /*
- * We aren't logging changes to the DASD used in directory inodes,
- * but we need to write them to disk. If we don't unmount cleanly,
- * mount will recalculate the DASD used.
- */
- if (S_ISDIR(ip->i_mode)
- && (ip->i_ipmnt->i_mntflag & JFS_DASD_ENABLED))
- memcpy(&dp->di_DASD, &ip->i_DASD, sizeof(struct dasd));
-#endif /* _JFS_FASTDASD */
-
/* release the buffer holding the updated on-disk inode.
* the buffer will be later written by commit processing.
*/
@@ -834,9 +822,9 @@ int diWrite(tid_t tid, struct inode *ip)
/*
- * NAME: diFree(ip)
+ * NAME: diFree(ip)
*
- * FUNCTION: free a specified inode from the inode working map
+ * FUNCTION: free a specified inode from the inode working map
* for a fileset or aggregate.
*
* if the inode to be freed represents the first (only)
@@ -865,11 +853,11 @@ int diWrite(tid_t tid, struct inode *ip)
* any updates and are held until all updates are complete.
*
* PARAMETERS:
- * ip - inode to be freed.
+ * ip - inode to be freed.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
+ * 0 - success
+ * -EIO - i/o error.
*/
int diFree(struct inode *ip)
{
@@ -902,7 +890,8 @@ int diFree(struct inode *ip)
* the map.
*/
if (iagno >= imap->im_nextiag) {
- dump_mem("imap", imap, 32);
+ print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ imap, 32, 0);
jfs_error(ip->i_sb,
"diFree: inum = %d, iagno = %d, nextiag = %d",
(uint) inum, iagno, imap->im_nextiag);
@@ -964,8 +953,8 @@ int diFree(struct inode *ip)
return -EIO;
}
/*
- * inode extent still has some inodes or below low water mark:
- * keep the inode extent;
+ * inode extent still has some inodes or below low water mark:
+ * keep the inode extent;
*/
if (bitmap ||
imap->im_agctl[agno].numfree < 96 ||
@@ -1047,12 +1036,12 @@ int diFree(struct inode *ip)
/*
- * inode extent has become free and above low water mark:
- * free the inode extent;
+ * inode extent has become free and above low water mark:
+ * free the inode extent;
*/
/*
- * prepare to update iag list(s) (careful update step 1)
+ * prepare to update iag list(s) (careful update step 1)
*/
amp = bmp = cmp = dmp = NULL;
fwd = back = -1;
@@ -1152,7 +1141,7 @@ int diFree(struct inode *ip)
invalidate_pxd_metapages(ip, freepxd);
/*
- * update iag list(s) (careful update step 2)
+ * update iag list(s) (careful update step 2)
*/
/* add the iag to the ag extent free list if this is the
* first free extent for the iag.
@@ -1338,20 +1327,20 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
/*
- * NAME: diAlloc(pip,dir,ip)
+ * NAME: diAlloc(pip,dir,ip)
*
- * FUNCTION: allocate a disk inode from the inode working map
+ * FUNCTION: allocate a disk inode from the inode working map
* for a fileset or aggregate.
*
* PARAMETERS:
- * pip - pointer to incore inode for the parent inode.
- * dir - 'true' if the new disk inode is for a directory.
- * ip - pointer to a new inode
+ * pip - pointer to incore inode for the parent inode.
+ * dir - 'true' if the new disk inode is for a directory.
+ * ip - pointer to a new inode
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
int diAlloc(struct inode *pip, bool dir, struct inode *ip)
{
@@ -1433,7 +1422,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
addext = (imap->im_agctl[agno].numfree < 32 && iagp->nfreeexts);
/*
- * try to allocate from the IAG
+ * try to allocate from the IAG
*/
/* check if the inode may be allocated from the iag
* (i.e. the inode has free inodes or new extent can be added).
@@ -1633,9 +1622,9 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
/*
- * NAME: diAllocAG(imap,agno,dir,ip)
+ * NAME: diAllocAG(imap,agno,dir,ip)
*
- * FUNCTION: allocate a disk inode from the allocation group.
+ * FUNCTION: allocate a disk inode from the allocation group.
*
* this routine first determines if a new extent of free
* inodes should be added for the allocation group, with
@@ -1649,17 +1638,17 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
* PRE CONDITION: Already have the AG lock for this AG.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * agno - allocation group to allocate from.
- * dir - 'true' if the new disk inode is for a directory.
- * ip - pointer to the new inode to be filled in on successful return
+ * imap - pointer to inode map control structure.
+ * agno - allocation group to allocate from.
+ * dir - 'true' if the new disk inode is for a directory.
+ * ip - pointer to the new inode to be filled in on successful return
* with the disk inode number allocated, its extent address
* and the start of the ag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int
diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
@@ -1709,9 +1698,9 @@ diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
/*
- * NAME: diAllocAny(imap,agno,dir,iap)
+ * NAME: diAllocAny(imap,agno,dir,iap)
*
- * FUNCTION: allocate a disk inode from any other allocation group.
+ * FUNCTION: allocate a disk inode from any other allocation group.
*
* this routine is called when an allocation attempt within
* the primary allocation group has failed. if attempts to
@@ -1719,17 +1708,17 @@ diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
* specified primary group.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * agno - primary allocation group (to avoid).
- * dir - 'true' if the new disk inode is for a directory.
- * ip - pointer to a new inode to be filled in on successful return
+ * imap - pointer to inode map control structure.
+ * agno - primary allocation group (to avoid).
+ * dir - 'true' if the new disk inode is for a directory.
+ * ip - pointer to a new inode to be filled in on successful return
* with the disk inode number allocated, its extent address
* and the start of the ag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int
diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
@@ -1772,9 +1761,9 @@ diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
/*
- * NAME: diAllocIno(imap,agno,ip)
+ * NAME: diAllocIno(imap,agno,ip)
*
- * FUNCTION: allocate a disk inode from the allocation group's free
+ * FUNCTION: allocate a disk inode from the allocation group's free
* inode list, returning an error if this free list is
* empty (i.e. no iags on the list).
*
@@ -1785,16 +1774,16 @@ diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
* PRE CONDITION: Already have AG lock for this AG.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * agno - allocation group.
- * ip - pointer to new inode to be filled in on successful return
+ * imap - pointer to inode map control structure.
+ * agno - allocation group.
+ * ip - pointer to new inode to be filled in on successful return
* with the disk inode number allocated, its extent address
* and the start of the ag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
{
@@ -1890,7 +1879,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
/*
- * NAME: diAllocExt(imap,agno,ip)
+ * NAME: diAllocExt(imap,agno,ip)
*
* FUNCTION: add a new extent of free inodes to an iag, allocating
* an inode from this extent to satisfy the current allocation
@@ -1910,16 +1899,16 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
* for the purpose of satisfying this request.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * agno - allocation group number.
- * ip - pointer to new inode to be filled in on successful return
+ * imap - pointer to inode map control structure.
+ * agno - allocation group number.
+ * ip - pointer to new inode to be filled in on successful return
* with the disk inode number allocated, its extent address
* and the start of the ag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
{
@@ -2010,7 +1999,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
/*
- * NAME: diAllocBit(imap,iagp,ino)
+ * NAME: diAllocBit(imap,iagp,ino)
*
* FUNCTION: allocate a backed inode from an iag.
*
@@ -2030,14 +2019,14 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
* this AG. Must have read lock on imap inode.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * iagp - pointer to iag.
- * ino - inode number to be allocated within the iag.
+ * imap - pointer to inode map control structure.
+ * iagp - pointer to iag.
+ * ino - inode number to be allocated within the iag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
{
@@ -2144,11 +2133,11 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
/*
- * NAME: diNewExt(imap,iagp,extno)
+ * NAME: diNewExt(imap,iagp,extno)
*
- * FUNCTION: initialize a new extent of inodes for an iag, allocating
- * the first inode of the extent for use for the current
- * allocation request.
+ * FUNCTION: initialize a new extent of inodes for an iag, allocating
+ * the first inode of the extent for use for the current
+ * allocation request.
*
* disk resources are allocated for the new extent of inodes
* and the inodes themselves are initialized to reflect their
@@ -2177,14 +2166,14 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
* this AG. Must have read lock on imap inode.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * iagp - pointer to iag.
- * extno - extent number.
+ * imap - pointer to inode map control structure.
+ * iagp - pointer to iag.
+ * extno - extent number.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
{
@@ -2430,7 +2419,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
/*
- * NAME: diNewIAG(imap,iagnop,agno)
+ * NAME: diNewIAG(imap,iagnop,agno)
*
* FUNCTION: allocate a new iag for an allocation group.
*
@@ -2443,16 +2432,16 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
* and returned to satisfy the request.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * iagnop - pointer to an iag number set with the number of the
+ * imap - pointer to inode map control structure.
+ * iagnop - pointer to an iag number set with the number of the
* newly allocated iag upon successful return.
- * agno - allocation group number.
+ * agno - allocation group number.
* bpp - Buffer pointer to be filled in with new IAG's buffer
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*
* serialization:
* AG lock held on entry/exit;
@@ -2461,7 +2450,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
*
* note: new iag transaction:
* . synchronously write iag;
- * . write log of xtree and inode of imap;
+ * . write log of xtree and inode of imap;
* . commit;
* . synchronous write of xtree (right to left, bottom to top);
* . at start of logredo(): init in-memory imap with one additional iag page;
@@ -2481,9 +2470,6 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
s64 xaddr = 0;
s64 blkno;
tid_t tid;
-#ifdef _STILL_TO_PORT
- xad_t xad;
-#endif /* _STILL_TO_PORT */
struct inode *iplist[1];
/* pick up pointers to the inode map and mount inodes */
@@ -2674,15 +2660,15 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
}
/*
- * NAME: diIAGRead()
+ * NAME: diIAGRead()
*
- * FUNCTION: get the buffer for the specified iag within a fileset
+ * FUNCTION: get the buffer for the specified iag within a fileset
* or aggregate inode map.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * iagno - iag number.
- * bpp - point to buffer pointer to be filled in on successful
+ * imap - pointer to inode map control structure.
+ * iagno - iag number.
+ * bpp - point to buffer pointer to be filled in on successful
* exit.
*
* SERIALIZATION:
@@ -2691,8 +2677,8 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
* the read lock is unnecessary.)
*
* RETURN VALUES:
- * 0 - success.
- * -EIO - i/o error.
+ * 0 - success.
+ * -EIO - i/o error.
*/
static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
{
@@ -2712,17 +2698,17 @@ static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
}
/*
- * NAME: diFindFree()
+ * NAME: diFindFree()
*
- * FUNCTION: find the first free bit in a word starting at
+ * FUNCTION: find the first free bit in a word starting at
* the specified bit position.
*
* PARAMETERS:
- * word - word to be examined.
- * start - starting bit position.
+ * word - word to be examined.
+ * start - starting bit position.
*
* RETURN VALUES:
- * bit position of first free bit in the word or 32 if
+ * bit position of first free bit in the word or 32 if
* no free bits were found.
*/
static int diFindFree(u32 word, int start)
@@ -2897,7 +2883,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
atomic_read(&imap->im_numfree));
/*
- * reconstruct imap
+ * reconstruct imap
*
* coalesce contiguous k (newAGSize/oldAGSize) AGs;
* i.e., (AGi, ..., AGj) where i = k*n and j = k*(n+1) - 1 to AGn;
@@ -2913,7 +2899,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
}
/*
- * process each iag page of the map.
+ * process each iag page of the map.
*
* rebuild AG Free Inode List, AG Free Inode Extent List;
*/
@@ -2932,7 +2918,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
/* leave free iag in the free iag list */
if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
- release_metapage(bp);
+ release_metapage(bp);
continue;
}
@@ -3063,13 +3049,13 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
}
/*
- * NAME: copy_from_dinode()
+ * NAME: copy_from_dinode()
*
- * FUNCTION: Copies inode info from disk inode to in-memory inode
+ * FUNCTION: Copies inode info from disk inode to in-memory inode
*
* RETURN VALUES:
- * 0 - success
- * -ENOMEM - insufficient memory
+ * 0 - success
+ * -ENOMEM - insufficient memory
*/
static int copy_from_dinode(struct dinode * dip, struct inode *ip)
{
@@ -3151,9 +3137,9 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
}
/*
- * NAME: copy_to_dinode()
+ * NAME: copy_to_dinode()
*
- * FUNCTION: Copies inode info from in-memory inode to disk inode
+ * FUNCTION: Copies inode info from in-memory inode to disk inode
*/
static void copy_to_dinode(struct dinode * dip, struct inode *ip)
{
diff --git a/fs/jfs/jfs_imap.h b/fs/jfs/jfs_imap.h
index 4f9c346ed498..610a0e9d8941 100644
--- a/fs/jfs/jfs_imap.h
+++ b/fs/jfs/jfs_imap.h
@@ -24,17 +24,17 @@
* jfs_imap.h: disk inode manager
*/
-#define EXTSPERIAG 128 /* number of disk inode extent per iag */
-#define IMAPBLKNO 0 /* lblkno of dinomap within inode map */
-#define SMAPSZ 4 /* number of words per summary map */
+#define EXTSPERIAG 128 /* number of disk inode extent per iag */
+#define IMAPBLKNO 0 /* lblkno of dinomap within inode map */
+#define SMAPSZ 4 /* number of words per summary map */
#define EXTSPERSUM 32 /* number of extents per summary map entry */
#define L2EXTSPERSUM 5 /* l2 number of extents per summary map */
#define PGSPERIEXT 4 /* number of 4K pages per dinode extent */
-#define MAXIAGS ((1<<20)-1) /* maximum number of iags */
-#define MAXAG 128 /* maximum number of allocation groups */
+#define MAXIAGS ((1<<20)-1) /* maximum number of iags */
+#define MAXAG 128 /* maximum number of allocation groups */
-#define AMAPSIZE 512 /* bytes in the IAG allocation maps */
-#define SMAPSIZE 16 /* bytes in the IAG summary maps */
+#define AMAPSIZE 512 /* bytes in the IAG allocation maps */
+#define SMAPSIZE 16 /* bytes in the IAG summary maps */
/* convert inode number to iag number */
#define INOTOIAG(ino) ((ino) >> L2INOSPERIAG)
@@ -60,31 +60,31 @@
* inode allocation group page (per 4096 inodes of an AG)
*/
struct iag {
- __le64 agstart; /* 8: starting block of ag */
- __le32 iagnum; /* 4: inode allocation group number */
- __le32 inofreefwd; /* 4: ag inode free list forward */
- __le32 inofreeback; /* 4: ag inode free list back */
- __le32 extfreefwd; /* 4: ag inode extent free list forward */
- __le32 extfreeback; /* 4: ag inode extent free list back */
- __le32 iagfree; /* 4: iag free list */
+ __le64 agstart; /* 8: starting block of ag */
+ __le32 iagnum; /* 4: inode allocation group number */
+ __le32 inofreefwd; /* 4: ag inode free list forward */
+ __le32 inofreeback; /* 4: ag inode free list back */
+ __le32 extfreefwd; /* 4: ag inode extent free list forward */
+ __le32 extfreeback; /* 4: ag inode extent free list back */
+ __le32 iagfree; /* 4: iag free list */
/* summary map: 1 bit per inode extent */
__le32 inosmap[SMAPSZ]; /* 16: sum map of mapwords w/ free inodes;
- * note: this indicates free and backed
- * inodes, if the extent is not backed the
- * value will be 1. if the extent is
- * backed but all inodes are being used the
- * value will be 1. if the extent is
- * backed but at least one of the inodes is
- * free the value will be 0.
+ * note: this indicates free and backed
+ * inodes, if the extent is not backed the
+ * value will be 1. if the extent is
+ * backed but all inodes are being used the
+ * value will be 1. if the extent is
+ * backed but at least one of the inodes is
+ * free the value will be 0.
*/
__le32 extsmap[SMAPSZ]; /* 16: sum map of mapwords w/ free extents */
- __le32 nfreeinos; /* 4: number of free inodes */
- __le32 nfreeexts; /* 4: number of free extents */
+ __le32 nfreeinos; /* 4: number of free inodes */
+ __le32 nfreeexts; /* 4: number of free extents */
/* (72) */
u8 pad[1976]; /* 1976: pad to 2048 bytes */
/* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */
- __le32 wmap[EXTSPERIAG]; /* 512: working allocation map */
+ __le32 wmap[EXTSPERIAG]; /* 512: working allocation map */
__le32 pmap[EXTSPERIAG]; /* 512: persistent allocation map */
pxd_t inoext[EXTSPERIAG]; /* 1024: inode extent addresses */
}; /* (4096) */
@@ -93,44 +93,44 @@ struct iag {
* per AG control information (in inode map control page)
*/
struct iagctl_disk {
- __le32 inofree; /* 4: free inode list anchor */
- __le32 extfree; /* 4: free extent list anchor */
- __le32 numinos; /* 4: number of backed inodes */
- __le32 numfree; /* 4: number of free inodes */
+ __le32 inofree; /* 4: free inode list anchor */
+ __le32 extfree; /* 4: free extent list anchor */
+ __le32 numinos; /* 4: number of backed inodes */
+ __le32 numfree; /* 4: number of free inodes */
}; /* (16) */
struct iagctl {
- int inofree; /* free inode list anchor */
- int extfree; /* free extent list anchor */
- int numinos; /* number of backed inodes */
- int numfree; /* number of free inodes */
+ int inofree; /* free inode list anchor */
+ int extfree; /* free extent list anchor */
+ int numinos; /* number of backed inodes */
+ int numfree; /* number of free inodes */
};
/*
* per fileset/aggregate inode map control page
*/
struct dinomap_disk {
- __le32 in_freeiag; /* 4: free iag list anchor */
- __le32 in_nextiag; /* 4: next free iag number */
- __le32 in_numinos; /* 4: num of backed inodes */
+ __le32 in_freeiag; /* 4: free iag list anchor */
+ __le32 in_nextiag; /* 4: next free iag number */
+ __le32 in_numinos; /* 4: num of backed inodes */
__le32 in_numfree; /* 4: num of free backed inodes */
__le32 in_nbperiext; /* 4: num of blocks per inode extent */
- __le32 in_l2nbperiext; /* 4: l2 of in_nbperiext */
- __le32 in_diskblock; /* 4: for standalone test driver */
- __le32 in_maxag; /* 4: for standalone test driver */
- u8 pad[2016]; /* 2016: pad to 2048 */
+ __le32 in_l2nbperiext; /* 4: l2 of in_nbperiext */
+ __le32 in_diskblock; /* 4: for standalone test driver */
+ __le32 in_maxag; /* 4: for standalone test driver */
+ u8 pad[2016]; /* 2016: pad to 2048 */
struct iagctl_disk in_agctl[MAXAG]; /* 2048: AG control information */
}; /* (4096) */
struct dinomap {
- int in_freeiag; /* free iag list anchor */
- int in_nextiag; /* next free iag number */
- int in_numinos; /* num of backed inodes */
- int in_numfree; /* num of free backed inodes */
+ int in_freeiag; /* free iag list anchor */
+ int in_nextiag; /* next free iag number */
+ int in_numinos; /* num of backed inodes */
+ int in_numfree; /* num of free backed inodes */
int in_nbperiext; /* num of blocks per inode extent */
- int in_l2nbperiext; /* l2 of in_nbperiext */
- int in_diskblock; /* for standalone test driver */
- int in_maxag; /* for standalone test driver */
+ int in_l2nbperiext; /* l2 of in_nbperiext */
+ int in_diskblock; /* for standalone test driver */
+ int in_maxag; /* for standalone test driver */
struct iagctl in_agctl[MAXAG]; /* AG control information */
};
@@ -139,9 +139,9 @@ struct dinomap {
*/
struct inomap {
struct dinomap im_imap; /* 4096: inode allocation control */
- struct inode *im_ipimap; /* 4: ptr to inode for imap */
- struct mutex im_freelock; /* 4: iag free list lock */
- struct mutex im_aglock[MAXAG]; /* 512: per AG locks */
+ struct inode *im_ipimap; /* 4: ptr to inode for imap */
+ struct mutex im_freelock; /* 4: iag free list lock */
+ struct mutex im_aglock[MAXAG]; /* 512: per AG locks */
u32 *im_DBGdimap;
atomic_t im_numinos; /* num of backed inodes */
atomic_t im_numfree; /* num of free backed inodes */
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index 8f453eff3c83..cb8f30985ad1 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -40,7 +40,7 @@ struct jfs_inode_info {
uint mode2; /* jfs-specific mode */
uint saved_uid; /* saved for uid mount option */
uint saved_gid; /* saved for gid mount option */
- pxd_t ixpxd; /* inode extent descriptor */
+ pxd_t ixpxd; /* inode extent descriptor */
dxd_t acl; /* dxd describing acl */
dxd_t ea; /* dxd describing ea */
time_t otime; /* time created */
@@ -190,7 +190,7 @@ struct jfs_sb_info {
uint gengen; /* inode generation generator*/
uint inostamp; /* shows inode belongs to fileset*/
- /* Formerly in ipbmap */
+ /* Formerly in ipbmap */
struct bmap *bmap; /* incore bmap descriptor */
struct nls_table *nls_tab; /* current codepage */
struct inode *direct_inode; /* metadata inode */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 44a2f33cb98d..de3e4a506dbc 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -244,7 +244,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
goto writeRecord;
/*
- * initialize/update page/transaction recovery lsn
+ * initialize/update page/transaction recovery lsn
*/
lsn = log->lsn;
@@ -263,7 +263,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * initialize/update lsn of tblock of the page
+ * initialize/update lsn of tblock of the page
*
* transaction inherits oldest lsn of pages associated
* with allocation/deallocation of resources (their
@@ -307,7 +307,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
LOGSYNC_UNLOCK(log, flags);
/*
- * write the log record
+ * write the log record
*/
writeRecord:
lsn = lmWriteRecord(log, tblk, lrd, tlck);
@@ -372,7 +372,7 @@ lmWriteRecord(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
goto moveLrd;
/*
- * move log record data
+ * move log record data
*/
/* retrieve source meta-data page to log */
if (tlck->flag & tlckPAGELOCK) {
@@ -465,7 +465,7 @@ lmWriteRecord(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * move log record descriptor
+ * move log record descriptor
*/
moveLrd:
lrd->length = cpu_to_le16(len);
@@ -574,7 +574,7 @@ static int lmNextPage(struct jfs_log * log)
LOGGC_LOCK(log);
/*
- * write or queue the full page at the tail of write queue
+ * write or queue the full page at the tail of write queue
*/
/* get the tail tblk on commit queue */
if (list_empty(&log->cqueue))
@@ -625,7 +625,7 @@ static int lmNextPage(struct jfs_log * log)
LOGGC_UNLOCK(log);
/*
- * allocate/initialize next page
+ * allocate/initialize next page
*/
/* if log wraps, the first data page of log is 2
* (0 never used, 1 is superblock).
@@ -953,7 +953,7 @@ static int lmLogSync(struct jfs_log * log, int hard_sync)
}
/*
- * forward syncpt
+ * forward syncpt
*/
/* if last sync is same as last syncpt,
* invoke sync point forward processing to update sync.
@@ -989,7 +989,7 @@ static int lmLogSync(struct jfs_log * log, int hard_sync)
lsn = log->lsn;
/*
- * setup next syncpt trigger (SWAG)
+ * setup next syncpt trigger (SWAG)
*/
logsize = log->logsize;
@@ -1000,11 +1000,11 @@ static int lmLogSync(struct jfs_log * log, int hard_sync)
if (more < 2 * LOGPSIZE) {
jfs_warn("\n ... Log Wrap ... Log Wrap ... Log Wrap ...\n");
/*
- * log wrapping
+ * log wrapping
*
* option 1 - panic ? No.!
* option 2 - shutdown file systems
- * associated with log ?
+ * associated with log ?
* option 3 - extend log ?
*/
/*
@@ -1062,7 +1062,7 @@ void jfs_syncpt(struct jfs_log *log, int hard_sync)
/*
* NAME: lmLogOpen()
*
- * FUNCTION: open the log on first open;
+ * FUNCTION: open the log on first open;
* insert filesystem in the active list of the log.
*
* PARAMETER: ipmnt - file system mount inode
@@ -1113,7 +1113,7 @@ int lmLogOpen(struct super_block *sb)
init_waitqueue_head(&log->syncwait);
/*
- * external log as separate logical volume
+ * external log as separate logical volume
*
* file systems to log may have n-to-1 relationship;
*/
@@ -1155,7 +1155,7 @@ journal_found:
return 0;
/*
- * unwind on error
+ * unwind on error
*/
shutdown: /* unwind lbmLogInit() */
list_del(&log->journal_list);
@@ -1427,7 +1427,7 @@ int lmLogInit(struct jfs_log * log)
return 0;
/*
- * unwind on error
+ * unwind on error
*/
errout30: /* release log page */
log->wqueue = NULL;
@@ -1480,7 +1480,7 @@ int lmLogClose(struct super_block *sb)
if (test_bit(log_INLINELOG, &log->flag)) {
/*
- * in-line log in host file system
+ * in-line log in host file system
*/
rc = lmLogShutdown(log);
kfree(log);
@@ -1504,7 +1504,7 @@ int lmLogClose(struct super_block *sb)
goto out;
/*
- * external log as separate logical volume
+ * external log as separate logical volume
*/
list_del(&log->journal_list);
bdev = log->bdev;
@@ -1622,20 +1622,26 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
if (!list_empty(&log->synclist)) {
struct logsyncblk *lp;
+ printk(KERN_ERR "jfs_flush_journal: synclist not empty\n");
list_for_each_entry(lp, &log->synclist, synclist) {
if (lp->xflag & COMMIT_PAGE) {
struct metapage *mp = (struct metapage *)lp;
- dump_mem("orphan metapage", lp,
- sizeof(struct metapage));
- dump_mem("page", mp->page, sizeof(struct page));
- }
- else
- dump_mem("orphan tblock", lp,
- sizeof(struct tblock));
+ print_hex_dump(KERN_ERR, "metapage: ",
+ DUMP_PREFIX_ADDRESS, 16, 4,
+ mp, sizeof(struct metapage), 0);
+ print_hex_dump(KERN_ERR, "page: ",
+ DUMP_PREFIX_ADDRESS, 16,
+ sizeof(long), mp->page,
+ sizeof(struct page), 0);
+ } else
+ print_hex_dump(KERN_ERR, "tblock:",
+ DUMP_PREFIX_ADDRESS, 16, 4,
+ lp, sizeof(struct tblock), 0);
}
}
+#else
+ WARN_ON(!list_empty(&log->synclist));
#endif
- //assert(list_empty(&log->synclist));
clear_bit(log_FLUSH, &log->flag);
}
@@ -1723,7 +1729,7 @@ int lmLogShutdown(struct jfs_log * log)
*
* PARAMETE: log - pointer to logs inode.
* fsdev - kdev_t of filesystem.
- * serial - pointer to returned log serial number
+ * serial - pointer to returned log serial number
* activate - insert/remove device from active list.
*
* RETURN: 0 - success
@@ -1963,7 +1969,7 @@ static void lbmfree(struct lbuf * bp)
* FUNCTION: add a log buffer to the log redrive list
*
* PARAMETER:
- * bp - log buffer
+ * bp - log buffer
*
* NOTES:
* Takes log_redrive_lock.
@@ -2054,7 +2060,7 @@ static void lbmWrite(struct jfs_log * log, struct lbuf * bp, int flag,
bp->l_flag = flag;
/*
- * insert bp at tail of write queue associated with log
+ * insert bp at tail of write queue associated with log
*
* (request is either for bp already/currently at head of queue
* or new bp to be inserted at tail)
@@ -2117,7 +2123,7 @@ static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag)
log->base + (bp->l_pn << (L2LOGPSIZE - log->l2bsize));
/*
- * initiate pageout of the page
+ * initiate pageout of the page
*/
lbmStartIO(bp);
}
@@ -2128,7 +2134,7 @@ static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag)
*
* FUNCTION: Interface to DD strategy routine
*
- * RETURN: none
+ * RETURN: none
*
* serialization: LCACHE_LOCK() is NOT held during log i/o;
*/
@@ -2222,7 +2228,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
bio_put(bio);
/*
- * pagein completion
+ * pagein completion
*/
if (bp->l_flag & lbmREAD) {
bp->l_flag &= ~lbmREAD;
@@ -2236,7 +2242,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
}
/*
- * pageout completion
+ * pageout completion
*
* the bp at the head of write queue has completed pageout.
*
@@ -2302,7 +2308,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
}
/*
- * synchronous pageout:
+ * synchronous pageout:
*
* buffer has not necessarily been removed from write queue
* (e.g., synchronous write of partial-page with COMMIT):
@@ -2316,7 +2322,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
}
/*
- * Group Commit pageout:
+ * Group Commit pageout:
*/
else if (bp->l_flag & lbmGC) {
LCACHE_UNLOCK(flags);
@@ -2324,7 +2330,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
}
/*
- * asynchronous pageout:
+ * asynchronous pageout:
*
* buffer must have been removed from write queue:
* insert buffer at head of freelist where it can be recycled
@@ -2375,7 +2381,7 @@ int jfsIOWait(void *arg)
* FUNCTION: format file system log
*
* PARAMETERS:
- * log - volume log
+ * log - volume log
* logAddress - start address of log space in FS block
* logSize - length of log space in FS block;
*
@@ -2407,16 +2413,16 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
npages = logSize >> sbi->l2nbperpage;
/*
- * log space:
+ * log space:
*
* page 0 - reserved;
* page 1 - log superblock;
* page 2 - log data page: A SYNC log record is written
- * into this page at logform time;
+ * into this page at logform time;
* pages 3-N - log data page: set to empty log data pages;
*/
/*
- * init log superblock: log page 1
+ * init log superblock: log page 1
*/
logsuper = (struct logsuper *) bp->l_ldata;
@@ -2436,7 +2442,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
goto exit;
/*
- * init pages 2 to npages-1 as log data pages:
+ * init pages 2 to npages-1 as log data pages:
*
* log page sequence number (lpsn) initialization:
*
@@ -2479,7 +2485,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
goto exit;
/*
- * initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
+ * initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
*/
for (lspn = 0; lspn < npages - 3; lspn++) {
lp->h.page = lp->t.page = cpu_to_le32(lspn);
@@ -2495,7 +2501,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
rc = 0;
exit:
/*
- * finalize log
+ * finalize log
*/
/* release the buffer */
lbmFree(bp);
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index a53fb17ea219..1f85ef0ec045 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -144,7 +144,7 @@ struct logpage {
*
* (this comment should be rewritten !)
* jfs uses only "after" log records (only a single writer is allowed
- * in a page, pages are written to temporary paging space if
+ * in a page, pages are written to temporary paging space if
* if they must be written to disk before commit, and i/o is
* scheduled for modified pages to their home location after
* the log records containing the after values and the commit
@@ -153,7 +153,7 @@ struct logpage {
*
* a log record consists of a data area of variable length followed by
* a descriptor of fixed size LOGRDSIZE bytes.
- * the data area is rounded up to an integral number of 4-bytes and
+ * the data area is rounded up to an integral number of 4-bytes and
* must be no longer than LOGPSIZE.
* the descriptor is of size of multiple of 4-bytes and aligned on a
* 4-byte boundary.
@@ -215,13 +215,13 @@ struct lrd {
union {
/*
- * COMMIT: commit
+ * COMMIT: commit
*
* transaction commit: no type-dependent information;
*/
/*
- * REDOPAGE: after-image
+ * REDOPAGE: after-image
*
* apply after-image;
*
@@ -236,7 +236,7 @@ struct lrd {
} redopage; /* (20) */
/*
- * NOREDOPAGE: the page is freed
+ * NOREDOPAGE: the page is freed
*
* do not apply after-image records which precede this record
* in the log with the same page block number to this page.
@@ -252,7 +252,7 @@ struct lrd {
} noredopage; /* (20) */
/*
- * UPDATEMAP: update block allocation map
+ * UPDATEMAP: update block allocation map
*
* either in-line PXD,
* or out-of-line XADLIST;
@@ -268,7 +268,7 @@ struct lrd {
} updatemap; /* (20) */
/*
- * NOREDOINOEXT: the inode extent is freed
+ * NOREDOINOEXT: the inode extent is freed
*
* do not apply after-image records which precede this
* record in the log with the any of the 4 page block
@@ -286,7 +286,7 @@ struct lrd {
} noredoinoext; /* (20) */
/*
- * SYNCPT: log sync point
+ * SYNCPT: log sync point
*
* replay log upto syncpt address specified;
*/
@@ -295,13 +295,13 @@ struct lrd {
} syncpt;
/*
- * MOUNT: file system mount
+ * MOUNT: file system mount
*
* file system mount: no type-dependent information;
*/
/*
- * ? FREEXTENT: free specified extent(s)
+ * ? FREEXTENT: free specified extent(s)
*
* free specified extent(s) from block allocation map
* N.B.: nextents should be length of data/sizeof(xad_t)
@@ -314,7 +314,7 @@ struct lrd {
} freextent;
/*
- * ? NOREDOFILE: this file is freed
+ * ? NOREDOFILE: this file is freed
*
* do not apply records which precede this record in the log
* with the same inode number.
@@ -330,7 +330,7 @@ struct lrd {
} noredofile;
/*
- * ? NEWPAGE:
+ * ? NEWPAGE:
*
* metadata type dependent
*/
@@ -342,7 +342,7 @@ struct lrd {
} newpage;
/*
- * ? DUMMY: filler
+ * ? DUMMY: filler
*
* no type-dependent information
*/
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 43d4f69afbec..77c7f1129dde 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -472,7 +472,8 @@ add_failed:
printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
goto skip;
dump_bio:
- dump_mem("bio", bio, sizeof(*bio));
+ print_hex_dump(KERN_ERR, "JFS: dump of bio: ", DUMP_PREFIX_ADDRESS, 16,
+ 4, bio, sizeof(*bio), 0);
skip:
bio_put(bio);
unlock_page(page);
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index 4dd479834897..644429acb8c0 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -80,7 +80,7 @@ static int logMOUNT(struct super_block *sb);
*/
int jfs_mount(struct super_block *sb)
{
- int rc = 0; /* Return code */
+ int rc = 0; /* Return code */
struct jfs_sb_info *sbi = JFS_SBI(sb);
struct inode *ipaimap = NULL;
struct inode *ipaimap2 = NULL;
@@ -169,7 +169,7 @@ int jfs_mount(struct super_block *sb)
sbi->ipaimap2 = NULL;
/*
- * mount (the only/single) fileset
+ * mount (the only/single) fileset
*/
/*
* open fileset inode allocation map (aka fileset inode)
@@ -195,7 +195,7 @@ int jfs_mount(struct super_block *sb)
goto out;
/*
- * unwind on error
+ * unwind on error
*/
errout41: /* close fileset inode allocation map inode */
diFreeSpecial(ipimap);
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 25430d0b0d59..7aa1f7004eaf 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -18,7 +18,7 @@
*/
/*
- * jfs_txnmgr.c: transaction manager
+ * jfs_txnmgr.c: transaction manager
*
* notes:
* transaction starts with txBegin() and ends with txCommit()
@@ -60,7 +60,7 @@
#include "jfs_debug.h"
/*
- * transaction management structures
+ * transaction management structures
*/
static struct {
int freetid; /* index of a free tid structure */
@@ -103,19 +103,19 @@ module_param(nTxLock, int, 0);
MODULE_PARM_DESC(nTxLock,
"Number of transaction locks (max:65536)");
-struct tblock *TxBlock; /* transaction block table */
-static int TxLockLWM; /* Low water mark for number of txLocks used */
-static int TxLockHWM; /* High water mark for number of txLocks used */
-static int TxLockVHWM; /* Very High water mark */
-struct tlock *TxLock; /* transaction lock table */
+struct tblock *TxBlock; /* transaction block table */
+static int TxLockLWM; /* Low water mark for number of txLocks used */
+static int TxLockHWM; /* High water mark for number of txLocks used */
+static int TxLockVHWM; /* Very High water mark */
+struct tlock *TxLock; /* transaction lock table */
/*
- * transaction management lock
+ * transaction management lock
*/
static DEFINE_SPINLOCK(jfsTxnLock);
-#define TXN_LOCK() spin_lock(&jfsTxnLock)
-#define TXN_UNLOCK() spin_unlock(&jfsTxnLock)
+#define TXN_LOCK() spin_lock(&jfsTxnLock)
+#define TXN_UNLOCK() spin_unlock(&jfsTxnLock)
#define LAZY_LOCK_INIT() spin_lock_init(&TxAnchor.LazyLock);
#define LAZY_LOCK(flags) spin_lock_irqsave(&TxAnchor.LazyLock, flags)
@@ -148,7 +148,7 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event)
#define TXN_WAKEUP(event) wake_up_all(event)
/*
- * statistics
+ * statistics
*/
static struct {
tid_t maxtid; /* 4: biggest tid ever used */
@@ -181,8 +181,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
static void LogSyncRelease(struct metapage * mp);
/*
- * transaction block/lock management
- * ---------------------------------
+ * transaction block/lock management
+ * ---------------------------------
*/
/*
@@ -227,9 +227,9 @@ static void txLockFree(lid_t lid)
}
/*
- * NAME: txInit()
+ * NAME: txInit()
*
- * FUNCTION: initialize transaction management structures
+ * FUNCTION: initialize transaction management structures
*
* RETURN:
*
@@ -333,9 +333,9 @@ int txInit(void)
}
/*
- * NAME: txExit()
+ * NAME: txExit()
*
- * FUNCTION: clean up when module is unloaded
+ * FUNCTION: clean up when module is unloaded
*/
void txExit(void)
{
@@ -346,12 +346,12 @@ void txExit(void)
}
/*
- * NAME: txBegin()
+ * NAME: txBegin()
*
- * FUNCTION: start a transaction.
+ * FUNCTION: start a transaction.
*
- * PARAMETER: sb - superblock
- * flag - force for nested tx;
+ * PARAMETER: sb - superblock
+ * flag - force for nested tx;
*
* RETURN: tid - transaction id
*
@@ -447,13 +447,13 @@ tid_t txBegin(struct super_block *sb, int flag)
}
/*
- * NAME: txBeginAnon()
+ * NAME: txBeginAnon()
*
- * FUNCTION: start an anonymous transaction.
+ * FUNCTION: start an anonymous transaction.
* Blocks if logsync or available tlocks are low to prevent
* anonymous tlocks from depleting supply.
*
- * PARAMETER: sb - superblock
+ * PARAMETER: sb - superblock
*
* RETURN: none
*/
@@ -489,11 +489,11 @@ void txBeginAnon(struct super_block *sb)
}
/*
- * txEnd()
+ * txEnd()
*
* function: free specified transaction block.
*
- * logsync barrier processing:
+ * logsync barrier processing:
*
* serialization:
*/
@@ -577,13 +577,13 @@ wakeup:
}
/*
- * txLock()
+ * txLock()
*
* function: acquire a transaction lock on the specified <mp>
*
* parameter:
*
- * return: transaction lock id
+ * return: transaction lock id
*
* serialization:
*/
@@ -829,12 +829,16 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
/* Only locks on ipimap or ipaimap should reach here */
/* assert(jfs_ip->fileset == AGGREGATE_I); */
if (jfs_ip->fileset != AGGREGATE_I) {
- jfs_err("txLock: trying to lock locked page!");
- dump_mem("ip", ip, sizeof(struct inode));
- dump_mem("mp", mp, sizeof(struct metapage));
- dump_mem("Locker's tblk", tid_to_tblock(tid),
- sizeof(struct tblock));
- dump_mem("Tlock", tlck, sizeof(struct tlock));
+ printk(KERN_ERR "txLock: trying to lock locked page!");
+ print_hex_dump(KERN_ERR, "ip: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ ip, sizeof(*ip), 0);
+ print_hex_dump(KERN_ERR, "mp: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ mp, sizeof(*mp), 0);
+ print_hex_dump(KERN_ERR, "Locker's tblock: ",
+ DUMP_PREFIX_ADDRESS, 16, 4, tid_to_tblock(tid),
+ sizeof(struct tblock), 0);
+ print_hex_dump(KERN_ERR, "Tlock: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ tlck, sizeof(*tlck), 0);
BUG();
}
INCREMENT(stattx.waitlock); /* statistics */
@@ -857,17 +861,17 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
}
/*
- * NAME: txRelease()
+ * NAME: txRelease()
*
- * FUNCTION: Release buffers associated with transaction locks, but don't
+ * FUNCTION: Release buffers associated with transaction locks, but don't
* mark homeok yet. The allows other transactions to modify
* buffers, but won't let them go to disk until commit record
* actually gets written.
*
* PARAMETER:
- * tblk -
+ * tblk -
*
- * RETURN: Errors from subroutines.
+ * RETURN: Errors from subroutines.
*/
static void txRelease(struct tblock * tblk)
{
@@ -896,10 +900,10 @@ static void txRelease(struct tblock * tblk)
}
/*
- * NAME: txUnlock()
+ * NAME: txUnlock()
*
- * FUNCTION: Initiates pageout of pages modified by tid in journalled
- * objects and frees their lockwords.
+ * FUNCTION: Initiates pageout of pages modified by tid in journalled
+ * objects and frees their lockwords.
*/
static void txUnlock(struct tblock * tblk)
{
@@ -983,10 +987,10 @@ static void txUnlock(struct tblock * tblk)
}
/*
- * txMaplock()
+ * txMaplock()
*
* function: allocate a transaction lock for freed page/entry;
- * for freed page, maplock is used as xtlock/dtlock type;
+ * for freed page, maplock is used as xtlock/dtlock type;
*/
struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
{
@@ -1057,7 +1061,7 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
}
/*
- * txLinelock()
+ * txLinelock()
*
* function: allocate a transaction lock for log vector list
*/
@@ -1092,39 +1096,39 @@ struct linelock *txLinelock(struct linelock * tlock)
}
/*
- * transaction commit management
- * -----------------------------
+ * transaction commit management
+ * -----------------------------
*/
/*
- * NAME: txCommit()
- *
- * FUNCTION: commit the changes to the objects specified in
- * clist. For journalled segments only the
- * changes of the caller are committed, ie by tid.
- * for non-journalled segments the data are flushed to
- * disk and then the change to the disk inode and indirect
- * blocks committed (so blocks newly allocated to the
- * segment will be made a part of the segment atomically).
- *
- * all of the segments specified in clist must be in
- * one file system. no more than 6 segments are needed
- * to handle all unix svcs.
- *
- * if the i_nlink field (i.e. disk inode link count)
- * is zero, and the type of inode is a regular file or
- * directory, or symbolic link , the inode is truncated
- * to zero length. the truncation is committed but the
- * VM resources are unaffected until it is closed (see
- * iput and iclose).
+ * NAME: txCommit()
+ *
+ * FUNCTION: commit the changes to the objects specified in
+ * clist. For journalled segments only the
+ * changes of the caller are committed, ie by tid.
+ * for non-journalled segments the data are flushed to
+ * disk and then the change to the disk inode and indirect
+ * blocks committed (so blocks newly allocated to the
+ * segment will be made a part of the segment atomically).
+ *
+ * all of the segments specified in clist must be in
+ * one file system. no more than 6 segments are needed
+ * to handle all unix svcs.
+ *
+ * if the i_nlink field (i.e. disk inode link count)
+ * is zero, and the type of inode is a regular file or
+ * directory, or symbolic link , the inode is truncated
+ * to zero length. the truncation is committed but the
+ * VM resources are unaffected until it is closed (see
+ * iput and iclose).
*
* PARAMETER:
*
* RETURN:
*
* serialization:
- * on entry the inode lock on each segment is assumed
- * to be held.
+ * on entry the inode lock on each segment is assumed
+ * to be held.
*
* i/o error:
*/
@@ -1175,7 +1179,7 @@ int txCommit(tid_t tid, /* transaction identifier */
if ((flag & (COMMIT_FORCE | COMMIT_SYNC)) == 0)
tblk->xflag |= COMMIT_LAZY;
/*
- * prepare non-journaled objects for commit
+ * prepare non-journaled objects for commit
*
* flush data pages of non-journaled file
* to prevent the file getting non-initialized disk blocks
@@ -1186,7 +1190,7 @@ int txCommit(tid_t tid, /* transaction identifier */
cd.nip = nip;
/*
- * acquire transaction lock on (on-disk) inodes
+ * acquire transaction lock on (on-disk) inodes
*
* update on-disk inode from in-memory inode
* acquiring transaction locks for AFTER records
@@ -1262,7 +1266,7 @@ int txCommit(tid_t tid, /* transaction identifier */
}
/*
- * write log records from transaction locks
+ * write log records from transaction locks
*
* txUpdateMap() resets XAD_NEW in XAD.
*/
@@ -1294,7 +1298,7 @@ int txCommit(tid_t tid, /* transaction identifier */
!test_cflag(COMMIT_Nolink, tblk->u.ip)));
/*
- * write COMMIT log record
+ * write COMMIT log record
*/
lrd->type = cpu_to_le16(LOG_COMMIT);
lrd->length = 0;
@@ -1303,7 +1307,7 @@ int txCommit(tid_t tid, /* transaction identifier */
lmGroupCommit(log, tblk);
/*
- * - transaction is now committed -
+ * - transaction is now committed -
*/
/*
@@ -1314,11 +1318,11 @@ int txCommit(tid_t tid, /* transaction identifier */
txForce(tblk);
/*
- * update allocation map.
+ * update allocation map.
*
* update inode allocation map and inode:
* free pager lock on memory object of inode if any.
- * update block allocation map.
+ * update block allocation map.
*
* txUpdateMap() resets XAD_NEW in XAD.
*/
@@ -1326,7 +1330,7 @@ int txCommit(tid_t tid, /* transaction identifier */
txUpdateMap(tblk);
/*
- * free transaction locks and pageout/free pages
+ * free transaction locks and pageout/free pages
*/
txRelease(tblk);
@@ -1335,7 +1339,7 @@ int txCommit(tid_t tid, /* transaction identifier */
/*
- * reset in-memory object state
+ * reset in-memory object state
*/
for (k = 0; k < cd.nip; k++) {
ip = cd.iplist[k];
@@ -1358,11 +1362,11 @@ int txCommit(tid_t tid, /* transaction identifier */
}
/*
- * NAME: txLog()
+ * NAME: txLog()
*
- * FUNCTION: Writes AFTER log records for all lines modified
- * by tid for segments specified by inodes in comdata.
- * Code assumes only WRITELOCKS are recorded in lockwords.
+ * FUNCTION: Writes AFTER log records for all lines modified
+ * by tid for segments specified by inodes in comdata.
+ * Code assumes only WRITELOCKS are recorded in lockwords.
*
* PARAMETERS:
*
@@ -1421,12 +1425,12 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd)
}
/*
- * diLog()
+ * diLog()
*
- * function: log inode tlock and format maplock to update bmap;
+ * function: log inode tlock and format maplock to update bmap;
*/
static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
- struct tlock * tlck, struct commit * cd)
+ struct tlock * tlck, struct commit * cd)
{
int rc = 0;
struct metapage *mp;
@@ -1442,7 +1446,7 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
pxd = &lrd->log.redopage.pxd;
/*
- * inode after image
+ * inode after image
*/
if (tlck->type & tlckENTRY) {
/* log after-image for logredo(): */
@@ -1456,7 +1460,7 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
tlck->flag |= tlckWRITEPAGE;
} else if (tlck->type & tlckFREE) {
/*
- * free inode extent
+ * free inode extent
*
* (pages of the freed inode extent have been invalidated and
* a maplock for free of the extent has been formatted at
@@ -1498,7 +1502,7 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
jfs_err("diLog: UFO type tlck:0x%p", tlck);
#ifdef _JFS_WIP
/*
- * alloc/free external EA extent
+ * alloc/free external EA extent
*
* a maplock for txUpdateMap() to update bPWMAP for alloc/free
* of the extent has been formatted at txLock() time;
@@ -1534,9 +1538,9 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * dataLog()
+ * dataLog()
*
- * function: log data tlock
+ * function: log data tlock
*/
static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct tlock * tlck)
@@ -1580,9 +1584,9 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * dtLog()
+ * dtLog()
*
- * function: log dtree tlock and format maplock to update bmap;
+ * function: log dtree tlock and format maplock to update bmap;
*/
static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct tlock * tlck)
@@ -1603,10 +1607,10 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
/*
- * page extension via relocation: entry insertion;
- * page extension in-place: entry insertion;
- * new right page from page split, reinitialized in-line
- * root from root page split: entry insertion;
+ * page extension via relocation: entry insertion;
+ * page extension in-place: entry insertion;
+ * new right page from page split, reinitialized in-line
+ * root from root page split: entry insertion;
*/
if (tlck->type & (tlckNEW | tlckEXTEND)) {
/* log after-image of the new page for logredo():
@@ -1641,8 +1645,8 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * entry insertion/deletion,
- * sibling page link update (old right page before split);
+ * entry insertion/deletion,
+ * sibling page link update (old right page before split);
*/
if (tlck->type & (tlckENTRY | tlckRELINK)) {
/* log after-image for logredo(): */
@@ -1658,11 +1662,11 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * page deletion: page has been invalidated
- * page relocation: source extent
+ * page deletion: page has been invalidated
+ * page relocation: source extent
*
- * a maplock for free of the page has been formatted
- * at txLock() time);
+ * a maplock for free of the page has been formatted
+ * at txLock() time);
*/
if (tlck->type & (tlckFREE | tlckRELOCATE)) {
/* log LOG_NOREDOPAGE of the deleted page for logredo()
@@ -1683,9 +1687,9 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * xtLog()
+ * xtLog()
*
- * function: log xtree tlock and format maplock to update bmap;
+ * function: log xtree tlock and format maplock to update bmap;
*/
static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct tlock * tlck)
@@ -1725,8 +1729,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
xadlock = (struct xdlistlock *) maplock;
/*
- * entry insertion/extension;
- * sibling page link update (old right page before split);
+ * entry insertion/extension;
+ * sibling page link update (old right page before split);
*/
if (tlck->type & (tlckNEW | tlckGROW | tlckRELINK)) {
/* log after-image for logredo():
@@ -1801,7 +1805,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * page deletion: file deletion/truncation (ref. xtTruncate())
+ * page deletion: file deletion/truncation (ref. xtTruncate())
*
* (page will be invalidated after log is written and bmap
* is updated from the page);
@@ -1908,13 +1912,13 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * page/entry truncation: file truncation (ref. xtTruncate())
+ * page/entry truncation: file truncation (ref. xtTruncate())
*
- * |----------+------+------+---------------|
- * | | |
- * | | hwm - hwm before truncation
- * | next - truncation point
- * lwm - lwm before truncation
+ * |----------+------+------+---------------|
+ * | | |
+ * | | hwm - hwm before truncation
+ * | next - truncation point
+ * lwm - lwm before truncation
* header ?
*/
if (tlck->type & tlckTRUNCATE) {
@@ -1937,7 +1941,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
twm = xtlck->twm.offset;
/*
- * write log records
+ * write log records
*/
/* log after-image for logredo():
*
@@ -1997,7 +2001,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * format maplock(s) for txUpdateMap() to update bmap
+ * format maplock(s) for txUpdateMap() to update bmap
*/
maplock->index = 0;
@@ -2069,9 +2073,9 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * mapLog()
+ * mapLog()
*
- * function: log from maplock of freed data extents;
+ * function: log from maplock of freed data extents;
*/
static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct tlock * tlck)
@@ -2081,7 +2085,7 @@ static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
pxd_t *pxd;
/*
- * page relocation: free the source page extent
+ * page relocation: free the source page extent
*
* a maplock for txUpdateMap() for free of the page
* has been formatted at txLock() time saving the src
@@ -2155,10 +2159,10 @@ static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * txEA()
+ * txEA()
*
- * function: acquire maplock for EA/ACL extents or
- * set COMMIT_INLINE flag;
+ * function: acquire maplock for EA/ACL extents or
+ * set COMMIT_INLINE flag;
*/
void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
{
@@ -2207,10 +2211,10 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
}
/*
- * txForce()
+ * txForce()
*
* function: synchronously write pages locked by transaction
- * after txLog() but before txUpdateMap();
+ * after txLog() but before txUpdateMap();
*/
static void txForce(struct tblock * tblk)
{
@@ -2273,10 +2277,10 @@ static void txForce(struct tblock * tblk)
}
/*
- * txUpdateMap()
+ * txUpdateMap()
*
- * function: update persistent allocation map (and working map
- * if appropriate);
+ * function: update persistent allocation map (and working map
+ * if appropriate);
*
* parameter:
*/
@@ -2298,7 +2302,7 @@ static void txUpdateMap(struct tblock * tblk)
/*
- * update block allocation map
+ * update block allocation map
*
* update allocation state in pmap (and wmap) and
* update lsn of the pmap page;
@@ -2382,7 +2386,7 @@ static void txUpdateMap(struct tblock * tblk)
}
}
/*
- * update inode allocation map
+ * update inode allocation map
*
* update allocation state in pmap and
* update lsn of the pmap page;
@@ -2407,24 +2411,24 @@ static void txUpdateMap(struct tblock * tblk)
}
/*
- * txAllocPMap()
+ * txAllocPMap()
*
* function: allocate from persistent map;
*
* parameter:
- * ipbmap -
- * malock -
- * xad list:
- * pxd:
- *
- * maptype -
- * allocate from persistent map;
- * free from persistent map;
- * (e.g., tmp file - free from working map at releae
- * of last reference);
- * free from persistent and working map;
- *
- * lsn - log sequence number;
+ * ipbmap -
+ * malock -
+ * xad list:
+ * pxd:
+ *
+ * maptype -
+ * allocate from persistent map;
+ * free from persistent map;
+ * (e.g., tmp file - free from working map at releae
+ * of last reference);
+ * free from persistent and working map;
+ *
+ * lsn - log sequence number;
*/
static void txAllocPMap(struct inode *ip, struct maplock * maplock,
struct tblock * tblk)
@@ -2478,9 +2482,9 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock,
}
/*
- * txFreeMap()
+ * txFreeMap()
*
- * function: free from persistent and/or working map;
+ * function: free from persistent and/or working map;
*
* todo: optimization
*/
@@ -2579,9 +2583,9 @@ void txFreeMap(struct inode *ip,
}
/*
- * txFreelock()
+ * txFreelock()
*
- * function: remove tlock from inode anonymous locklist
+ * function: remove tlock from inode anonymous locklist
*/
void txFreelock(struct inode *ip)
{
@@ -2619,7 +2623,7 @@ void txFreelock(struct inode *ip)
}
/*
- * txAbort()
+ * txAbort()
*
* function: abort tx before commit;
*
@@ -2679,7 +2683,7 @@ void txAbort(tid_t tid, int dirty)
}
/*
- * txLazyCommit(void)
+ * txLazyCommit(void)
*
* All transactions except those changing ipimap (COMMIT_FORCE) are
* processed by this routine. This insures that the inode and block
@@ -2728,7 +2732,7 @@ static void txLazyCommit(struct tblock * tblk)
}
/*
- * jfs_lazycommit(void)
+ * jfs_lazycommit(void)
*
* To be run as a kernel daemon. If lbmIODone is called in an interrupt
* context, or where blocking is not wanted, this routine will process
@@ -2913,7 +2917,7 @@ void txResume(struct super_block *sb)
}
/*
- * jfs_sync(void)
+ * jfs_sync(void)
*
* To be run as a kernel daemon. This is awakened when tlocks run low.
* We write any inodes that have anonymous tlocks so they will become
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index 7863cf21afca..ab7288937019 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -94,7 +94,7 @@ extern struct tblock *TxBlock; /* transaction block table */
*/
struct tlock {
lid_t next; /* 2: index next lockword on tid locklist
- * next lockword on freelist
+ * next lockword on freelist
*/
tid_t tid; /* 2: transaction id holding lock */
diff --git a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
index 09b252958687..649f9817accd 100644
--- a/fs/jfs/jfs_types.h
+++ b/fs/jfs/jfs_types.h
@@ -21,7 +21,7 @@
/*
* jfs_types.h:
*
- * basic type/utility definitions
+ * basic type/utility definitions
*
* note: this header file must be the 1st include file
* of JFS include list in all JFS .c file.
@@ -54,8 +54,8 @@ struct timestruc_t {
*/
#define LEFTMOSTONE 0x80000000
-#define HIGHORDER 0x80000000u /* high order bit on */
-#define ONES 0xffffffffu /* all bit on */
+#define HIGHORDER 0x80000000u /* high order bit on */
+#define ONES 0xffffffffu /* all bit on */
/*
* logical xd (lxd)
@@ -148,7 +148,7 @@ typedef struct {
#define sizeDXD(dxd) le32_to_cpu((dxd)->size)
/*
- * directory entry argument
+ * directory entry argument
*/
struct component_name {
int namlen;
@@ -160,14 +160,14 @@ struct component_name {
* DASD limit information - stored in directory inode
*/
struct dasd {
- u8 thresh; /* Alert Threshold (in percent) */
- u8 delta; /* Alert Threshold delta (in percent) */
+ u8 thresh; /* Alert Threshold (in percent) */
+ u8 delta; /* Alert Threshold delta (in percent) */
u8 rsrvd1;
- u8 limit_hi; /* DASD limit (in logical blocks) */
- __le32 limit_lo; /* DASD limit (in logical blocks) */
+ u8 limit_hi; /* DASD limit (in logical blocks) */
+ __le32 limit_lo; /* DASD limit (in logical blocks) */
u8 rsrvd2[3];
- u8 used_hi; /* DASD usage (in logical blocks) */
- __le32 used_lo; /* DASD usage (in logical blocks) */
+ u8 used_hi; /* DASD usage (in logical blocks) */
+ __le32 used_lo; /* DASD usage (in logical blocks) */
};
#define DASDLIMIT(dasdp) \
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index a386f48c73fc..7971f37534a3 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -60,7 +60,7 @@ int jfs_umount(struct super_block *sb)
jfs_info("UnMount JFS: sb:0x%p", sb);
/*
- * update superblock and close log
+ * update superblock and close log
*
* if mounted read-write and log based recovery was enabled
*/
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index acc97c46d8a4..1543906a2e0d 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
- * jfs_xtree.c: extent allocation descriptor B+-tree manager
+ * jfs_xtree.c: extent allocation descriptor B+-tree manager
*/
#include <linux/fs.h>
@@ -32,30 +32,30 @@
/*
* xtree local flag
*/
-#define XT_INSERT 0x00000001
+#define XT_INSERT 0x00000001
/*
- * xtree key/entry comparison: extent offset
+ * xtree key/entry comparison: extent offset
*
* return:
- * -1: k < start of extent
- * 0: start_of_extent <= k <= end_of_extent
- * 1: k > end_of_extent
+ * -1: k < start of extent
+ * 0: start_of_extent <= k <= end_of_extent
+ * 1: k > end_of_extent
*/
#define XT_CMP(CMP, K, X, OFFSET64)\
{\
- OFFSET64 = offsetXAD(X);\
- (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
- ((K) < OFFSET64) ? -1 : 0;\
+ OFFSET64 = offsetXAD(X);\
+ (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
+ ((K) < OFFSET64) ? -1 : 0;\
}
/* write a xad entry */
#define XT_PUTENTRY(XAD, FLAG, OFF, LEN, ADDR)\
{\
- (XAD)->flag = (FLAG);\
- XADoffset((XAD), (OFF));\
- XADlength((XAD), (LEN));\
- XADaddress((XAD), (ADDR));\
+ (XAD)->flag = (FLAG);\
+ XADoffset((XAD), (OFF));\
+ XADlength((XAD), (LEN));\
+ XADaddress((XAD), (ADDR));\
}
#define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)
@@ -76,13 +76,13 @@
MP = NULL;\
RC = -EIO;\
}\
- }\
+ }\
}
/* for consistency */
#define XT_PUTPAGE(MP) BT_PUTPAGE(MP)
-#define XT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
+#define XT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
BT_GETSEARCH(IP, LEAF, BN, MP, xtpage_t, P, INDEX, i_xtroot)
/* xtree entry parameter descriptor */
struct xtsplit {
@@ -97,7 +97,7 @@ struct xtsplit {
/*
- * statistics
+ * statistics
*/
#ifdef CONFIG_JFS_STATISTICS
static struct {
@@ -136,7 +136,7 @@ static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * fp);
#endif /* _STILL_TO_PORT */
/*
- * xtLookup()
+ * xtLookup()
*
* function: map a single page into a physical extent;
*/
@@ -179,7 +179,7 @@ int xtLookup(struct inode *ip, s64 lstart,
}
/*
- * compute the physical extent covering logical extent
+ * compute the physical extent covering logical extent
*
* N.B. search may have failed (e.g., hole in sparse file),
* and returned the index of the next entry.
@@ -220,27 +220,27 @@ int xtLookup(struct inode *ip, s64 lstart,
/*
- * xtLookupList()
+ * xtLookupList()
*
* function: map a single logical extent into a list of physical extent;
*
* parameter:
- * struct inode *ip,
- * struct lxdlist *lxdlist, lxd list (in)
- * struct xadlist *xadlist, xad list (in/out)
- * int flag)
+ * struct inode *ip,
+ * struct lxdlist *lxdlist, lxd list (in)
+ * struct xadlist *xadlist, xad list (in/out)
+ * int flag)
*
* coverage of lxd by xad under assumption of
* . lxd's are ordered and disjoint.
* . xad's are ordered and disjoint.
*
* return:
- * 0: success
+ * 0: success
*
* note: a page being written (even a single byte) is backed fully,
- * except the last page which is only backed with blocks
- * required to cover the last byte;
- * the extent backing a page is fully contained within an xad;
+ * except the last page which is only backed with blocks
+ * required to cover the last byte;
+ * the extent backing a page is fully contained within an xad;
*/
int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
struct xadlist * xadlist, int flag)
@@ -284,7 +284,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
return rc;
/*
- * compute the physical extent covering logical extent
+ * compute the physical extent covering logical extent
*
* N.B. search may have failed (e.g., hole in sparse file),
* and returned the index of the next entry.
@@ -343,7 +343,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
if (lstart >= size)
goto mapend;
- /* compare with the current xad */
+ /* compare with the current xad */
goto compare1;
}
/* lxd is covered by xad */
@@ -430,7 +430,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
/*
* lxd is partially covered by xad
*/
- else { /* (xend < lend) */
+ else { /* (xend < lend) */
/*
* get next xad
@@ -477,22 +477,22 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
/*
- * xtSearch()
+ * xtSearch()
*
- * function: search for the xad entry covering specified offset.
+ * function: search for the xad entry covering specified offset.
*
* parameters:
- * ip - file object;
- * xoff - extent offset;
- * nextp - address of next extent (if any) for search miss
- * cmpp - comparison result:
- * btstack - traverse stack;
- * flag - search process flag (XT_INSERT);
+ * ip - file object;
+ * xoff - extent offset;
+ * nextp - address of next extent (if any) for search miss
+ * cmpp - comparison result:
+ * btstack - traverse stack;
+ * flag - search process flag (XT_INSERT);
*
* returns:
- * btstack contains (bn, index) of search path traversed to the entry.
- * *cmpp is set to result of comparison with the entry returned.
- * the page containing the entry is pinned at exit.
+ * btstack contains (bn, index) of search path traversed to the entry.
+ * *cmpp is set to result of comparison with the entry returned.
+ * the page containing the entry is pinned at exit.
*/
static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
int *cmpp, struct btstack * btstack, int flag)
@@ -517,7 +517,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
btstack->nsplit = 0;
/*
- * search down tree from root:
+ * search down tree from root:
*
* between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
* internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -642,7 +642,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
XT_CMP(cmp, xoff, &p->xad[index], t64);
if (cmp == 0) {
/*
- * search hit
+ * search hit
*/
/* search hit - leaf page:
* return the entry found
@@ -692,7 +692,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
}
/*
- * search miss
+ * search miss
*
* base is the smallest index with key (Kj) greater than
* search key (K) and may be zero or maxentry index.
@@ -773,22 +773,22 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
}
/*
- * xtInsert()
+ * xtInsert()
*
* function:
*
* parameter:
- * tid - transaction id;
- * ip - file object;
- * xflag - extent flag (XAD_NOTRECORDED):
- * xoff - extent offset;
- * xlen - extent length;
- * xaddrp - extent address pointer (in/out):
- * if (*xaddrp)
- * caller allocated data extent at *xaddrp;
- * else
- * allocate data extent and return its xaddr;
- * flag -
+ * tid - transaction id;
+ * ip - file object;
+ * xflag - extent flag (XAD_NOTRECORDED):
+ * xoff - extent offset;
+ * xlen - extent length;
+ * xaddrp - extent address pointer (in/out):
+ * if (*xaddrp)
+ * caller allocated data extent at *xaddrp;
+ * else
+ * allocate data extent and return its xaddr;
+ * flag -
*
* return:
*/
@@ -813,7 +813,7 @@ int xtInsert(tid_t tid, /* transaction id */
jfs_info("xtInsert: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
/*
- * search for the entry location at which to insert:
+ * search for the entry location at which to insert:
*
* xtFastSearch() and xtSearch() both returns (leaf page
* pinned, index at which to insert).
@@ -853,13 +853,13 @@ int xtInsert(tid_t tid, /* transaction id */
}
/*
- * insert entry for new extent
+ * insert entry for new extent
*/
xflag |= XAD_NEW;
/*
- * if the leaf page is full, split the page and
- * propagate up the router entry for the new page from split
+ * if the leaf page is full, split the page and
+ * propagate up the router entry for the new page from split
*
* The xtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -886,7 +886,7 @@ int xtInsert(tid_t tid, /* transaction id */
}
/*
- * insert the new entry into the leaf page
+ * insert the new entry into the leaf page
*/
/*
* acquire a transaction lock on the leaf page;
@@ -930,16 +930,16 @@ int xtInsert(tid_t tid, /* transaction id */
/*
- * xtSplitUp()
+ * xtSplitUp()
*
* function:
- * split full pages as propagating insertion up the tree
+ * split full pages as propagating insertion up the tree
*
* parameter:
- * tid - transaction id;
- * ip - file object;
- * split - entry parameter descriptor;
- * btstack - traverse stack from xtSearch()
+ * tid - transaction id;
+ * ip - file object;
+ * split - entry parameter descriptor;
+ * btstack - traverse stack from xtSearch()
*
* return:
*/
@@ -1199,22 +1199,22 @@ xtSplitUp(tid_t tid,
/*
- * xtSplitPage()
+ * xtSplitPage()
*
* function:
- * split a full non-root page into
- * original/split/left page and new right page
- * i.e., the original/split page remains as left page.
+ * split a full non-root page into
+ * original/split/left page and new right page
+ * i.e., the original/split page remains as left page.
*
* parameter:
- * int tid,
- * struct inode *ip,
- * struct xtsplit *split,
- * struct metapage **rmpp,
- * u64 *rbnp,
+ * int tid,
+ * struct inode *ip,
+ * struct xtsplit *split,
+ * struct metapage **rmpp,
+ * u64 *rbnp,
*
* return:
- * Pointer to page in which to insert or NULL on error.
+ * Pointer to page in which to insert or NULL on error.
*/
static int
xtSplitPage(tid_t tid, struct inode *ip,
@@ -1248,9 +1248,9 @@ xtSplitPage(tid_t tid, struct inode *ip,
rbn = addressPXD(pxd);
/* Allocate blocks to quota. */
- if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
- rc = -EDQUOT;
- goto clean_up;
+ if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+ rc = -EDQUOT;
+ goto clean_up;
}
quota_allocation += lengthPXD(pxd);
@@ -1304,7 +1304,7 @@ xtSplitPage(tid_t tid, struct inode *ip,
skip = split->index;
/*
- * sequential append at tail (after last entry of last page)
+ * sequential append at tail (after last entry of last page)
*
* if splitting the last page on a level because of appending
* a entry to it (skip is maxentry), it's likely that the access is
@@ -1342,7 +1342,7 @@ xtSplitPage(tid_t tid, struct inode *ip,
}
/*
- * non-sequential insert (at possibly middle page)
+ * non-sequential insert (at possibly middle page)
*/
/*
@@ -1465,25 +1465,24 @@ xtSplitPage(tid_t tid, struct inode *ip,
/*
- * xtSplitRoot()
+ * xtSplitRoot()
*
* function:
- * split the full root page into
- * original/root/split page and new right page
- * i.e., root remains fixed in tree anchor (inode) and
- * the root is copied to a single new right child page
- * since root page << non-root page, and
- * the split root page contains a single entry for the
- * new right child page.
+ * split the full root page into original/root/split page and new
+ * right page
+ * i.e., root remains fixed in tree anchor (inode) and the root is
+ * copied to a single new right child page since root page <<
+ * non-root page, and the split root page contains a single entry
+ * for the new right child page.
*
* parameter:
- * int tid,
- * struct inode *ip,
- * struct xtsplit *split,
- * struct metapage **rmpp)
+ * int tid,
+ * struct inode *ip,
+ * struct xtsplit *split,
+ * struct metapage **rmpp)
*
* return:
- * Pointer to page in which to insert or NULL on error.
+ * Pointer to page in which to insert or NULL on error.
*/
static int
xtSplitRoot(tid_t tid,
@@ -1505,7 +1504,7 @@ xtSplitRoot(tid_t tid,
INCREMENT(xtStat.split);
/*
- * allocate a single (right) child page
+ * allocate a single (right) child page
*/
pxdlist = split->pxdlist;
pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1573,7 +1572,7 @@ xtSplitRoot(tid_t tid,
}
/*
- * reset the root
+ * reset the root
*
* init root with the single entry for the new right page
* set the 1st entry offset to 0, which force the left-most key
@@ -1610,7 +1609,7 @@ xtSplitRoot(tid_t tid,
/*
- * xtExtend()
+ * xtExtend()
*
* function: extend in-place;
*
@@ -1677,7 +1676,7 @@ int xtExtend(tid_t tid, /* transaction id */
goto extendOld;
/*
- * extent overflow: insert entry for new extent
+ * extent overflow: insert entry for new extent
*/
//insertNew:
xoff = offsetXAD(xad) + MAXXLEN;
@@ -1685,8 +1684,8 @@ int xtExtend(tid_t tid, /* transaction id */
nextindex = le16_to_cpu(p->header.nextindex);
/*
- * if the leaf page is full, insert the new entry and
- * propagate up the router entry for the new page from split
+ * if the leaf page is full, insert the new entry and
+ * propagate up the router entry for the new page from split
*
* The xtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -1731,7 +1730,7 @@ int xtExtend(tid_t tid, /* transaction id */
}
}
/*
- * insert the new entry into the leaf page
+ * insert the new entry into the leaf page
*/
else {
/* insert the new entry: mark the entry NEW */
@@ -1771,11 +1770,11 @@ int xtExtend(tid_t tid, /* transaction id */
#ifdef _NOTYET
/*
- * xtTailgate()
+ * xtTailgate()
*
* function: split existing 'tail' extent
- * (split offset >= start offset of tail extent), and
- * relocate and extend the split tail half;
+ * (split offset >= start offset of tail extent), and
+ * relocate and extend the split tail half;
*
* note: existing extent may or may not have been committed.
* caller is responsible for pager buffer cache update, and
@@ -1804,7 +1803,7 @@ int xtTailgate(tid_t tid, /* transaction id */
/*
printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
- (ulong)xoff, xlen, (ulong)xaddr);
+ (ulong)xoff, xlen, (ulong)xaddr);
*/
/* there must exist extent to be tailgated */
@@ -1842,18 +1841,18 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
xad = &p->xad[index];
/*
printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
- (ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
+ (ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
*/
if ((llen = xoff - offsetXAD(xad)) == 0)
goto updateOld;
/*
- * partially replace extent: insert entry for new extent
+ * partially replace extent: insert entry for new extent
*/
//insertNew:
/*
- * if the leaf page is full, insert the new entry and
- * propagate up the router entry for the new page from split
+ * if the leaf page is full, insert the new entry and
+ * propagate up the router entry for the new page from split
*
* The xtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -1898,7 +1897,7 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
}
}
/*
- * insert the new entry into the leaf page
+ * insert the new entry into the leaf page
*/
else {
/* insert the new entry: mark the entry NEW */
@@ -1955,17 +1954,17 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
#endif /* _NOTYET */
/*
- * xtUpdate()
+ * xtUpdate()
*
* function: update XAD;
*
- * update extent for allocated_but_not_recorded or
- * compressed extent;
+ * update extent for allocated_but_not_recorded or
+ * compressed extent;
*
* parameter:
- * nxad - new XAD;
- * logical extent of the specified XAD must be completely
- * contained by an existing XAD;
+ * nxad - new XAD;
+ * logical extent of the specified XAD must be completely
+ * contained by an existing XAD;
*/
int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
{ /* new XAD */
@@ -2416,19 +2415,19 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p);
/*
- * xtAppend()
+ * xtAppend()
*
* function: grow in append mode from contiguous region specified ;
*
* parameter:
- * tid - transaction id;
- * ip - file object;
- * xflag - extent flag:
- * xoff - extent offset;
- * maxblocks - max extent length;
- * xlen - extent length (in/out);
- * xaddrp - extent address pointer (in/out):
- * flag -
+ * tid - transaction id;
+ * ip - file object;
+ * xflag - extent flag:
+ * xoff - extent offset;
+ * maxblocks - max extent length;
+ * xlen - extent length (in/out);
+ * xaddrp - extent address pointer (in/out):
+ * flag -
*
* return:
*/
@@ -2460,7 +2459,7 @@ int xtAppend(tid_t tid, /* transaction id */
(ulong) xoff, maxblocks, xlen, (ulong) xaddr);
/*
- * search for the entry location at which to insert:
+ * search for the entry location at which to insert:
*
* xtFastSearch() and xtSearch() both returns (leaf page
* pinned, index at which to insert).
@@ -2482,13 +2481,13 @@ int xtAppend(tid_t tid, /* transaction id */
xlen = min(xlen, (int)(next - xoff));
//insert:
/*
- * insert entry for new extent
+ * insert entry for new extent
*/
xflag |= XAD_NEW;
/*
- * if the leaf page is full, split the page and
- * propagate up the router entry for the new page from split
+ * if the leaf page is full, split the page and
+ * propagate up the router entry for the new page from split
*
* The xtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -2545,7 +2544,7 @@ int xtAppend(tid_t tid, /* transaction id */
return 0;
/*
- * insert the new entry into the leaf page
+ * insert the new entry into the leaf page
*/
insertLeaf:
/*
@@ -2589,17 +2588,17 @@ int xtAppend(tid_t tid, /* transaction id */
/* - TBD for defragmentaion/reorganization -
*
- * xtDelete()
+ * xtDelete()
*
* function:
- * delete the entry with the specified key.
+ * delete the entry with the specified key.
*
- * N.B.: whole extent of the entry is assumed to be deleted.
+ * N.B.: whole extent of the entry is assumed to be deleted.
*
* parameter:
*
* return:
- * ENOENT: if the entry is not found.
+ * ENOENT: if the entry is not found.
*
* exception:
*/
@@ -2665,10 +2664,10 @@ int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag)
/* - TBD for defragmentaion/reorganization -
*
- * xtDeleteUp()
+ * xtDeleteUp()
*
* function:
- * free empty pages as propagating deletion up the tree
+ * free empty pages as propagating deletion up the tree
*
* parameter:
*
@@ -2815,15 +2814,15 @@ xtDeleteUp(tid_t tid, struct inode *ip,
/*
- * NAME: xtRelocate()
+ * NAME: xtRelocate()
*
- * FUNCTION: relocate xtpage or data extent of regular file;
- * This function is mainly used by defragfs utility.
+ * FUNCTION: relocate xtpage or data extent of regular file;
+ * This function is mainly used by defragfs utility.
*
- * NOTE: This routine does not have the logic to handle
- * uncommitted allocated extent. The caller should call
- * txCommit() to commit all the allocation before call
- * this routine.
+ * NOTE: This routine does not have the logic to handle
+ * uncommitted allocated extent. The caller should call
+ * txCommit() to commit all the allocation before call
+ * this routine.
*/
int
xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
@@ -2865,8 +2864,8 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
xtype, (ulong) xoff, xlen, (ulong) oxaddr, (ulong) nxaddr);
/*
- * 1. get and validate the parent xtpage/xad entry
- * covering the source extent to be relocated;
+ * 1. get and validate the parent xtpage/xad entry
+ * covering the source extent to be relocated;
*/
if (xtype == DATAEXT) {
/* search in leaf entry */
@@ -2910,7 +2909,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
jfs_info("xtRelocate: parent xad entry validated.");
/*
- * 2. relocate the extent
+ * 2. relocate the extent
*/
if (xtype == DATAEXT) {
/* if the extent is allocated-but-not-recorded
@@ -2923,7 +2922,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
XT_PUTPAGE(pmp);
/*
- * cmRelocate()
+ * cmRelocate()
*
* copy target data pages to be relocated;
*
@@ -2945,8 +2944,8 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
pno = offset >> CM_L2BSIZE;
npages = (nbytes + (CM_BSIZE - 1)) >> CM_L2BSIZE;
/*
- npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
- (offset >> CM_L2BSIZE) + 1;
+ npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
+ (offset >> CM_L2BSIZE) + 1;
*/
sxaddr = oxaddr;
dxaddr = nxaddr;
@@ -2981,7 +2980,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
jfs_info("xtRelocate: target data extent relocated.");
- } else { /* (xtype == XTPAGE) */
+ } else { /* (xtype == XTPAGE) */
/*
* read in the target xtpage from the source extent;
@@ -3026,16 +3025,14 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
*/
if (lmp) {
BT_MARK_DIRTY(lmp, ip);
- tlck =
- txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
+ tlck = txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
lp->header.next = cpu_to_le64(nxaddr);
XT_PUTPAGE(lmp);
}
if (rmp) {
BT_MARK_DIRTY(rmp, ip);
- tlck =
- txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
+ tlck = txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
rp->header.prev = cpu_to_le64(nxaddr);
XT_PUTPAGE(rmp);
}
@@ -3062,7 +3059,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
* scan may be skipped by commit() and logredo();
*/
BT_MARK_DIRTY(mp, ip);
- /* tlckNEW init xtlck->lwm.offset = XTENTRYSTART; */
+ /* tlckNEW init xtlck->lwm.offset = XTENTRYSTART; */
tlck = txLock(tid, ip, mp, tlckXTREE | tlckNEW);
xtlck = (struct xtlock *) & tlck->lock;
@@ -3084,7 +3081,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
}
/*
- * 3. acquire maplock for the source extent to be freed;
+ * 3. acquire maplock for the source extent to be freed;
*
* acquire a maplock saving the src relocated extent address;
* to free of the extent at commit time;
@@ -3105,7 +3102,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
* is no buffer associated with this lock since the buffer
* has been redirected to the target location.
*/
- else /* (xtype == XTPAGE) */
+ else /* (xtype == XTPAGE) */
tlck = txMaplock(tid, ip, tlckMAP | tlckRELOCATE);
pxdlock = (struct pxd_lock *) & tlck->lock;
@@ -3115,7 +3112,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
pxdlock->index = 1;
/*
- * 4. update the parent xad entry for relocation;
+ * 4. update the parent xad entry for relocation;
*
* acquire tlck for the parent entry with XAD_NEW as entry
* update which will write LOG_REDOPAGE and update bmap for
@@ -3143,22 +3140,22 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
/*
- * xtSearchNode()
+ * xtSearchNode()
*
- * function: search for the internal xad entry covering specified extent.
- * This function is mainly used by defragfs utility.
+ * function: search for the internal xad entry covering specified extent.
+ * This function is mainly used by defragfs utility.
*
* parameters:
- * ip - file object;
- * xad - extent to find;
- * cmpp - comparison result:
- * btstack - traverse stack;
- * flag - search process flag;
+ * ip - file object;
+ * xad - extent to find;
+ * cmpp - comparison result:
+ * btstack - traverse stack;
+ * flag - search process flag;
*
* returns:
- * btstack contains (bn, index) of search path traversed to the entry.
- * *cmpp is set to result of comparison with the entry returned.
- * the page containing the entry is pinned at exit.
+ * btstack contains (bn, index) of search path traversed to the entry.
+ * *cmpp is set to result of comparison with the entry returned.
+ * the page containing the entry is pinned at exit.
*/
static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
int *cmpp, struct btstack * btstack, int flag)
@@ -3181,7 +3178,7 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
xaddr = addressXAD(xad);
/*
- * search down tree from root:
+ * search down tree from root:
*
* between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
* internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -3217,7 +3214,7 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
XT_CMP(cmp, xoff, &p->xad[index], t64);
if (cmp == 0) {
/*
- * search hit
+ * search hit
*
* verify for exact match;
*/
@@ -3245,7 +3242,7 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
}
/*
- * search miss - non-leaf page:
+ * search miss - non-leaf page:
*
* base is the smallest index with key (Kj) greater than
* search key (K) and may be zero or maxentry index.
@@ -3268,15 +3265,15 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
/*
- * xtRelink()
+ * xtRelink()
*
* function:
- * link around a freed page.
+ * link around a freed page.
*
* Parameter:
- * int tid,
- * struct inode *ip,
- * xtpage_t *p)
+ * int tid,
+ * struct inode *ip,
+ * xtpage_t *p)
*
* returns:
*/
@@ -3338,7 +3335,7 @@ static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * p)
/*
- * xtInitRoot()
+ * xtInitRoot()
*
* initialize file root (inline in inode)
*/
@@ -3385,42 +3382,42 @@ void xtInitRoot(tid_t tid, struct inode *ip)
#define MAX_TRUNCATE_LEAVES 50
/*
- * xtTruncate()
+ * xtTruncate()
*
* function:
- * traverse for truncation logging backward bottom up;
- * terminate at the last extent entry at the current subtree
- * root page covering new down size.
- * truncation may occur within the last extent entry.
+ * traverse for truncation logging backward bottom up;
+ * terminate at the last extent entry at the current subtree
+ * root page covering new down size.
+ * truncation may occur within the last extent entry.
*
* parameter:
- * int tid,
- * struct inode *ip,
- * s64 newsize,
- * int type) {PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
+ * int tid,
+ * struct inode *ip,
+ * s64 newsize,
+ * int type) {PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
*
* return:
*
* note:
- * PWMAP:
- * 1. truncate (non-COMMIT_NOLINK file)
- * by jfs_truncate() or jfs_open(O_TRUNC):
- * xtree is updated;
+ * PWMAP:
+ * 1. truncate (non-COMMIT_NOLINK file)
+ * by jfs_truncate() or jfs_open(O_TRUNC):
+ * xtree is updated;
* 2. truncate index table of directory when last entry removed
- * map update via tlock at commit time;
- * PMAP:
+ * map update via tlock at commit time;
+ * PMAP:
* Call xtTruncate_pmap instead
- * WMAP:
- * 1. remove (free zero link count) on last reference release
- * (pmap has been freed at commit zero link count);
- * 2. truncate (COMMIT_NOLINK file, i.e., tmp file):
- * xtree is updated;
- * map update directly at truncation time;
+ * WMAP:
+ * 1. remove (free zero link count) on last reference release
+ * (pmap has been freed at commit zero link count);
+ * 2. truncate (COMMIT_NOLINK file, i.e., tmp file):
+ * xtree is updated;
+ * map update directly at truncation time;
*
- * if (DELETE)
- * no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
- * else if (TRUNCATE)
- * must write LOG_NOREDOPAGE for deleted index page;
+ * if (DELETE)
+ * no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
+ * else if (TRUNCATE)
+ * must write LOG_NOREDOPAGE for deleted index page;
*
* pages may already have been tlocked by anonymous transactions
* during file growth (i.e., write) before truncation;
@@ -3493,7 +3490,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
* retained in the new sized file.
* if type is PMAP, the data and index pages are NOT
* freed, and the data and index blocks are NOT freed
- * from working map.
+ * from working map.
* (this will allow continued access of data/index of
* temporary file (zerolink count file truncated to zero-length)).
*/
@@ -3542,7 +3539,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
goto getChild;
/*
- * leaf page
+ * leaf page
*/
freed = 0;
@@ -3916,7 +3913,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
}
/*
- * internal page: go down to child page of current entry
+ * internal page: go down to child page of current entry
*/
getChild:
/* save current parent entry for the child page */
@@ -3965,7 +3962,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
/*
- * xtTruncate_pmap()
+ * xtTruncate_pmap()
*
* function:
* Perform truncate to zero lenghth for deleted file, leaving the
@@ -3974,9 +3971,9 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
* is committed to disk.
*
* parameter:
- * tid_t tid,
- * struct inode *ip,
- * s64 committed_size)
+ * tid_t tid,
+ * struct inode *ip,
+ * s64 committed_size)
*
* return: new committed size
*
@@ -4050,7 +4047,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
}
/*
- * leaf page
+ * leaf page
*/
if (++locked_leaves > MAX_TRUNCATE_LEAVES) {
@@ -4062,7 +4059,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
xoff = offsetXAD(xad);
xlen = lengthXAD(xad);
XT_PUTPAGE(mp);
- return (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
+ return (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
}
tlck = txLock(tid, ip, mp, tlckXTREE);
tlck->type = tlckXTREE | tlckFREE;
@@ -4099,8 +4096,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
*/
tlck = txLock(tid, ip, mp, tlckXTREE);
xtlck = (struct xtlock *) & tlck->lock;
- xtlck->hwm.offset =
- le16_to_cpu(p->header.nextindex) - 1;
+ xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1;
tlck->type = tlckXTREE | tlckFREE;
XT_PUTPAGE(mp);
@@ -4118,7 +4114,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
else
index--;
/*
- * internal page: go down to child page of current entry
+ * internal page: go down to child page of current entry
*/
getChild:
/* save current parent entry for the child page */
diff --git a/fs/jfs/jfs_xtree.h b/fs/jfs/jfs_xtree.h
index 164f6f2b1019..70815c8a3d6a 100644
--- a/fs/jfs/jfs_xtree.h
+++ b/fs/jfs/jfs_xtree.h
@@ -19,14 +19,14 @@
#define _H_JFS_XTREE
/*
- * jfs_xtree.h: extent allocation descriptor B+-tree manager
+ * jfs_xtree.h: extent allocation descriptor B+-tree manager
*/
#include "jfs_btree.h"
/*
- * extent allocation descriptor (xad)
+ * extent allocation descriptor (xad)
*/
typedef struct xad {
unsigned flag:8; /* 1: flag */
@@ -38,30 +38,30 @@ typedef struct xad {
__le32 addr2; /* 4: address in unit of fsblksize */
} xad_t; /* (16) */
-#define MAXXLEN ((1 << 24) - 1)
+#define MAXXLEN ((1 << 24) - 1)
-#define XTSLOTSIZE 16
-#define L2XTSLOTSIZE 4
+#define XTSLOTSIZE 16
+#define L2XTSLOTSIZE 4
/* xad_t field construction */
#define XADoffset(xad, offset64)\
{\
- (xad)->off1 = ((u64)offset64) >> 32;\
- (xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\
+ (xad)->off1 = ((u64)offset64) >> 32;\
+ (xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\
}
#define XADaddress(xad, address64)\
{\
- (xad)->addr1 = ((u64)address64) >> 32;\
- (xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
+ (xad)->addr1 = ((u64)address64) >> 32;\
+ (xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
}
-#define XADlength(xad, length32) (xad)->len = __cpu_to_le24(length32)
+#define XADlength(xad, length32) (xad)->len = __cpu_to_le24(length32)
/* xad_t field extraction */
#define offsetXAD(xad)\
- ( ((s64)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2))
+ ( ((s64)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2))
#define addressXAD(xad)\
- ( ((s64)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2))
-#define lengthXAD(xad) __le24_to_cpu((xad)->len)
+ ( ((s64)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2))
+#define lengthXAD(xad) __le24_to_cpu((xad)->len)
/* xad list */
struct xadlist {
@@ -71,22 +71,22 @@ struct xadlist {
};
/* xad_t flags */
-#define XAD_NEW 0x01 /* new */
-#define XAD_EXTENDED 0x02 /* extended */
-#define XAD_COMPRESSED 0x04 /* compressed with recorded length */
+#define XAD_NEW 0x01 /* new */
+#define XAD_EXTENDED 0x02 /* extended */
+#define XAD_COMPRESSED 0x04 /* compressed with recorded length */
#define XAD_NOTRECORDED 0x08 /* allocated but not recorded */
-#define XAD_COW 0x10 /* copy-on-write */
+#define XAD_COW 0x10 /* copy-on-write */
/* possible values for maxentry */
-#define XTROOTINITSLOT_DIR 6
-#define XTROOTINITSLOT 10
-#define XTROOTMAXSLOT 18
-#define XTPAGEMAXSLOT 256
-#define XTENTRYSTART 2
+#define XTROOTINITSLOT_DIR 6
+#define XTROOTINITSLOT 10
+#define XTROOTMAXSLOT 18
+#define XTPAGEMAXSLOT 256
+#define XTENTRYSTART 2
/*
- * xtree page:
+ * xtree page:
*/
typedef union {
struct xtheader {
@@ -106,7 +106,7 @@ typedef union {
} xtpage_t;
/*
- * external declaration
+ * external declaration
*/
extern int xtLookup(struct inode *ip, s64 lstart, s64 llen,
int *pflag, s64 * paddr, int *plen, int flag);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 41c204771262..25161c4121e4 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -328,7 +328,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
* dentry - child directory dentry
*
* RETURN: -EINVAL - if name is . or ..
- * -EINVAL - if . or .. exist but are invalid.
+ * -EINVAL - if . or .. exist but are invalid.
* errors from subroutines
*
* note:
@@ -517,7 +517,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
inode_dec_link_count(ip);
/*
- * commit zero link count object
+ * commit zero link count object
*/
if (ip->i_nlink == 0) {
assert(!test_cflag(COMMIT_Nolink, ip));
@@ -596,7 +596,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
/*
* NAME: commitZeroLink()
*
- * FUNCTION: for non-directory, called by jfs_remove(),
+ * FUNCTION: for non-directory, called by jfs_remove(),
* truncate a regular file, directory or symbolic
* link to zero length. return 0 if type is not
* one of these.
@@ -676,7 +676,7 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
/*
* NAME: jfs_free_zero_link()
*
- * FUNCTION: for non-directory, called by iClose(),
+ * FUNCTION: for non-directory, called by iClose(),
* free resources of a file from cache and WORKING map
* for a file previously committed with zero link count
* while associated with a pager object,
@@ -855,12 +855,12 @@ static int jfs_link(struct dentry *old_dentry,
* NAME: jfs_symlink(dip, dentry, name)
*
* FUNCTION: creates a symbolic link to <symlink> by name <name>
- * in directory <dip>
+ * in directory <dip>
*
- * PARAMETER: dip - parent directory vnode
- * dentry - dentry of symbolic link
- * name - the path name of the existing object
- * that will be the source of the link
+ * PARAMETER: dip - parent directory vnode
+ * dentry - dentry of symbolic link
+ * name - the path name of the existing object
+ * that will be the source of the link
*
* RETURN: errors from subroutines
*
@@ -1052,9 +1052,9 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
/*
- * NAME: jfs_rename
+ * NAME: jfs_rename
*
- * FUNCTION: rename a file or directory
+ * FUNCTION: rename a file or directory
*/
static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
@@ -1331,9 +1331,9 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/*
- * NAME: jfs_mknod
+ * NAME: jfs_mknod
*
- * FUNCTION: Create a special file (device)
+ * FUNCTION: Create a special file (device)
*/
static int jfs_mknod(struct inode *dir, struct dentry *dentry,
int mode, dev_t rdev)
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 79d625f3f733..71984ee95346 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -29,17 +29,17 @@
#include "jfs_txnmgr.h"
#include "jfs_debug.h"
-#define BITSPERPAGE (PSIZE << 3)
-#define L2MEGABYTE 20
-#define MEGABYTE (1 << L2MEGABYTE)
-#define MEGABYTE32 (MEGABYTE << 5)
+#define BITSPERPAGE (PSIZE << 3)
+#define L2MEGABYTE 20
+#define MEGABYTE (1 << L2MEGABYTE)
+#define MEGABYTE32 (MEGABYTE << 5)
/* convert block number to bmap file page number */
#define BLKTODMAPN(b)\
- (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)
+ (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)
/*
- * jfs_extendfs()
+ * jfs_extendfs()
*
* function: extend file system;
*
@@ -48,9 +48,9 @@
* workspace space
*
* input:
- * new LVSize: in LV blocks (required)
- * new LogSize: in LV blocks (optional)
- * new FSSize: in LV blocks (optional)
+ * new LVSize: in LV blocks (required)
+ * new LogSize: in LV blocks (optional)
+ * new FSSize: in LV blocks (optional)
*
* new configuration:
* 1. set new LogSize as specified or default from new LVSize;
@@ -125,8 +125,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
}
/*
- * reconfigure LV spaces
- * ---------------------
+ * reconfigure LV spaces
+ * ---------------------
*
* validate new size, or, if not specified, determine new size
*/
@@ -198,7 +198,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
log_formatted = 1;
}
/*
- * quiesce file system
+ * quiesce file system
*
* (prepare to move the inline log and to prevent map update)
*
@@ -270,8 +270,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
}
/*
- * extend block allocation map
- * ---------------------------
+ * extend block allocation map
+ * ---------------------------
*
* extendfs() for new extension, retry after crash recovery;
*
@@ -283,7 +283,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
* s_size: aggregate size in physical blocks;
*/
/*
- * compute the new block allocation map configuration
+ * compute the new block allocation map configuration
*
* map dinode:
* di_size: map file size in byte;
@@ -301,7 +301,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
newNpages = BLKTODMAPN(t64) + 1;
/*
- * extend map from current map (WITHOUT growing mapfile)
+ * extend map from current map (WITHOUT growing mapfile)
*
* map new extension with unmapped part of the last partial
* dmap page, if applicable, and extra page(s) allocated
@@ -341,8 +341,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
XSize -= nblocks;
/*
- * grow map file to cover remaining extension
- * and/or one extra dmap page for next extendfs();
+ * grow map file to cover remaining extension
+ * and/or one extra dmap page for next extendfs();
*
* allocate new map pages and its backing blocks, and
* update map file xtree
@@ -422,8 +422,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
dbFinalizeBmap(ipbmap);
/*
- * update inode allocation map
- * ---------------------------
+ * update inode allocation map
+ * ---------------------------
*
* move iag lists from old to new iag;
* agstart field is not updated for logredo() to reconstruct
@@ -442,8 +442,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
}
/*
- * finalize
- * --------
+ * finalize
+ * --------
*
* extension is committed when on-disk super block is
* updated with new descriptors: logredo will recover
@@ -480,7 +480,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
diFreeSpecial(ipbmap2);
/*
- * update superblock
+ * update superblock
*/
if ((rc = readSuper(sb, &bh)))
goto error_out;
@@ -530,7 +530,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
resume:
/*
- * resume file system transactions
+ * resume file system transactions
*/
txResume(sb);
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index b753ba216450..b2375f0774b7 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -63,9 +63,9 @@
*
* On-disk:
*
- * FEALISTs are stored on disk using blocks allocated by dbAlloc() and
- * written directly. An EA list may be in-lined in the inode if there is
- * sufficient room available.
+ * FEALISTs are stored on disk using blocks allocated by dbAlloc() and
+ * written directly. An EA list may be in-lined in the inode if there is
+ * sufficient room available.
*/
struct ea_buffer {
@@ -590,7 +590,8 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
size_check:
if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
printk(KERN_ERR "ea_get: invalid extended attribute\n");
- dump_mem("xattr", ea_buf->xattr, ea_size);
+ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
+ ea_buf->xattr, ea_size, 1);
ea_release(inode, ea_buf);
rc = -EIO;
goto clean_up;
diff --git a/fs/minix/file.c b/fs/minix/file.c
index f92baa1d7570..17765f697e50 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -23,7 +23,7 @@ const struct file_operations minix_file_operations = {
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = minix_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations minix_file_inode_operations = {
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 9eb8eb4e4a08..8689b736fdd9 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -41,7 +41,9 @@ static int nfs_file_open(struct inode *, struct file *);
static int nfs_file_release(struct inode *, struct file *);
static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
static int nfs_file_mmap(struct file *, struct vm_area_struct *);
-static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
+static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t count, unsigned int flags);
static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
unsigned long nr_segs, loff_t pos);
static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
@@ -65,7 +67,7 @@ const struct file_operations nfs_file_operations = {
.fsync = nfs_fsync,
.lock = nfs_lock,
.flock = nfs_flock,
- .sendfile = nfs_file_sendfile,
+ .splice_read = nfs_file_splice_read,
.check_flags = nfs_check_flags,
};
@@ -224,20 +226,21 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
}
static ssize_t
-nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
- read_actor_t actor, void *target)
+nfs_file_splice_read(struct file *filp, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t count,
+ unsigned int flags)
{
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
ssize_t res;
- dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n",
+ dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long long) *ppos);
res = nfs_revalidate_mapping(inode, filp->f_mapping);
if (!res)
- res = generic_file_sendfile(filp, ppos, count, actor, target);
+ res = generic_file_splice_read(filp, ppos, pipe, count, flags);
return res;
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7e6aa245b5d5..8604e35bd48e 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -23,7 +23,7 @@
#include <linux/file.h>
#include <linux/mount.h>
#include <linux/major.h>
-#include <linux/ext2_fs.h>
+#include <linux/splice.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
@@ -801,26 +801,32 @@ found:
}
/*
- * Grab and keep cached pages assosiated with a file in the svc_rqst
- * so that they can be passed to the netowork sendmsg/sendpage routines
- * directrly. They will be released after the sending has completed.
+ * Grab and keep cached pages associated with a file in the svc_rqst
+ * so that they can be passed to the network sendmsg/sendpage routines
+ * directly. They will be released after the sending has completed.
*/
static int
-nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
+nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
{
- unsigned long count = desc->count;
- struct svc_rqst *rqstp = desc->arg.data;
+ struct svc_rqst *rqstp = sd->u.data;
struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
+ struct page *page = buf->page;
+ size_t size;
+ int ret;
+
+ ret = buf->ops->confirm(pipe, buf);
+ if (unlikely(ret))
+ return ret;
- if (size > count)
- size = count;
+ size = sd->len;
if (rqstp->rq_res.page_len == 0) {
get_page(page);
put_page(*pp);
*pp = page;
rqstp->rq_resused++;
- rqstp->rq_res.page_base = offset;
+ rqstp->rq_res.page_base = buf->offset;
rqstp->rq_res.page_len = size;
} else if (page != pp[-1]) {
get_page(page);
@@ -832,11 +838,15 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
} else
rqstp->rq_res.page_len += size;
- desc->count = count - size;
- desc->written += size;
return size;
}
+static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
+ struct splice_desc *sd)
+{
+ return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
+}
+
static __be32
nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
@@ -861,10 +871,15 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
if (ra && ra->p_set)
file->f_ra = ra->p_ra;
- if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
- rqstp->rq_resused = 1;
- host_err = file->f_op->sendfile(file, &offset, *count,
- nfsd_read_actor, rqstp);
+ if (file->f_op->splice_read && rqstp->rq_splice_ok) {
+ struct splice_desc sd = {
+ .len = 0,
+ .total_len = *count,
+ .pos = offset,
+ .u.data = rqstp,
+ };
+
+ host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
} else {
oldfs = get_fs();
set_fs(KERNEL_DS);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 7ed56390b582..ffcc504a1667 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2276,7 +2276,7 @@ const struct file_operations ntfs_file_ops = {
mounted filesystem. */
.mmap = generic_file_mmap, /* Mmap file. */
.open = ntfs_file_open, /* Open file. */
- .sendfile = generic_file_sendfile, /* Zero-copy data send with
+ .splice_read = generic_file_splice_read /* Zero-copy data send with
the data source being on
the ntfs partition. We do
not need to care about the
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index ac6c96431bbc..4979b6675717 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -31,7 +31,7 @@
#include <linux/pagemap.h>
#include <linux/uio.h>
#include <linux/sched.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
#include <linux/mount.h>
#include <linux/writeback.h>
@@ -1583,7 +1583,7 @@ static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe,
ssize_t copied = 0;
struct ocfs2_splice_write_priv sp;
- ret = buf->ops->pin(pipe, buf);
+ ret = buf->ops->confirm(pipe, buf);
if (ret)
goto out;
@@ -1604,7 +1604,7 @@ static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe,
* might enter ocfs2_buffered_write_cluster() more
* than once, so keep track of our progress here.
*/
- copied = ocfs2_buffered_write_cluster(sd->file,
+ copied = ocfs2_buffered_write_cluster(sd->u.file,
(loff_t)sd->pos + total,
count,
ocfs2_map_and_write_splice_data,
@@ -1636,9 +1636,14 @@ static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,
int ret, err;
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
-
- ret = __splice_from_pipe(pipe, out, ppos, len, flags,
- ocfs2_splice_write_actor);
+ struct splice_desc sd = {
+ .total_len = len,
+ .flags = flags,
+ .pos = *ppos,
+ .u.file = out,
+ };
+
+ ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor);
if (ret > 0) {
*ppos += ret;
@@ -1817,7 +1822,6 @@ const struct inode_operations ocfs2_special_file_iops = {
const struct file_operations ocfs2_fops = {
.read = do_sync_read,
.write = do_sync_write,
- .sendfile = generic_file_sendfile,
.mmap = ocfs2_mmap,
.fsync = ocfs2_sync_file,
.release = ocfs2_file_release,
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index 9f7ad4244f63..1e064c4a4f86 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -45,7 +45,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int blocksize, offset, size,res;
loff_t i_size;
- dasd_information_t *info;
+ dasd_information2_t *info;
struct hd_geometry *geo;
char type[5] = {0,};
char name[7] = {0,};
@@ -64,14 +64,17 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
if (i_size == 0)
goto out_exit;
- if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
+ info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
+ if (info == NULL)
goto out_exit;
- if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
+ geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL);
+ if (geo == NULL)
goto out_nogeo;
- if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL)
+ label = kmalloc(sizeof(union label_t), GFP_KERNEL);
+ if (label == NULL)
goto out_nolab;
- if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
+ if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 ||
ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
goto out_freeall;
@@ -96,84 +99,108 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
res = 1;
/*
- * Three different types: CMS1, VOL1 and LNX1/unlabeled
+ * Three different formats: LDL, CDL and unformated disk
+ *
+ * identified by info->format
+ *
+ * unformated disks we do not have to care about
*/
- if (strncmp(type, "CMS1", 4) == 0) {
- /*
- * VM style CMS1 labeled disk
- */
- if (label->cms.disk_offset != 0) {
- printk("CMS1/%8s(MDSK):", name);
- /* disk is reserved minidisk */
- blocksize = label->cms.block_size;
- offset = label->cms.disk_offset;
- size = (label->cms.block_count - 1) * (blocksize >> 9);
+ if (info->format == DASD_FORMAT_LDL) {
+ if (strncmp(type, "CMS1", 4) == 0) {
+ /*
+ * VM style CMS1 labeled disk
+ */
+ if (label->cms.disk_offset != 0) {
+ printk("CMS1/%8s(MDSK):", name);
+ /* disk is reserved minidisk */
+ blocksize = label->cms.block_size;
+ offset = label->cms.disk_offset;
+ size = (label->cms.block_count - 1)
+ * (blocksize >> 9);
+ } else {
+ printk("CMS1/%8s:", name);
+ offset = (info->label_block + 1);
+ size = i_size >> 9;
+ }
} else {
- printk("CMS1/%8s:", name);
+ /*
+ * Old style LNX1 or unlabeled disk
+ */
+ if (strncmp(type, "LNX1", 4) == 0)
+ printk ("LNX1/%8s:", name);
+ else
+ printk("(nonl)");
offset = (info->label_block + 1);
size = i_size >> 9;
}
put_partition(state, 1, offset*(blocksize >> 9),
- size-offset*(blocksize >> 9));
- } else if ((strncmp(type, "VOL1", 4) == 0) &&
- (!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
+ size-offset*(blocksize >> 9));
+ } else if (info->format == DASD_FORMAT_CDL) {
/*
- * New style VOL1 labeled disk
+ * New style CDL formatted disk
*/
unsigned int blk;
int counter;
- printk("VOL1/%8s:", name);
-
- /* get block number and read then go through format1 labels */
- blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
- counter = 0;
- while ((data = read_dev_sector(bdev, blk*(blocksize/512),
- &sect)) != NULL) {
- struct vtoc_format1_label f1;
-
- memcpy(&f1, data, sizeof(struct vtoc_format1_label));
- put_dev_sector(sect);
-
- /* skip FMT4 / FMT5 / FMT7 labels */
- if (f1.DS1FMTID == _ascebc['4']
- || f1.DS1FMTID == _ascebc['5']
- || f1.DS1FMTID == _ascebc['7']) {
- blk++;
- continue;
- }
-
- /* only FMT1 valid at this point */
- if (f1.DS1FMTID != _ascebc['1'])
- break;
-
- /* OK, we got valid partition data */
- offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
- size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
- offset + geo->sectors;
- if (counter >= state->limit)
- break;
- put_partition(state, counter + 1,
- offset * (blocksize >> 9),
- size * (blocksize >> 9));
- counter++;
- blk++;
- }
- if (!data)
- /* Are we not supposed to report this ? */
- goto out_readerr;
- } else {
/*
- * Old style LNX1 or unlabeled disk
+ * check if VOL1 label is available
+ * if not, something is wrong, skipping partition detection
*/
- if (strncmp(type, "LNX1", 4) == 0)
- printk ("LNX1/%8s:", name);
- else
- printk("(nonl)/%8s:", name);
- offset = (info->label_block + 1);
- size = i_size >> 9;
- put_partition(state, 1, offset*(blocksize >> 9),
- size-offset*(blocksize >> 9));
+ if (strncmp(type, "VOL1", 4) == 0) {
+ printk("VOL1/%8s:", name);
+ /*
+ * get block number and read then go through format1
+ * labels
+ */
+ blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
+ counter = 0;
+ data = read_dev_sector(bdev, blk * (blocksize/512),
+ &sect);
+ while (data != NULL) {
+ struct vtoc_format1_label f1;
+
+ memcpy(&f1, data,
+ sizeof(struct vtoc_format1_label));
+ put_dev_sector(sect);
+
+ /* skip FMT4 / FMT5 / FMT7 labels */
+ if (f1.DS1FMTID == _ascebc['4']
+ || f1.DS1FMTID == _ascebc['5']
+ || f1.DS1FMTID == _ascebc['7']) {
+ blk++;
+ data = read_dev_sector(bdev, blk *
+ (blocksize/512),
+ &sect);
+ continue;
+ }
+
+ /* only FMT1 valid at this point */
+ if (f1.DS1FMTID != _ascebc['1'])
+ break;
+
+ /* OK, we got valid partition data */
+ offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
+ size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
+ offset + geo->sectors;
+ if (counter >= state->limit)
+ break;
+ put_partition(state, counter + 1,
+ offset * (blocksize >> 9),
+ size * (blocksize >> 9));
+ counter++;
+ blk++;
+ data = read_dev_sector(bdev,
+ blk * (blocksize/512),
+ &sect);
+ }
+
+ if (!data)
+ /* Are we not supposed to report this ? */
+ goto out_readerr;
+ } else
+ printk(KERN_WARNING "Warning, expected Label VOL1 not "
+ "found, treating as CDL formated Disk");
+
}
printk("\n");
diff --git a/fs/pipe.c b/fs/pipe.c
index 3a89592bdf57..d007830d9c87 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -164,6 +164,20 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
page_cache_release(page);
}
+/**
+ * generic_pipe_buf_map - virtually map a pipe buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer that should be mapped
+ * @atomic: whether to use an atomic map
+ *
+ * Description:
+ * This function returns a kernel virtual address mapping for the
+ * passed in @pipe_buffer. If @atomic is set, an atomic map is provided
+ * and the caller has to be careful not to fault before calling
+ * the unmap function.
+ *
+ * Note that this function occupies KM_USER0 if @atomic != 0.
+ */
void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
struct pipe_buffer *buf, int atomic)
{
@@ -175,6 +189,15 @@ void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
return kmap(buf->page);
}
+/**
+ * generic_pipe_buf_unmap - unmap a previously mapped pipe buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer that should be unmapped
+ * @map_data: the data that the mapping function returned
+ *
+ * Description:
+ * This function undoes the mapping that ->map() provided.
+ */
void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
struct pipe_buffer *buf, void *map_data)
{
@@ -185,11 +208,28 @@ void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
kunmap(buf->page);
}
+/**
+ * generic_pipe_buf_steal - attempt to take ownership of a @pipe_buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer to attempt to steal
+ *
+ * Description:
+ * This function attempts to steal the @struct page attached to
+ * @buf. If successful, this function returns 0 and returns with
+ * the page locked. The caller may then reuse the page for whatever
+ * he wishes, the typical use is insertion into a different file
+ * page cache.
+ */
int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
struct page *page = buf->page;
+ /*
+ * A reference of one is golden, that means that the owner of this
+ * page is the only one holding a reference to it. lock the page
+ * and return OK.
+ */
if (page_count(page) == 1) {
lock_page(page);
return 0;
@@ -198,12 +238,32 @@ int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
return 1;
}
-void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/**
+ * generic_pipe_buf_get - get a reference to a @struct pipe_buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer to get a reference to
+ *
+ * Description:
+ * This function grabs an extra reference to @buf. It's used in
+ * in the tee() system call, when we duplicate the buffers in one
+ * pipe into another.
+ */
+void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
{
page_cache_get(buf->page);
}
-int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/**
+ * generic_pipe_buf_confirm - verify contents of the pipe buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer to confirm
+ *
+ * Description:
+ * This function does nothing, because the generic pipe code uses
+ * pages that are always good when inserted into the pipe.
+ */
+int generic_pipe_buf_confirm(struct pipe_inode_info *info,
+ struct pipe_buffer *buf)
{
return 0;
}
@@ -212,7 +272,7 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
.can_merge = 1,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
- .pin = generic_pipe_buf_pin,
+ .confirm = generic_pipe_buf_confirm,
.release = anon_pipe_buf_release,
.steal = generic_pipe_buf_steal,
.get = generic_pipe_buf_get,
@@ -252,7 +312,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
if (chars > total_len)
chars = total_len;
- error = ops->pin(pipe, buf);
+ error = ops->confirm(pipe, buf);
if (error) {
if (!ret)
error = ret;
@@ -373,7 +433,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
int error, atomic = 1;
void *addr;
- error = ops->pin(pipe, buf);
+ error = ops->confirm(pipe, buf);
if (error)
goto out;
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 74f30e0c0381..98e78e2f18d6 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -165,7 +165,6 @@ static inline char * task_state(struct task_struct *p, char *buffer)
rcu_read_lock();
buffer += sprintf(buffer,
"State:\t%s\n"
- "SleepAVG:\t%lu%%\n"
"Tgid:\t%d\n"
"Pid:\t%d\n"
"PPid:\t%d\n"
@@ -173,7 +172,6 @@ static inline char * task_state(struct task_struct *p, char *buffer)
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n",
get_task_state(p),
- (p->sleep_avg/1024)*100/(1020000000/1024),
p->tgid, p->pid,
pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
@@ -312,6 +310,41 @@ int proc_pid_status(struct task_struct *task, char * buffer)
return buffer - orig;
}
+static clock_t task_utime(struct task_struct *p)
+{
+ clock_t utime = cputime_to_clock_t(p->utime),
+ total = utime + cputime_to_clock_t(p->stime);
+ u64 temp;
+
+ /*
+ * Use CFS's precise accounting:
+ */
+ temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
+
+ if (total) {
+ temp *= utime;
+ do_div(temp, total);
+ }
+ utime = (clock_t)temp;
+
+ return utime;
+}
+
+static clock_t task_stime(struct task_struct *p)
+{
+ clock_t stime = cputime_to_clock_t(p->stime);
+
+ /*
+ * Use CFS's precise accounting. (we subtract utime from
+ * the total, to make sure the total observed by userspace
+ * grows monotonically - apps rely on that):
+ */
+ stime = nsec_to_clock_t(p->se.sum_exec_runtime) - task_utime(p);
+
+ return stime;
+}
+
+
static int do_task_stat(struct task_struct *task, char * buffer, int whole)
{
unsigned long vsize, eip, esp, wchan = ~0UL;
@@ -326,7 +359,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
unsigned long long start_time;
unsigned long cmin_flt = 0, cmaj_flt = 0;
unsigned long min_flt = 0, maj_flt = 0;
- cputime_t cutime, cstime, utime, stime;
+ cputime_t cutime, cstime;
+ clock_t utime, stime;
unsigned long rsslim = 0;
char tcomm[sizeof(task->comm)];
unsigned long flags;
@@ -344,7 +378,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
sigemptyset(&sigign);
sigemptyset(&sigcatch);
- cutime = cstime = utime = stime = cputime_zero;
+ cutime = cstime = cputime_zero;
+ utime = stime = 0;
rcu_read_lock();
if (lock_task_sighand(task, &flags)) {
@@ -370,15 +405,15 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
do {
min_flt += t->min_flt;
maj_flt += t->maj_flt;
- utime = cputime_add(utime, t->utime);
- stime = cputime_add(stime, t->stime);
+ utime += task_utime(t);
+ stime += task_stime(t);
t = next_thread(t);
} while (t != task);
min_flt += sig->min_flt;
maj_flt += sig->maj_flt;
- utime = cputime_add(utime, sig->utime);
- stime = cputime_add(stime, sig->stime);
+ utime += cputime_to_clock_t(sig->utime);
+ stime += cputime_to_clock_t(sig->stime);
}
sid = signal_session(sig);
@@ -394,8 +429,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
if (!whole) {
min_flt = task->min_flt;
maj_flt = task->maj_flt;
- utime = task->utime;
- stime = task->stime;
+ utime = task_utime(task);
+ stime = task_stime(task);
}
/* scale priority and nice values from timeslices to -20..20 */
@@ -426,8 +461,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
cmin_flt,
maj_flt,
cmaj_flt,
- cputime_to_clock_t(utime),
- cputime_to_clock_t(stime),
+ utime,
+ stime,
cputime_to_clock_t(cutime),
cputime_to_clock_t(cstime),
priority,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a5fa1fdafc4e..46ea5d56e1bb 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -296,7 +296,7 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
*/
static int proc_pid_schedstat(struct task_struct *task, char *buffer)
{
- return sprintf(buffer, "%lu %lu %lu\n",
+ return sprintf(buffer, "%llu %llu %lu\n",
task->sched_info.cpu_time,
task->sched_info.run_delay,
task->sched_info.pcnt);
@@ -929,6 +929,69 @@ static const struct file_operations proc_fault_inject_operations = {
};
#endif
+#ifdef CONFIG_SCHED_DEBUG
+/*
+ * Print out various scheduling related per-task fields:
+ */
+static int sched_show(struct seq_file *m, void *v)
+{
+ struct inode *inode = m->private;
+ struct task_struct *p;
+
+ WARN_ON(!inode);
+
+ p = get_proc_task(inode);
+ if (!p)
+ return -ESRCH;
+ proc_sched_show_task(p, m);
+
+ put_task_struct(p);
+
+ return 0;
+}
+
+static ssize_t
+sched_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct task_struct *p;
+
+ WARN_ON(!inode);
+
+ p = get_proc_task(inode);
+ if (!p)
+ return -ESRCH;
+ proc_sched_set_task(p);
+
+ put_task_struct(p);
+
+ return count;
+}
+
+static int sched_open(struct inode *inode, struct file *filp)
+{
+ int ret;
+
+ ret = single_open(filp, sched_show, NULL);
+ if (!ret) {
+ struct seq_file *m = filp->private_data;
+
+ m->private = inode;
+ }
+ return ret;
+}
+
+static const struct file_operations proc_pid_sched_operations = {
+ .open = sched_open,
+ .read = seq_read,
+ .write = sched_write,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+#endif
+
static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
@@ -1963,6 +2026,9 @@ static const struct pid_entry tgid_base_stuff[] = {
INF("environ", S_IRUSR, pid_environ),
INF("auxv", S_IRUSR, pid_auxv),
INF("status", S_IRUGO, pid_status),
+#ifdef CONFIG_SCHED_DEBUG
+ REG("sched", S_IRUGO|S_IWUSR, pid_sched),
+#endif
INF("cmdline", S_IRUGO, pid_cmdline),
INF("stat", S_IRUGO, tgid_stat),
INF("statm", S_IRUGO, pid_statm),
@@ -2247,6 +2313,9 @@ static const struct pid_entry tid_base_stuff[] = {
INF("environ", S_IRUSR, pid_environ),
INF("auxv", S_IRUSR, pid_auxv),
INF("status", S_IRUGO, pid_status),
+#ifdef CONFIG_SCHED_DEBUG
+ REG("sched", S_IRUGO|S_IWUSR, pid_sched),
+#endif
INF("cmdline", S_IRUGO, pid_cmdline),
INF("stat", S_IRUGO, tid_stat),
INF("statm", S_IRUGO, pid_statm),
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 44649981bbc8..867f42b02035 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -25,7 +25,7 @@ const struct file_operations qnx4_file_operations =
.read = do_sync_read,
.aio_read = generic_file_aio_read,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
#ifdef CONFIG_QNX4FS_RW
.write = do_sync_write,
.aio_write = generic_file_aio_write,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 2f14774a124f..97bdc0b2f9d2 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -41,7 +41,7 @@ const struct file_operations ramfs_file_operations = {
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = simple_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.llseek = generic_file_llseek,
};
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 5d258c40a2fd..cad2b7ace630 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -42,7 +42,7 @@ const struct file_operations ramfs_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.fsync = simple_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.llseek = generic_file_llseek,
};
diff --git a/fs/read_write.c b/fs/read_write.c
index 4d03008f015b..507ddff48a9a 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/pagemap.h>
+#include <linux/splice.h>
#include "read_write.h"
#include <asm/uaccess.h>
@@ -25,7 +26,7 @@ const struct file_operations generic_ro_fops = {
.read = do_sync_read,
.aio_read = generic_file_aio_read,
.mmap = generic_file_readonly_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
EXPORT_SYMBOL(generic_ro_fops);
@@ -708,7 +709,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
struct inode * in_inode, * out_inode;
loff_t pos;
ssize_t retval;
- int fput_needed_in, fput_needed_out;
+ int fput_needed_in, fput_needed_out, fl;
/*
* Get input file, and verify that it is ok..
@@ -723,7 +724,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
in_inode = in_file->f_path.dentry->d_inode;
if (!in_inode)
goto fput_in;
- if (!in_file->f_op || !in_file->f_op->sendfile)
+ if (!in_file->f_op || !in_file->f_op->splice_read)
goto fput_in;
retval = -ESPIPE;
if (!ppos)
@@ -776,7 +777,18 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
count = max - pos;
}
- retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
+ fl = 0;
+#if 0
+ /*
+ * We need to debate whether we can enable this or not. The
+ * man page documents EAGAIN return for the output at least,
+ * and the application is arguably buggy if it doesn't expect
+ * EAGAIN on a non-blocking file descriptor.
+ */
+ if (in_file->f_flags & O_NONBLOCK)
+ fl = SPLICE_F_NONBLOCK;
+#endif
+ retval = do_splice_direct(in_file, ppos, out_file, count, fl);
if (retval > 0) {
add_rchar(current, retval);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 9e451a68580f..30eebfb1b2d8 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1531,7 +1531,6 @@ const struct file_operations reiserfs_file_operations = {
.open = generic_file_open,
.release = reiserfs_file_release,
.fsync = reiserfs_sync_file,
- .sendfile = generic_file_sendfile,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.splice_read = generic_file_splice_read,
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index aea3f8aa54c0..c5d78a7e492b 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -262,8 +262,9 @@ out:
}
static ssize_t
-smb_file_sendfile(struct file *file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
+smb_file_splice_read(struct file *file, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t count,
+ unsigned int flags)
{
struct dentry *dentry = file->f_path.dentry;
ssize_t status;
@@ -277,7 +278,7 @@ smb_file_sendfile(struct file *file, loff_t *ppos,
DENTRY_PATH(dentry), status);
goto out;
}
- status = generic_file_sendfile(file, ppos, count, actor, target);
+ status = generic_file_splice_read(file, ppos, pipe, count, flags);
out:
return status;
}
@@ -416,7 +417,7 @@ const struct file_operations smb_file_operations =
.open = smb_file_open,
.release = smb_file_release,
.fsync = smb_fsync,
- .sendfile = smb_file_sendfile,
+ .splice_read = smb_file_splice_read,
};
const struct inode_operations smb_file_inode_operations =
diff --git a/fs/splice.c b/fs/splice.c
index e7d7080de2f9..ed2ce995475c 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -20,7 +20,7 @@
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/pagemap.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
#include <linux/mm_inline.h>
#include <linux/swap.h>
#include <linux/writeback.h>
@@ -29,22 +29,6 @@
#include <linux/syscalls.h>
#include <linux/uio.h>
-struct partial_page {
- unsigned int offset;
- unsigned int len;
-};
-
-/*
- * Passed to splice_to_pipe
- */
-struct splice_pipe_desc {
- struct page **pages; /* page map */
- struct partial_page *partial; /* pages[] may not be contig */
- int nr_pages; /* number of pages in map */
- unsigned int flags; /* splice flags */
- const struct pipe_buf_operations *ops;/* ops associated with output pipe */
-};
-
/*
* Attempt to steal a page from a pipe buffer. This should perhaps go into
* a vm helper function, it's already simplified quite a bit by the
@@ -101,8 +85,12 @@ static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,
buf->flags &= ~PIPE_BUF_FLAG_LRU;
}
-static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
+/*
+ * Check whether the contents of buf is OK to access. Since the content
+ * is a page cache page, IO may be in flight.
+ */
+static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
{
struct page *page = buf->page;
int err;
@@ -143,7 +131,7 @@ static const struct pipe_buf_operations page_cache_pipe_buf_ops = {
.can_merge = 0,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
- .pin = page_cache_pipe_buf_pin,
+ .confirm = page_cache_pipe_buf_confirm,
.release = page_cache_pipe_buf_release,
.steal = page_cache_pipe_buf_steal,
.get = generic_pipe_buf_get,
@@ -163,18 +151,25 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = {
.can_merge = 0,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
- .pin = generic_pipe_buf_pin,
+ .confirm = generic_pipe_buf_confirm,
.release = page_cache_pipe_buf_release,
.steal = user_page_pipe_buf_steal,
.get = generic_pipe_buf_get,
};
-/*
- * Pipe output worker. This sets up our pipe format with the page cache
- * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
+/**
+ * splice_to_pipe - fill passed data into a pipe
+ * @pipe: pipe to fill
+ * @spd: data to fill
+ *
+ * Description:
+ * @spd contains a map of pages and len/offset tupples, a long with
+ * the struct pipe_buf_operations associated with these pages. This
+ * function will link that data to the pipe.
+ *
*/
-static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
- struct splice_pipe_desc *spd)
+ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
+ struct splice_pipe_desc *spd)
{
unsigned int spd_pages = spd->nr_pages;
int ret, do_wakeup, page_nr;
@@ -201,6 +196,7 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
buf->page = spd->pages[page_nr];
buf->offset = spd->partial[page_nr].offset;
buf->len = spd->partial[page_nr].len;
+ buf->private = spd->partial[page_nr].private;
buf->ops = spd->ops;
if (spd->flags & SPLICE_F_GIFT)
buf->flags |= PIPE_BUF_FLAG_GIFT;
@@ -296,19 +292,15 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
/*
- * Now fill in the holes:
- */
- error = 0;
-
- /*
* Lookup the (hopefully) full range of pages we need.
*/
spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages);
/*
* If find_get_pages_contig() returned fewer pages than we needed,
- * allocate the rest.
+ * allocate the rest and fill in the holes.
*/
+ error = 0;
index += spd.nr_pages;
while (spd.nr_pages < nr_pages) {
/*
@@ -470,11 +462,16 @@ fill_it:
/**
* generic_file_splice_read - splice data from file to a pipe
* @in: file to splice from
+ * @ppos: position in @in
* @pipe: pipe to splice to
* @len: number of bytes to splice
* @flags: splice modifier flags
*
- * Will read pages from given file and fill them into a pipe.
+ * Description:
+ * Will read pages from given file and fill them into a pipe. Can be
+ * used as long as the address_space operations for the source implements
+ * a readpage() hook.
+ *
*/
ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
@@ -528,11 +525,11 @@ EXPORT_SYMBOL(generic_file_splice_read);
static int pipe_to_sendpage(struct pipe_inode_info *pipe,
struct pipe_buffer *buf, struct splice_desc *sd)
{
- struct file *file = sd->file;
+ struct file *file = sd->u.file;
loff_t pos = sd->pos;
int ret, more;
- ret = buf->ops->pin(pipe, buf);
+ ret = buf->ops->confirm(pipe, buf);
if (!ret) {
more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
@@ -566,7 +563,7 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe,
static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
struct splice_desc *sd)
{
- struct file *file = sd->file;
+ struct file *file = sd->u.file;
struct address_space *mapping = file->f_mapping;
unsigned int offset, this_len;
struct page *page;
@@ -576,7 +573,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
/*
* make sure the data in this buffer is uptodate
*/
- ret = buf->ops->pin(pipe, buf);
+ ret = buf->ops->confirm(pipe, buf);
if (unlikely(ret))
return ret;
@@ -663,36 +660,37 @@ out_ret:
return ret;
}
-/*
- * Pipe input worker. Most of this logic works like a regular pipe, the
- * key here is the 'actor' worker passed in that actually moves the data
- * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
+/**
+ * __splice_from_pipe - splice data from a pipe to given actor
+ * @pipe: pipe to splice from
+ * @sd: information to @actor
+ * @actor: handler that splices the data
+ *
+ * Description:
+ * This function does little more than loop over the pipe and call
+ * @actor to do the actual moving of a single struct pipe_buffer to
+ * the desired destination. See pipe_to_file, pipe_to_sendpage, or
+ * pipe_to_user.
+ *
*/
-ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
- struct file *out, loff_t *ppos, size_t len,
- unsigned int flags, splice_actor *actor)
+ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
+ splice_actor *actor)
{
int ret, do_wakeup, err;
- struct splice_desc sd;
ret = 0;
do_wakeup = 0;
- sd.total_len = len;
- sd.flags = flags;
- sd.file = out;
- sd.pos = *ppos;
-
for (;;) {
if (pipe->nrbufs) {
struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
const struct pipe_buf_operations *ops = buf->ops;
- sd.len = buf->len;
- if (sd.len > sd.total_len)
- sd.len = sd.total_len;
+ sd->len = buf->len;
+ if (sd->len > sd->total_len)
+ sd->len = sd->total_len;
- err = actor(pipe, buf, &sd);
+ err = actor(pipe, buf, sd);
if (err <= 0) {
if (!ret && err != -ENODATA)
ret = err;
@@ -704,10 +702,10 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
buf->offset += err;
buf->len -= err;
- sd.len -= err;
- sd.pos += err;
- sd.total_len -= err;
- if (sd.len)
+ sd->len -= err;
+ sd->pos += err;
+ sd->total_len -= err;
+ if (sd->len)
continue;
if (!buf->len) {
@@ -719,7 +717,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
do_wakeup = 1;
}
- if (!sd.total_len)
+ if (!sd->total_len)
break;
}
@@ -732,7 +730,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
break;
}
- if (flags & SPLICE_F_NONBLOCK) {
+ if (sd->flags & SPLICE_F_NONBLOCK) {
if (!ret)
ret = -EAGAIN;
break;
@@ -766,12 +764,32 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
}
EXPORT_SYMBOL(__splice_from_pipe);
+/**
+ * splice_from_pipe - splice data from a pipe to a file
+ * @pipe: pipe to splice from
+ * @out: file to splice to
+ * @ppos: position in @out
+ * @len: how many bytes to splice
+ * @flags: splice modifier flags
+ * @actor: handler that splices the data
+ *
+ * Description:
+ * See __splice_from_pipe. This function locks the input and output inodes,
+ * otherwise it's identical to __splice_from_pipe().
+ *
+ */
ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
loff_t *ppos, size_t len, unsigned int flags,
splice_actor *actor)
{
ssize_t ret;
struct inode *inode = out->f_mapping->host;
+ struct splice_desc sd = {
+ .total_len = len,
+ .flags = flags,
+ .pos = *ppos,
+ .u.file = out,
+ };
/*
* The actor worker might be calling ->prepare_write and
@@ -780,7 +798,7 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
* pipe->inode, we have to order lock acquiry here.
*/
inode_double_lock(inode, pipe->inode);
- ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor);
+ ret = __splice_from_pipe(pipe, &sd, actor);
inode_double_unlock(inode, pipe->inode);
return ret;
@@ -790,12 +808,14 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
* generic_file_splice_write_nolock - generic_file_splice_write without mutexes
* @pipe: pipe info
* @out: file to write to
+ * @ppos: position in @out
* @len: number of bytes to splice
* @flags: splice modifier flags
*
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file. The caller is responsible
- * for acquiring i_mutex on both inodes.
+ * Description:
+ * Will either move or copy pages (determined by @flags options) from
+ * the given pipe inode to the given file. The caller is responsible
+ * for acquiring i_mutex on both inodes.
*
*/
ssize_t
@@ -804,6 +824,12 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
{
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
+ struct splice_desc sd = {
+ .total_len = len,
+ .flags = flags,
+ .pos = *ppos,
+ .u.file = out,
+ };
ssize_t ret;
int err;
@@ -811,7 +837,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
if (unlikely(err))
return err;
- ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+ ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
if (ret > 0) {
unsigned long nr_pages;
@@ -841,11 +867,13 @@ EXPORT_SYMBOL(generic_file_splice_write_nolock);
* generic_file_splice_write - splice data from a pipe to a file
* @pipe: pipe info
* @out: file to write to
+ * @ppos: position in @out
* @len: number of bytes to splice
* @flags: splice modifier flags
*
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file.
+ * Description:
+ * Will either move or copy pages (determined by @flags options) from
+ * the given pipe inode to the given file.
*
*/
ssize_t
@@ -896,13 +924,15 @@ EXPORT_SYMBOL(generic_file_splice_write);
/**
* generic_splice_sendpage - splice data from a pipe to a socket
- * @inode: pipe inode
+ * @pipe: pipe to splice from
* @out: socket to write to
+ * @ppos: position in @out
* @len: number of bytes to splice
* @flags: splice modifier flags
*
- * Will send @len bytes from the pipe to a network socket. No data copying
- * is involved.
+ * Description:
+ * Will send @len bytes from the pipe to a network socket. No data copying
+ * is involved.
*
*/
ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
@@ -956,14 +986,27 @@ static long do_splice_to(struct file *in, loff_t *ppos,
return in->f_op->splice_read(in, ppos, pipe, len, flags);
}
-long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
- size_t len, unsigned int flags)
+/**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+ * @in: file to splice from
+ * @sd: actor information on where to splice to
+ * @actor: handles the data splicing
+ *
+ * Description:
+ * This is a special case helper to splice directly between two
+ * points, without requiring an explicit pipe. Internally an allocated
+ * pipe is cached in the process, and reused during the life time of
+ * that process.
+ *
+ */
+ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+ splice_direct_actor *actor)
{
struct pipe_inode_info *pipe;
long ret, bytes;
- loff_t out_off;
umode_t i_mode;
- int i;
+ size_t len;
+ int i, flags;
/*
* We require the input being a regular file, as we don't want to
@@ -999,7 +1042,13 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
*/
ret = 0;
bytes = 0;
- out_off = 0;
+ len = sd->total_len;
+ flags = sd->flags;
+
+ /*
+ * Don't block on output, we have to drain the direct pipe.
+ */
+ sd->flags &= ~SPLICE_F_NONBLOCK;
while (len) {
size_t read_len, max_read_len;
@@ -1009,19 +1058,19 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
*/
max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
- ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
+ ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags);
if (unlikely(ret < 0))
goto out_release;
read_len = ret;
+ sd->total_len = read_len;
/*
* NOTE: nonblocking mode only applies to the input. We
* must not do the output in nonblocking mode as then we
* could get stuck data in the internal pipe:
*/
- ret = do_splice_from(pipe, out, &out_off, read_len,
- flags & ~SPLICE_F_NONBLOCK);
+ ret = actor(pipe, sd);
if (unlikely(ret < 0))
goto out_release;
@@ -1066,6 +1115,48 @@ out_release:
return bytes;
return ret;
+
+}
+EXPORT_SYMBOL(splice_direct_to_actor);
+
+static int direct_splice_actor(struct pipe_inode_info *pipe,
+ struct splice_desc *sd)
+{
+ struct file *file = sd->u.file;
+
+ return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
+}
+
+/**
+ * do_splice_direct - splices data directly between two files
+ * @in: file to splice from
+ * @ppos: input file offset
+ * @out: file to splice to
+ * @len: number of bytes to splice
+ * @flags: splice modifier flags
+ *
+ * Description:
+ * For use by do_sendfile(). splice can easily emulate sendfile, but
+ * doing it in the application would incur an extra system call
+ * (splice in + splice out, as compared to just sendfile()). So this helper
+ * can splice directly through a process-private pipe.
+ *
+ */
+long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+ size_t len, unsigned int flags)
+{
+ struct splice_desc sd = {
+ .len = len,
+ .total_len = len,
+ .flags = flags,
+ .pos = *ppos,
+ .u.file = out,
+ };
+ size_t ret;
+
+ ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
+ *ppos = sd.pos;
+ return ret;
}
/*
@@ -1248,28 +1339,131 @@ static int get_iovec_page_array(const struct iovec __user *iov,
return error;
}
+static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
+{
+ char *src;
+ int ret;
+
+ ret = buf->ops->confirm(pipe, buf);
+ if (unlikely(ret))
+ return ret;
+
+ /*
+ * See if we can use the atomic maps, by prefaulting in the
+ * pages and doing an atomic copy
+ */
+ if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) {
+ src = buf->ops->map(pipe, buf, 1);
+ ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset,
+ sd->len);
+ buf->ops->unmap(pipe, buf, src);
+ if (!ret) {
+ ret = sd->len;
+ goto out;
+ }
+ }
+
+ /*
+ * No dice, use slow non-atomic map and copy
+ */
+ src = buf->ops->map(pipe, buf, 0);
+
+ ret = sd->len;
+ if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len))
+ ret = -EFAULT;
+
+out:
+ if (ret > 0)
+ sd->u.userptr += ret;
+ buf->ops->unmap(pipe, buf, src);
+ return ret;
+}
+
+/*
+ * For lack of a better implementation, implement vmsplice() to userspace
+ * as a simple copy of the pipes pages to the user iov.
+ */
+static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags)
+{
+ struct pipe_inode_info *pipe;
+ struct splice_desc sd;
+ ssize_t size;
+ int error;
+ long ret;
+
+ pipe = pipe_info(file->f_path.dentry->d_inode);
+ if (!pipe)
+ return -EBADF;
+
+ if (pipe->inode)
+ mutex_lock(&pipe->inode->i_mutex);
+
+ error = ret = 0;
+ while (nr_segs) {
+ void __user *base;
+ size_t len;
+
+ /*
+ * Get user address base and length for this iovec.
+ */
+ error = get_user(base, &iov->iov_base);
+ if (unlikely(error))
+ break;
+ error = get_user(len, &iov->iov_len);
+ if (unlikely(error))
+ break;
+
+ /*
+ * Sanity check this iovec. 0 read succeeds.
+ */
+ if (unlikely(!len))
+ break;
+ if (unlikely(!base)) {
+ error = -EFAULT;
+ break;
+ }
+
+ sd.len = 0;
+ sd.total_len = len;
+ sd.flags = flags;
+ sd.u.userptr = base;
+ sd.pos = 0;
+
+ size = __splice_from_pipe(pipe, &sd, pipe_to_user);
+ if (size < 0) {
+ if (!ret)
+ ret = size;
+
+ break;
+ }
+
+ ret += size;
+
+ if (size < len)
+ break;
+
+ nr_segs--;
+ iov++;
+ }
+
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+
+ if (!ret)
+ ret = error;
+
+ return ret;
+}
+
/*
* vmsplice splices a user address range into a pipe. It can be thought of
* as splice-from-memory, where the regular splice is splice-from-file (or
* to file). In both cases the output is a pipe, naturally.
- *
- * Note that vmsplice only supports splicing _from_ user memory to a pipe,
- * not the other way around. Splicing from user memory is a simple operation
- * that can be supported without any funky alignment restrictions or nasty
- * vm tricks. We simply map in the user memory and fill them into a pipe.
- * The reverse isn't quite as easy, though. There are two possible solutions
- * for that:
- *
- * - memcpy() the data internally, at which point we might as well just
- * do a regular read() on the buffer anyway.
- * - Lots of nasty vm tricks, that are neither fast nor flexible (it
- * has restriction limitations on both ends of the pipe).
- *
- * Alas, it isn't here.
- *
*/
-static long do_vmsplice(struct file *file, const struct iovec __user *iov,
- unsigned long nr_segs, unsigned int flags)
+static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags)
{
struct pipe_inode_info *pipe;
struct page *pages[PIPE_BUFFERS];
@@ -1284,10 +1478,6 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
pipe = pipe_info(file->f_path.dentry->d_inode);
if (!pipe)
return -EBADF;
- if (unlikely(nr_segs > UIO_MAXIOV))
- return -EINVAL;
- else if (unlikely(!nr_segs))
- return 0;
spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
flags & SPLICE_F_GIFT);
@@ -1297,6 +1487,22 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
return splice_to_pipe(pipe, &spd);
}
+/*
+ * Note that vmsplice only really supports true splicing _from_ user memory
+ * to a pipe, not the other way around. Splicing from user memory is a simple
+ * operation that can be supported without any funky alignment restrictions
+ * or nasty vm tricks. We simply map in the user memory and fill them into
+ * a pipe. The reverse isn't quite as easy, though. There are two possible
+ * solutions for that:
+ *
+ * - memcpy() the data internally, at which point we might as well just
+ * do a regular read() on the buffer anyway.
+ * - Lots of nasty vm tricks, that are neither fast nor flexible (it
+ * has restriction limitations on both ends of the pipe).
+ *
+ * Currently we punt and implement it as a normal copy, see pipe_to_user().
+ *
+ */
asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
unsigned long nr_segs, unsigned int flags)
{
@@ -1304,11 +1510,18 @@ asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
long error;
int fput;
+ if (unlikely(nr_segs > UIO_MAXIOV))
+ return -EINVAL;
+ else if (unlikely(!nr_segs))
+ return 0;
+
error = -EBADF;
file = fget_light(fd, &fput);
if (file) {
if (file->f_mode & FMODE_WRITE)
- error = do_vmsplice(file, iov, nr_segs, flags);
+ error = vmsplice_to_pipe(file, iov, nr_segs, flags);
+ else if (file->f_mode & FMODE_READ)
+ error = vmsplice_to_user(file, iov, nr_segs, flags);
fput_light(file, fput);
}
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 0732ddb9020b..589be21d884e 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -27,7 +27,7 @@ const struct file_operations sysv_file_operations = {
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = sysv_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations sysv_file_inode_operations = {
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 51b5764685e7..df070bee8d4f 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -261,7 +261,7 @@ const struct file_operations udf_file_operations = {
.aio_write = udf_file_aio_write,
.release = udf_release_file,
.fsync = udf_fsync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations udf_file_inode_operations = {
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 1e096323bad4..6705d74c6d2d 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -60,5 +60,5 @@ const struct file_operations ufs_file_operations = {
.mmap = generic_file_mmap,
.open = generic_file_open,
.fsync = ufs_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index cb51dc961355..8c43cd2e237a 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -124,30 +124,6 @@ xfs_file_aio_write_invis(
}
STATIC ssize_t
-xfs_file_sendfile(
- struct file *filp,
- loff_t *pos,
- size_t count,
- read_actor_t actor,
- void *target)
-{
- return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
- filp, pos, 0, count, actor, target, NULL);
-}
-
-STATIC ssize_t
-xfs_file_sendfile_invis(
- struct file *filp,
- loff_t *pos,
- size_t count,
- read_actor_t actor,
- void *target)
-{
- return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
- filp, pos, IO_INVIS, count, actor, target, NULL);
-}
-
-STATIC ssize_t
xfs_file_splice_read(
struct file *infilp,
loff_t *ppos,
@@ -452,7 +428,6 @@ const struct file_operations xfs_file_operations = {
.write = do_sync_write,
.aio_read = xfs_file_aio_read,
.aio_write = xfs_file_aio_write,
- .sendfile = xfs_file_sendfile,
.splice_read = xfs_file_splice_read,
.splice_write = xfs_file_splice_write,
.unlocked_ioctl = xfs_file_ioctl,
@@ -475,7 +450,6 @@ const struct file_operations xfs_invis_file_operations = {
.write = do_sync_write,
.aio_read = xfs_file_aio_read_invis,
.aio_write = xfs_file_aio_write_invis,
- .sendfile = xfs_file_sendfile_invis,
.splice_read = xfs_file_splice_read_invis,
.splice_write = xfs_file_splice_write_invis,
.unlocked_ioctl = xfs_file_ioctl_invis,
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 715adad7dd4d..af24a457d3a3 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -101,7 +101,6 @@
* Feature macros (disable/enable)
*/
#undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */
-#define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */
#define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */
#ifdef CONFIG_SMP
#define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index ed90403f0ee7..765ec16a6e39 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -287,50 +287,6 @@ xfs_read(
}
ssize_t
-xfs_sendfile(
- bhv_desc_t *bdp,
- struct file *filp,
- loff_t *offset,
- int ioflags,
- size_t count,
- read_actor_t actor,
- void *target,
- cred_t *credp)
-{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
- xfs_mount_t *mp = ip->i_mount;
- ssize_t ret;
-
- XFS_STATS_INC(xs_read_calls);
- if (XFS_FORCED_SHUTDOWN(mp))
- return -EIO;
-
- xfs_ilock(ip, XFS_IOLOCK_SHARED);
-
- if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
- (!(ioflags & IO_INVIS))) {
- bhv_vrwlock_t locktype = VRWLOCK_READ;
- int error;
-
- error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
- *offset, count,
- FILP_DELAY_FLAG(filp), &locktype);
- if (error) {
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return -error;
- }
- }
- xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
- (void *)(unsigned long)target, count, *offset, ioflags);
- ret = generic_file_sendfile(filp, offset, count, actor, target);
- if (ret > 0)
- XFS_STATS_ADD(xs_read_bytes, ret);
-
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return ret;
-}
-
-ssize_t
xfs_splice_read(
bhv_desc_t *bdp,
struct file *infilp,
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 7ac51b1d2161..7c60a1eed88b 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -90,9 +90,6 @@ extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
-extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
- loff_t *, int, size_t, read_actor_t,
- void *, struct cred *);
extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
struct pipe_inode_info *, size_t, int, int,
struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index d1b2d01843d1..013048a92643 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -139,9 +139,6 @@ typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
-typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
- loff_t *, int, size_t, read_actor_t,
- void *, struct cred *);
typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
struct pipe_inode_info *, size_t, int, int,
struct cred *);
@@ -206,7 +203,6 @@ typedef struct bhv_vnodeops {
vop_close_t vop_close;
vop_read_t vop_read;
vop_write_t vop_write;
- vop_sendfile_t vop_sendfile;
vop_splice_read_t vop_splice_read;
vop_splice_write_t vop_splice_write;
vop_ioctl_t vop_ioctl;
@@ -254,8 +250,6 @@ typedef struct bhv_vnodeops {
VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \
VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
-#define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr) \
- VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr)
#define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \
VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
#define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index de17aed578f0..70bc82f65311 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -4680,9 +4680,6 @@ bhv_vnodeops_t xfs_vnodeops = {
.vop_open = xfs_open,
.vop_close = xfs_close,
.vop_read = xfs_read,
-#ifdef HAVE_SENDFILE
- .vop_sendfile = xfs_sendfile,
-#endif
#ifdef HAVE_SPLICE
.vop_splice_read = xfs_splice_read,
.vop_splice_write = xfs_splice_write,
diff --git a/include/asm-generic/bitops/sched.h b/include/asm-generic/bitops/sched.h
index 815bb0148060..604fab7031a6 100644
--- a/include/asm-generic/bitops/sched.h
+++ b/include/asm-generic/bitops/sched.h
@@ -6,28 +6,23 @@
/*
* Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
+ * way of searching a 100-bit bitmap. It's guaranteed that at least
+ * one of the 100 bits is cleared.
*/
static inline int sched_find_first_bit(const unsigned long *b)
{
#if BITS_PER_LONG == 64
- if (unlikely(b[0]))
+ if (b[0])
return __ffs(b[0]);
- if (likely(b[1]))
- return __ffs(b[1]) + 64;
- return __ffs(b[2]) + 128;
+ return __ffs(b[1]) + 64;
#elif BITS_PER_LONG == 32
- if (unlikely(b[0]))
+ if (b[0])
return __ffs(b[0]);
- if (unlikely(b[1]))
+ if (b[1])
return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
+ if (b[2])
return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
+ return __ffs(b[3]) + 96;
#else
#error BITS_PER_LONG not defined
#endif
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index 964c5eddc21b..0b3ff9c48409 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -129,29 +129,12 @@
#define PHYS_TO_XKPHYS(cm,a) (_CONST64_(0x8000000000000000) | \
((cm)<<59) | (a))
-#if defined (CONFIG_CPU_R4300) \
- || defined (CONFIG_CPU_R4X00) \
- || defined (CONFIG_CPU_R5000) \
- || defined (CONFIG_CPU_RM7000) \
- || defined (CONFIG_CPU_RM9000) \
- || defined (CONFIG_CPU_NEVADA) \
- || defined (CONFIG_CPU_TX49XX) \
- || defined (CONFIG_CPU_MIPS64)
-#define TO_PHYS_MASK _CONST64_(0x0000000fffffffff) /* 2^^36 - 1 */
-#endif
-
-#if defined (CONFIG_CPU_R8000)
-/* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */
-#define TO_PHYS_MASK _CONST64_(0x000000ffffffffff) /* 2^^40 - 1 */
-#endif
-
-#if defined (CONFIG_CPU_R10000)
-#define TO_PHYS_MASK _CONST64_(0x000000ffffffffff) /* 2^^40 - 1 */
-#endif
-
-#if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A)
-#define TO_PHYS_MASK _CONST64_(0x00000fffffffffff) /* 2^^44 - 1 */
-#endif
+/*
+ * The ultimate limited of the 64-bit MIPS architecture: 2 bits for selecting
+ * the region, 3 bits for the CCA mode. This leaves 59 bits of which the
+ * R8000 implements most with its 48-bit physical address space.
+ */
+#define TO_PHYS_MASK _CONST64_(0x07ffffffffffffff) /* 2^^59 - 1 */
#ifndef CONFIG_CPU_R8000
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index b0c329783ac5..087126a5faf9 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -109,18 +109,12 @@
#define MACH_COSINE_ORION 0
/*
- * Valid machtype for group GALILEO
- */
-#define MACH_GROUP_GALILEO 11 /* Galileo Eval Boards */
-#define MACH_EV64120A 0 /* EV64120A */
-
-/*
* Valid machtype for group MOMENCO
*/
#define MACH_GROUP_MOMENCO 12 /* Momentum Boards */
#define MACH_MOMENCO_OCELOT 0
#define MACH_MOMENCO_OCELOT_G 1 /* no more supported (may 2007) */
-#define MACH_MOMENCO_OCELOT_C 2
+#define MACH_MOMENCO_OCELOT_C 2 /* no more supported (jun 2007) */
#define MACH_MOMENCO_JAGUAR_ATX 3 /* no more supported (may 2007) */
#define MACH_MOMENCO_OCELOT_3 4
@@ -194,13 +188,6 @@
#define MACH_HP_LASERJET 1
/*
- * Valid machtype for group LASAT
- */
-#define MACH_GROUP_LASAT 21
-#define MACH_LASAT_100 0 /* Masquerade II/SP100/SP50/SP25 */
-#define MACH_LASAT_200 1 /* Masquerade PRO/SP200 */
-
-/*
* Valid machtype for group TITAN
*/
#define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
@@ -213,6 +200,27 @@
#define MACH_GROUP_NEC_EMMA2RH 25 /* NEC EMMA2RH (was 23) */
#define MACH_NEC_MARKEINS 0 /* NEC EMMA2RH Mark-eins */
+/*
+ * Valid machtype for group LEMOTE
+ */
+#define MACH_GROUP_LEMOTE 27
+#define MACH_LEMOTE_FULONG 0
+
+/*
+ * Valid machtype for group PMC-MSP
+ */
+#define MACH_GROUP_MSP 26 /* PMC-Sierra MSP boards/CPUs */
+#define MACH_MSP4200_EVAL 0 /* PMC-Sierra MSP4200 Evaluation */
+#define MACH_MSP4200_GW 1 /* PMC-Sierra MSP4200 Gateway demo */
+#define MACH_MSP4200_FPGA 2 /* PMC-Sierra MSP4200 Emulation */
+#define MACH_MSP7120_EVAL 3 /* PMC-Sierra MSP7120 Evaluation */
+#define MACH_MSP7120_GW 4 /* PMC-Sierra MSP7120 Residential GW */
+#define MACH_MSP7120_FPGA 5 /* PMC-Sierra MSP7120 Emulation */
+#define MACH_MSP_OTHER 255 /* PMC-Sierra unknown board type */
+
+#define MACH_GROUP_WINDRIVER 28 /* Windriver boards */
+#define MACH_WRPPMC 1
+
#define CL_SIZE COMMAND_LINE_SIZE
const char *get_system_type(void);
diff --git a/include/asm-mips/cacheops.h b/include/asm-mips/cacheops.h
index c4a1ec31ff6a..df7f2deb3b56 100644
--- a/include/asm-mips/cacheops.h
+++ b/include/asm-mips/cacheops.h
@@ -20,7 +20,11 @@
#define Index_Load_Tag_D 0x05
#define Index_Store_Tag_I 0x08
#define Index_Store_Tag_D 0x09
+#if defined(CONFIG_CPU_LOONGSON2)
+#define Hit_Invalidate_I 0x00
+#else
#define Hit_Invalidate_I 0x10
+#endif
#define Hit_Invalidate_D 0x11
#define Hit_Writeback_Inv_D 0x15
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 5e4bed123b48..d95a83e3e1d7 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -150,6 +150,10 @@
#define cpu_has_mipsmt (cpu_data[0].ases & MIPS_ASE_MIPSMT)
#endif
+#ifndef cpu_has_userlocal
+#define cpu_has_userlocal (cpu_data[0].options & MIPS_CPU_ULRI)
+#endif
+
#ifdef CONFIG_32BIT
# ifndef cpu_has_nofpuex
# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX)
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index 2924069075e0..3857358fb6de 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -89,6 +89,8 @@
#define PRID_IMP_34K 0x9500
#define PRID_IMP_24KE 0x9600
#define PRID_IMP_74K 0x9700
+#define PRID_IMP_LOONGSON1 0x4200
+#define PRID_IMP_LOONGSON2 0x6300
/*
* These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -107,6 +109,7 @@
* Definitions for 7:0 on legacy processors
*/
+#define PRID_REV_MASK 0x00ff
#define PRID_REV_TX4927 0x0022
#define PRID_REV_TX4937 0x0030
@@ -123,6 +126,7 @@
#define PRID_REV_VR4122 0x0070
#define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */
#define PRID_REV_VR4130 0x0080
+#define PRID_REV_34K_V1_0_2 0x0022
/*
* Older processors used to encode processor version and revision in two
@@ -211,7 +215,10 @@
#define CPU_SB1A 62
#define CPU_74K 63
#define CPU_R14000 64
-#define CPU_LAST 64
+#define CPU_LOONGSON1 65
+#define CPU_LOONGSON2 66
+
+#define CPU_LAST 66
/*
* ISA Level encodings
@@ -257,6 +264,7 @@
#define MIPS_CPU_PREFETCH 0x00080000 /* CPU has usable prefetch */
#define MIPS_CPU_VINT 0x00100000 /* CPU supports MIPSR2 vectored interrupts */
#define MIPS_CPU_VEIC 0x00200000 /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI 0x00400000 /* CPU has ULRI feature */
/*
* CPU ASE encodings
diff --git a/include/asm-mips/div64.h b/include/asm-mips/div64.h
index 66189f5f6399..716371bd0980 100644
--- a/include/asm-mips/div64.h
+++ b/include/asm-mips/div64.h
@@ -20,7 +20,7 @@
*/
#define do_div64_32(res, high, low, base) ({ \
- unsigned long __quot, __mod; \
+ unsigned long __quot32, __mod32; \
unsigned long __cf, __tmp, __tmp2, __i; \
\
__asm__(".set push\n\t" \
@@ -48,12 +48,13 @@
"bnez %4, 0b\n\t" \
" srl %5, %1, 0x1f\n\t" \
".set pop" \
- : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
+ : "=&r" (__mod32), "=&r" (__tmp), \
+ "=&r" (__quot32), "=&r" (__cf), \
"=&r" (__i), "=&r" (__tmp2) \
: "Jr" (base), "0" (high), "1" (low)); \
\
- (res) = __quot; \
- __mod; })
+ (res) = __quot32; \
+ __mod32; })
#define do_div(n, base) ({ \
unsigned long long __quot; \
diff --git a/include/asm-mips/gpio.h b/include/asm-mips/gpio.h
new file mode 100644
index 000000000000..06e46faf862d
--- /dev/null
+++ b/include/asm-mips/gpio.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MIPS_GPIO_H
+#define __ASM_MIPS_GPIO_H
+
+#include <gpio.h>
+
+#endif /* __ASM_MIPS_GPIO_H */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 92ec2618560c..12bcc1f9fba9 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -178,6 +178,11 @@ extern void __iounmap(const volatile void __iomem *addr);
static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
unsigned long flags)
{
+ void __iomem *addr = plat_ioremap(offset, size, flags);
+
+ if (addr)
+ return addr;
+
#define __IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
if (cpu_has_64bit_addresses) {
@@ -282,6 +287,9 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
static inline void iounmap(const volatile void __iomem *addr)
{
+ if (plat_iounmap(addr))
+ return;
+
#define __IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1)
if (cpu_has_64bit_addresses ||
diff --git a/include/asm-mips/lasat/ds1603.h b/include/asm-mips/lasat/ds1603.h
deleted file mode 100644
index edcd7544b358..000000000000
--- a/include/asm-mips/lasat/ds1603.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <asm/addrspace.h>
-
-/* Lasat 100 */
-#define DS1603_REG_100 (KSEG1ADDR(0x1c810000))
-#define DS1603_RST_100 (1 << 2)
-#define DS1603_CLK_100 (1 << 0)
-#define DS1603_DATA_SHIFT_100 1
-#define DS1603_DATA_100 (1 << DS1603_DATA_SHIFT_100)
-
-/* Lasat 200 */
-#define DS1603_REG_200 (KSEG1ADDR(0x11000000))
-#define DS1603_RST_200 (1 << 3)
-#define DS1603_CLK_200 (1 << 4)
-#define DS1603_DATA_200 (1 << 5)
-
-#define DS1603_DATA_REG_200 (DS1603_REG_200 + 0x10000)
-#define DS1603_DATA_READ_SHIFT_200 9
-#define DS1603_DATA_READ_200 (1 << DS1603_DATA_READ_SHIFT_200)
diff --git a/include/asm-mips/lasat/eeprom.h b/include/asm-mips/lasat/eeprom.h
deleted file mode 100644
index 7b53edd5cd5f..000000000000
--- a/include/asm-mips/lasat/eeprom.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <asm/addrspace.h>
-
-/* lasat 100 */
-#define AT93C_REG_100 KSEG1ADDR(0x1c810000)
-#define AT93C_RDATA_REG_100 AT93C_REG_100
-#define AT93C_RDATA_SHIFT_100 4
-#define AT93C_WDATA_SHIFT_100 4
-#define AT93C_CS_M_100 ( 1 << 5 )
-#define AT93C_CLK_M_100 ( 1 << 3 )
-
-/* lasat 200 */
-#define AT93C_REG_200 KSEG1ADDR(0x11000000)
-#define AT93C_RDATA_REG_200 (AT93C_REG_200+0x10000)
-#define AT93C_RDATA_SHIFT_200 8
-#define AT93C_WDATA_SHIFT_200 2
-#define AT93C_CS_M_200 ( 1 << 0 )
-#define AT93C_CLK_M_200 ( 1 << 1 )
diff --git a/include/asm-mips/lasat/head.h b/include/asm-mips/lasat/head.h
deleted file mode 100644
index f5589f31a197..000000000000
--- a/include/asm-mips/lasat/head.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Image header stuff
- */
-#ifndef _HEAD_H
-#define _HEAD_H
-
-#define LASAT_K_MAGIC0_VAL 0xfedeabba
-#define LASAT_K_MAGIC1_VAL 0x00bedead
-
-#ifndef _LANGUAGE_ASSEMBLY
-#include <linux/types.h>
-struct bootloader_header {
- u32 magic[2];
- u32 version;
- u32 image_start;
- u32 image_size;
- u32 kernel_start;
- u32 kernel_entry;
-};
-#endif
-
-#endif /* _HEAD_H */
diff --git a/include/asm-mips/lasat/lasat.h b/include/asm-mips/lasat/lasat.h
deleted file mode 100644
index 42077e367a5b..000000000000
--- a/include/asm-mips/lasat/lasat.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * lasat.h
- *
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Configuration for LASAT boards, loads the appropriate include files.
- */
-#ifndef _LASAT_H
-#define _LASAT_H
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-extern struct lasat_misc {
- volatile u32 *reset_reg;
- volatile u32 *flash_wp_reg;
- u32 flash_wp_bit;
-} *lasat_misc;
-
-enum lasat_mtdparts {
- LASAT_MTD_BOOTLOADER,
- LASAT_MTD_SERVICE,
- LASAT_MTD_NORMAL,
- LASAT_MTD_CONFIG,
- LASAT_MTD_FS,
- LASAT_MTD_LAST
-};
-
-/*
- * The format of the data record in the EEPROM.
- * See Documentation/LASAT/eeprom.txt for a detailed description
- * of the fields in this struct, and the LASAT Hardware Configuration
- * field specification for a detailed description of the config
- * field.
- */
-#include <linux/types.h>
-
-#define LASAT_EEPROM_VERSION 7
-struct lasat_eeprom_struct {
- unsigned int version;
- unsigned int cfg[3];
- unsigned char hwaddr[6];
- unsigned char print_partno[12];
- unsigned char term0;
- unsigned char print_serial[14];
- unsigned char term1;
- unsigned char prod_partno[12];
- unsigned char term2;
- unsigned char prod_serial[14];
- unsigned char term3;
- unsigned char passwd_hash[16];
- unsigned char pwdnull;
- unsigned char vendid;
- unsigned char ts_ref;
- unsigned char ts_signoff;
- unsigned char reserved[11];
- unsigned char debugaccess;
- unsigned short prid;
- unsigned int serviceflag;
- unsigned int ipaddr;
- unsigned int netmask;
- unsigned int crc32;
-};
-
-struct lasat_eeprom_struct_pre7 {
- unsigned int version;
- unsigned int flags[3];
- unsigned char hwaddr0[6];
- unsigned char hwaddr1[6];
- unsigned char print_partno[9];
- unsigned char term0;
- unsigned char print_serial[14];
- unsigned char term1;
- unsigned char prod_partno[9];
- unsigned char term2;
- unsigned char prod_serial[14];
- unsigned char term3;
- unsigned char passwd_hash[24];
- unsigned char pwdnull;
- unsigned char vendor;
- unsigned char ts_ref;
- unsigned char ts_signoff;
- unsigned char reserved[6];
- unsigned int writecount;
- unsigned int ipaddr;
- unsigned int netmask;
- unsigned int crc32;
-};
-
-/* Configuration descriptor encoding - see the doc for details */
-
-#define LASAT_W0_DSCTYPE(v) ( ( (v) ) & 0xf )
-#define LASAT_W0_BMID(v) ( ( (v) >> 0x04 ) & 0xf )
-#define LASAT_W0_CPUTYPE(v) ( ( (v) >> 0x08 ) & 0xf )
-#define LASAT_W0_BUSSPEED(v) ( ( (v) >> 0x0c ) & 0xf )
-#define LASAT_W0_CPUCLK(v) ( ( (v) >> 0x10 ) & 0xf )
-#define LASAT_W0_SDRAMBANKSZ(v) ( ( (v) >> 0x14 ) & 0xf )
-#define LASAT_W0_SDRAMBANKS(v) ( ( (v) >> 0x18 ) & 0xf )
-#define LASAT_W0_L2CACHE(v) ( ( (v) >> 0x1c ) & 0xf )
-
-#define LASAT_W1_EDHAC(v) ( ( (v) ) & 0xf )
-#define LASAT_W1_HIFN(v) ( ( (v) >> 0x04 ) & 0x1 )
-#define LASAT_W1_ISDN(v) ( ( (v) >> 0x05 ) & 0x1 )
-#define LASAT_W1_IDE(v) ( ( (v) >> 0x06 ) & 0x1 )
-#define LASAT_W1_HDLC(v) ( ( (v) >> 0x07 ) & 0x1 )
-#define LASAT_W1_USVERSION(v) ( ( (v) >> 0x08 ) & 0x1 )
-#define LASAT_W1_4MACS(v) ( ( (v) >> 0x09 ) & 0x1 )
-#define LASAT_W1_EXTSERIAL(v) ( ( (v) >> 0x0a ) & 0x1 )
-#define LASAT_W1_FLASHSIZE(v) ( ( (v) >> 0x0c ) & 0xf )
-#define LASAT_W1_PCISLOTS(v) ( ( (v) >> 0x10 ) & 0xf )
-#define LASAT_W1_PCI1OPT(v) ( ( (v) >> 0x14 ) & 0xf )
-#define LASAT_W1_PCI2OPT(v) ( ( (v) >> 0x18 ) & 0xf )
-#define LASAT_W1_PCI3OPT(v) ( ( (v) >> 0x1c ) & 0xf )
-
-/* Routines specific to LASAT boards */
-
-#define LASAT_BMID_MASQUERADE2 0
-#define LASAT_BMID_MASQUERADEPRO 1
-#define LASAT_BMID_SAFEPIPE25 2
-#define LASAT_BMID_SAFEPIPE50 3
-#define LASAT_BMID_SAFEPIPE100 4
-#define LASAT_BMID_SAFEPIPE5000 5
-#define LASAT_BMID_SAFEPIPE7000 6
-#define LASAT_BMID_SAFEPIPE1000 7
-//#define LASAT_BMID_SAFEPIPE30 7
-//#define LASAT_BMID_SAFEPIPE5100 8
-//#define LASAT_BMID_SAFEPIPE7100 9
-#define LASAT_BMID_UNKNOWN 0xf
-#define LASAT_MAX_BMID_NAMES 9 // no larger than 15!
-
-#define LASAT_HAS_EDHAC ( 1 << 0 )
-#define LASAT_EDHAC_FAST ( 1 << 1 )
-#define LASAT_HAS_EADI ( 1 << 2 )
-#define LASAT_HAS_HIFN ( 1 << 3 )
-#define LASAT_HAS_ISDN ( 1 << 4 )
-#define LASAT_HAS_LEASEDLINE_IF ( 1 << 5 )
-#define LASAT_HAS_HDC ( 1 << 6 )
-
-#define LASAT_PRID_MASQUERADE2 0
-#define LASAT_PRID_MASQUERADEPRO 1
-#define LASAT_PRID_SAFEPIPE25 2
-#define LASAT_PRID_SAFEPIPE50 3
-#define LASAT_PRID_SAFEPIPE100 4
-#define LASAT_PRID_SAFEPIPE5000 5
-#define LASAT_PRID_SAFEPIPE7000 6
-#define LASAT_PRID_SAFEPIPE30 7
-#define LASAT_PRID_SAFEPIPE5100 8
-#define LASAT_PRID_SAFEPIPE7100 9
-
-#define LASAT_PRID_SAFEPIPE1110 10
-#define LASAT_PRID_SAFEPIPE3020 11
-#define LASAT_PRID_SAFEPIPE3030 12
-#define LASAT_PRID_SAFEPIPE5020 13
-#define LASAT_PRID_SAFEPIPE5030 14
-#define LASAT_PRID_SAFEPIPE1120 15
-#define LASAT_PRID_SAFEPIPE1130 16
-#define LASAT_PRID_SAFEPIPE6010 17
-#define LASAT_PRID_SAFEPIPE6110 18
-#define LASAT_PRID_SAFEPIPE6210 19
-#define LASAT_PRID_SAFEPIPE1020 20
-#define LASAT_PRID_SAFEPIPE1040 21
-#define LASAT_PRID_SAFEPIPE1060 22
-
-struct lasat_info {
- unsigned int li_cpu_hz;
- unsigned int li_bus_hz;
- unsigned int li_bmid;
- unsigned int li_memsize;
- unsigned int li_flash_size;
- unsigned int li_prid;
- unsigned char li_bmstr[16];
- unsigned char li_namestr[32];
- unsigned char li_typestr[16];
- /* Info on the Flash layout */
- unsigned int li_flash_base;
- unsigned long li_flashpart_base[LASAT_MTD_LAST];
- unsigned long li_flashpart_size[LASAT_MTD_LAST];
- struct lasat_eeprom_struct li_eeprom_info;
- unsigned int li_eeprom_upgrade_version;
- unsigned int li_debugaccess;
-};
-
-extern struct lasat_info lasat_board_info;
-
-static inline unsigned long lasat_flash_partition_start(int partno)
-{
- if (partno < 0 || partno >= LASAT_MTD_LAST)
- return 0;
-
- return lasat_board_info.li_flashpart_base[partno];
-}
-
-static inline unsigned long lasat_flash_partition_size(int partno)
-{
- if (partno < 0 || partno >= LASAT_MTD_LAST)
- return 0;
-
- return lasat_board_info.li_flashpart_size[partno];
-}
-
-/* Called from setup() to initialize the global board_info struct */
-extern int lasat_init_board_info(void);
-
-/* Write the modified EEPROM info struct */
-extern void lasat_write_eeprom_info(void);
-
-#define N_MACHTYPES 2
-/* for calibration of delays */
-
-/* the lasat_ndelay function is necessary because it is used at an
- * early stage of the boot process where ndelay is not calibrated.
- * It is used for the bit-banging rtc and eeprom drivers */
-
-#include <asm/delay.h>
-/* calculating with the slowest board with 100 MHz clock */
-#define LASAT_100_DIVIDER 20
-/* All 200's run at 250 MHz clock */
-#define LASAT_200_DIVIDER 8
-
-extern unsigned int lasat_ndelay_divider;
-
-static inline void lasat_ndelay(unsigned int ns)
-{
- __delay(ns / lasat_ndelay_divider);
-}
-
-#endif /* !defined (_LANGUAGE_ASSEMBLY) */
-
-#define LASAT_SERVICEMODE_MAGIC_1 0xdeadbeef
-#define LASAT_SERVICEMODE_MAGIC_2 0xfedeabba
-
-/* Lasat 100 boards */
-#define LASAT_GT_BASE (KSEG1ADDR(0x14000000))
-
-/* Lasat 200 boards */
-#define Vrc5074_PHYS_BASE 0x1fa00000
-#define Vrc5074_BASE (KSEG1ADDR(Vrc5074_PHYS_BASE))
-#define PCI_WINDOW1 0x1a000000
-
-#endif /* _LASAT_H */
diff --git a/include/asm-mips/lasat/lasatint.h b/include/asm-mips/lasat/lasatint.h
deleted file mode 100644
index 065474feeccc..000000000000
--- a/include/asm-mips/lasat/lasatint.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#define LASATINT_END 16
-
-/* lasat 100 */
-#define LASAT_INT_STATUS_REG_100 (KSEG1ADDR(0x1c880000))
-#define LASAT_INT_MASK_REG_100 (KSEG1ADDR(0x1c890000))
-#define LASATINT_MASK_SHIFT_100 0
-
-/* lasat 200 */
-#define LASAT_INT_STATUS_REG_200 (KSEG1ADDR(0x1104003c))
-#define LASAT_INT_MASK_REG_200 (KSEG1ADDR(0x1104003c))
-#define LASATINT_MASK_SHIFT_200 16
-
diff --git a/include/asm-mips/lasat/picvue.h b/include/asm-mips/lasat/picvue.h
deleted file mode 100644
index 42a492edc40e..000000000000
--- a/include/asm-mips/lasat/picvue.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Lasat 100 */
-#define PVC_REG_100 KSEG1ADDR(0x1c820000)
-#define PVC_DATA_SHIFT_100 0
-#define PVC_DATA_M_100 0xFF
-#define PVC_E_100 (1 << 8)
-#define PVC_RW_100 (1 << 9)
-#define PVC_RS_100 (1 << 10)
-
-/* Lasat 200 */
-#define PVC_REG_200 KSEG1ADDR(0x11000000)
-#define PVC_DATA_SHIFT_200 24
-#define PVC_DATA_M_200 (0xFF << PVC_DATA_SHIFT_200)
-#define PVC_E_200 (1 << 16)
-#define PVC_RW_200 (1 << 17)
-#define PVC_RS_200 (1 << 18)
diff --git a/include/asm-mips/lasat/serial.h b/include/asm-mips/lasat/serial.h
deleted file mode 100644
index 9e88c7669c7a..000000000000
--- a/include/asm-mips/lasat/serial.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <asm/lasat/lasat.h>
-
-/* Lasat 100 boards serial configuration */
-#define LASAT_BASE_BAUD_100 ( 7372800 / 16 )
-#define LASAT_UART_REGS_BASE_100 0x1c8b0000
-#define LASAT_UART_REGS_SHIFT_100 2
-#define LASATINT_UART_100 8
-
-/* * LASAT 200 boards serial configuration */
-#define LASAT_BASE_BAUD_200 (100000000 / 16 / 12)
-#define LASAT_UART_REGS_BASE_200 (Vrc5074_PHYS_BASE + 0x0300)
-#define LASAT_UART_REGS_SHIFT_200 3
-#define LASATINT_UART_200 13
diff --git a/include/asm-mips/mach-au1x00/au1xxx_gpio.h b/include/asm-mips/mach-au1x00/au1xxx_gpio.h
deleted file mode 100644
index 27911e054ffc..000000000000
--- a/include/asm-mips/mach-au1x00/au1xxx_gpio.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __AU1XXX_GPIO_H
-#define __AU1XXX_GPIO_H
-
-void au1xxx_gpio1_set_inputs(void);
-void au1xxx_gpio_tristate(int signal);
-void au1xxx_gpio_write(int signal, int value);
-int au1xxx_gpio_read(int signal);
-
-typedef volatile struct
-{
- u32 dir;
- u32 reserved;
- u32 output;
- u32 pinstate;
- u32 inten;
- u32 enable;
-
-} AU1X00_GPIO2;
-
-#endif //__AU1XXX_GPIO_H
diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
index 8fcae21adbd5..4663e8b415c9 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_ide.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
@@ -88,26 +88,26 @@ static const struct drive_list_entry dma_white_list [] = {
/*
* Hitachi
*/
- { "HITACHI_DK14FA-20" , "ALL" },
- { "HTS726060M9AT00" , "ALL" },
+ { "HITACHI_DK14FA-20" , NULL },
+ { "HTS726060M9AT00" , NULL },
/*
* Maxtor
*/
- { "Maxtor 6E040L0" , "ALL" },
- { "Maxtor 6Y080P0" , "ALL" },
- { "Maxtor 6Y160P0" , "ALL" },
+ { "Maxtor 6E040L0" , NULL },
+ { "Maxtor 6Y080P0" , NULL },
+ { "Maxtor 6Y160P0" , NULL },
/*
* Seagate
*/
- { "ST3120026A" , "ALL" },
- { "ST320014A" , "ALL" },
- { "ST94011A" , "ALL" },
- { "ST340016A" , "ALL" },
+ { "ST3120026A" , NULL },
+ { "ST320014A" , NULL },
+ { "ST94011A" , NULL },
+ { "ST340016A" , NULL },
/*
* Western Digital
*/
- { "WDC WD400UE-00HCT0" , "ALL" },
- { "WDC WD400JB-00JJC0" , "ALL" },
+ { "WDC WD400UE-00HCT0" , NULL },
+ { "WDC WD400JB-00JJC0" , NULL },
{ NULL , NULL }
};
@@ -116,9 +116,9 @@ static const struct drive_list_entry dma_black_list [] = {
/*
* Western Digital
*/
- { "WDC WD100EB-00CGH0" , "ALL" },
- { "WDC WD200BB-00AUA1" , "ALL" },
- { "WDC AC24300L" , "ALL" },
+ { "WDC WD100EB-00CGH0" , NULL },
+ { "WDC WD200BB-00AUA1" , NULL },
+ { "WDC AC24300L" , NULL },
{ NULL , NULL }
};
#endif
diff --git a/include/asm-mips/mach-au1x00/gpio.h b/include/asm-mips/mach-au1x00/gpio.h
new file mode 100644
index 000000000000..2dc61e009a08
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/gpio.h
@@ -0,0 +1,69 @@
+#ifndef _AU1XXX_GPIO_H_
+#define _AU1XXX_GPIO_H_
+
+#include <linux/types.h>
+
+#define AU1XXX_GPIO_BASE 200
+
+struct au1x00_gpio2 {
+ u32 dir;
+ u32 reserved;
+ u32 output;
+ u32 pinstate;
+ u32 inten;
+ u32 enable;
+};
+
+extern int au1xxx_gpio_get_value(unsigned gpio);
+extern void au1xxx_gpio_set_value(unsigned gpio, int value);
+extern int au1xxx_gpio_direction_input(unsigned gpio);
+extern int au1xxx_gpio_direction_output(unsigned gpio, int value);
+
+
+/* Wrappers for the arch-neutral GPIO API */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+ /* Not yet implemented */
+ return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+ /* Not yet implemented */
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ return au1xxx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ return au1xxx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return au1xxx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ au1xxx_gpio_set_value(gpio, value);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return irq;
+}
+
+/* For cansleep */
+#include <asm-generic/gpio.h>
+
+#endif /* _AU1XXX_GPIO_H_ */
diff --git a/include/asm-mips/mach-au1x00/ioremap.h b/include/asm-mips/mach-au1x00/ioremap.h
index 098fca4289bb..364cea2dc71f 100644
--- a/include/asm-mips/mach-au1x00/ioremap.h
+++ b/include/asm-mips/mach-au1x00/ioremap.h
@@ -28,4 +28,15 @@ static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
return __fixup_bigphys_addr(phys_addr, size);
}
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+ unsigned long flags)
+{
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return 0;
+}
+
#endif /* __ASM_MACH_AU1X00_IOREMAP_H */
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
index 684a501c04cf..9c9d2b998ca4 100644
--- a/include/asm-mips/mach-cobalt/cobalt.h
+++ b/include/asm-mips/mach-cobalt/cobalt.h
@@ -30,7 +30,6 @@
#define COBALT_CPU_IRQ MIPS_CPU_IRQ_BASE
#define COBALT_GALILEO_IRQ (COBALT_CPU_IRQ + 2)
-#define COBALT_SCC_IRQ (COBALT_CPU_IRQ + 3) /* pre-production has 85C30 */
#define COBALT_RAQ_SCSI_IRQ (COBALT_CPU_IRQ + 3)
#define COBALT_ETH0_IRQ (COBALT_CPU_IRQ + 3)
#define COBALT_QUBE1_ETH0_IRQ (COBALT_CPU_IRQ + 4)
@@ -71,10 +70,6 @@
extern int cobalt_board_id;
-#define PCI_CFG_SET(devfn,where) \
- GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) | \
- (PCI_FUNC (devfn) << 8) | (where)))
-
#define COBALT_LED_PORT (*(volatile unsigned char *) CKSEG1ADDR(0x1c000000))
# define COBALT_LED_BAR_LEFT (1 << 0) /* Qube */
# define COBALT_LED_BAR_RIGHT (1 << 1) /* Qube */
diff --git a/include/asm-mips/mach-ev64120/mach-gt64120.h b/include/asm-mips/mach-ev64120/mach-gt64120.h
deleted file mode 100644
index 7e272ce57ea3..000000000000
--- a/include/asm-mips/mach-ev64120/mach-gt64120.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This is a direct copy of the ev96100.h file, with a global
- * search and replace. The numbers are the same.
- *
- * The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef __ASM_GALILEO_BOARDS_MIPS_EV64120_H
-#define __ASM_GALILEO_BOARDS_MIPS_EV64120_H
-
-/*
- * GT64120 config space base address
- */
-extern unsigned long gt64120_base;
-
-#define GT64120_BASE (gt64120_base)
-
-/*
- * PCI Bus allocation
- */
-#define GT_PCI_MEM_BASE 0x12000000UL
-#define GT_PCI_MEM_SIZE 0x02000000UL
-#define GT_PCI_IO_BASE 0x10000000UL
-#define GT_PCI_IO_SIZE 0x02000000UL
-#define GT_ISA_IO_BASE PCI_IO_BASE
-
-/*
- * Duart I/O ports.
- */
-#define EV64120_COM1_BASE_ADDR (0x1d000000 + 0x20)
-#define EV64120_COM2_BASE_ADDR (0x1d000000 + 0x00)
-
-
-/*
- * EV64120 interrupt controller register base.
- */
-#define EV64120_ICTRL_REGS_BASE (KSEG1ADDR(0x1f000000))
-
-/*
- * EV64120 UART register base.
- */
-#define EV64120_UART0_REGS_BASE (KSEG1ADDR(EV64120_COM1_BASE_ADDR))
-#define EV64120_UART1_REGS_BASE (KSEG1ADDR(EV64120_COM2_BASE_ADDR))
-#define EV64120_BASE_BAUD ( 3686400 / 16 )
-#define EV64120_UART_IRQ 6
-
-/*
- * PCI interrupts will come in on either the INTA or INTD interrups lines,
- * which are mapped to the #2 and #5 interrupt pins of the MIPS. On our
- * boards, they all either come in on IntD or they all come in on IntA, they
- * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
- * "requested" interrupt numbers and go through the list whenever we get an
- * IntA/D.
- *
- * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and
- * INTD is 11.
- */
-#define GT_TIMER 4
-#define GT_INTA 2
-#define GT_INTD 5
-
-#endif /* __ASM_GALILEO_BOARDS_MIPS_EV64120_H */
diff --git a/include/asm-mips/mach-generic/gpio.h b/include/asm-mips/mach-generic/gpio.h
new file mode 100644
index 000000000000..6eaf5efedf3a
--- /dev/null
+++ b/include/asm-mips/mach-generic/gpio.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_MACH_GENERIC_GPIO_H
+#define __ASM_MACH_GENERIC_GPIO_H
+
+int gpio_request(unsigned gpio, const char *label);
+void gpio_free(unsigned gpio);
+int gpio_direction_input(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+int gpio_to_irq(unsigned gpio);
+int irq_to_gpio(unsigned irq);
+
+#include <asm-generic/gpio.h> /* cansleep wrappers */
+
+#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/include/asm-mips/mach-generic/ioremap.h b/include/asm-mips/mach-generic/ioremap.h
index 9b64ff6e485d..b379938d47f0 100644
--- a/include/asm-mips/mach-generic/ioremap.h
+++ b/include/asm-mips/mach-generic/ioremap.h
@@ -20,4 +20,15 @@ static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
return phys_addr;
}
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+ unsigned long flags)
+{
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return 0;
+}
+
#endif /* __ASM_MACH_GENERIC_IOREMAP_H */
diff --git a/include/asm-mips/mach-generic/spaces.h b/include/asm-mips/mach-generic/spaces.h
index 0ae9997bc9a8..c9fa4b14968d 100644
--- a/include/asm-mips/mach-generic/spaces.h
+++ b/include/asm-mips/mach-generic/spaces.h
@@ -10,38 +10,54 @@
#ifndef _ASM_MACH_GENERIC_SPACES_H
#define _ASM_MACH_GENERIC_SPACES_H
+#include <linux/const.h>
+
+/*
+ * This gives the physical RAM offset.
+ */
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET _AC(0, UL)
+#endif
#ifdef CONFIG_32BIT
-#define CAC_BASE 0x80000000
-#define IO_BASE 0xa0000000
-#define UNCAC_BASE 0xa0000000
-#define MAP_BASE 0xc0000000
+#define CAC_BASE _AC(0x80000000, UL)
+#define IO_BASE _AC(0xa0000000, UL)
+#define UNCAC_BASE _AC(0xa0000000, UL)
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET 0x80000000UL
+#ifndef MAP_BASE
+#define MAP_BASE _AC(0xc0000000, UL)
+#endif
/*
* Memory above this physical address will be considered highmem.
*/
#ifndef HIGHMEM_START
-#define HIGHMEM_START 0x20000000UL
+#define HIGHMEM_START _AC(0x20000000, UL)
#endif
#endif /* CONFIG_32BIT */
#ifdef CONFIG_64BIT
-/*
- * This handles the memory map.
- */
+#ifndef CAC_BASE
#ifdef CONFIG_DMA_NONCOHERENT
-#define PAGE_OFFSET 0x9800000000000000UL
+#define CAC_BASE _AC(0x9800000000000000, UL)
#else
-#define PAGE_OFFSET 0xa800000000000000UL
+#define CAC_BASE _AC(0xa800000000000000, UL)
+#endif
+#endif
+
+#ifndef IO_BASE
+#define IO_BASE _AC(0x9000000000000000, UL)
+#endif
+
+#ifndef UNCAC_BASE
+#define UNCAC_BASE _AC(0x9000000000000000, UL)
+#endif
+
+#ifndef MAP_BASE
+#define MAP_BASE _AC(0xc000000000000000, UL)
#endif
/*
@@ -50,22 +66,20 @@
* in the distant future. Nobody will care for a few years :-)
*/
#ifndef HIGHMEM_START
-#define HIGHMEM_START (1UL << 59UL)
+#define HIGHMEM_START (_AC(1, UL) << _AC(59, UL))
#endif
-#ifdef CONFIG_DMA_NONCOHERENT
-#define CAC_BASE 0x9800000000000000UL
-#else
-#define CAC_BASE 0xa800000000000000UL
-#endif
-#define IO_BASE 0x9000000000000000UL
-#define UNCAC_BASE 0x9000000000000000UL
-#define MAP_BASE 0xc000000000000000UL
-
#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
#endif /* CONFIG_64BIT */
+/*
+ * This handles the memory map.
+ */
+#ifndef PAGE_OFFSET
+#define PAGE_OFFSET (CAC_BASE + PHYS_OFFSET)
+#endif
+
#endif /* __ASM_MACH_GENERIC_SPACES_H */
diff --git a/include/asm-mips/mach-ip22/spaces.h b/include/asm-mips/mach-ip22/spaces.h
index ab20c026fd19..7f9fa6f66059 100644
--- a/include/asm-mips/mach-ip22/spaces.h
+++ b/include/asm-mips/mach-ip22/spaces.h
@@ -11,44 +11,17 @@
#define _ASM_MACH_IP22_SPACES_H
-#ifdef CONFIG_32BIT
-
-#define CAC_BASE 0x80000000
-#define IO_BASE 0xa0000000
-#define UNCAC_BASE 0xa0000000
-#define MAP_BASE 0xc0000000
-
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET 0x80000000UL
-
-/*
- * Memory above this physical address will be considered highmem.
- */
-#ifndef HIGHMEM_START
-#define HIGHMEM_START 0x20000000UL
-#endif
-
-#endif /* CONFIG_32BIT */
-
#ifdef CONFIG_64BIT
-#define PAGE_OFFSET 0xffffffff80000000UL
-#ifndef HIGHMEM_START
-#define HIGHMEM_START (1UL << 59UL)
-#endif
+#define PAGE_OFFSET 0xffffffff80000000UL
#define CAC_BASE 0xffffffff80000000
#define IO_BASE 0xffffffffa0000000
#define UNCAC_BASE 0xffffffffa0000000
#define MAP_BASE 0xc000000000000000
-#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
-#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
-
#endif /* CONFIG_64BIT */
+#include <asm/mach-generic/spaces.h>
+
#endif /* __ASM_MACH_IP22_SPACES_H */
diff --git a/include/asm-mips/mach-ip27/spaces.h b/include/asm-mips/mach-ip27/spaces.h
index 45e61785ef42..b18802a0b17e 100644
--- a/include/asm-mips/mach-ip27/spaces.h
+++ b/include/asm-mips/mach-ip27/spaces.h
@@ -14,22 +14,17 @@
* IP27 uses the R10000's uncached attribute feature. Attribute 3 selects
* uncached memory addressing.
*/
-#define CAC_BASE 0xa800000000000000
#define HSPEC_BASE 0x9000000000000000
#define IO_BASE 0x9200000000000000
#define MSPEC_BASE 0x9400000000000000
#define UNCAC_BASE 0x9600000000000000
-#define MAP_BASE 0xc000000000000000
-#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
-#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
#define TO_MSPEC(x) (MSPEC_BASE | ((x) & TO_PHYS_MASK))
#define TO_HSPEC(x) (HSPEC_BASE | ((x) & TO_PHYS_MASK))
-#define PAGE_OFFSET CAC_BASE
-
#define HIGHMEM_START (~0UL)
+#include <asm/mach-generic/spaces.h>
+
#endif /* _ASM_MACH_IP27_SPACES_H */
diff --git a/include/asm-mips/mach-ip32/spaces.h b/include/asm-mips/mach-ip32/spaces.h
deleted file mode 100644
index 44abe5c02389..000000000000
--- a/include/asm-mips/mach-ip32/spaces.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1999, 2000, 03, 04, 05 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2000, 2002 Maciej W. Rozycki
- * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef _ASM_MACH_IP32_SPACES_H
-#define _ASM_MACH_IP32_SPACES_H
-
-/*
- * Memory above this physical address will be considered highmem.
- * Fixme: 59 bits is a fictive number and makes assumptions about processors
- * in the distant future. Nobody will care for a few years :-)
- */
-#ifndef HIGHMEM_START
-#define HIGHMEM_START (1UL << 59UL)
-#endif
-
-#define CAC_BASE 0x9800000000000000UL
-#define IO_BASE 0x9000000000000000UL
-#define UNCAC_BASE 0x9000000000000000UL
-#define MAP_BASE 0xc000000000000000UL
-
-#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
-#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
-
-/*
- * This handles the memory map.
- */
-#define PAGE_OFFSET CAC_BASE
-
-#endif /* __ASM_MACH_IP32_SPACES_H */
diff --git a/include/asm-mips/mach-jmr3927/ioremap.h b/include/asm-mips/mach-jmr3927/ioremap.h
new file mode 100644
index 000000000000..aa131ad7f717
--- /dev/null
+++ b/include/asm-mips/mach-jmr3927/ioremap.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-mips/mach-jmr3927/ioremap.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_JMR3927_IOREMAP_H
+#define __ASM_MACH_JMR3927_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+ return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+ unsigned long flags)
+{
+#define TXX9_DIRECTMAP_BASE 0xff000000ul
+ if (offset >= TXX9_DIRECTMAP_BASE &&
+ offset < TXX9_DIRECTMAP_BASE + 0xf0000)
+ return (void __iomem *)offset;
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return (unsigned long)addr >= TXX9_DIRECTMAP_BASE;
+}
+
+#endif /* __ASM_MACH_JMR3927_IOREMAP_H */
diff --git a/include/asm-mips/mach-lasat/mach-gt64120.h b/include/asm-mips/mach-lasat/mach-gt64120.h
deleted file mode 100644
index 1a9ad45cc135..000000000000
--- a/include/asm-mips/mach-lasat/mach-gt64120.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This is a direct copy of the ev96100.h file, with a global
- * search and replace. The numbers are the same.
- *
- * The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef _ASM_GT64120_LASAT_GT64120_DEP_H
-#define _ASM_GT64120_LASAT_GT64120_DEP_H
-
-/*
- * GT64120 config space base address on Lasat 100
- */
-#define GT64120_BASE (KSEG1ADDR(0x14000000))
-
-/*
- * PCI Bus allocation
- *
- * (Guessing ...)
- */
-#define GT_PCI_MEM_BASE 0x12000000UL
-#define GT_PCI_MEM_SIZE 0x02000000UL
-#define GT_PCI_IO_BASE 0x10000000UL
-#define GT_PCI_IO_SIZE 0x02000000UL
-#define GT_ISA_IO_BASE PCI_IO_BASE
-
-#endif /* _ASM_GT64120_LASAT_GT64120_DEP_H */
diff --git a/include/asm-mips/mach-lemote/dma-coherence.h b/include/asm-mips/mach-lemote/dma-coherence.h
new file mode 100644
index 000000000000..7e914777ebc4
--- /dev/null
+++ b/include/asm-mips/mach-lemote/dma-coherence.h
@@ -0,0 +1,42 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006, 07 Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ */
+#ifndef __ASM_MACH_LEMOTE_DMA_COHERENCE_H
+#define __ASM_MACH_LEMOTE_DMA_COHERENCE_H
+
+struct device;
+
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
+ size_t size)
+{
+ return virt_to_phys(addr) | 0x80000000;
+}
+
+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
+ struct page *page)
+{
+ return page_to_phys(page) | 0x80000000;
+}
+
+static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+ return dma_addr & 0x7fffffff;
+}
+
+static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+ return 0;
+}
+
+#endif /* __ASM_MACH_LEMOTE_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-lemote/mc146818rtc.h b/include/asm-mips/mach-lemote/mc146818rtc.h
new file mode 100644
index 000000000000..ed5147e11085
--- /dev/null
+++ b/include/asm-mips/mach-lemote/mc146818rtc.h
@@ -0,0 +1,36 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03, 07 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * RTC routines for PC style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_LEMOTE_MC146818RTC_H
+#define __ASM_MACH_LEMOTE_MC146818RTC_H
+
+#include <linux/io.h>
+
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_IRQ 8
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+ outb_p(addr, RTC_PORT(0));
+ return inb_p(RTC_PORT(1));
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+ outb_p(addr, RTC_PORT(0));
+ outb_p(data, RTC_PORT(1));
+}
+
+#define RTC_ALWAYS_BCD 0
+
+#ifndef mc146818_decode_year
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
+#endif
+
+#endif /* __ASM_MACH_LEMOTE_MC146818RTC_H */
diff --git a/include/asm-mips/mach-mips/kernel-entry-init.h b/include/asm-mips/mach-mips/kernel-entry-init.h
new file mode 100644
index 000000000000..0b793e7bf67e
--- /dev/null
+++ b/include/asm-mips/mach-mips/kernel-entry-init.h
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Chris Dearman (chris@mips.com)
+ * Copyright (C) 2007 Mips Technologies, Inc.
+ */
+#ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+
+ .macro kernel_entry_setup
+#ifdef CONFIG_MIPS_MT_SMTC
+ mfc0 t0, CP0_CONFIG
+ bgez t0, 9f
+ mfc0 t0, CP0_CONFIG, 1
+ bgez t0, 9f
+ mfc0 t0, CP0_CONFIG, 2
+ bgez t0, 9f
+ mfc0 t0, CP0_CONFIG, 3
+ and t0, 1<<2
+ bnez t0, 0f
+9:
+ /* Assume we came from YAMON... */
+ PTR_LA v0, 0x9fc00534 /* YAMON print */
+ lw v0, (v0)
+ move a0, zero
+ PTR_LA a1, nonmt_processor
+ jal v0
+
+ PTR_LA v0, 0x9fc00520 /* YAMON exit */
+ lw v0, (v0)
+ li a0, 1
+ jal v0
+
+1: b 1b
+
+ __INITDATA
+nonmt_processor:
+ .asciz "SMTC kernel requires the MT ASE to run\n"
+ __FINIT
+0:
+#endif
+ .endm
+
+/*
+ * Do SMP slave processor setup necessary before we can safely execute C code.
+ */
+ .macro smp_slave_setup
+ .endm
+
+#endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */
diff --git a/include/asm-mips/mach-sim/cpu-feature-overrides.h b/include/asm-mips/mach-mipssim/cpu-feature-overrides.h
index 779b02205737..779b02205737 100644
--- a/include/asm-mips/mach-sim/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-mipssim/cpu-feature-overrides.h
diff --git a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
deleted file mode 100644
index 57a12ded0613..000000000000
--- a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- * Copyright (C) 2004 Ralf Baechle
- */
-#ifndef __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Momentum Ocelot-3 is based on Rm7900 processor which
- * is based on the E9000 core.
- */
-#define cpu_has_watch 1
-#define cpu_has_mips16 0
-#define cpu_has_divec 0
-#define cpu_has_vce 0
-#define cpu_has_cache_cdex_p 0
-#define cpu_has_cache_cdex_s 0
-#define cpu_has_prefetch 1
-#define cpu_has_mcheck 0
-#define cpu_has_ejtag 0
-
-#define cpu_has_llsc 1
-#define cpu_has_vtag_icache 0
-#define cpu_has_dc_aliases 0
-#define cpu_has_ic_fills_f_dc 0
-#define cpu_has_dsp 0
-#define cpu_icache_snoops_remote_store 0
-
-#define cpu_has_nofpuex 0
-#define cpu_has_64bits 1
-
-#define cpu_has_inclusive_pcaches 0
-
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 32
-#define cpu_scache_line_size() 32
-
-#define cpu_has_mips32r1 0
-#define cpu_has_mips32r2 0
-#define cpu_has_mips64r1 0
-#define cpu_has_mips64r2 0
-
-#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-tx49xx/ioremap.h b/include/asm-mips/mach-tx49xx/ioremap.h
new file mode 100644
index 000000000000..88cf546719b8
--- /dev/null
+++ b/include/asm-mips/mach-tx49xx/ioremap.h
@@ -0,0 +1,42 @@
+/*
+ * include/asm-mips/mach-tx49xx/ioremap.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_TX49XX_IOREMAP_H
+#define __ASM_MACH_TX49XX_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+ return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+ unsigned long flags)
+{
+#ifdef CONFIG_64BIT
+#define TXX9_DIRECTMAP_BASE 0xfff000000ul
+#else
+#define TXX9_DIRECTMAP_BASE 0xff000000ul
+#endif
+ if (offset >= TXX9_DIRECTMAP_BASE &&
+ offset < TXX9_DIRECTMAP_BASE + 0x400000)
+ return (void __iomem *)(unsigned long)(int)offset;
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return (unsigned long)addr >= (unsigned long)(int)TXX9_DIRECTMAP_BASE;
+}
+
+#endif /* __ASM_MACH_TX49XX_IOREMAP_H */
diff --git a/include/asm-mips/mips-boards/bonito64.h b/include/asm-mips/mips-boards/bonito64.h
index cd7125610100..dc3fc32eedd8 100644
--- a/include/asm-mips/mips-boards/bonito64.h
+++ b/include/asm-mips/mips-boards/bonito64.h
@@ -26,7 +26,12 @@
/* offsets from base register */
#define BONITO(x) (x)
-#else /* !__ASSEMBLY__ */
+#elif defined(CONFIG_LEMOTE_FULONG)
+
+#define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x)))
+#define BONITO_IRQ_BASE 32
+
+#else
/*
* Algorithmics Bonito64 system controller register base.
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 89c81922d47c..706b3691f57e 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -7,7 +7,7 @@
* Copyright (C) 2000 Silicon Graphics, Inc.
* Modified for further R[236]000 support by Paul M. Antoine, 1996.
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2000, 07 MIPS Technologies, Inc.
* Copyright (C) 2003, 2004 Maciej W. Rozycki
*/
#ifndef _ASM_MIPSREGS_H
@@ -15,6 +15,7 @@
#include <linux/linkage.h>
#include <asm/hazards.h>
+#include <asm/war.h>
/*
* The following macros are especially useful for __asm__
@@ -533,9 +534,13 @@
#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6)
#define MIPS_CONF3_LPA (_ULCAST_(1) << 7)
#define MIPS_CONF3_DSP (_ULCAST_(1) << 10)
+#define MIPS_CONF3_ULRI (_ULCAST_(1) << 13)
#define MIPS_CONF7_WII (_ULCAST_(1) << 31)
+#define MIPS_CONF7_RPS (_ULCAST_(1) << 2)
+
+
/*
* Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
*/
@@ -772,6 +777,9 @@ do { \
#define read_c0_context() __read_ulong_c0_register($4, 0)
#define write_c0_context(val) __write_ulong_c0_register($4, 0, val)
+#define read_c0_userlocal() __read_ulong_c0_register($4, 2)
+#define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val)
+
#define read_c0_pagemask() __read_32bit_c0_register($5, 0)
#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val)
@@ -1294,10 +1302,39 @@ static inline void tlb_probe(void)
static inline void tlb_read(void)
{
+#if MIPS34K_MISSED_ITLB_WAR
+ int res = 0;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " .set noat \n"
+ " .set mips32r2 \n"
+ " .word 0x41610001 # dvpe $1 \n"
+ " move %0, $1 \n"
+ " ehb \n"
+ " .set pop \n"
+ : "=r" (res));
+
+ instruction_hazard();
+#endif
+
__asm__ __volatile__(
".set noreorder\n\t"
"tlbr\n\t"
".set reorder");
+
+#if MIPS34K_MISSED_ITLB_WAR
+ if ((res & _ULCAST_(1)))
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " .set noat \n"
+ " .set mips32r2 \n"
+ " .word 0x41600021 # evpe \n"
+ " ehb \n"
+ " .set pop \n");
+#endif
}
static inline void tlb_write_indexed(void)
diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h
index c5ef324fd69f..de6d09ebbd80 100644
--- a/include/asm-mips/module.h
+++ b/include/asm-mips/module.h
@@ -112,6 +112,8 @@ search_module_dbetables(unsigned long addr)
#define MODULE_PROC_FAMILY "RM9000 "
#elif defined CONFIG_CPU_SB1
#define MODULE_PROC_FAMILY "SB1 "
+#elif defined CONFIG_CPU_LOONGSON2
+#define MODULE_PROC_FAMILY "LOONGSON2 "
#else
#error MODULE_PROC_FAMILY undefined for your processor configuration
#endif
diff --git a/include/asm-mips/nile4.h b/include/asm-mips/nile4.h
deleted file mode 100644
index c3ca959aa4d9..000000000000
--- a/include/asm-mips/nile4.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions
- *
- * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- * Sony Software Development Center Europe (SDCE), Brussels
- *
- * This file is based on the following documentation:
- *
- * NEC Vrc 5074 System Controller Data Sheet, June 1998
- */
-
-#ifndef _ASM_NILE4_H
-#define _ASM_NILE4_H
-
-#define NILE4_BASE 0xbfa00000
-#define NILE4_SIZE 0x00200000 /* 2 MB */
-
-
- /*
- * Physical Device Address Registers (PDARs)
- */
-
-#define NILE4_SDRAM0 0x0000 /* SDRAM Bank 0 [R/W] */
-#define NILE4_SDRAM1 0x0008 /* SDRAM Bank 1 [R/W] */
-#define NILE4_DCS2 0x0010 /* Device Chip-Select 2 [R/W] */
-#define NILE4_DCS3 0x0018 /* Device Chip-Select 3 [R/W] */
-#define NILE4_DCS4 0x0020 /* Device Chip-Select 4 [R/W] */
-#define NILE4_DCS5 0x0028 /* Device Chip-Select 5 [R/W] */
-#define NILE4_DCS6 0x0030 /* Device Chip-Select 6 [R/W] */
-#define NILE4_DCS7 0x0038 /* Device Chip-Select 7 [R/W] */
-#define NILE4_DCS8 0x0040 /* Device Chip-Select 8 [R/W] */
-#define NILE4_PCIW0 0x0060 /* PCI Address Window 0 [R/W] */
-#define NILE4_PCIW1 0x0068 /* PCI Address Window 1 [R/W] */
-#define NILE4_INTCS 0x0070 /* Controller Internal Registers and Devices */
- /* [R/W] */
-#define NILE4_BOOTCS 0x0078 /* Boot ROM Chip-Select [R/W] */
-
-
- /*
- * CPU Interface Registers
- */
-
-#define NILE4_CPUSTAT 0x0080 /* CPU Status [R/W] */
-#define NILE4_INTCTRL 0x0088 /* Interrupt Control [R/W] */
-#define NILE4_INTSTAT0 0x0090 /* Interrupt Status 0 [R] */
-#define NILE4_INTSTAT1 0x0098 /* Interrupt Status 1 and CPU Interrupt */
- /* Enable [R/W] */
-#define NILE4_INTCLR 0x00A0 /* Interrupt Clear [R/W] */
-#define NILE4_INTPPES 0x00A8 /* PCI Interrupt Control [R/W] */
-
-
- /*
- * Memory-Interface Registers
- */
-
-#define NILE4_MEMCTRL 0x00C0 /* Memory Control */
-#define NILE4_ACSTIME 0x00C8 /* Memory Access Timing [R/W] */
-#define NILE4_CHKERR 0x00D0 /* Memory Check Error Status [R] */
-
-
- /*
- * PCI-Bus Registers
- */
-
-#define NILE4_PCICTRL 0x00E0 /* PCI Control [R/W] */
-#define NILE4_PCIARB 0x00E8 /* PCI Arbiter [R/W] */
-#define NILE4_PCIINIT0 0x00F0 /* PCI Master (Initiator) 0 [R/W] */
-#define NILE4_PCIINIT1 0x00F8 /* PCI Master (Initiator) 1 [R/W] */
-#define NILE4_PCIERR 0x00B8 /* PCI Error [R/W] */
-
-
- /*
- * Local-Bus Registers
- */
-
-#define NILE4_LCNFG 0x0100 /* Local Bus Configuration [R/W] */
-#define NILE4_LCST2 0x0110 /* Local Bus Chip-Select Timing 2 [R/W] */
-#define NILE4_LCST3 0x0118 /* Local Bus Chip-Select Timing 3 [R/W] */
-#define NILE4_LCST4 0x0120 /* Local Bus Chip-Select Timing 4 [R/W] */
-#define NILE4_LCST5 0x0128 /* Local Bus Chip-Select Timing 5 [R/W] */
-#define NILE4_LCST6 0x0130 /* Local Bus Chip-Select Timing 6 [R/W] */
-#define NILE4_LCST7 0x0138 /* Local Bus Chip-Select Timing 7 [R/W] */
-#define NILE4_LCST8 0x0140 /* Local Bus Chip-Select Timing 8 [R/W] */
-#define NILE4_DCSFN 0x0150 /* Device Chip-Select Muxing and Output */
- /* Enables [R/W] */
-#define NILE4_DCSIO 0x0158 /* Device Chip-Selects As I/O Bits [R/W] */
-#define NILE4_BCST 0x0178 /* Local Boot Chip-Select Timing [R/W] */
-
-
- /*
- * DMA Registers
- */
-
-#define NILE4_DMACTRL0 0x0180 /* DMA Control 0 [R/W] */
-#define NILE4_DMASRCA0 0x0188 /* DMA Source Address 0 [R/W] */
-#define NILE4_DMADESA0 0x0190 /* DMA Destination Address 0 [R/W] */
-#define NILE4_DMACTRL1 0x0198 /* DMA Control 1 [R/W] */
-#define NILE4_DMASRCA1 0x01A0 /* DMA Source Address 1 [R/W] */
-#define NILE4_DMADESA1 0x01A8 /* DMA Destination Address 1 [R/W] */
-
-
- /*
- * Timer Registers
- */
-
-#define NILE4_T0CTRL 0x01C0 /* SDRAM Refresh Control [R/W] */
-#define NILE4_T0CNTR 0x01C8 /* SDRAM Refresh Counter [R/W] */
-#define NILE4_T1CTRL 0x01D0 /* CPU-Bus Read Time-Out Control [R/W] */
-#define NILE4_T1CNTR 0x01D8 /* CPU-Bus Read Time-Out Counter [R/W] */
-#define NILE4_T2CTRL 0x01E0 /* General-Purpose Timer Control [R/W] */
-#define NILE4_T2CNTR 0x01E8 /* General-Purpose Timer Counter [R/W] */
-#define NILE4_T3CTRL 0x01F0 /* Watchdog Timer Control [R/W] */
-#define NILE4_T3CNTR 0x01F8 /* Watchdog Timer Counter [R/W] */
-
-
- /*
- * PCI Configuration Space Registers
- */
-
-#define NILE4_PCI_BASE 0x0200
-
-#define NILE4_VID 0x0200 /* PCI Vendor ID [R] */
-#define NILE4_DID 0x0202 /* PCI Device ID [R] */
-#define NILE4_PCICMD 0x0204 /* PCI Command [R/W] */
-#define NILE4_PCISTS 0x0206 /* PCI Status [R/W] */
-#define NILE4_REVID 0x0208 /* PCI Revision ID [R] */
-#define NILE4_CLASS 0x0209 /* PCI Class Code [R] */
-#define NILE4_CLSIZ 0x020C /* PCI Cache Line Size [R/W] */
-#define NILE4_MLTIM 0x020D /* PCI Latency Timer [R/W] */
-#define NILE4_HTYPE 0x020E /* PCI Header Type [R] */
-#define NILE4_BIST 0x020F /* BIST [R] (unimplemented) */
-#define NILE4_BARC 0x0210 /* PCI Base Address Register Control [R/W] */
-#define NILE4_BAR0 0x0218 /* PCI Base Address Register 0 [R/W] */
-#define NILE4_BAR1 0x0220 /* PCI Base Address Register 1 [R/W] */
-#define NILE4_CIS 0x0228 /* PCI Cardbus CIS Pointer [R] */
- /* (unimplemented) */
-#define NILE4_SSVID 0x022C /* PCI Sub-System Vendor ID [R/W] */
-#define NILE4_SSID 0x022E /* PCI Sub-System ID [R/W] */
-#define NILE4_ROM 0x0230 /* Expansion ROM Base Address [R] */
- /* (unimplemented) */
-#define NILE4_INTLIN 0x023C /* PCI Interrupt Line [R/W] */
-#define NILE4_INTPIN 0x023D /* PCI Interrupt Pin [R] */
-#define NILE4_MINGNT 0x023E /* PCI Min_Gnt [R] (unimplemented) */
-#define NILE4_MAXLAT 0x023F /* PCI Max_Lat [R] (unimplemented) */
-#define NILE4_BAR2 0x0240 /* PCI Base Address Register 2 [R/W] */
-#define NILE4_BAR3 0x0248 /* PCI Base Address Register 3 [R/W] */
-#define NILE4_BAR4 0x0250 /* PCI Base Address Register 4 [R/W] */
-#define NILE4_BAR5 0x0258 /* PCI Base Address Register 5 [R/W] */
-#define NILE4_BAR6 0x0260 /* PCI Base Address Register 6 [R/W] */
-#define NILE4_BAR7 0x0268 /* PCI Base Address Register 7 [R/W] */
-#define NILE4_BAR8 0x0270 /* PCI Base Address Register 8 [R/W] */
-#define NILE4_BARB 0x0278 /* PCI Base Address Register BOOT [R/W] */
-
-
- /*
- * Serial-Port Registers
- */
-
-#define NILE4_UART_BASE 0x0300
-
-#define NILE4_UARTRBR 0x0300 /* UART Receiver Data Buffer [R] */
-#define NILE4_UARTTHR 0x0300 /* UART Transmitter Data Holding [W] */
-#define NILE4_UARTIER 0x0308 /* UART Interrupt Enable [R/W] */
-#define NILE4_UARTDLL 0x0300 /* UART Divisor Latch LSB [R/W] */
-#define NILE4_UARTDLM 0x0308 /* UART Divisor Latch MSB [R/W] */
-#define NILE4_UARTIIR 0x0310 /* UART Interrupt ID [R] */
-#define NILE4_UARTFCR 0x0310 /* UART FIFO Control [W] */
-#define NILE4_UARTLCR 0x0318 /* UART Line Control [R/W] */
-#define NILE4_UARTMCR 0x0320 /* UART Modem Control [R/W] */
-#define NILE4_UARTLSR 0x0328 /* UART Line Status [R/W] */
-#define NILE4_UARTMSR 0x0330 /* UART Modem Status [R/W] */
-#define NILE4_UARTSCR 0x0338 /* UART Scratch [R/W] */
-
-#define NILE4_UART_BASE_BAUD 520833 /* 100 MHz / 12 / 16 */
-
-
- /*
- * Interrupt Lines
- */
-
-#define NILE4_INT_CPCE 0 /* CPU-Interface Parity-Error Interrupt */
-#define NILE4_INT_CNTD 1 /* CPU No-Target Decode Interrupt */
-#define NILE4_INT_MCE 2 /* Memory-Check Error Interrupt */
-#define NILE4_INT_DMA 3 /* DMA Controller Interrupt */
-#define NILE4_INT_UART 4 /* UART Interrupt */
-#define NILE4_INT_WDOG 5 /* Watchdog Timer Interrupt */
-#define NILE4_INT_GPT 6 /* General-Purpose Timer Interrupt */
-#define NILE4_INT_LBRTD 7 /* Local-Bus Ready Timer Interrupt */
-#define NILE4_INT_INTA 8 /* PCI Interrupt Signal INTA# */
-#define NILE4_INT_INTB 9 /* PCI Interrupt Signal INTB# */
-#define NILE4_INT_INTC 10 /* PCI Interrupt Signal INTC# */
-#define NILE4_INT_INTD 11 /* PCI Interrupt Signal INTD# */
-#define NILE4_INT_INTE 12 /* PCI Interrupt Signal INTE# (ISA cascade) */
-#define NILE4_INT_RESV 13 /* Reserved */
-#define NILE4_INT_PCIS 14 /* PCI SERR# Interrupt */
-#define NILE4_INT_PCIE 15 /* PCI Internal Error Interrupt */
-
-
- /*
- * Nile 4 Register Access
- */
-
-static inline void nile4_sync(void)
-{
- volatile u32 *p = (volatile u32 *)0xbfc00000;
- (void)(*p);
-}
-
-static inline void nile4_out32(u32 offset, u32 val)
-{
- *(volatile u32 *)(NILE4_BASE+offset) = val;
- nile4_sync();
-}
-
-static inline u32 nile4_in32(u32 offset)
-{
- u32 val = *(volatile u32 *)(NILE4_BASE+offset);
- nile4_sync();
- return val;
-}
-
-static inline void nile4_out16(u32 offset, u16 val)
-{
- *(volatile u16 *)(NILE4_BASE+offset) = val;
- nile4_sync();
-}
-
-static inline u16 nile4_in16(u32 offset)
-{
- u16 val = *(volatile u16 *)(NILE4_BASE+offset);
- nile4_sync();
- return val;
-}
-
-static inline void nile4_out8(u32 offset, u8 val)
-{
- *(volatile u8 *)(NILE4_BASE+offset) = val;
- nile4_sync();
-}
-
-static inline u8 nile4_in8(u32 offset)
-{
- u8 val = *(volatile u8 *)(NILE4_BASE+offset);
- nile4_sync();
- return val;
-}
-
-
- /*
- * Physical Device Address Registers
- */
-
-extern void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
- int on_memory_bus, int visible);
-
-
- /*
- * PCI Master Registers
- */
-
-#define NILE4_PCICMD_IACK 0 /* PCI Interrupt Acknowledge */
-#define NILE4_PCICMD_IO 1 /* PCI I/O Space */
-#define NILE4_PCICMD_MEM 3 /* PCI Memory Space */
-#define NILE4_PCICMD_CFG 5 /* PCI Configuration Space */
-
-
- /*
- * PCI Address Spaces
- *
- * Note that these are multiplexed using PCIINIT[01]!
- */
-
-#define NILE4_PCI_IO_BASE 0xa6000000
-#define NILE4_PCI_MEM_BASE 0xa8000000
-#define NILE4_PCI_CFG_BASE NILE4_PCI_MEM_BASE
-#define NILE4_PCI_IACK_BASE NILE4_PCI_IO_BASE
-
-
-extern void nile4_set_pmr(u32 pmr, u32 type, u32 addr);
-
-
- /*
- * Interrupt Programming
- */
-
-#define NUM_I8259_INTERRUPTS 16
-#define NUM_NILE4_INTERRUPTS 16
-
-#define IRQ_I8259_CASCADE NILE4_INT_INTE
-#define is_i8259_irq(irq) ((irq) < NUM_I8259_INTERRUPTS)
-#define nile4_to_irq(n) ((n)+NUM_I8259_INTERRUPTS)
-#define irq_to_nile4(n) ((n)-NUM_I8259_INTERRUPTS)
-
-extern void nile4_map_irq(int nile4_irq, int cpu_irq);
-extern void nile4_map_irq_all(int cpu_irq);
-extern void nile4_enable_irq(unsigned int nile4_irq);
-extern void nile4_disable_irq(unsigned int nile4_irq);
-extern void nile4_disable_irq_all(void);
-extern u16 nile4_get_irq_stat(int cpu_irq);
-extern void nile4_enable_irq_output(int cpu_irq);
-extern void nile4_disable_irq_output(int cpu_irq);
-extern void nile4_set_pci_irq_polarity(int pci_irq, int high);
-extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level);
-extern void nile4_clear_irq(int nile4_irq);
-extern void nile4_clear_irq_mask(u32 mask);
-extern u8 nile4_i8259_iack(void);
-extern void nile4_dump_irq_status(void); /* Debug */
-
-#endif
-
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 5c3239dad0f2..b92dd8c760da 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -34,12 +34,8 @@
#ifndef __ASSEMBLY__
-/*
- * This gives the physical RAM offset.
- */
-#ifndef PHYS_OFFSET
-#define PHYS_OFFSET 0UL
-#endif
+#include <linux/pfn.h>
+#include <asm/io.h>
/*
* It's normally defined only for FLATMEM config but it's
@@ -48,9 +44,6 @@
*/
#define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET)
-#include <linux/pfn.h>
-#include <asm/io.h>
-
extern void clear_page(void * page);
extern void copy_page(void * to, void * from);
@@ -150,11 +143,15 @@ typedef struct { unsigned long pgprot; } pgprot_t;
* __pa()/__va() should be used only during mem init.
*/
#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
-#define __pa_page_offset(x) ((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0)
+#define __pa(x) \
+({ \
+ unsigned long __x = (unsigned long)(x); \
+ __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x); \
+})
#else
-#define __pa_page_offset(x) PAGE_OFFSET
+#define __pa(x) \
+ ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
#endif
-#define __pa(x) ((unsigned long)(x) - __pa_page_offset(x) + PHYS_OFFSET)
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x),0))
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 3eea3ba0fca5..a59d54749eef 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -56,7 +56,7 @@ extern void register_pci_controller(struct pci_controller *hose);
/*
* board supplied pci irq fixup routine
*/
-extern int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
+extern int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
/* Can be used to override the logic in pci_scan_bus for skipping
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h
new file mode 100644
index 000000000000..c84bcf9570b1
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h
@@ -0,0 +1,151 @@
+/*
+ * Defines for the MSP interrupt controller.
+ *
+ * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_CIC_INT_H
+#define _MSP_CIC_INT_H
+
+/*
+ * The PMC-Sierra CIC interrupts are all centrally managed by the
+ * CIC sub-system.
+ * We attempt to keep the interrupt numbers as consistent as possible
+ * across all of the MSP devices, but some differences will creep in ...
+ * The interrupts which are directly forwarded to the MIPS core interrupts
+ * are assigned interrupts in the range 0-7, interrupts cascaded through
+ * the CIC are assigned interrupts 8-39. The cascade occurs on C_IRQ4
+ * (MSP_INT_CIC). Currently we don't really distinguish between VPE1
+ * and VPE0 (or thread contexts for that matter). Will have to fix.
+ * The PER interrupts are assigned interrupts in the range 40-71.
+*/
+
+
+/*
+ * IRQs directly forwarded to the CPU
+ */
+#define MSP_MIPS_INTBASE 0
+#define MSP_INT_SW0 0 /* IRQ for swint0, C_SW0 */
+#define MSP_INT_SW1 1 /* IRQ for swint1, C_SW1 */
+#define MSP_INT_MAC0 2 /* IRQ for MAC 0, C_IRQ0 */
+#define MSP_INT_MAC1 3 /* IRQ for MAC 1, C_IRQ1 */
+#define MSP_INT_USB 4 /* IRQ for USB, C_IRQ2 */
+#define MSP_INT_SAR 5 /* IRQ for ADSL2+ SAR, C_IRQ3 */
+#define MSP_INT_CIC 6 /* IRQ for CIC block, C_IRQ4 */
+#define MSP_INT_SEC 7 /* IRQ for Sec engine, C_IRQ5 */
+
+/*
+ * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4)
+ * These defines should be tied to the register definitions for the CIC
+ * interrupt routine. For now, just use hard-coded values.
+ */
+#define MSP_CIC_INTBASE (MSP_MIPS_INTBASE + 8)
+#define MSP_INT_EXT0 (MSP_CIC_INTBASE + 0)
+ /* External interrupt 0 */
+#define MSP_INT_EXT1 (MSP_CIC_INTBASE + 1)
+ /* External interrupt 1 */
+#define MSP_INT_EXT2 (MSP_CIC_INTBASE + 2)
+ /* External interrupt 2 */
+#define MSP_INT_EXT3 (MSP_CIC_INTBASE + 3)
+ /* External interrupt 3 */
+#define MSP_INT_CPUIF (MSP_CIC_INTBASE + 4)
+ /* CPU interface interrupt */
+#define MSP_INT_EXT4 (MSP_CIC_INTBASE + 5)
+ /* External interrupt 4 */
+#define MSP_INT_CIC_USB (MSP_CIC_INTBASE + 6)
+ /* Cascaded IRQ for USB */
+#define MSP_INT_MBOX (MSP_CIC_INTBASE + 7)
+ /* Sec engine mailbox IRQ */
+#define MSP_INT_EXT5 (MSP_CIC_INTBASE + 8)
+ /* External interrupt 5 */
+#define MSP_INT_TDM (MSP_CIC_INTBASE + 9)
+ /* TDM interrupt */
+#define MSP_INT_CIC_MAC0 (MSP_CIC_INTBASE + 10)
+ /* Cascaded IRQ for MAC 0 */
+#define MSP_INT_CIC_MAC1 (MSP_CIC_INTBASE + 11)
+ /* Cascaded IRQ for MAC 1 */
+#define MSP_INT_CIC_SEC (MSP_CIC_INTBASE + 12)
+ /* Cascaded IRQ for sec engine */
+#define MSP_INT_PER (MSP_CIC_INTBASE + 13)
+ /* Peripheral interrupt */
+#define MSP_INT_TIMER0 (MSP_CIC_INTBASE + 14)
+ /* SLP timer 0 */
+#define MSP_INT_TIMER1 (MSP_CIC_INTBASE + 15)
+ /* SLP timer 1 */
+#define MSP_INT_TIMER2 (MSP_CIC_INTBASE + 16)
+ /* SLP timer 2 */
+#define MSP_INT_VPE0_TIMER (MSP_CIC_INTBASE + 17)
+ /* VPE0 MIPS timer */
+#define MSP_INT_BLKCP (MSP_CIC_INTBASE + 18)
+ /* Block Copy */
+#define MSP_INT_UART0 (MSP_CIC_INTBASE + 19)
+ /* UART 0 */
+#define MSP_INT_PCI (MSP_CIC_INTBASE + 20)
+ /* PCI subsystem */
+#define MSP_INT_EXT6 (MSP_CIC_INTBASE + 21)
+ /* External interrupt 5 */
+#define MSP_INT_PCI_MSI (MSP_CIC_INTBASE + 22)
+ /* PCI Message Signal */
+#define MSP_INT_CIC_SAR (MSP_CIC_INTBASE + 23)
+ /* Cascaded ADSL2+ SAR IRQ */
+#define MSP_INT_DSL (MSP_CIC_INTBASE + 24)
+ /* ADSL2+ IRQ */
+#define MSP_INT_CIC_ERR (MSP_CIC_INTBASE + 25)
+ /* SLP error condition */
+#define MSP_INT_VPE1_TIMER (MSP_CIC_INTBASE + 26)
+ /* VPE1 MIPS timer */
+#define MSP_INT_VPE0_PC (MSP_CIC_INTBASE + 27)
+ /* VPE0 Performance counter */
+#define MSP_INT_VPE1_PC (MSP_CIC_INTBASE + 28)
+ /* VPE1 Performance counter */
+#define MSP_INT_EXT7 (MSP_CIC_INTBASE + 29)
+ /* External interrupt 5 */
+#define MSP_INT_VPE0_SW (MSP_CIC_INTBASE + 30)
+ /* VPE0 Software interrupt */
+#define MSP_INT_VPE1_SW (MSP_CIC_INTBASE + 31)
+ /* VPE0 Software interrupt */
+
+/*
+ * IRQs cascaded on CIC PER interrupt (MSP_INT_PER)
+ */
+#define MSP_PER_INTBASE (MSP_CIC_INTBASE + 32)
+/* Reserved 0-1 */
+#define MSP_INT_UART1 (MSP_PER_INTBASE + 2)
+ /* UART 1 */
+/* Reserved 3-5 */
+#define MSP_INT_2WIRE (MSP_PER_INTBASE + 6)
+ /* 2-wire */
+#define MSP_INT_TM0 (MSP_PER_INTBASE + 7)
+ /* Peripheral timer block out 0 */
+#define MSP_INT_TM1 (MSP_PER_INTBASE + 8)
+ /* Peripheral timer block out 1 */
+/* Reserved 9 */
+#define MSP_INT_SPRX (MSP_PER_INTBASE + 10)
+ /* SPI RX complete */
+#define MSP_INT_SPTX (MSP_PER_INTBASE + 11)
+ /* SPI TX complete */
+#define MSP_INT_GPIO (MSP_PER_INTBASE + 12)
+ /* GPIO */
+#define MSP_INT_PER_ERR (MSP_PER_INTBASE + 13)
+ /* Peripheral error */
+/* Reserved 14-31 */
+
+#endif /* !_MSP_CIC_INT_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_int.h
new file mode 100644
index 000000000000..1d9f05474820
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_int.h
@@ -0,0 +1,43 @@
+/*
+ * Defines for the MSP interrupt handlers.
+ *
+ * Copyright (C) 2005, PMC-Sierra, Inc. All rights reserved.
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_INT_H
+#define _MSP_INT_H
+
+/*
+ * The PMC-Sierra MSP product line has at least two different interrupt
+ * controllers, the SLP register based scheme and the CIC interrupt
+ * controller block mechanism. This file distinguishes between them
+ * so that devices see a uniform interface.
+ */
+
+#if defined(CONFIG_IRQ_MSP_SLP)
+ #include "msp_slp_int.h"
+#elif defined(CONFIG_IRQ_MSP_CIC)
+ #include "msp_cic_int.h"
+#else
+ #error "What sort of interrupt controller does *your* MSP have?"
+#endif
+
+#endif /* !_MSP_INT_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h b/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h
new file mode 100644
index 000000000000..415606903617
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2000-2006 PMC-Sierra INC.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ *
+ * PMC-SIERRA INC. DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _MSP_PCI_H_
+#define _MSP_PCI_H_
+
+#define MSP_HAS_PCI(ID) (((u32)(ID) <= 0x4236) && ((u32)(ID) >= 0x4220))
+
+/*
+ * It is convenient to program the OATRAN register so that
+ * Athena virtual address space and PCI address space are
+ * the same. This is not a requirement, just a convenience.
+ *
+ * The only hard restrictions on the value of OATRAN is that
+ * OATRAN must not be programmed to allow translated memory
+ * addresses to fall within the lowest 512MB of
+ * PCI address space. This region is hardcoded
+ * for use as Athena PCI Host Controller target
+ * access memory space to the Athena's SDRAM.
+ *
+ * Note that OATRAN applies only to memory accesses, not
+ * to I/O accesses.
+ *
+ * To program OATRAN to make Athena virtual address space
+ * and PCI address space have the same values, OATRAN
+ * is to be programmed to 0xB8000000. The top seven
+ * bits of the value mimic the seven bits clipped off
+ * by the PCI Host controller.
+ *
+ * With OATRAN at the said value, when the CPU does
+ * an access to its virtual address at, say 0xB900_5000,
+ * the address appearing on the PCI bus will be
+ * 0xB900_5000.
+ * - Michael Penner
+ */
+#define MSP_PCI_OATRAN 0xB8000000UL
+
+#define MSP_PCI_SPACE_BASE (MSP_PCI_OATRAN + 0x1002000UL)
+#define MSP_PCI_SPACE_SIZE (0x3000000UL - 0x2000)
+#define MSP_PCI_SPACE_END \
+ (MSP_PCI_SPACE_BASE + MSP_PCI_SPACE_SIZE - 1)
+#define MSP_PCI_IOSPACE_BASE (MSP_PCI_OATRAN + 0x1001000UL)
+#define MSP_PCI_IOSPACE_SIZE 0x1000
+#define MSP_PCI_IOSPACE_END \
+ (MSP_PCI_IOSPACE_BASE + MSP_PCI_IOSPACE_SIZE - 1)
+
+/* IRQ for PCI status interrupts */
+#define PCI_STAT_IRQ 20
+
+#define QFLUSH_REG_1 0xB7F40000
+
+typedef volatile unsigned int pcireg;
+typedef void * volatile ppcireg;
+
+struct pci_block_copy
+{
+ pcireg unused1; /* +0x00 */
+ pcireg unused2; /* +0x04 */
+ ppcireg unused3; /* +0x08 */
+ ppcireg unused4; /* +0x0C */
+ pcireg unused5; /* +0x10 */
+ pcireg unused6; /* +0x14 */
+ pcireg unused7; /* +0x18 */
+ ppcireg unused8; /* +0x1C */
+ ppcireg unused9; /* +0x20 */
+ pcireg unusedA; /* +0x24 */
+ ppcireg unusedB; /* +0x28 */
+ ppcireg unusedC; /* +0x2C */
+};
+
+enum
+{
+ config_device_vendor, /* 0 */
+ config_status_command, /* 1 */
+ config_class_revision, /* 2 */
+ config_BIST_header_latency_cache, /* 3 */
+ config_BAR0, /* 4 */
+ config_BAR1, /* 5 */
+ config_BAR2, /* 6 */
+ config_not_used7, /* 7 */
+ config_not_used8, /* 8 */
+ config_not_used9, /* 9 */
+ config_CIS, /* 10 */
+ config_subsystem, /* 11 */
+ config_not_used12, /* 12 */
+ config_capabilities, /* 13 */
+ config_not_used14, /* 14 */
+ config_lat_grant_irq, /* 15 */
+ config_message_control,/* 16 */
+ config_message_addr, /* 17 */
+ config_message_data, /* 18 */
+ config_VPD_addr, /* 19 */
+ config_VPD_data, /* 20 */
+ config_maxregs /* 21 - number of registers */
+};
+
+struct msp_pci_regs
+{
+ pcireg hop_unused_00; /* +0x00 */
+ pcireg hop_unused_04; /* +0x04 */
+ pcireg hop_unused_08; /* +0x08 */
+ pcireg hop_unused_0C; /* +0x0C */
+ pcireg hop_unused_10; /* +0x10 */
+ pcireg hop_unused_14; /* +0x14 */
+ pcireg hop_unused_18; /* +0x18 */
+ pcireg hop_unused_1C; /* +0x1C */
+ pcireg hop_unused_20; /* +0x20 */
+ pcireg hop_unused_24; /* +0x24 */
+ pcireg hop_unused_28; /* +0x28 */
+ pcireg hop_unused_2C; /* +0x2C */
+ pcireg hop_unused_30; /* +0x30 */
+ pcireg hop_unused_34; /* +0x34 */
+ pcireg if_control; /* +0x38 */
+ pcireg oatran; /* +0x3C */
+ pcireg reset_ctl; /* +0x40 */
+ pcireg config_addr; /* +0x44 */
+ pcireg hop_unused_48; /* +0x48 */
+ pcireg msg_signaled_int_status; /* +0x4C */
+ pcireg msg_signaled_int_mask; /* +0x50 */
+ pcireg if_status; /* +0x54 */
+ pcireg if_mask; /* +0x58 */
+ pcireg hop_unused_5C; /* +0x5C */
+ pcireg hop_unused_60; /* +0x60 */
+ pcireg hop_unused_64; /* +0x64 */
+ pcireg hop_unused_68; /* +0x68 */
+ pcireg hop_unused_6C; /* +0x6C */
+ pcireg hop_unused_70; /* +0x70 */
+
+ struct pci_block_copy pci_bc[2] __attribute__((aligned(64)));
+
+ pcireg error_hdr1; /* +0xE0 */
+ pcireg error_hdr2; /* +0xE4 */
+
+ pcireg config[config_maxregs] __attribute__((aligned(256)));
+
+};
+
+#define BPCI_CFGADDR_BUSNUM_SHF 16
+#define BPCI_CFGADDR_FUNCTNUM_SHF 8
+#define BPCI_CFGADDR_REGNUM_SHF 2
+#define BPCI_CFGADDR_ENABLE (1<<31)
+
+#define BPCI_IFCONTROL_RTO (1<<20) /* Retry timeout */
+#define BPCI_IFCONTROL_HCE (1<<16) /* Host configuration enable */
+#define BPCI_IFCONTROL_CTO_SHF 12 /* Shift count for CTO bits */
+#define BPCI_IFCONTROL_SE (1<<5) /* Enable exceptions on errors */
+#define BPCI_IFCONTROL_BIST (1<<4) /* Use BIST in per. mode */
+#define BPCI_IFCONTROL_CAP (1<<3) /* Enable capabilities */
+#define BPCI_IFCONTROL_MMC_SHF 0 /* Shift count for MMC bits */
+
+#define BPCI_IFSTATUS_MGT (1<<8) /* Master Grant timeout */
+#define BPCI_IFSTATUS_MTT (1<<9) /* Master TRDY timeout */
+#define BPCI_IFSTATUS_MRT (1<<10) /* Master retry timeout */
+#define BPCI_IFSTATUS_BC0F (1<<13) /* Block copy 0 fault */
+#define BPCI_IFSTATUS_BC1F (1<<14) /* Block copy 1 fault */
+#define BPCI_IFSTATUS_PCIU (1<<15) /* PCI unable to respond */
+#define BPCI_IFSTATUS_BSIZ (1<<16) /* PCI access with illegal size */
+#define BPCI_IFSTATUS_BADD (1<<17) /* PCI access with illegal addr */
+#define BPCI_IFSTATUS_RTO (1<<18) /* Retry time out */
+#define BPCI_IFSTATUS_SER (1<<19) /* System error */
+#define BPCI_IFSTATUS_PER (1<<20) /* Parity error */
+#define BPCI_IFSTATUS_LCA (1<<21) /* Local CPU abort */
+#define BPCI_IFSTATUS_MEM (1<<22) /* Memory prot. violation */
+#define BPCI_IFSTATUS_ARB (1<<23) /* Arbiter timed out */
+#define BPCI_IFSTATUS_STA (1<<27) /* Signaled target abort */
+#define BPCI_IFSTATUS_TA (1<<28) /* Target abort */
+#define BPCI_IFSTATUS_MA (1<<29) /* Master abort */
+#define BPCI_IFSTATUS_PEI (1<<30) /* Parity error as initiator */
+#define BPCI_IFSTATUS_PET (1<<31) /* Parity error as target */
+
+#define BPCI_RESETCTL_PR (1<<0) /* True if reset asserted */
+#define BPCI_RESETCTL_RT (1<<4) /* Release time */
+#define BPCI_RESETCTL_CT (1<<8) /* Config time */
+#define BPCI_RESETCTL_PE (1<<12) /* PCI enabled */
+#define BPCI_RESETCTL_HM (1<<13) /* PCI host mode */
+#define BPCI_RESETCTL_RI (1<<14) /* PCI reset in */
+
+extern struct msp_pci_regs msp_pci_regs
+ __attribute__((section(".register")));
+extern unsigned long msp_pci_config_space
+ __attribute__((section(".register")));
+
+#endif /* !_MSP_PCI_H_ */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h b/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h
new file mode 100644
index 000000000000..14ca7dc382a8
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h
@@ -0,0 +1,176 @@
+/*
+ * MIPS boards bootprom interface for the Linux kernel.
+ *
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _ASM_MSP_PROM_H
+#define _ASM_MSP_PROM_H
+
+#include <linux/types.h>
+
+#define DEVICEID "deviceid"
+#define FEATURES "features"
+#define PROM_ENV "prom_env"
+#define PROM_ENV_FILE "/proc/"PROM_ENV
+#define PROM_ENV_SIZE 256
+
+#define CPU_DEVID_FAMILY 0x0000ff00
+#define CPU_DEVID_REVISION 0x000000ff
+
+#define FPGA_IS_POLO(revision) \
+ (((revision >= 0xb0) && (revision < 0xd0)))
+#define FPGA_IS_5000(revision) \
+ ((revision >= 0x80) && (revision <= 0x90))
+#define FPGA_IS_ZEUS(revision) ((revision < 0x7f))
+#define FPGA_IS_DUET(revision) \
+ (((revision >= 0xa0) && (revision < 0xb0)))
+#define FPGA_IS_MSP4200(revision) ((revision >= 0xd0))
+#define FPGA_IS_MSP7100(revision) ((revision >= 0xd0))
+
+#define MACHINE_TYPE_POLO "POLO"
+#define MACHINE_TYPE_DUET "DUET"
+#define MACHINE_TYPE_ZEUS "ZEUS"
+#define MACHINE_TYPE_MSP2000REVB "MSP2000REVB"
+#define MACHINE_TYPE_MSP5000 "MSP5000"
+#define MACHINE_TYPE_MSP4200 "MSP4200"
+#define MACHINE_TYPE_MSP7120 "MSP7120"
+#define MACHINE_TYPE_MSP7130 "MSP7130"
+#define MACHINE_TYPE_OTHER "OTHER"
+
+#define MACHINE_TYPE_POLO_FPGA "POLO-FPGA"
+#define MACHINE_TYPE_DUET_FPGA "DUET-FPGA"
+#define MACHINE_TYPE_ZEUS_FPGA "ZEUS_FPGA"
+#define MACHINE_TYPE_MSP2000REVB_FPGA "MSP2000REVB-FPGA"
+#define MACHINE_TYPE_MSP5000_FPGA "MSP5000-FPGA"
+#define MACHINE_TYPE_MSP4200_FPGA "MSP4200-FPGA"
+#define MACHINE_TYPE_MSP7100_FPGA "MSP7100-FPGA"
+#define MACHINE_TYPE_OTHER_FPGA "OTHER-FPGA"
+
+/* Device Family definitions */
+#define FAMILY_FPGA 0x0000
+#define FAMILY_ZEUS 0x1000
+#define FAMILY_POLO 0x2000
+#define FAMILY_DUET 0x4000
+#define FAMILY_TRIAD 0x5000
+#define FAMILY_MSP4200 0x4200
+#define FAMILY_MSP4200_FPGA 0x4f00
+#define FAMILY_MSP7100 0x7100
+#define FAMILY_MSP7100_FPGA 0x7f00
+
+/* Device Type definitions */
+#define TYPE_MSP7120 0x7120
+#define TYPE_MSP7130 0x7130
+
+#define ENET_KEY 'E'
+#define ENETTXD_KEY 'e'
+#define PCI_KEY 'P'
+#define PCIMUX_KEY 'p'
+#define SEC_KEY 'S'
+#define SPAD_KEY 'D'
+#define TDM_KEY 'T'
+#define ZSP_KEY 'Z'
+
+#define FEATURE_NOEXIST '-'
+#define FEATURE_EXIST '+'
+
+#define ENET_MII 'M'
+#define ENET_RMII 'R'
+
+#define ENETTXD_FALLING 'F'
+#define ENETTXD_RISING 'R'
+
+#define PCI_HOST 'H'
+#define PCI_PERIPHERAL 'P'
+
+#define PCIMUX_FULL 'F'
+#define PCIMUX_SINGLE 'S'
+
+#define SEC_DUET 'D'
+#define SEC_POLO 'P'
+#define SEC_SLOW 'S'
+#define SEC_TRIAD 'T'
+
+#define SPAD_POLO 'P'
+
+#define TDM_DUET 'D' /* DUET TDMs might exist */
+#define TDM_POLO 'P' /* POLO TDMs might exist */
+#define TDM_TRIAD 'T' /* TRIAD TDMs might exist */
+
+#define ZSP_DUET 'D' /* one DUET zsp engine */
+#define ZSP_TRIAD 'T' /* two TRIAD zsp engines */
+
+extern char *prom_getcmdline(void);
+extern char *prom_getenv(char *name);
+extern void prom_init_cmdline(void);
+extern void prom_meminit(void);
+extern void prom_fixup_mem_map(unsigned long start_mem,
+ unsigned long end_mem);
+
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+extern bool get_ramroot(void **start, unsigned long *size);
+#endif
+
+extern int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr);
+extern unsigned long get_deviceid(void);
+extern char identify_enet(unsigned long interface_num);
+extern char identify_enetTxD(unsigned long interface_num);
+extern char identify_pci(void);
+extern char identify_sec(void);
+extern char identify_spad(void);
+extern char identify_sec(void);
+extern char identify_tdm(void);
+extern char identify_zsp(void);
+extern unsigned long identify_family(void);
+extern unsigned long identify_revision(void);
+
+/*
+ * The following macro calls prom_printf and puts the format string
+ * into an init section so it can be reclaimed.
+ */
+#define ppfinit(f, x...) \
+ do { \
+ static char _f[] __initdata = KERN_INFO f; \
+ printk(_f, ## x); \
+ } while (0)
+
+/* Memory descriptor management. */
+#define PROM_MAX_PMEMBLOCKS 7 /* 6 used */
+
+enum yamon_memtypes {
+ yamon_dontuse,
+ yamon_prom,
+ yamon_free,
+};
+
+struct prom_pmemblock {
+ unsigned long base; /* Within KSEG0. */
+ unsigned int size; /* In bytes. */
+ unsigned int type; /* free or prom memory */
+};
+
+extern int prom_argc;
+extern char **prom_argv;
+extern char **prom_envp;
+extern int *prom_vec;
+extern struct prom_pmemblock *prom_getmdesc(void);
+
+#endif /* !_ASM_MSP_PROM_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h
new file mode 100644
index 000000000000..60a5a38dd5b2
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h
@@ -0,0 +1,236 @@
+/*
+ * SMP/VPE-safe functions to access "registers" (see note).
+ *
+ * NOTES:
+* - These macros use ll/sc instructions, so it is your responsibility to
+ * ensure these are available on your platform before including this file.
+ * - The MIPS32 spec states that ll/sc results are undefined for uncached
+ * accesses. This means they can't be used on HW registers accessed
+ * through kseg1. Code which requires these macros for this purpose must
+ * front-end the registers with cached memory "registers" and have a single
+ * thread update the actual HW registers.
+ * - A maximum of 2k of code can be inserted between ll and sc. Every
+ * memory accesses between the instructions will increase the chance of
+ * sc failing and having to loop.
+ * - When using custom_read_reg32/custom_write_reg32 only perform the
+ * necessary logical operations on the register value in between these
+ * two calls. All other logic should be performed before the first call.
+ * - There is a bug on the R10000 chips which has a workaround. If you
+ * are affected by this bug, make sure to define the symbol 'R10000_LLSC_WAR'
+ * to be non-zero. If you are using this header from within linux, you may
+ * include <asm/war.h> before including this file to have this defined
+ * appropriately for you.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_REGOPS_H__
+#define __ASM_REGOPS_H__
+
+#include <linux/types.h>
+
+#include <asm/war.h>
+
+#ifndef R10000_LLSC_WAR
+#define R10000_LLSC_WAR 0
+#endif
+
+#if R10000_LLSC_WAR == 1
+#define __beqz "beqzl "
+#else
+#define __beqz "beqz "
+#endif
+
+#ifndef _LINUX_TYPES_H
+typedef unsigned int u32;
+#endif
+
+/*
+ * Sets all the masked bits to the corresponding value bits
+ */
+static inline void set_value_reg32(volatile u32 *const addr,
+ u32 const mask,
+ u32 const value)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips3 \n"
+ "1: ll %0, %1 # set_value_reg32 \n"
+ " and %0, %2 \n"
+ " or %0, %3 \n"
+ " sc %0, %1 \n"
+ " "__beqz"%0, 1b \n"
+ " nop \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*addr)
+ : "ir" (~mask), "ir" (value), "m" (*addr));
+}
+
+/*
+ * Sets all the masked bits to '1'
+ */
+static inline void set_reg32(volatile u32 *const addr,
+ u32 const mask)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips3 \n"
+ "1: ll %0, %1 # set_reg32 \n"
+ " or %0, %2 \n"
+ " sc %0, %1 \n"
+ " "__beqz"%0, 1b \n"
+ " nop \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*addr)
+ : "ir" (mask), "m" (*addr));
+}
+
+/*
+ * Sets all the masked bits to '0'
+ */
+static inline void clear_reg32(volatile u32 *const addr,
+ u32 const mask)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips3 \n"
+ "1: ll %0, %1 # clear_reg32 \n"
+ " and %0, %2 \n"
+ " sc %0, %1 \n"
+ " "__beqz"%0, 1b \n"
+ " nop \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*addr)
+ : "ir" (~mask), "m" (*addr));
+}
+
+/*
+ * Toggles all masked bits from '0' to '1' and '1' to '0'
+ */
+static inline void toggle_reg32(volatile u32 *const addr,
+ u32 const mask)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips3 \n"
+ "1: ll %0, %1 # toggle_reg32 \n"
+ " xor %0, %2 \n"
+ " sc %0, %1 \n"
+ " "__beqz"%0, 1b \n"
+ " nop \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*addr)
+ : "ir" (mask), "m" (*addr));
+}
+
+/*
+ * Read all masked bits others are returned as '0'
+ */
+static inline u32 read_reg32(volatile u32 *const addr,
+ u32 const mask)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " lw %0, %1 # read \n"
+ " and %0, %2 # mask \n"
+ " .set pop \n"
+ : "=&r" (temp)
+ : "m" (*addr), "ir" (mask));
+
+ return temp;
+}
+
+/*
+ * blocking_read_reg32 - Read address with blocking load
+ *
+ * Uncached writes need to be read back to ensure they reach RAM.
+ * The returned value must be 'used' to prevent from becoming a
+ * non-blocking load.
+ */
+static inline u32 blocking_read_reg32(volatile u32 *const addr)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " lw %0, %1 # read \n"
+ " move %0, %0 # block \n"
+ " .set pop \n"
+ : "=&r" (temp)
+ : "m" (*addr));
+
+ return temp;
+}
+
+/*
+ * For special strange cases only:
+ *
+ * If you need custom processing within a ll/sc loop, use the following macros
+ * VERY CAREFULLY:
+ *
+ * u32 tmp; <-- Define a variable to hold the data
+ *
+ * custom_read_reg32(address, tmp); <-- Reads the address and put the value
+ * in the 'tmp' variable given
+ *
+ * From here on out, you are (basicly) atomic, so don't do anything too
+ * fancy!
+ * Also, this code may loop if the end of this block fails to write
+ * everything back safely due do the other CPU, so do NOT do anything
+ * with side-effects!
+ *
+ * custom_write_reg32(address, tmp); <-- Writes back 'tmp' safely.
+ */
+#define custom_read_reg32(address, tmp) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set mips3 \n" \
+ "1: ll %0, %1 #custom_read_reg32 \n" \
+ " .set pop \n" \
+ : "=r" (tmp), "=m" (*address) \
+ : "m" (*address))
+
+#define custom_write_reg32(address, tmp) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set mips3 \n" \
+ " sc %0, %1 #custom_write_reg32 \n" \
+ " "__beqz"%0, 1b \n" \
+ " nop \n" \
+ " .set pop \n" \
+ : "=&r" (tmp), "=m" (*address) \
+ : "0" (tmp), "m" (*address))
+
+#endif /* __ASM_REGOPS_H__ */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
new file mode 100644
index 000000000000..0b56f55206c6
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
@@ -0,0 +1,667 @@
+/*
+ * Defines for the address space, registers and register configuration
+ * (bit masks, access macros etc) for the PMC-Sierra line of MSP products.
+ * This file contains addess maps for all the devices in the line of
+ * products but only has register definitions and configuration masks for
+ * registers which aren't definitely associated with any device. Things
+ * like clock settings, reset access, the ELB etc. Individual device
+ * drivers will reference the appropriate XXX_BASE value defined here
+ * and have individual registers offset from that.
+ *
+ * Copyright (C) 2005-2007 PMC-Sierra, Inc. All rights reserved.
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#include <asm/addrspace.h>
+#include <linux/types.h>
+
+#ifndef _ASM_MSP_REGS_H
+#define _ASM_MSP_REGS_H
+
+/*
+ ########################################################################
+ # Address space and device base definitions #
+ ########################################################################
+ */
+
+/*
+ ***************************************************************************
+ * System Logic and Peripherals (ELB, UART0, etc) device address space *
+ ***************************************************************************
+ */
+#define MSP_SLP_BASE 0x1c000000
+ /* System Logic and Peripherals */
+#define MSP_RST_BASE (MSP_SLP_BASE + 0x10)
+ /* System reset register base */
+#define MSP_RST_SIZE 0x0C /* System reset register space */
+
+#define MSP_WTIMER_BASE (MSP_SLP_BASE + 0x04C)
+ /* watchdog timer base */
+#define MSP_ITIMER_BASE (MSP_SLP_BASE + 0x054)
+ /* internal timer base */
+#define MSP_UART0_BASE (MSP_SLP_BASE + 0x100)
+ /* UART0 controller base */
+#define MSP_BCPY_CTRL_BASE (MSP_SLP_BASE + 0x120)
+ /* Block Copy controller base */
+#define MSP_BCPY_DESC_BASE (MSP_SLP_BASE + 0x160)
+ /* Block Copy descriptor base */
+
+/*
+ ***************************************************************************
+ * PCI address space *
+ ***************************************************************************
+ */
+#define MSP_PCI_BASE 0x19000000
+
+/*
+ ***************************************************************************
+ * MSbus device address space *
+ ***************************************************************************
+ */
+#define MSP_MSB_BASE 0x18000000
+ /* MSbus address start */
+#define MSP_PER_BASE (MSP_MSB_BASE + 0x400000)
+ /* Peripheral device registers */
+#define MSP_MAC0_BASE (MSP_MSB_BASE + 0x600000)
+ /* MAC A device registers */
+#define MSP_MAC1_BASE (MSP_MSB_BASE + 0x700000)
+ /* MAC B device registers */
+#define MSP_MAC_SIZE 0xE0 /* MAC register space */
+
+#define MSP_SEC_BASE (MSP_MSB_BASE + 0x800000)
+ /* Security Engine registers */
+#define MSP_MAC2_BASE (MSP_MSB_BASE + 0x900000)
+ /* MAC C device registers */
+#define MSP_ADSL2_BASE (MSP_MSB_BASE + 0xA80000)
+ /* ADSL2 device registers */
+#define MSP_USB_BASE (MSP_MSB_BASE + 0xB40000)
+ /* USB device registers */
+#define MSP_USB_BASE_START (MSP_MSB_BASE + 0xB40100)
+ /* USB device registers */
+#define MSP_USB_BASE_END (MSP_MSB_BASE + 0xB401FF)
+ /* USB device registers */
+#define MSP_CPUIF_BASE (MSP_MSB_BASE + 0xC00000)
+ /* CPU interface registers */
+
+/* Devices within the MSbus peripheral block */
+#define MSP_UART1_BASE (MSP_PER_BASE + 0x030)
+ /* UART1 controller base */
+#define MSP_SPI_BASE (MSP_PER_BASE + 0x058)
+ /* SPI/MPI control registers */
+#define MSP_TWI_BASE (MSP_PER_BASE + 0x090)
+ /* Two-wire control registers */
+#define MSP_PTIMER_BASE (MSP_PER_BASE + 0x0F0)
+ /* Programmable timer control */
+
+/*
+ ***************************************************************************
+ * Physical Memory configuration address space *
+ ***************************************************************************
+ */
+#define MSP_MEM_CFG_BASE 0x17f00000
+
+#define MSP_MEM_INDIRECT_CTL_10 0x10
+
+/*
+ * Notes:
+ * 1) The SPI registers are split into two blocks, one offset from the
+ * MSP_SPI_BASE by 0x00 and the other offset from the MSP_SPI_BASE by
+ * 0x68. The SPI driver definitions for the register must be aware
+ * of this.
+ * 2) The block copy engine register are divided into two regions, one
+ * for the control/configuration of the engine proper and one for the
+ * values of the descriptors used in the copy process. These have
+ * different base defines (CTRL_BASE vs DESC_BASE)
+ * 3) These constants are for physical addresses which means that they
+ * work correctly with "ioremap" and friends. This means that device
+ * drivers will need to remap these addresses using ioremap and perhaps
+ * the readw/writew macros. Or they could use the regptr() macro
+ * defined below, but the readw/writew calls are the correct thing.
+ * 4) The UARTs have an additional status register offset from the base
+ * address. This register isn't used in the standard 8250 driver but
+ * may be used in other software. Consult the hardware datasheet for
+ * offset details.
+ * 5) For some unknown reason the security engine (MSP_SEC_BASE) registers
+ * start at an offset of 0x84 from the base address but the block of
+ * registers before this is reserved for the security engine. The
+ * driver will have to be aware of this but it makes the register
+ * definitions line up better with the documentation.
+ */
+
+/*
+ ########################################################################
+ # System register definitions. Not associated with a specific device #
+ ########################################################################
+ */
+
+/*
+ * This macro maps the physical register number into uncached space
+ * and (for C code) casts it into a u32 pointer so it can be dereferenced
+ * Normally these would be accessed with ioremap and readX/writeX, but
+ * these are convenient for a lot of internal kernel code.
+ */
+#ifdef __ASSEMBLER__
+ #define regptr(addr) (KSEG1ADDR(addr))
+#else
+ #define regptr(addr) ((volatile u32 *const)(KSEG1ADDR(addr)))
+#endif
+
+/*
+ ***************************************************************************
+ * System Logic and Peripherals (RESET, ELB, etc) registers *
+ ***************************************************************************
+ */
+
+/* System Control register definitions */
+#define DEV_ID_REG regptr(MSP_SLP_BASE + 0x00)
+ /* Device-ID RO */
+#define FWR_ID_REG regptr(MSP_SLP_BASE + 0x04)
+ /* Firmware-ID Register RW */
+#define SYS_ID_REG0 regptr(MSP_SLP_BASE + 0x08)
+ /* System-ID Register-0 RW */
+#define SYS_ID_REG1 regptr(MSP_SLP_BASE + 0x0C)
+ /* System-ID Register-1 RW */
+
+/* System Reset register definitions */
+#define RST_STS_REG regptr(MSP_SLP_BASE + 0x10)
+ /* System Reset Status RO */
+#define RST_SET_REG regptr(MSP_SLP_BASE + 0x14)
+ /* System Set Reset WO */
+#define RST_CLR_REG regptr(MSP_SLP_BASE + 0x18)
+ /* System Clear Reset WO */
+
+/* System Clock Registers */
+#define PCI_SLP_REG regptr(MSP_SLP_BASE + 0x1C)
+ /* PCI clock generator RW */
+#define URT_SLP_REG regptr(MSP_SLP_BASE + 0x20)
+ /* UART clock generator RW */
+/* reserved (MSP_SLP_BASE + 0x24) */
+/* reserved (MSP_SLP_BASE + 0x28) */
+#define PLL1_SLP_REG regptr(MSP_SLP_BASE + 0x2C)
+ /* PLL1 clock generator RW */
+#define PLL0_SLP_REG regptr(MSP_SLP_BASE + 0x30)
+ /* PLL0 clock generator RW */
+#define MIPS_SLP_REG regptr(MSP_SLP_BASE + 0x34)
+ /* MIPS clock generator RW */
+#define VE_SLP_REG regptr(MSP_SLP_BASE + 0x38)
+ /* Voice Eng clock generator RW */
+/* reserved (MSP_SLP_BASE + 0x3C) */
+#define MSB_SLP_REG regptr(MSP_SLP_BASE + 0x40)
+ /* MS-Bus clock generator RW */
+#define SMAC_SLP_REG regptr(MSP_SLP_BASE + 0x44)
+ /* Sec & MAC clock generator RW */
+#define PERF_SLP_REG regptr(MSP_SLP_BASE + 0x48)
+ /* Per & TDM clock generator RW */
+
+/* Interrupt Controller Registers */
+#define SLP_INT_STS_REG regptr(MSP_SLP_BASE + 0x70)
+ /* Interrupt status register RW */
+#define SLP_INT_MSK_REG regptr(MSP_SLP_BASE + 0x74)
+ /* Interrupt enable/mask RW */
+#define SE_MBOX_REG regptr(MSP_SLP_BASE + 0x78)
+ /* Security Engine mailbox RW */
+#define VE_MBOX_REG regptr(MSP_SLP_BASE + 0x7C)
+ /* Voice Engine mailbox RW */
+
+/* ELB Controller Registers */
+#define CS0_CNFG_REG regptr(MSP_SLP_BASE + 0x80)
+ /* ELB CS0 Configuration Reg */
+#define CS0_ADDR_REG regptr(MSP_SLP_BASE + 0x84)
+ /* ELB CS0 Base Address Reg */
+#define CS0_MASK_REG regptr(MSP_SLP_BASE + 0x88)
+ /* ELB CS0 Mask Register */
+#define CS0_ACCESS_REG regptr(MSP_SLP_BASE + 0x8C)
+ /* ELB CS0 access register */
+
+#define CS1_CNFG_REG regptr(MSP_SLP_BASE + 0x90)
+ /* ELB CS1 Configuration Reg */
+#define CS1_ADDR_REG regptr(MSP_SLP_BASE + 0x94)
+ /* ELB CS1 Base Address Reg */
+#define CS1_MASK_REG regptr(MSP_SLP_BASE + 0x98)
+ /* ELB CS1 Mask Register */
+#define CS1_ACCESS_REG regptr(MSP_SLP_BASE + 0x9C)
+ /* ELB CS1 access register */
+
+#define CS2_CNFG_REG regptr(MSP_SLP_BASE + 0xA0)
+ /* ELB CS2 Configuration Reg */
+#define CS2_ADDR_REG regptr(MSP_SLP_BASE + 0xA4)
+ /* ELB CS2 Base Address Reg */
+#define CS2_MASK_REG regptr(MSP_SLP_BASE + 0xA8)
+ /* ELB CS2 Mask Register */
+#define CS2_ACCESS_REG regptr(MSP_SLP_BASE + 0xAC)
+ /* ELB CS2 access register */
+
+#define CS3_CNFG_REG regptr(MSP_SLP_BASE + 0xB0)
+ /* ELB CS3 Configuration Reg */
+#define CS3_ADDR_REG regptr(MSP_SLP_BASE + 0xB4)
+ /* ELB CS3 Base Address Reg */
+#define CS3_MASK_REG regptr(MSP_SLP_BASE + 0xB8)
+ /* ELB CS3 Mask Register */
+#define CS3_ACCESS_REG regptr(MSP_SLP_BASE + 0xBC)
+ /* ELB CS3 access register */
+
+#define CS4_CNFG_REG regptr(MSP_SLP_BASE + 0xC0)
+ /* ELB CS4 Configuration Reg */
+#define CS4_ADDR_REG regptr(MSP_SLP_BASE + 0xC4)
+ /* ELB CS4 Base Address Reg */
+#define CS4_MASK_REG regptr(MSP_SLP_BASE + 0xC8)
+ /* ELB CS4 Mask Register */
+#define CS4_ACCESS_REG regptr(MSP_SLP_BASE + 0xCC)
+ /* ELB CS4 access register */
+
+#define CS5_CNFG_REG regptr(MSP_SLP_BASE + 0xD0)
+ /* ELB CS5 Configuration Reg */
+#define CS5_ADDR_REG regptr(MSP_SLP_BASE + 0xD4)
+ /* ELB CS5 Base Address Reg */
+#define CS5_MASK_REG regptr(MSP_SLP_BASE + 0xD8)
+ /* ELB CS5 Mask Register */
+#define CS5_ACCESS_REG regptr(MSP_SLP_BASE + 0xDC)
+ /* ELB CS5 access register */
+
+/* reserved 0xE0 - 0xE8 */
+#define ELB_1PC_EN_REG regptr(MSP_SLP_BASE + 0xEC)
+ /* ELB single PC card detect */
+
+/* reserved 0xF0 - 0xF8 */
+#define ELB_CLK_CFG_REG regptr(MSP_SLP_BASE + 0xFC)
+ /* SDRAM read/ELB timing Reg */
+
+/* Extended UART status registers */
+#define UART0_STATUS_REG regptr(MSP_UART0_BASE + 0x0c0)
+ /* UART Status Register 0 */
+#define UART1_STATUS_REG regptr(MSP_UART1_BASE + 0x170)
+ /* UART Status Register 1 */
+
+/* Performance monitoring registers */
+#define PERF_MON_CTRL_REG regptr(MSP_SLP_BASE + 0x140)
+ /* Performance monitor control */
+#define PERF_MON_CLR_REG regptr(MSP_SLP_BASE + 0x144)
+ /* Performance monitor clear */
+#define PERF_MON_CNTH_REG regptr(MSP_SLP_BASE + 0x148)
+ /* Perf monitor counter high */
+#define PERF_MON_CNTL_REG regptr(MSP_SLP_BASE + 0x14C)
+ /* Perf monitor counter low */
+
+/* System control registers */
+#define SYS_CTRL_REG regptr(MSP_SLP_BASE + 0x150)
+ /* System control register */
+#define SYS_ERR1_REG regptr(MSP_SLP_BASE + 0x154)
+ /* System Error status 1 */
+#define SYS_ERR2_REG regptr(MSP_SLP_BASE + 0x158)
+ /* System Error status 2 */
+#define SYS_INT_CFG_REG regptr(MSP_SLP_BASE + 0x15C)
+ /* System Interrupt config */
+
+/* Voice Engine Memory configuration */
+#define VE_MEM_REG regptr(MSP_SLP_BASE + 0x17C)
+ /* Voice engine memory config */
+
+/* CPU/SLP Error Status registers */
+#define CPU_ERR1_REG regptr(MSP_SLP_BASE + 0x180)
+ /* CPU/SLP Error status 1 */
+#define CPU_ERR2_REG regptr(MSP_SLP_BASE + 0x184)
+ /* CPU/SLP Error status 1 */
+
+#define EXTENDED_GPIO_REG regptr(MSP_SLP_BASE + 0x188)
+ /* Extended GPIO register */
+
+/* System Error registers */
+#define SLP_ERR_STS_REG regptr(MSP_SLP_BASE + 0x190)
+ /* Int status for SLP errors */
+#define SLP_ERR_MSK_REG regptr(MSP_SLP_BASE + 0x194)
+ /* Int mask for SLP errors */
+#define SLP_ELB_ERST_REG regptr(MSP_SLP_BASE + 0x198)
+ /* External ELB reset */
+#define SLP_BOOT_STS_REG regptr(MSP_SLP_BASE + 0x19C)
+ /* Boot Status */
+
+/* Extended ELB addressing */
+#define CS0_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A0)
+ /* CS0 Extended address */
+#define CS1_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A4)
+ /* CS1 Extended address */
+#define CS2_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A8)
+ /* CS2 Extended address */
+#define CS3_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1AC)
+ /* CS3 Extended address */
+/* reserved 0x1B0 */
+#define CS5_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1B4)
+ /* CS5 Extended address */
+
+/* PLL Adjustment registers */
+#define PLL_LOCK_REG regptr(MSP_SLP_BASE + 0x200)
+ /* PLL0 lock status */
+#define PLL_ARST_REG regptr(MSP_SLP_BASE + 0x204)
+ /* PLL Analog reset status */
+#define PLL0_ADJ_REG regptr(MSP_SLP_BASE + 0x208)
+ /* PLL0 Adjustment value */
+#define PLL1_ADJ_REG regptr(MSP_SLP_BASE + 0x20C)
+ /* PLL1 Adjustment value */
+
+/*
+ ***************************************************************************
+ * Peripheral Register definitions *
+ ***************************************************************************
+ */
+
+/* Peripheral status */
+#define PER_CTRL_REG regptr(MSP_PER_BASE + 0x50)
+ /* Peripheral control register */
+#define PER_STS_REG regptr(MSP_PER_BASE + 0x54)
+ /* Peripheral status register */
+
+/* SPI/MPI Registers */
+#define SMPI_TX_SZ_REG regptr(MSP_PER_BASE + 0x58)
+ /* SPI/MPI Tx Size register */
+#define SMPI_RX_SZ_REG regptr(MSP_PER_BASE + 0x5C)
+ /* SPI/MPI Rx Size register */
+#define SMPI_CTL_REG regptr(MSP_PER_BASE + 0x60)
+ /* SPI/MPI Control register */
+#define SMPI_MS_REG regptr(MSP_PER_BASE + 0x64)
+ /* SPI/MPI Chip Select reg */
+#define SMPI_CORE_DATA_REG regptr(MSP_PER_BASE + 0xC0)
+ /* SPI/MPI Core Data reg */
+#define SMPI_CORE_CTRL_REG regptr(MSP_PER_BASE + 0xC4)
+ /* SPI/MPI Core Control reg */
+#define SMPI_CORE_STAT_REG regptr(MSP_PER_BASE + 0xC8)
+ /* SPI/MPI Core Status reg */
+#define SMPI_CORE_SSEL_REG regptr(MSP_PER_BASE + 0xCC)
+ /* SPI/MPI Core Ssel reg */
+#define SMPI_FIFO_REG regptr(MSP_PER_BASE + 0xD0)
+ /* SPI/MPI Data FIFO reg */
+
+/* Peripheral Block Error Registers */
+#define PER_ERR_STS_REG regptr(MSP_PER_BASE + 0x70)
+ /* Error Bit Status Register */
+#define PER_ERR_MSK_REG regptr(MSP_PER_BASE + 0x74)
+ /* Error Bit Mask Register */
+#define PER_HDR1_REG regptr(MSP_PER_BASE + 0x78)
+ /* Error Header 1 Register */
+#define PER_HDR2_REG regptr(MSP_PER_BASE + 0x7C)
+ /* Error Header 2 Register */
+
+/* Peripheral Block Interrupt Registers */
+#define PER_INT_STS_REG regptr(MSP_PER_BASE + 0x80)
+ /* Interrupt status register */
+#define PER_INT_MSK_REG regptr(MSP_PER_BASE + 0x84)
+ /* Interrupt Mask Register */
+#define GPIO_INT_STS_REG regptr(MSP_PER_BASE + 0x88)
+ /* GPIO interrupt status reg */
+#define GPIO_INT_MSK_REG regptr(MSP_PER_BASE + 0x8C)
+ /* GPIO interrupt MASK Reg */
+
+/* POLO GPIO registers */
+#define POLO_GPIO_DAT1_REG regptr(MSP_PER_BASE + 0x0E0)
+ /* Polo GPIO[8:0] data reg */
+#define POLO_GPIO_CFG1_REG regptr(MSP_PER_BASE + 0x0E4)
+ /* Polo GPIO[7:0] config reg */
+#define POLO_GPIO_CFG2_REG regptr(MSP_PER_BASE + 0x0E8)
+ /* Polo GPIO[15:8] config reg */
+#define POLO_GPIO_OD1_REG regptr(MSP_PER_BASE + 0x0EC)
+ /* Polo GPIO[31:0] output drive */
+#define POLO_GPIO_CFG3_REG regptr(MSP_PER_BASE + 0x170)
+ /* Polo GPIO[23:16] config reg */
+#define POLO_GPIO_DAT2_REG regptr(MSP_PER_BASE + 0x174)
+ /* Polo GPIO[15:9] data reg */
+#define POLO_GPIO_DAT3_REG regptr(MSP_PER_BASE + 0x178)
+ /* Polo GPIO[23:16] data reg */
+#define POLO_GPIO_DAT4_REG regptr(MSP_PER_BASE + 0x17C)
+ /* Polo GPIO[31:24] data reg */
+#define POLO_GPIO_DAT5_REG regptr(MSP_PER_BASE + 0x180)
+ /* Polo GPIO[39:32] data reg */
+#define POLO_GPIO_DAT6_REG regptr(MSP_PER_BASE + 0x184)
+ /* Polo GPIO[47:40] data reg */
+#define POLO_GPIO_DAT7_REG regptr(MSP_PER_BASE + 0x188)
+ /* Polo GPIO[54:48] data reg */
+#define POLO_GPIO_CFG4_REG regptr(MSP_PER_BASE + 0x18C)
+ /* Polo GPIO[31:24] config reg */
+#define POLO_GPIO_CFG5_REG regptr(MSP_PER_BASE + 0x190)
+ /* Polo GPIO[39:32] config reg */
+#define POLO_GPIO_CFG6_REG regptr(MSP_PER_BASE + 0x194)
+ /* Polo GPIO[47:40] config reg */
+#define POLO_GPIO_CFG7_REG regptr(MSP_PER_BASE + 0x198)
+ /* Polo GPIO[54:48] config reg */
+#define POLO_GPIO_OD2_REG regptr(MSP_PER_BASE + 0x19C)
+ /* Polo GPIO[54:32] output drive */
+
+/* Generic GPIO registers */
+#define GPIO_DATA1_REG regptr(MSP_PER_BASE + 0x170)
+ /* GPIO[1:0] data register */
+#define GPIO_DATA2_REG regptr(MSP_PER_BASE + 0x174)
+ /* GPIO[5:2] data register */
+#define GPIO_DATA3_REG regptr(MSP_PER_BASE + 0x178)
+ /* GPIO[9:6] data register */
+#define GPIO_DATA4_REG regptr(MSP_PER_BASE + 0x17C)
+ /* GPIO[15:10] data register */
+#define GPIO_CFG1_REG regptr(MSP_PER_BASE + 0x180)
+ /* GPIO[1:0] config register */
+#define GPIO_CFG2_REG regptr(MSP_PER_BASE + 0x184)
+ /* GPIO[5:2] config register */
+#define GPIO_CFG3_REG regptr(MSP_PER_BASE + 0x188)
+ /* GPIO[9:6] config register */
+#define GPIO_CFG4_REG regptr(MSP_PER_BASE + 0x18C)
+ /* GPIO[15:10] config register */
+#define GPIO_OD_REG regptr(MSP_PER_BASE + 0x190)
+ /* GPIO[15:0] output drive */
+
+/*
+ ***************************************************************************
+ * CPU Interface register definitions *
+ ***************************************************************************
+ */
+#define PCI_FLUSH_REG regptr(MSP_CPUIF_BASE + 0x00)
+ /* PCI-SDRAM queue flush trigger */
+#define OCP_ERR1_REG regptr(MSP_CPUIF_BASE + 0x04)
+ /* OCP Error Attribute 1 */
+#define OCP_ERR2_REG regptr(MSP_CPUIF_BASE + 0x08)
+ /* OCP Error Attribute 2 */
+#define OCP_STS_REG regptr(MSP_CPUIF_BASE + 0x0C)
+ /* OCP Error Status */
+#define CPUIF_PM_REG regptr(MSP_CPUIF_BASE + 0x10)
+ /* CPU policy configuration */
+#define CPUIF_CFG_REG regptr(MSP_CPUIF_BASE + 0x10)
+ /* Misc configuration options */
+
+/* Central Interrupt Controller Registers */
+#define MSP_CIC_BASE (MSP_CPUIF_BASE + 0x8000)
+ /* Central Interrupt registers */
+#define CIC_EXT_CFG_REG regptr(MSP_CIC_BASE + 0x00)
+ /* External interrupt config */
+#define CIC_STS_REG regptr(MSP_CIC_BASE + 0x04)
+ /* CIC Interrupt Status */
+#define CIC_VPE0_MSK_REG regptr(MSP_CIC_BASE + 0x08)
+ /* VPE0 Interrupt Mask */
+#define CIC_VPE1_MSK_REG regptr(MSP_CIC_BASE + 0x0C)
+ /* VPE1 Interrupt Mask */
+#define CIC_TC0_MSK_REG regptr(MSP_CIC_BASE + 0x10)
+ /* Thread Context 0 Int Mask */
+#define CIC_TC1_MSK_REG regptr(MSP_CIC_BASE + 0x14)
+ /* Thread Context 1 Int Mask */
+#define CIC_TC2_MSK_REG regptr(MSP_CIC_BASE + 0x18)
+ /* Thread Context 2 Int Mask */
+#define CIC_TC3_MSK_REG regptr(MSP_CIC_BASE + 0x18)
+ /* Thread Context 3 Int Mask */
+#define CIC_TC4_MSK_REG regptr(MSP_CIC_BASE + 0x18)
+ /* Thread Context 4 Int Mask */
+#define CIC_PCIMSI_STS_REG regptr(MSP_CIC_BASE + 0x18)
+#define CIC_PCIMSI_MSK_REG regptr(MSP_CIC_BASE + 0x18)
+#define CIC_PCIFLSH_REG regptr(MSP_CIC_BASE + 0x18)
+#define CIC_VPE0_SWINT_REG regptr(MSP_CIC_BASE + 0x08)
+
+
+/*
+ ***************************************************************************
+ * Memory controller registers *
+ ***************************************************************************
+ */
+#define MEM_CFG1_REG regptr(MSP_MEM_CFG_BASE + 0x00)
+#define MEM_SS_ADDR regptr(MSP_MEM_CFG_BASE + 0x00)
+#define MEM_SS_DATA regptr(MSP_MEM_CFG_BASE + 0x04)
+#define MEM_SS_WRITE regptr(MSP_MEM_CFG_BASE + 0x08)
+
+/*
+ ***************************************************************************
+ * PCI controller registers *
+ ***************************************************************************
+ */
+#define PCI_BASE_REG regptr(MSP_PCI_BASE + 0x00)
+#define PCI_CONFIG_SPACE_REG regptr(MSP_PCI_BASE + 0x800)
+#define PCI_JTAG_DEVID_REG regptr(MSP_SLP_BASE + 0x13c)
+
+/*
+ ########################################################################
+ # Register content & macro definitions #
+ ########################################################################
+ */
+
+/*
+ ***************************************************************************
+ * DEV_ID defines *
+ ***************************************************************************
+ */
+#define DEV_ID_PCI_DIS (1 << 26) /* Set if PCI disabled */
+#define DEV_ID_PCI_HOST (1 << 20) /* Set if PCI host */
+#define DEV_ID_SINGLE_PC (1 << 19) /* Set if single PC Card */
+#define DEV_ID_FAMILY (0xff << 8) /* family ID code */
+#define POLO_ZEUS_SUB_FAMILY (0x7 << 16) /* sub family for Polo/Zeus */
+
+#define MSPFPGA_ID (0x00 << 8) /* you are on your own here */
+#define MSP5000_ID (0x50 << 8)
+#define MSP4F00_ID (0x4f << 8) /* FPGA version of MSP4200 */
+#define MSP4E00_ID (0x4f << 8) /* FPGA version of MSP7120 */
+#define MSP4200_ID (0x42 << 8)
+#define MSP4000_ID (0x40 << 8)
+#define MSP2XXX_ID (0x20 << 8)
+#define MSPZEUS_ID (0x10 << 8)
+
+#define MSP2004_SUB_ID (0x0 << 16)
+#define MSP2005_SUB_ID (0x1 << 16)
+#define MSP2006_SUB_ID (0x1 << 16)
+#define MSP2007_SUB_ID (0x2 << 16)
+#define MSP2010_SUB_ID (0x3 << 16)
+#define MSP2015_SUB_ID (0x4 << 16)
+#define MSP2020_SUB_ID (0x5 << 16)
+#define MSP2100_SUB_ID (0x6 << 16)
+
+/*
+ ***************************************************************************
+ * RESET defines *
+ ***************************************************************************
+ */
+#define MSP_GR_RST (0x01 << 0) /* Global reset bit */
+#define MSP_MR_RST (0x01 << 1) /* MIPS reset bit */
+#define MSP_PD_RST (0x01 << 2) /* PVC DMA reset bit */
+#define MSP_PP_RST (0x01 << 3) /* PVC reset bit */
+/* reserved */
+#define MSP_EA_RST (0x01 << 6) /* Mac A reset bit */
+#define MSP_EB_RST (0x01 << 7) /* Mac B reset bit */
+#define MSP_SE_RST (0x01 << 8) /* Security Eng reset bit */
+#define MSP_PB_RST (0x01 << 9) /* Per block reset bit */
+#define MSP_EC_RST (0x01 << 10) /* Mac C reset bit */
+#define MSP_TW_RST (0x01 << 11) /* TWI reset bit */
+#define MSP_SPI_RST (0x01 << 12) /* SPI/MPI reset bit */
+#define MSP_U1_RST (0x01 << 13) /* UART1 reset bit */
+#define MSP_U0_RST (0x01 << 14) /* UART0 reset bit */
+
+/*
+ ***************************************************************************
+ * UART defines *
+ ***************************************************************************
+ */
+#ifndef CONFIG_MSP_FPGA
+#define MSP_BASE_BAUD 25000000
+#else
+#define MSP_BASE_BAUD 6000000
+#endif
+#define MSP_UART_REG_LEN 0x20
+
+/*
+ ***************************************************************************
+ * ELB defines *
+ ***************************************************************************
+ */
+#define PCCARD_32 0x02 /* Set if is PCCARD 32 (Cardbus) */
+#define SINGLE_PCCARD 0x01 /* Set to enable single PC card */
+
+/*
+ ***************************************************************************
+ * CIC defines *
+ ***************************************************************************
+ */
+
+/* CIC_EXT_CFG_REG */
+#define EXT_INT_POL(eirq) (1 << (eirq + 8))
+#define EXT_INT_EDGE(eirq) (1 << eirq)
+
+#define CIC_EXT_SET_TRIGGER_LEVEL(reg, eirq) (reg &= ~EXT_INT_EDGE(eirq))
+#define CIC_EXT_SET_TRIGGER_EDGE(reg, eirq) (reg |= EXT_INT_EDGE(eirq))
+#define CIC_EXT_SET_ACTIVE_HI(reg, eirq) (reg |= EXT_INT_POL(eirq))
+#define CIC_EXT_SET_ACTIVE_LO(reg, eirq) (reg &= ~EXT_INT_POL(eirq))
+#define CIC_EXT_SET_ACTIVE_RISING CIC_EXT_SET_ACTIVE_HI
+#define CIC_EXT_SET_ACTIVE_FALLING CIC_EXT_SET_ACTIVE_LO
+
+#define CIC_EXT_IS_TRIGGER_LEVEL(reg, eirq) \
+ ((reg & EXT_INT_EDGE(eirq)) == 0)
+#define CIC_EXT_IS_TRIGGER_EDGE(reg, eirq) (reg & EXT_INT_EDGE(eirq))
+#define CIC_EXT_IS_ACTIVE_HI(reg, eirq) (reg & EXT_INT_POL(eirq))
+#define CIC_EXT_IS_ACTIVE_LO(reg, eirq) \
+ ((reg & EXT_INT_POL(eirq)) == 0)
+#define CIC_EXT_IS_ACTIVE_RISING CIC_EXT_IS_ACTIVE_HI
+#define CIC_EXT_IS_ACTIVE_FALLING CIC_EXT_IS_ACTIVE_LO
+
+/*
+ ***************************************************************************
+ * Memory Controller defines *
+ ***************************************************************************
+ */
+
+/* Indirect memory controller registers */
+#define DDRC_CFG(n) (n)
+#define DDRC_DEBUG(n) (0x04 + n)
+#define DDRC_CTL(n) (0x40 + n)
+
+/* Macro to perform DDRC indirect write */
+#define DDRC_INDIRECT_WRITE(reg, mask, value) \
+({ \
+ *MEM_SS_ADDR = (((mask) & 0xf) << 8) | ((reg) & 0xff); \
+ *MEM_SS_DATA = (value); \
+ *MEM_SS_WRITE = 1; \
+})
+
+/*
+ ***************************************************************************
+ * SPI/MPI Mode *
+ ***************************************************************************
+ */
+#define SPI_MPI_RX_BUSY 0x00008000 /* SPI/MPI Receive Busy */
+#define SPI_MPI_FIFO_EMPTY 0x00004000 /* SPI/MPI Fifo Empty */
+#define SPI_MPI_TX_BUSY 0x00002000 /* SPI/MPI Transmit Busy */
+#define SPI_MPI_FIFO_FULL 0x00001000 /* SPI/MPU FIFO full */
+
+/*
+ ***************************************************************************
+ * SPI/MPI Control Register *
+ ***************************************************************************
+ */
+#define SPI_MPI_RX_START 0x00000004 /* Start receive command */
+#define SPI_MPI_FLUSH_Q 0x00000002 /* Flush SPI/MPI Queue */
+#define SPI_MPI_TX_START 0x00000001 /* Start Transmit Command */
+
+#endif /* !_ASM_MSP_REGS_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h
new file mode 100644
index 000000000000..96d4c8ce8c83
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h
@@ -0,0 +1,141 @@
+/*
+ * Defines for the MSP interrupt controller.
+ *
+ * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_SLP_INT_H
+#define _MSP_SLP_INT_H
+
+/*
+ * The PMC-Sierra SLP interrupts are arranged in a 3 level cascaded
+ * hierarchical system. The first level are the direct MIPS interrupts
+ * and are assigned the interrupt range 0-7. The second level is the SLM
+ * interrupt controller and is assigned the range 8-39. The third level
+ * comprises the Peripherial block, the PCI block, the PCI MSI block and
+ * the SLP. The PCI interrupts and the SLP errors are handled by the
+ * relevant subsystems so the core interrupt code needs only concern
+ * itself with the Peripheral block. These are assigned interrupts in
+ * the range 40-71.
+ */
+
+/*
+ * IRQs directly connected to CPU
+ */
+#define MSP_MIPS_INTBASE 0
+#define MSP_INT_SW0 0 /* IRQ for swint0, C_SW0 */
+#define MSP_INT_SW1 1 /* IRQ for swint1, C_SW1 */
+#define MSP_INT_MAC0 2 /* IRQ for MAC 0, C_IRQ0 */
+#define MSP_INT_MAC1 3 /* IRQ for MAC 1, C_IRQ1 */
+#define MSP_INT_C_IRQ2 4 /* Wired off, C_IRQ2 */
+#define MSP_INT_VE 5 /* IRQ for Voice Engine, C_IRQ3 */
+#define MSP_INT_SLP 6 /* IRQ for SLM block, C_IRQ4 */
+#define MSP_INT_TIMER 7 /* IRQ for the MIPS timer, C_IRQ5 */
+
+/*
+ * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4)
+ * These defines should be tied to the register definition for the SLM
+ * interrupt routine. For now, just use hard-coded values.
+ */
+#define MSP_SLP_INTBASE (MSP_MIPS_INTBASE + 8)
+#define MSP_INT_EXT0 (MSP_SLP_INTBASE + 0)
+ /* External interrupt 0 */
+#define MSP_INT_EXT1 (MSP_SLP_INTBASE + 1)
+ /* External interrupt 1 */
+#define MSP_INT_EXT2 (MSP_SLP_INTBASE + 2)
+ /* External interrupt 2 */
+#define MSP_INT_EXT3 (MSP_SLP_INTBASE + 3)
+ /* External interrupt 3 */
+/* Reserved 4-7 */
+
+/*
+ *************************************************************************
+ * DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER *
+ * Some MSP produces have this interrupt labelled as Voice and some are *
+ * SEC mbox ... *
+ *************************************************************************
+ */
+#define MSP_INT_SLP_VE (MSP_SLP_INTBASE + 8)
+ /* Cascaded IRQ for Voice Engine*/
+#define MSP_INT_SLP_TDM (MSP_SLP_INTBASE + 9)
+ /* TDM interrupt */
+#define MSP_INT_SLP_MAC0 (MSP_SLP_INTBASE + 10)
+ /* Cascaded IRQ for MAC 0 */
+#define MSP_INT_SLP_MAC1 (MSP_SLP_INTBASE + 11)
+ /* Cascaded IRQ for MAC 1 */
+#define MSP_INT_SEC (MSP_SLP_INTBASE + 12)
+ /* IRQ for security engine */
+#define MSP_INT_PER (MSP_SLP_INTBASE + 13)
+ /* Peripheral interrupt */
+#define MSP_INT_TIMER0 (MSP_SLP_INTBASE + 14)
+ /* SLP timer 0 */
+#define MSP_INT_TIMER1 (MSP_SLP_INTBASE + 15)
+ /* SLP timer 1 */
+#define MSP_INT_TIMER2 (MSP_SLP_INTBASE + 16)
+ /* SLP timer 2 */
+#define MSP_INT_SLP_TIMER (MSP_SLP_INTBASE + 17)
+ /* Cascaded MIPS timer */
+#define MSP_INT_BLKCP (MSP_SLP_INTBASE + 18)
+ /* Block Copy */
+#define MSP_INT_UART0 (MSP_SLP_INTBASE + 19)
+ /* UART 0 */
+#define MSP_INT_PCI (MSP_SLP_INTBASE + 20)
+ /* PCI subsystem */
+#define MSP_INT_PCI_DBELL (MSP_SLP_INTBASE + 21)
+ /* PCI doorbell */
+#define MSP_INT_PCI_MSI (MSP_SLP_INTBASE + 22)
+ /* PCI Message Signal */
+#define MSP_INT_PCI_BC0 (MSP_SLP_INTBASE + 23)
+ /* PCI Block Copy 0 */
+#define MSP_INT_PCI_BC1 (MSP_SLP_INTBASE + 24)
+ /* PCI Block Copy 1 */
+#define MSP_INT_SLP_ERR (MSP_SLP_INTBASE + 25)
+ /* SLP error condition */
+#define MSP_INT_MAC2 (MSP_SLP_INTBASE + 26)
+ /* IRQ for MAC2 */
+/* Reserved 26-31 */
+
+/*
+ * IRQs cascaded on SLP PER interrupt (MSP_INT_PER)
+ */
+#define MSP_PER_INTBASE (MSP_SLP_INTBASE + 32)
+/* Reserved 0-1 */
+#define MSP_INT_UART1 (MSP_PER_INTBASE + 2)
+ /* UART 1 */
+/* Reserved 3-5 */
+#define MSP_INT_2WIRE (MSP_PER_INTBASE + 6)
+ /* 2-wire */
+#define MSP_INT_TM0 (MSP_PER_INTBASE + 7)
+ /* Peripheral timer block out 0 */
+#define MSP_INT_TM1 (MSP_PER_INTBASE + 8)
+ /* Peripheral timer block out 1 */
+/* Reserved 9 */
+#define MSP_INT_SPRX (MSP_PER_INTBASE + 10)
+ /* SPI RX complete */
+#define MSP_INT_SPTX (MSP_PER_INTBASE + 11)
+ /* SPI TX complete */
+#define MSP_INT_GPIO (MSP_PER_INTBASE + 12)
+ /* GPIO */
+#define MSP_INT_PER_ERR (MSP_PER_INTBASE + 13)
+ /* Peripheral error */
+/* Reserved 14-31 */
+
+#endif /* !_MSP_SLP_INT_H */
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 5f80ba71ab92..1d8b9a8ae324 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -82,10 +82,6 @@ struct mips_fpu_struct {
unsigned int fcr31;
};
-#define INIT_FPU { \
- {0,} \
-}
-
#define NUM_DSP_REGS 6
typedef __u32 dspreg_t;
@@ -95,8 +91,6 @@ struct mips_dsp_state {
unsigned int dspcontrol;
};
-#define INIT_DSP {{0,},}
-
#define INIT_CPUMASK { \
{0,} \
}
@@ -155,41 +149,63 @@ struct thread_struct {
#define MF_N64 0
#ifdef CONFIG_MIPS_MT_FPAFF
-#define FPAFF_INIT 0, INIT_CPUMASK,
+#define FPAFF_INIT \
+ .emulated_fp = 0, \
+ .user_cpus_allowed = INIT_CPUMASK,
#else
#define FPAFF_INIT
#endif /* CONFIG_MIPS_MT_FPAFF */
-#define INIT_THREAD { \
- /* \
- * saved main processor registers \
- */ \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, \
- /* \
- * saved cp0 stuff \
- */ \
- 0, \
- /* \
- * saved fpu/fpu emulator stuff \
- */ \
- INIT_FPU, \
- /* \
- * fpu affinity state (null if not FPAFF) \
- */ \
- FPAFF_INIT \
- /* \
- * saved dsp/dsp emulator stuff \
- */ \
- INIT_DSP, \
- /* \
- * Other stuff associated with the process \
- */ \
- 0, 0, 0, 0, \
- /* \
- * For now the default is to fix address errors \
- */ \
- MF_FIXADE, 0, 0 \
+#define INIT_THREAD { \
+ /* \
+ * Saved main processor registers \
+ */ \
+ .reg16 = 0, \
+ .reg17 = 0, \
+ .reg18 = 0, \
+ .reg19 = 0, \
+ .reg20 = 0, \
+ .reg21 = 0, \
+ .reg22 = 0, \
+ .reg23 = 0, \
+ .reg29 = 0, \
+ .reg30 = 0, \
+ .reg31 = 0, \
+ /* \
+ * Saved cp0 stuff \
+ */ \
+ .cp0_status = 0, \
+ /* \
+ * Saved FPU/FPU emulator stuff \
+ */ \
+ .fpu = { \
+ .fpr = {0,}, \
+ .fcr31 = 0, \
+ }, \
+ /* \
+ * FPU affinity state (null if not FPAFF) \
+ */ \
+ FPAFF_INIT \
+ /* \
+ * Saved DSP stuff \
+ */ \
+ .dsp = { \
+ .dspr = {0, }, \
+ .dspcontrol = 0, \
+ }, \
+ /* \
+ * Other stuff associated with the process \
+ */ \
+ .cp0_badvaddr = 0, \
+ .cp0_baduaddr = 0, \
+ .error_code = 0, \
+ .trap_no = 0, \
+ /* \
+ * For now the default is to fix address errors \
+ */ \
+ .mflags = MF_FIXADE, \
+ .irix_trampoline = 0, \
+ .irix_oldctx = 0, \
}
struct task_struct;
@@ -237,7 +253,7 @@ unsigned long get_wchan(struct task_struct *p);
#define ARCH_HAS_PREFETCH
-extern inline void prefetch(const void *addr)
+static inline void prefetch(const void *addr)
{
__asm__ __volatile__(
" .set mips4 \n"
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index ce51213d84f9..c07ebd8eb9e7 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -19,159 +19,4 @@
*/
#define BASE_BAUD (1843200 / 16)
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#ifdef CONFIG_MACH_JAZZ
-#include <asm/jazz.h>
-
-#ifndef CONFIG_OLIVETTI_M700
- /* Some Jazz machines seem to have an 8MHz crystal clock but I don't know
- exactly which ones ... XXX */
-#define JAZZ_BASE_BAUD ( 8000000 / 16 ) /* ( 3072000 / 16) */
-#else
-/* but the M700 isn't such a strange beast */
-#define JAZZ_BASE_BAUD BASE_BAUD
-#endif
-
-#define _JAZZ_SERIAL_INIT(int, base) \
- { .baud_base = JAZZ_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS, \
- .iomem_base = (u8 *) base, .iomem_reg_shift = 0, \
- .io_type = SERIAL_IO_MEM }
-#define JAZZ_SERIAL_PORT_DEFNS \
- _JAZZ_SERIAL_INIT(JAZZ_SERIAL1_IRQ, JAZZ_SERIAL1_BASE), \
- _JAZZ_SERIAL_INIT(JAZZ_SERIAL2_IRQ, JAZZ_SERIAL2_BASE),
-#else
-#define JAZZ_SERIAL_PORT_DEFNS
-#endif
-
-/*
- * Galileo EV64120 evaluation board
- */
-#ifdef CONFIG_MIPS_EV64120
-#include <mach-gt64120.h>
-#define EV64120_SERIAL_PORT_DEFNS \
- { .baud_base = EV64120_BASE_BAUD, .irq = EV64120_UART_IRQ, \
- .flags = STD_COM_FLAGS, \
- .iomem_base = EV64120_UART0_REGS_BASE, .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM }, \
- { .baud_base = EV64120_BASE_BAUD, .irq = EV64120_UART_IRQ, \
- .flags = STD_COM_FLAGS, \
- .iomem_base = EV64120_UART1_REGS_BASE, .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM },
-#else
-#define EV64120_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
-#define STD_SERIAL_PORT_DEFNS \
- /* UART CLK PORT IRQ FLAGS */ \
- { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
- { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
- { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
-
-#else /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-#define STD_SERIAL_PORT_DEFNS
-#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-
-#ifdef CONFIG_MOMENCO_OCELOT_3
-#define OCELOT_3_BASE_BAUD ( 20000000 / 16 )
-#define OCELOT_3_SERIAL_IRQ 6
-#define OCELOT_3_SERIAL_BASE (signed)0xfd000020
-
-#define _OCELOT_3_SERIAL_INIT(int, base) \
- { .baud_base = OCELOT_3_BASE_BAUD, irq: int, \
- .flags = STD_COM_FLAGS, \
- .iomem_base = (u8 *) base, iomem_reg_shift: 2, \
- io_type: SERIAL_IO_MEM }
-
-#define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \
- _OCELOT_3_SERIAL_INIT(OCELOT_3_SERIAL_IRQ, OCELOT_3_SERIAL_BASE)
-#else
-#define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MOMENCO_OCELOT
-/* Ordinary NS16552 duart with a 20MHz crystal. */
-#define OCELOT_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_SERIAL1_IRQ 4
-#define OCELOT_SERIAL1_BASE 0xe0001020
-
-#define _OCELOT_SERIAL_INIT(int, base) \
- { .baud_base = OCELOT_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS, \
- .iomem_base = (u8 *) base, .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM }
-#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
- _OCELOT_SERIAL_INIT(OCELOT_SERIAL1_IRQ, OCELOT_SERIAL1_BASE)
-#else
-#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MOMENCO_OCELOT_C
-/* Ordinary NS16552 duart with a 20MHz crystal. */
-#define OCELOT_C_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_C_SERIAL1_IRQ 80
-#define OCELOT_C_SERIAL1_BASE 0xfd000020
-
-#define OCELOT_C_SERIAL2_IRQ 81
-#define OCELOT_C_SERIAL2_BASE 0xfd000000
-
-#define _OCELOT_C_SERIAL_INIT(int, base) \
- { .baud_base = OCELOT_C_BASE_BAUD, \
- .irq = (int), \
- .flags = STD_COM_FLAGS, \
- .iomem_base = (u8 *) base, \
- .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM \
- }
-#define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \
- _OCELOT_C_SERIAL_INIT(OCELOT_C_SERIAL1_IRQ, OCELOT_C_SERIAL1_BASE), \
- _OCELOT_C_SERIAL_INIT(OCELOT_C_SERIAL2_IRQ, OCELOT_C_SERIAL2_BASE)
-#else
-#define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_DDB5477
-#include <asm/ddb5xxx/ddb5477.h>
-#define DDB5477_SERIAL_PORT_DEFNS \
- { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART0, \
- .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04200, \
- .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM}, \
- { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART1, \
- .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04240, \
- .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM},
-#else
-#define DDB5477_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_SGI_IP32
-/*
- * The IP32 (SGI O2) has standard serial ports (UART 16550A) mapped in memory
- * They are initialized in ip32_setup
- */
-#define IP32_SERIAL_PORT_DEFNS \
- {},{},
-#else
-#define IP32_SERIAL_PORT_DEFNS
-#endif /* CONFIG_SGI_IP32 */
-
-#define SERIAL_PORT_DFNS \
- DDB5477_SERIAL_PORT_DEFNS \
- EV64120_SERIAL_PORT_DEFNS \
- IP32_SERIAL_PORT_DEFNS \
- JAZZ_SERIAL_PORT_DEFNS \
- STD_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
-
#endif /* _ASM_SERIAL_H */
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index 1608fd71d6f7..13aef6af422c 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -49,13 +49,6 @@ extern struct call_data_struct *call_data;
extern cpumask_t phys_cpu_present_map;
#define cpu_possible_map phys_cpu_present_map
-extern cpumask_t cpu_callout_map;
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
-static inline int num_booting_cpus(void)
-{
- return cpus_weight(cpu_callout_map);
-}
-
/*
* These are defined by the board-specific code.
*/
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
index f257509b914f..ddaf36a1e389 100644
--- a/include/asm-mips/sni.h
+++ b/include/asm-mips/sni.h
@@ -146,9 +146,6 @@ extern unsigned int sni_brd_type;
#define SNI_A20R_IRQ_BASE MIPS_CPU_IRQ_BASE
#define SNI_A20R_IRQ_TIMER (SNI_A20R_IRQ_BASE+5)
-#define SNI_DS1216_A20R_BASE 0xbc081ffc
-#define SNI_DS1216_RM200_BASE 0xbcd41ffc
-
#define SNI_PCIT_INT_REG 0xbfff000c
#define SNI_PCIT_INT_START 24
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index bb0b289dbc9e..46bdb3f566f9 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -44,7 +44,7 @@ struct task_struct;
* different thread.
*/
-#define switch_to(prev,next,last) \
+#define __mips_mt_fpaff_switch_to(prev) \
do { \
if (cpu_has_fpu && \
(prev->thread.mflags & MF_FPUBOUND) && \
@@ -52,24 +52,24 @@ do { \
prev->thread.mflags &= ~MF_FPUBOUND; \
prev->cpus_allowed = prev->thread.user_cpus_allowed; \
} \
- if (cpu_has_dsp) \
- __save_dsp(prev); \
next->thread.emulated_fp = 0; \
- (last) = resume(prev, next, task_thread_info(next)); \
- if (cpu_has_dsp) \
- __restore_dsp(current); \
} while(0)
#else
+#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
+#endif
+
#define switch_to(prev,next,last) \
do { \
+ __mips_mt_fpaff_switch_to(prev); \
if (cpu_has_dsp) \
__save_dsp(prev); \
(last) = resume(prev, next, task_thread_info(next)); \
if (cpu_has_dsp) \
__restore_dsp(current); \
+ if (cpu_has_userlocal) \
+ write_c0_userlocal(task_thread_info(current)->tp_value);\
} while(0)
-#endif
/*
* On SMP systems, when the scheduler does migration-cost autodetection,
diff --git a/include/asm-mips/tx4938/rbtx4938.h b/include/asm-mips/tx4938/rbtx4938.h
index 0fbedafdcea8..74e7d8061e58 100644
--- a/include/asm-mips/tx4938/rbtx4938.h
+++ b/include/asm-mips/tx4938/rbtx4938.h
@@ -105,12 +105,6 @@
#define rbtx4938_pcireset_ptr \
((volatile unsigned char *)RBTX4938_PCIRESET_ADDR)
-/* SPI */
-#define RBTX4938_SEEPROM1_CHIPID 0
-#define RBTX4938_SEEPROM2_CHIPID 1
-#define RBTX4938_SEEPROM3_CHIPID 2
-#define RBTX4938_SRTC_CHIPID 3
-
/*
* IRQ mappings
*/
diff --git a/include/asm-mips/tx4938/spi.h b/include/asm-mips/tx4938/spi.h
index 0dbbab820a5a..6a60c83e152b 100644
--- a/include/asm-mips/tx4938/spi.h
+++ b/include/asm-mips/tx4938/spi.h
@@ -14,61 +14,7 @@
#ifndef __ASM_TX_BOARDS_TX4938_SPI_H
#define __ASM_TX_BOARDS_TX4938_SPI_H
-/* SPI */
-struct spi_dev_desc {
- unsigned int baud;
- unsigned short tcss, tcsh, tcsr; /* CS setup/hold/recovery time */
- unsigned int byteorder:1; /* 0:LSB-First, 1:MSB-First */
- unsigned int polarity:1; /* 0:High-Active */
- unsigned int phase:1; /* 0:Sample-Then-Shift */
-};
-
-extern void txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on)) __init;
-extern void txx9_spi_irqinit(int irc_irq) __init;
-extern int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
- unsigned char **inbufs, unsigned int *incounts,
- unsigned char **outbufs, unsigned int *outcounts,
- int cansleep);
-extern int spi_eeprom_write_enable(int chipid, int enable);
-extern int spi_eeprom_read_status(int chipid);
+extern int spi_eeprom_register(int chipid);
extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
-extern int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len);
-extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid) __init;
-
-#define TXX9_IMCLK (txx9_gbus_clock / 2)
-
-/*
-* SPI
-*/
-
-/* SPMCR : SPI Master Control */
-#define TXx9_SPMCR_OPMODE 0xc0
-#define TXx9_SPMCR_CONFIG 0x40
-#define TXx9_SPMCR_ACTIVE 0x80
-#define TXx9_SPMCR_SPSTP 0x02
-#define TXx9_SPMCR_BCLR 0x01
-
-/* SPCR0 : SPI Status */
-#define TXx9_SPCR0_TXIFL_MASK 0xc000
-#define TXx9_SPCR0_RXIFL_MASK 0x3000
-#define TXx9_SPCR0_SIDIE 0x0800
-#define TXx9_SPCR0_SOEIE 0x0400
-#define TXx9_SPCR0_RBSIE 0x0200
-#define TXx9_SPCR0_TBSIE 0x0100
-#define TXx9_SPCR0_IFSPSE 0x0010
-#define TXx9_SPCR0_SBOS 0x0004
-#define TXx9_SPCR0_SPHA 0x0002
-#define TXx9_SPCR0_SPOL 0x0001
-
-/* SPSR : SPI Status */
-#define TXx9_SPSR_TBSI 0x8000
-#define TXx9_SPSR_RBSI 0x4000
-#define TXx9_SPSR_TBS_MASK 0x3800
-#define TXx9_SPSR_RBS_MASK 0x0700
-#define TXx9_SPSR_SPOE 0x0080
-#define TXx9_SPSR_IFSD 0x0008
-#define TXx9_SPSR_SIDLE 0x0004
-#define TXx9_SPSR_STRDY 0x0002
-#define TXx9_SPSR_SRRDY 0x0001
#endif /* __ASM_TX_BOARDS_TX4938_SPI_H */
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index ec0eeebd8802..9de52a5b0f3d 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -169,10 +169,9 @@
/*
* On the RM9000 there is a problem which makes the CreateDirtyExclusive
- * cache operation unusable on SMP systems.
+ * eache operation unusable on SMP systems.
*/
-#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE) || \
- defined(CONFIG_BASLER_EXCITE)
+#if defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE)
#define RM9000_CDEX_SMP_WAR 1
#endif
@@ -182,11 +181,10 @@
* I-cache line worth of instructions being fetched may case spurious
* exceptions.
*/
-#if defined(CONFIG_BASLER_EXCITE) || defined(CONFIG_MOMENCO_JAGUAR_ATX) || \
- defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA) || \
- defined(CONFIG_MOMENCO_OCELOT) || defined(CONFIG_MOMENCO_OCELOT_3) || \
- defined(CONFIG_MOMENCO_OCELOT_C) || defined(CONFIG_PMC_YOSEMITE) || \
- defined(CONFIG_SGI_IP32) || defined(CONFIG_WR_PPMC)
+#if defined(CONFIG_BASLER_EXCITE) || defined(CONFIG_MIPS_ATLAS) || \
+ defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MOMENCO_OCELOT) || \
+ defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_SGI_IP32) || \
+ defined(CONFIG_WR_PPMC)
#define ICACHE_REFILLS_WORKAROUND_WAR 1
#endif
@@ -200,6 +198,14 @@
#endif
/*
+ * 34K core erratum: "Problems Executing the TLBR Instruction"
+ */
+#if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_FPGA)
+#define MIPS34K_MISSED_ITLB_WAR 1
+#endif
+
+/*
* Workarounds default to off
*/
#ifndef ICACHE_REFILLS_WORKAROUND_WAR
@@ -238,5 +244,8 @@
#ifndef R10000_LLSC_WAR
#define R10000_LLSC_WAR 0
#endif
+#ifndef MIPS34K_MISSED_ITLB_WAR
+#define MIPS34K_MISSED_ITLB_WAR 0
+#endif
#endif /* _ASM_WAR_H */
diff --git a/include/asm-mips/watch.h b/include/asm-mips/watch.h
deleted file mode 100644
index 6aa90cae1114..000000000000
--- a/include/asm-mips/watch.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997, 1998, 2000, 2001 by Ralf Baechle
- */
-#ifndef _ASM_WATCH_H
-#define _ASM_WATCH_H
-
-#include <linux/linkage.h>
-
-/*
- * Types of reference for watch_set()
- */
-enum wref_type {
- wr_save = 1,
- wr_load = 2
-};
-
-extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref);
-extern asmlinkage void __watch_clear(void);
-extern asmlinkage void __watch_reenable(void);
-
-#define watch_set(addr, ref) \
- if (cpu_has_watch) \
- __watch_set(addr, ref)
-#define watch_clear() \
- if (cpu_has_watch) \
- __watch_clear()
-#define watch_reenable() \
- if (cpu_has_watch) \
- __watch_reenable()
-
-#endif /* _ASM_WATCH_H */
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index c17bdbf22067..ea486952f778 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -24,7 +24,7 @@
*/
typedef struct {
- volatile int counter;
+ int counter;
} __attribute__ ((aligned (4))) atomic_t;
#define ATOMIC_INIT(i) { (i) }
@@ -141,7 +141,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
#ifdef __s390x__
typedef struct {
- volatile long long counter;
+ long long counter;
} __attribute__ ((aligned (8))) atomic64_t;
#define ATOMIC64_INIT(i) { (i) }
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h
index 241756f80df3..021e7c3223ec 100644
--- a/include/asm-s390/cmb.h
+++ b/include/asm-s390/cmb.h
@@ -88,7 +88,6 @@ extern u64 cmf_read(struct ccw_device *cdev, int index);
* any
**/
extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data);
-extern void cmf_reset(struct ccw_device *cdev);
#endif /* __KERNEL__ */
#endif /* S390_CMB_H */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 5cb480af65d5..3b972d4c6b29 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -357,8 +357,8 @@ extern void (*s390_base_ext_handler_fn)(void);
/*
* CPU idle notifier chain.
*/
-#define CPU_IDLE 0
-#define CPU_NOT_IDLE 1
+#define S390_CPU_IDLE 0
+#define S390_CPU_NOT_IDLE 1
struct notifier_block;
int register_idle_notifier(struct notifier_block *nb);
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h
index 21ed64773210..cb9faf1ea5cf 100644
--- a/include/asm-s390/sclp.h
+++ b/include/asm-s390/sclp.h
@@ -11,29 +11,6 @@
#include <linux/types.h>
#include <asm/chpid.h>
-struct sccb_header {
- u16 length;
- u8 function_code;
- u8 control_mask[3];
- u16 response_code;
-} __attribute__((packed));
-
-#define LOADPARM_LEN 8
-
-struct sclp_readinfo_sccb {
- struct sccb_header header; /* 0-7 */
- u16 rnmax; /* 8-9 */
- u8 rnsize; /* 10 */
- u8 _reserved0[24 - 11]; /* 11-23 */
- u8 loadparm[LOADPARM_LEN]; /* 24-31 */
- u8 _reserved1[91 - 32]; /* 32-90 */
- u8 flags; /* 91 */
- u8 _reserved2[100 - 92]; /* 92-99 */
- u32 rnsize2; /* 100-103 */
- u64 rnmax2; /* 104-111 */
- u8 _reserved3[4096 - 112]; /* 112-4095 */
-} __attribute__((packed, aligned(4096)));
-
#define SCLP_CHP_INFO_MASK_SIZE 32
struct sclp_chp_info {
@@ -42,12 +19,22 @@ struct sclp_chp_info {
u8 configured[SCLP_CHP_INFO_MASK_SIZE];
};
-extern struct sclp_readinfo_sccb s390_readinfo_sccb;
-extern void sclp_readinfo_early(void);
-extern int sclp_sdias_blk_count(void);
-extern int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
-extern int sclp_chp_configure(struct chp_id chpid);
-extern int sclp_chp_deconfigure(struct chp_id chpid);
-extern int sclp_chp_read_info(struct sclp_chp_info *info);
+#define LOADPARM_LEN 8
+
+struct sclp_ipl_info {
+ int is_valid;
+ int has_dump;
+ char loadparm[LOADPARM_LEN];
+};
+
+void sclp_readinfo_early(void);
+void sclp_facilities_detect(void);
+unsigned long long sclp_memory_detect(void);
+int sclp_sdias_blk_count(void);
+int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
+int sclp_chp_configure(struct chp_id chpid);
+int sclp_chp_deconfigure(struct chp_id chpid);
+int sclp_chp_read_info(struct sclp_chp_info *info);
+void sclp_get_ipl_info(struct sclp_ipl_info *info);
#endif /* _ASM_S390_SCLP_H */
diff --git a/include/asm-s390/sfp-machine.h b/include/asm-s390/sfp-machine.h
index 8ca8c77b2d04..4e16aede4b06 100644
--- a/include/asm-s390/sfp-machine.h
+++ b/include/asm-s390/sfp-machine.h
@@ -27,9 +27,9 @@
#define _FP_W_TYPE_SIZE 32
-#define _FP_W_TYPE unsigned long
-#define _FP_WS_TYPE signed long
-#define _FP_I_TYPE long
+#define _FP_W_TYPE unsigned int
+#define _FP_WS_TYPE signed int
+#define _FP_I_TYPE int
#define _FP_MUL_MEAT_S(R,X,Y) \
_FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
diff --git a/include/asm-s390/sfp-util.h b/include/asm-s390/sfp-util.h
index 8cabcd23d976..0addc6466d95 100644
--- a/include/asm-s390/sfp-util.h
+++ b/include/asm-s390/sfp-util.h
@@ -51,6 +51,16 @@
wl = __wl; \
})
+#ifdef __s390x__
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { unsigned long __n; \
+ unsigned int __r, __d; \
+ __n = ((unsigned long)(n1) << 32) + n0; \
+ __d = (d); \
+ (q) = __n / __d; \
+ (r) = __n % __d; \
+ } while (0)
+#else
#define udiv_qrnnd(q, r, n1, n0, d) \
do { unsigned int __r; \
(q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
@@ -58,6 +68,7 @@
} while (0)
extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
unsigned int , unsigned int);
+#endif
#define UDIV_NEEDS_NORMALIZATION 0
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index f317c270d4bf..afae306b177c 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -49,6 +49,7 @@ header-y += consolemap.h
header-y += const.h
header-y += cycx_cfm.h
header-y += dlm_device.h
+header-y += dlm_netlink.h
header-y += dm-ioctl.h
header-y += dn.h
header-y += dqblk_v1.h
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index db5b00a792f5..fae138bd2207 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -868,11 +868,6 @@ void kblockd_flush_work(struct work_struct *work);
*/
#define buffer_heads_over_limit 0
-static inline long blk_congestion_wait(int rw, long timeout)
-{
- return io_schedule_timeout(timeout);
-}
-
static inline long nr_blockdev_pages(void)
{
return 0;
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 1b1dcb9a40bb..be9d278761e0 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -85,7 +85,11 @@
* Only relevant to locks originating in userspace. A persistent lock will not
* be removed if the process holding the lock exits.
*
- * DLM_LKF_NODLKWT
+ * DLM_LKF_NODLCKWT
+ *
+ * Do not cancel the lock if it gets into conversion deadlock.
+ * Exclude this lock from being monitored due to DLM_LSFL_TIMEWARN.
+ *
* DLM_LKF_NODLCKBLK
*
* net yet implemented
@@ -149,6 +153,7 @@
#define DLM_LKF_ALTPR 0x00008000
#define DLM_LKF_ALTCW 0x00010000
#define DLM_LKF_FORCEUNLOCK 0x00020000
+#define DLM_LKF_TIMEOUT 0x00040000
/*
* Some return codes that are not in errno.h
@@ -199,11 +204,12 @@ struct dlm_lksb {
char * sb_lvbptr;
};
+#define DLM_LSFL_NODIR 0x00000001
+#define DLM_LSFL_TIMEWARN 0x00000002
+#define DLM_LSFL_FS 0x00000004
#ifdef __KERNEL__
-#define DLM_LSFL_NODIR 0x00000001
-
/*
* dlm_new_lockspace
*
diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
index c2735cab2ebf..9642277a152a 100644
--- a/include/linux/dlm_device.h
+++ b/include/linux/dlm_device.h
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -18,21 +18,24 @@
#define DLM_USER_LVB_LEN 32
/* Version of the device interface */
-#define DLM_DEVICE_VERSION_MAJOR 5
-#define DLM_DEVICE_VERSION_MINOR 1
+#define DLM_DEVICE_VERSION_MAJOR 6
+#define DLM_DEVICE_VERSION_MINOR 0
#define DLM_DEVICE_VERSION_PATCH 0
/* struct passed to the lock write */
struct dlm_lock_params {
__u8 mode;
__u8 namelen;
- __u16 flags;
+ __u16 unused;
+ __u32 flags;
__u32 lkid;
__u32 parent;
- void __user *castparam;
+ __u64 xid;
+ __u64 timeout;
+ void __user *castparam;
void __user *castaddr;
void __user *bastparam;
- void __user *bastaddr;
+ void __user *bastaddr;
struct dlm_lksb __user *lksb;
char lvb[DLM_USER_LVB_LEN];
char name[0];
@@ -62,9 +65,15 @@ struct dlm_write_request {
} i;
};
+struct dlm_device_version {
+ __u32 version[3];
+};
+
/* struct read from the "device" fd,
consists mainly of userspace pointers for the library to use */
+
struct dlm_lock_result {
+ __u32 version[3];
__u32 length;
void __user * user_astaddr;
void __user * user_astparam;
@@ -83,6 +92,7 @@ struct dlm_lock_result {
#define DLM_USER_CREATE_LOCKSPACE 4
#define DLM_USER_REMOVE_LOCKSPACE 5
#define DLM_USER_PURGE 6
+#define DLM_USER_DEADLOCK 7
/* Arbitrary length restriction */
#define MAX_LS_NAME_LEN 64
diff --git a/include/linux/dlm_netlink.h b/include/linux/dlm_netlink.h
new file mode 100644
index 000000000000..19276332707a
--- /dev/null
+++ b/include/linux/dlm_netlink.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#ifndef _DLM_NETLINK_H
+#define _DLM_NETLINK_H
+
+enum {
+ DLM_STATUS_WAITING = 1,
+ DLM_STATUS_GRANTED = 2,
+ DLM_STATUS_CONVERT = 3,
+};
+
+#define DLM_LOCK_DATA_VERSION 1
+
+struct dlm_lock_data {
+ uint16_t version;
+ uint32_t lockspace_id;
+ int nodeid;
+ int ownpid;
+ uint32_t id;
+ uint32_t remid;
+ uint64_t xid;
+ int8_t status;
+ int8_t grmode;
+ int8_t rqmode;
+ unsigned long timestamp;
+ int resource_namelen;
+ char resource_name[DLM_RESNAME_MAXLEN];
+};
+
+enum {
+ DLM_CMD_UNSPEC = 0,
+ DLM_CMD_HELLO, /* user->kernel */
+ DLM_CMD_TIMEOUT, /* kernel->user */
+ __DLM_CMD_MAX,
+};
+
+#define DLM_CMD_MAX (__DLM_CMD_MAX - 1)
+
+enum {
+ DLM_TYPE_UNSPEC = 0,
+ DLM_TYPE_LOCK,
+ __DLM_TYPE_MAX,
+};
+
+#define DLM_TYPE_MAX (__DLM_TYPE_MAX - 1)
+
+#define DLM_GENL_VERSION 0x1
+#define DLM_GENL_NAME "DLM"
+
+#endif /* _DLM_NETLINK_H */
diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
new file mode 100644
index 000000000000..d774b7778c91
--- /dev/null
+++ b/include/linux/eeprom_93cx6.h
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Module: eeprom_93cx6
+ Abstract: EEPROM reader datastructures for 93cx6 chipsets.
+ Supported chipsets: 93c46 & 93c66.
+ */
+
+/*
+ * EEPROM operation defines.
+ */
+#define PCI_EEPROM_WIDTH_93C46 6
+#define PCI_EEPROM_WIDTH_93C66 8
+#define PCI_EEPROM_WIDTH_OPCODE 3
+#define PCI_EEPROM_WRITE_OPCODE 0x05
+#define PCI_EEPROM_READ_OPCODE 0x06
+#define PCI_EEPROM_EWDS_OPCODE 0x10
+#define PCI_EEPROM_EWEN_OPCODE 0x13
+
+/**
+ * struct eeprom_93cx6 - control structure for setting the commands
+ * for reading the eeprom data.
+ * @data: private pointer for the driver.
+ * @register_read(struct eeprom_93cx6 *eeprom): handler to
+ * read the eeprom register, this function should set all reg_* fields.
+ * @register_write(struct eeprom_93cx6 *eeprom): handler to
+ * write to the eeprom register by using all reg_* fields.
+ * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
+ * @reg_data_in: register field to indicate data input
+ * @reg_data_out: register field to indicate data output
+ * @reg_data_clock: register field to set the data clock
+ * @reg_chip_select: register field to set the chip select
+ *
+ * This structure is used for the communication between the driver
+ * and the eeprom_93cx6 handlers for reading the eeprom.
+ */
+struct eeprom_93cx6 {
+ void *data;
+
+ void (*register_read)(struct eeprom_93cx6 *eeprom);
+ void (*register_write)(struct eeprom_93cx6 *eeprom);
+
+ int width;
+
+ char reg_data_in;
+ char reg_data_out;
+ char reg_data_clock;
+ char reg_chip_select;
+};
+
+extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
+ const u8 word, u16 *data);
+extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
+ const u8 word, __le16 *data, const u16 words);
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index efbe1fda1a22..1a45d6f41b09 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -30,16 +30,38 @@
#define FW_CDEV_EVENT_REQUEST 0x02
#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03
-/* The 'closure' fields are for user space to use. Data passed in the
- * 'closure' field for a request will be returned in the corresponding
- * event. It's a 64-bit type so that it's a fixed size type big
- * enough to hold a pointer on all platforms. */
-
+/**
+ * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
+ * @closure: For arbitrary use by userspace
+ * @type: Discriminates the fw_cdev_event_ types
+ *
+ * This struct may be used to access generic members of all fw_cdev_event_
+ * types regardless of the specific type.
+ *
+ * Data passed in the @closure field for a request will be returned in the
+ * corresponding event. It is big enough to hold a pointer on all platforms.
+ * The ioctl used to set @closure depends on the @type of event.
+ */
struct fw_cdev_event_common {
__u64 closure;
__u32 type;
};
+/**
+ * struct fw_cdev_event_bus_reset - Sent when a bus reset occurred
+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_GET_INFO ioctl
+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_BUS_RESET
+ * @node_id: New node ID of this node
+ * @local_node_id: Node ID of the local node, i.e. of the controller
+ * @bm_node_id: Node ID of the bus manager
+ * @irm_node_id: Node ID of the iso resource manager
+ * @root_node_id: Node ID of the root node
+ * @generation: New bus generation
+ *
+ * This event is sent when the bus the device belongs to goes through a bus
+ * reset. It provides information about the new bus configuration, such as
+ * new node ID for this device, new root ID, and others.
+ */
struct fw_cdev_event_bus_reset {
__u64 closure;
__u32 type;
@@ -51,6 +73,20 @@ struct fw_cdev_event_bus_reset {
__u32 generation;
};
+/**
+ * struct fw_cdev_event_response - Sent when a response packet was received
+ * @closure: See &fw_cdev_event_common;
+ * set by %FW_CDEV_IOC_SEND_REQUEST ioctl
+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE
+ * @rcode: Response code returned by the remote node
+ * @length: Data length, i.e. the response's payload size in bytes
+ * @data: Payload data, if any
+ *
+ * This event is sent when the stack receives a response to an outgoing request
+ * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl. The payload data for responses
+ * carrying data (read and lock responses) follows immediately and can be
+ * accessed through the @data field.
+ */
struct fw_cdev_event_response {
__u64 closure;
__u32 type;
@@ -59,6 +95,25 @@ struct fw_cdev_event_response {
__u32 data[0];
};
+/**
+ * struct fw_cdev_event_request - Sent on incoming request to an address region
+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST
+ * @tcode: Transaction code of the incoming request
+ * @offset: The offset into the 48-bit per-node address space
+ * @handle: Reference to the kernel-side pending request
+ * @length: Data length, i.e. the request's payload size in bytes
+ * @data: Incoming data, if any
+ *
+ * This event is sent when the stack receives an incoming request to an address
+ * region registered using the %FW_CDEV_IOC_ALLOCATE ioctl. The request is
+ * guaranteed to be completely contained in the specified region. Userspace is
+ * responsible for sending the response by %FW_CDEV_IOC_SEND_RESPONSE ioctl,
+ * using the same @handle.
+ *
+ * The payload data for requests carrying data (write and lock requests)
+ * follows immediately and can be accessed through the @data field.
+ */
struct fw_cdev_event_request {
__u64 closure;
__u32 type;
@@ -69,14 +124,39 @@ struct fw_cdev_event_request {
__u32 data[0];
};
+/**
+ * struct fw_cdev_event_iso_interrupt - Sent when an iso packet was completed
+ * @closure: See &fw_cdev_event_common;
+ * set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl
+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_ISO_INTERRUPT
+ * @cycle: Cycle counter of the interrupt packet
+ * @header_length: Total length of following headers, in bytes
+ * @header: Stripped headers, if any
+ *
+ * This event is sent when the controller has completed an &fw_cdev_iso_packet
+ * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers
+ * stripped of all packets up until and including the interrupt packet are
+ * returned in the @header field.
+ */
struct fw_cdev_event_iso_interrupt {
__u64 closure;
__u32 type;
__u32 cycle;
- __u32 header_length; /* Length in bytes of following headers. */
+ __u32 header_length;
__u32 header[0];
};
+/**
+ * union fw_cdev_event - Convenience union of fw_cdev_event_ types
+ * @common: Valid for all types
+ * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
+ * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
+ * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST
+ * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
+ *
+ * Convenience union for userspace use. Events could be read(2) into a char
+ * buffer and then cast to this union for further processing.
+ */
union fw_cdev_event {
struct fw_cdev_event_common common;
struct fw_cdev_event_bus_reset bus_reset;
@@ -105,35 +185,47 @@ union fw_cdev_event {
*/
#define FW_CDEV_VERSION 1
+/**
+ * struct fw_cdev_get_info - General purpose information ioctl
+ * @version: The version field is just a running serial number.
+ * We never break backwards compatibility, but may add more
+ * structs and ioctls in later revisions.
+ * @rom_length: If @rom is non-zero, at most rom_length bytes of configuration
+ * ROM will be copied into that user space address. In either
+ * case, @rom_length is updated with the actual length of the
+ * configuration ROM.
+ * @rom: If non-zero, address of a buffer to be filled by a copy of the
+ * local node's configuration ROM
+ * @bus_reset: If non-zero, address of a buffer to be filled by a
+ * &struct fw_cdev_event_bus_reset with the current state
+ * of the bus. This does not cause a bus reset to happen.
+ * @bus_reset_closure: Value of &closure in this and subsequent bus reset events
+ * @card: The index of the card this device belongs to
+ */
struct fw_cdev_get_info {
- /* The version field is just a running serial number. We
- * never break backwards compatibility. Userspace passes in
- * the version it expects and the kernel passes back the
- * highest version it can provide. Even if the structs in
- * this interface are extended in a later version, the kernel
- * will not copy back more data than what was present in the
- * interface version userspace expects. */
__u32 version;
-
- /* If non-zero, at most rom_length bytes of config rom will be
- * copied into that user space address. In either case,
- * rom_length is updated with the actual length of the config
- * rom. */
__u32 rom_length;
__u64 rom;
-
- /* If non-zero, a fw_cdev_event_bus_reset struct will be
- * copied here with the current state of the bus. This does
- * not cause a bus reset to happen. The value of closure in
- * this and sub-sequent bus reset events is set to
- * bus_reset_closure. */
__u64 bus_reset;
__u64 bus_reset_closure;
-
- /* The index of the card this devices belongs to. */
__u32 card;
};
+/**
+ * struct fw_cdev_send_request - Send an asynchronous request packet
+ * @tcode: Transaction code of the request
+ * @length: Length of outgoing payload, in bytes
+ * @offset: 48-bit offset at destination node
+ * @closure: Passed back to userspace in the response event
+ * @data: Userspace pointer to payload
+ * @generation: The bus generation where packet is valid
+ *
+ * Send a request to the device. This ioctl implements all outgoing requests.
+ * Both quadlet and block request specify the payload as a pointer to the data
+ * in the @data field. Once the transaction completes, the kernel writes an
+ * &fw_cdev_event_request event back. The @closure field is passed back to
+ * user space in the response event.
+ */
struct fw_cdev_send_request {
__u32 tcode;
__u32 length;
@@ -143,6 +235,19 @@ struct fw_cdev_send_request {
__u32 generation;
};
+/**
+ * struct fw_cdev_send_response - Send an asynchronous response packet
+ * @rcode: Response code as determined by the userspace handler
+ * @length: Length of outgoing payload, in bytes
+ * @data: Userspace pointer to payload
+ * @handle: The handle from the &fw_cdev_event_request
+ *
+ * Send a response to an incoming request. By setting up an address range using
+ * the %FW_CDEV_IOC_ALLOCATE ioctl, userspace can listen for incoming requests. An
+ * incoming request will generate an %FW_CDEV_EVENT_REQUEST, and userspace must
+ * send a reply using this ioctl. The event has a handle to the kernel-side
+ * pending transaction, which should be used with this ioctl.
+ */
struct fw_cdev_send_response {
__u32 rcode;
__u32 length;
@@ -150,6 +255,21 @@ struct fw_cdev_send_response {
__u32 handle;
};
+/**
+ * struct fw_cdev_allocate - Allocate a CSR address range
+ * @offset: Start offset of the address range
+ * @closure: To be passed back to userspace in request events
+ * @length: Length of the address range, in bytes
+ * @handle: Handle to the allocation, written by the kernel
+ *
+ * Allocate an address range in the 48-bit address space on the local node
+ * (the controller). This allows userspace to listen for requests with an
+ * offset within that address range. When the kernel receives a request
+ * within the range, an &fw_cdev_event_request event will be written back.
+ * The @closure field is passed back to userspace in the response event.
+ * The @handle field is an out parameter, returning a handle to the allocated
+ * range to be used for later deallocation of the range.
+ */
struct fw_cdev_allocate {
__u64 offset;
__u64 closure;
@@ -157,6 +277,11 @@ struct fw_cdev_allocate {
__u32 handle;
};
+/**
+ * struct fw_cdev_deallocate - Free an address range allocation
+ * @handle: Handle to the address range, as returned by the kernel when the
+ * range was allocated
+ */
struct fw_cdev_deallocate {
__u32 handle;
};
@@ -164,10 +289,41 @@ struct fw_cdev_deallocate {
#define FW_CDEV_LONG_RESET 0
#define FW_CDEV_SHORT_RESET 1
+/**
+ * struct fw_cdev_initiate_bus_reset - Initiate a bus reset
+ * @type: %FW_CDEV_SHORT_RESET or %FW_CDEV_LONG_RESET
+ *
+ * Initiate a bus reset for the bus this device is on. The bus reset can be
+ * either the original (long) bus reset or the arbitrated (short) bus reset
+ * introduced in 1394a-2000.
+ */
struct fw_cdev_initiate_bus_reset {
- __u32 type;
+ __u32 type; /* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */
};
+/**
+ * struct fw_cdev_add_descriptor - Add contents to the local node's config ROM
+ * @immediate: If non-zero, immediate key to insert before pointer
+ * @key: Upper 8 bits of root directory pointer
+ * @data: Userspace pointer to contents of descriptor block
+ * @length: Length of descriptor block data, in bytes
+ * @handle: Handle to the descriptor, written by the kernel
+ *
+ * Add a descriptor block and optionally a preceding immediate key to the local
+ * node's configuration ROM.
+ *
+ * The @key field specifies the upper 8 bits of the descriptor root directory
+ * pointer and the @data and @length fields specify the contents. The @key
+ * should be of the form 0xXX000000. The offset part of the root directory entry
+ * will be filled in by the kernel.
+ *
+ * If not 0, the @immediate field specifies an immediate key which will be
+ * inserted before the root directory pointer.
+ *
+ * If successful, the kernel adds the descriptor and writes back a handle to the
+ * kernel-side object to be used for later removal of the descriptor block and
+ * immediate key.
+ */
struct fw_cdev_add_descriptor {
__u32 immediate;
__u32 key;
@@ -176,6 +332,14 @@ struct fw_cdev_add_descriptor {
__u32 handle;
};
+/**
+ * struct fw_cdev_remove_descriptor - Remove contents from the configuration ROM
+ * @handle: Handle to the descriptor, as returned by the kernel when the
+ * descriptor was added
+ *
+ * Remove a descriptor block and accompanying immediate key from the local
+ * node's configuration ROM.
+ */
struct fw_cdev_remove_descriptor {
__u32 handle;
};
@@ -183,12 +347,24 @@ struct fw_cdev_remove_descriptor {
#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0
#define FW_CDEV_ISO_CONTEXT_RECEIVE 1
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8
-#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15
-
+/**
+ * struct fw_cdev_create_iso_context - Create a context for isochronous IO
+ * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE
+ * @header_size: Header size to strip for receive contexts
+ * @channel: Channel to bind to
+ * @speed: Speed to transmit at
+ * @closure: To be returned in &fw_cdev_event_iso_interrupt
+ * @handle: Handle to context, written back by kernel
+ *
+ * Prior to sending or receiving isochronous I/O, a context must be created.
+ * The context records information about the transmit or receive configuration
+ * and typically maps to an underlying hardware resource. A context is set up
+ * for either sending or receiving. It is bound to a specific isochronous
+ * channel.
+ *
+ * If a context was successfully created, the kernel writes back a handle to the
+ * context, which must be passed in for subsequent operations on that context.
+ */
struct fw_cdev_create_iso_context {
__u32 type;
__u32 header_size;
@@ -201,15 +377,49 @@ struct fw_cdev_create_iso_context {
#define FW_CDEV_ISO_PAYLOAD_LENGTH(v) (v)
#define FW_CDEV_ISO_INTERRUPT (1 << 16)
#define FW_CDEV_ISO_SKIP (1 << 17)
+#define FW_CDEV_ISO_SYNC (1 << 17)
#define FW_CDEV_ISO_TAG(v) ((v) << 18)
#define FW_CDEV_ISO_SY(v) ((v) << 20)
#define FW_CDEV_ISO_HEADER_LENGTH(v) ((v) << 24)
+/**
+ * struct fw_cdev_iso_packet - Isochronous packet
+ * @control: Contains the header length (8 uppermost bits), the sy field
+ * (4 bits), the tag field (2 bits), a sync flag (1 bit),
+ * a skip flag (1 bit), an interrupt flag (1 bit), and the
+ * payload length (16 lowermost bits)
+ * @header: Header and payload
+ *
+ * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.
+ *
+ * Use the FW_CDEV_ISO_ macros to fill in @control. The sy and tag fields are
+ * specified by IEEE 1394a and IEC 61883.
+ *
+ * FIXME - finish this documentation
+ */
struct fw_cdev_iso_packet {
__u32 control;
__u32 header[0];
};
+/**
+ * struct fw_cdev_queue_iso - Queue isochronous packets for I/O
+ * @packets: Userspace pointer to packet data
+ * @data: Pointer into mmap()'ed payload buffer
+ * @size: Size of packet data in bytes
+ * @handle: Isochronous context handle
+ *
+ * Queue a number of isochronous packets for reception or transmission.
+ * This ioctl takes a pointer to an array of &fw_cdev_iso_packet structs,
+ * which describe how to transmit from or receive into a contiguous region
+ * of a mmap()'ed payload buffer. As part of the packet descriptors,
+ * a series of headers can be supplied, which will be prepended to the
+ * payload during DMA.
+ *
+ * The kernel may or may not queue all packets, but will write back updated
+ * values of the @packets, @data and @size fields, so the ioctl can be
+ * resubmitted easily.
+ */
struct fw_cdev_queue_iso {
__u64 packets;
__u64 data;
@@ -217,6 +427,23 @@ struct fw_cdev_queue_iso {
__u32 handle;
};
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8
+#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15
+
+/**
+ * struct fw_cdev_start_iso - Start an isochronous transmission or reception
+ * @cycle: Cycle in which to start I/O. If @cycle is greater than or
+ * equal to 0, the I/O will start on that cycle.
+ * @sync: Determines the value to wait for for receive packets that have
+ * the %FW_CDEV_ISO_SYNC bit set
+ * @tags: Tag filter bit mask. Only valid for isochronous reception.
+ * Determines the tag values for which packets will be accepted.
+ * Use FW_CDEV_ISO_CONTEXT_MATCH_ macros to set @tags.
+ * @handle: Isochronous context handle within which to transmit or receive
+ */
struct fw_cdev_start_iso {
__s32 cycle;
__u32 sync;
@@ -224,6 +451,10 @@ struct fw_cdev_start_iso {
__u32 handle;
};
+/**
+ * struct fw_cdev_stop_iso - Stop an isochronous transmission or reception
+ * @handle: Handle of isochronous context to stop
+ */
struct fw_cdev_stop_iso {
__u32 handle;
};
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6a41f4cab14c..4f0b3bf5983c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1054,7 +1054,7 @@ struct block_device_operations {
};
/*
- * "descriptor" for what we're up to with a read for sendfile().
+ * "descriptor" for what we're up to with a read.
* This allows us to use the same read code yet
* have multiple different users of the data that
* we read from a file.
@@ -1105,7 +1105,6 @@ struct file_operations {
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
- ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
@@ -1762,7 +1761,6 @@ extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
unsigned long, loff_t, loff_t *, size_t, ssize_t);
extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
-extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
extern void do_generic_mapping_read(struct address_space *mapping,
struct file_ra_state *, struct file *,
loff_t *, read_descriptor_t *, read_actor_t);
@@ -1792,9 +1790,6 @@ extern int nonseekable_open(struct inode * inode, struct file * filp);
#ifdef CONFIG_FS_XIP
extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
loff_t *ppos);
-extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor,
- void *target);
extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma);
extern ssize_t xip_file_write(struct file *filp, const char __user *buf,
size_t len, loff_t *ppos);
diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h
index 8b7e4c1e32ae..a44a6a078f0a 100644
--- a/include/linux/gfs2_ondisk.h
+++ b/include/linux/gfs2_ondisk.h
@@ -54,18 +54,6 @@ struct gfs2_inum {
__be64 no_addr;
};
-struct gfs2_inum_host {
- __u64 no_formal_ino;
- __u64 no_addr;
-};
-
-static inline int gfs2_inum_equal(const struct gfs2_inum_host *ino1,
- const struct gfs2_inum_host *ino2)
-{
- return ino1->no_formal_ino == ino2->no_formal_ino &&
- ino1->no_addr == ino2->no_addr;
-}
-
/*
* Generic metadata head structure
* Every inplace buffer logged in the journal must start with this.
@@ -94,12 +82,6 @@ struct gfs2_meta_header {
__be32 __pad1; /* Was incarnation number in gfs1 */
};
-struct gfs2_meta_header_host {
- __u32 mh_magic;
- __u32 mh_type;
- __u32 mh_format;
-};
-
/*
* super-block structure
*
@@ -139,23 +121,6 @@ struct gfs2_sb {
/* In gfs1, quota and license dinodes followed */
};
-struct gfs2_sb_host {
- struct gfs2_meta_header_host sb_header;
-
- __u32 sb_fs_format;
- __u32 sb_multihost_format;
-
- __u32 sb_bsize;
- __u32 sb_bsize_shift;
-
- struct gfs2_inum_host sb_master_dir; /* Was jindex dinode in gfs1 */
- struct gfs2_inum_host sb_root_dir;
-
- char sb_lockproto[GFS2_LOCKNAME_LEN];
- char sb_locktable[GFS2_LOCKNAME_LEN];
- /* In gfs1, quota and license dinodes followed */
-};
-
/*
* resource index structure
*/
@@ -173,14 +138,6 @@ struct gfs2_rindex {
__u8 ri_reserved[64];
};
-struct gfs2_rindex_host {
- __u64 ri_addr; /* grp block disk address */
- __u64 ri_data0; /* first data location */
- __u32 ri_length; /* length of rgrp header in fs blocks */
- __u32 ri_data; /* num of data blocks in rgrp */
- __u32 ri_bitbytes; /* number of bytes in data bitmaps */
-};
-
/*
* resource group header structure
*/
@@ -212,13 +169,6 @@ struct gfs2_rgrp {
__u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */
};
-struct gfs2_rgrp_host {
- __u32 rg_flags;
- __u32 rg_free;
- __u32 rg_dinodes;
- __u64 rg_igeneration;
-};
-
/*
* quota structure
*/
@@ -230,12 +180,6 @@ struct gfs2_quota {
__u8 qu_reserved[64];
};
-struct gfs2_quota_host {
- __u64 qu_limit;
- __u64 qu_warn;
- __u64 qu_value;
-};
-
/*
* dinode structure
*/
@@ -315,29 +259,11 @@ struct gfs2_dinode {
struct gfs2_inum __pad4; /* Unused even in current gfs1 */
__be64 di_eattr; /* extended attribute block number */
+ __be32 di_atime_nsec; /* nsec portion of atime */
+ __be32 di_mtime_nsec; /* nsec portion of mtime */
+ __be32 di_ctime_nsec; /* nsec portion of ctime */
- __u8 di_reserved[56];
-};
-
-struct gfs2_dinode_host {
- __u64 di_size; /* number of bytes in file */
- __u64 di_blocks; /* number of blocks in file */
-
- /* This section varies from gfs1. Padding added to align with
- * remainder of dinode
- */
- __u64 di_goal_meta; /* rgrp to alloc from next */
- __u64 di_goal_data; /* data block goal */
- __u64 di_generation; /* generation number for NFS */
-
- __u32 di_flags; /* GFS2_DIF_... */
- __u16 di_height; /* height of metadata */
-
- /* These only apply to directories */
- __u16 di_depth; /* Number of bits in the table */
- __u32 di_entries; /* The number of entries in the directory */
-
- __u64 di_eattr; /* extended attribute block number */
+ __u8 di_reserved[44];
};
/*
@@ -414,16 +340,6 @@ struct gfs2_log_header {
__be32 lh_hash;
};
-struct gfs2_log_header_host {
- struct gfs2_meta_header_host lh_header;
-
- __u64 lh_sequence; /* Sequence number of this transaction */
- __u32 lh_flags; /* GFS2_LOG_HEAD_... */
- __u32 lh_tail; /* Block number of log tail */
- __u32 lh_blkno;
- __u32 lh_hash;
-};
-
/*
* Log type descriptor
*/
@@ -464,11 +380,6 @@ struct gfs2_inum_range {
__be64 ir_length;
};
-struct gfs2_inum_range_host {
- __u64 ir_start;
- __u64 ir_length;
-};
-
/*
* Statfs change
* Describes an change to the pool of free and allocated
@@ -481,12 +392,6 @@ struct gfs2_statfs_change {
__be64 sc_dinodes;
};
-struct gfs2_statfs_change_host {
- __u64 sc_total;
- __u64 sc_free;
- __u64 sc_dinodes;
-};
-
/*
* Quota change
* Describes an allocation change for a particular
@@ -501,39 +406,12 @@ struct gfs2_quota_change {
__be32 qc_id;
};
-struct gfs2_quota_change_host {
- __u64 qc_change;
- __u32 qc_flags; /* GFS2_QCF_... */
- __u32 qc_id;
+struct gfs2_quota_lvb {
+ __be32 qb_magic;
+ __u32 __pad;
+ __be64 qb_limit; /* Hard limit of # blocks to alloc */
+ __be64 qb_warn; /* Warn user when alloc is above this # */
+ __be64 qb_value; /* Current # blocks allocated */
};
-#ifdef __KERNEL__
-/* Translation functions */
-
-extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf);
-extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf);
-extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf);
-extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf);
-extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf);
-extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf);
-extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf);
-extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf);
-struct gfs2_inode;
-extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
-extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf);
-extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf);
-extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf);
-extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf);
-extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf);
-extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf);
-extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf);
-extern void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf);
-
-/* Printing functions */
-
-extern void gfs2_rindex_print(const struct gfs2_rindex_host *ri);
-extern void gfs2_dinode_print(const struct gfs2_inode *ip);
-
-#endif /* __KERNEL__ */
-
#endif /* __GFS2_ONDISK_DOT_H__ */
diff --git a/include/linux/gpio_mouse.h b/include/linux/gpio_mouse.h
new file mode 100644
index 000000000000..44ed7aa14d85
--- /dev/null
+++ b/include/linux/gpio_mouse.h
@@ -0,0 +1,61 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _GPIO_MOUSE_H
+#define _GPIO_MOUSE_H
+
+#define GPIO_MOUSE_POLARITY_ACT_HIGH 0x00
+#define GPIO_MOUSE_POLARITY_ACT_LOW 0x01
+
+#define GPIO_MOUSE_PIN_UP 0
+#define GPIO_MOUSE_PIN_DOWN 1
+#define GPIO_MOUSE_PIN_LEFT 2
+#define GPIO_MOUSE_PIN_RIGHT 3
+#define GPIO_MOUSE_PIN_BLEFT 4
+#define GPIO_MOUSE_PIN_BMIDDLE 5
+#define GPIO_MOUSE_PIN_BRIGHT 6
+#define GPIO_MOUSE_PIN_MAX 7
+
+/**
+ * struct gpio_mouse_platform_data
+ * @scan_ms: integer in ms specifying the scan periode.
+ * @polarity: Pin polarity, active high or low.
+ * @up: GPIO line for up value.
+ * @down: GPIO line for down value.
+ * @left: GPIO line for left value.
+ * @right: GPIO line for right value.
+ * @bleft: GPIO line for left button.
+ * @bmiddle: GPIO line for middle button.
+ * @bright: GPIO line for right button.
+ *
+ * This struct must be added to the platform_device in the board code.
+ * It is used by the gpio_mouse driver to setup GPIO lines and to
+ * calculate mouse movement.
+ */
+struct gpio_mouse_platform_data {
+ int scan_ms;
+ int polarity;
+
+ union {
+ struct {
+ int up;
+ int down;
+ int left;
+ int right;
+
+ int bleft;
+ int bmiddle;
+ int bright;
+ };
+ int pins[GPIO_MOUSE_PIN_MAX];
+ };
+};
+
+#endif /* _GPIO_MOUSE_H */
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 7803014f3a11..8d302298a161 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -79,6 +79,19 @@
#endif
#ifdef CONFIG_PREEMPT
+# define PREEMPT_CHECK_OFFSET 1
+#else
+# define PREEMPT_CHECK_OFFSET 0
+#endif
+
+/*
+ * Check whether we were atomic before we did preempt_disable():
+ * (used by the scheduler)
+ */
+#define in_atomic_preempt_off() \
+ ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
+
+#ifdef CONFIG_PREEMPT
# define preemptible() (preempt_count() == 0 && !irqs_disabled())
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 827ee748fd4c..898103b401f1 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -263,19 +263,28 @@ struct hid_item {
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
#define HID_QUIRK_MIGHTYMOUSE 0x00000400
-#define HID_QUIRK_CYMOTION 0x00000800
-#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
-#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
-#define HID_QUIRK_INVERT_HWHEEL 0x00004000
-#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000
-#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000
-#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000
-#define HID_QUIRK_IGNORE_MOUSE 0x00040000
-#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000
-#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
-#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
-#define HID_QUIRK_RESET_LEDS 0x00400000
-#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000
+#define HID_QUIRK_POWERBOOK_HAS_FN 0x00000800
+#define HID_QUIRK_POWERBOOK_FN_ON 0x00001000
+#define HID_QUIRK_INVERT_HWHEEL 0x00002000
+#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00004000
+#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00008000
+#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
+#define HID_QUIRK_IGNORE_MOUSE 0x00020000
+#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000
+#define HID_QUIRK_DUPLICATE_USAGES 0x00080000
+#define HID_QUIRK_RESET_LEDS 0x00100000
+#define HID_QUIRK_HIDINPUT 0x00200000
+#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL 0x00400000
+#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000
+
+/*
+ * Separate quirks for runtime report descriptor fixup
+ */
+
+#define HID_QUIRK_RDESC_CYMOTION 0x00000001
+#define HID_QUIRK_RDESC_LOGITECH 0x00000002
+#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
+#define HID_QUIRK_RDESC_PETALYNX 0x00000008
/*
* This is the global environment of the parser. This information is
@@ -488,6 +497,11 @@ struct hid_descriptor {
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
/* HID core API */
+
+#ifdef CONFIG_HID_DEBUG
+extern int hid_debug;
+#endif
+
extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
extern int hidinput_connect(struct hid_device *);
@@ -506,6 +520,7 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks);
int usbhid_quirks_init(char **quirks_param);
void usbhid_quirks_exit(void);
+void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
#ifdef CONFIG_HID_FF
int hid_ff_init(struct hid_device *hid);
@@ -523,14 +538,19 @@ static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
#else
static inline int hid_ff_init(struct hid_device *hid) { return -1; }
#endif
-#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
- __FILE__ , ## arg)
+
+#ifdef CONFIG_HID_DEBUG
+#define dbg_hid(format, arg...) if (hid_debug) \
+ printk(KERN_DEBUG "%s: " format ,\
+ __FILE__ , ## arg)
+#define dbg_hid_line(format, arg...) if (hid_debug) \
+ printk(format, ## arg)
#else
-#define dbg(format, arg...) do {} while (0)
+#define dbg_hid(format, arg...) do {} while (0)
+#define dbg_hid_line dbg_hid
#endif
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
__FILE__ , ## arg)
#endif
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 1e365acdd369..19ab25804056 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -25,6 +25,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/semaphore.h>
+#include <asm/mutex.h>
/******************************************************************************
* IDE driver configuration options (play with these as desired):
@@ -685,6 +686,8 @@ typedef struct hwif_s {
u8 mwdma_mask;
u8 swdma_mask;
+ u8 cbl; /* cable type */
+
hwif_chipset_t chipset; /* sub-module for tuning.. */
struct pci_dev *pci_dev; /* for pci chipsets */
@@ -735,8 +738,8 @@ typedef struct hwif_s {
void (*ide_dma_clear_irq)(ide_drive_t *drive);
void (*dma_host_on)(ide_drive_t *drive);
void (*dma_host_off)(ide_drive_t *drive);
- int (*ide_dma_lostirq)(ide_drive_t *drive);
- int (*ide_dma_timeout)(ide_drive_t *drive);
+ void (*dma_lost_irq)(ide_drive_t *drive);
+ void (*dma_timeout)(ide_drive_t *drive);
void (*OUTB)(u8 addr, unsigned long port);
void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
@@ -791,7 +794,6 @@ typedef struct hwif_s {
unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
unsigned reset : 1; /* reset after probe */
unsigned autodma : 1; /* auto-attempt using DMA at boot */
- unsigned udma_four : 1; /* 1=ATA-66 capable, 0=default */
unsigned no_lba48 : 1; /* 1 = cannot do LBA48 */
unsigned no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
unsigned auto_poll : 1; /* supports nop auto-poll */
@@ -863,7 +865,7 @@ typedef struct hwgroup_s {
typedef struct ide_driver_s ide_driver_t;
-extern struct semaphore ide_setting_sem;
+extern struct mutex ide_setting_mtx;
int set_io_32bit(ide_drive_t *, int);
int set_pio_mode(ide_drive_t *, int);
@@ -1304,8 +1306,8 @@ extern int __ide_dma_check(ide_drive_t *);
extern int ide_dma_setup(ide_drive_t *);
extern void ide_dma_start(ide_drive_t *);
extern int __ide_dma_end(ide_drive_t *);
-extern int __ide_dma_lostirq(ide_drive_t *);
-extern int __ide_dma_timeout(ide_drive_t *);
+extern void ide_dma_lost_irq(ide_drive_t *);
+extern void ide_dma_timeout(ide_drive_t *);
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
#else
@@ -1382,11 +1384,11 @@ extern const ide_pio_timings_t ide_pio_timings[6];
extern spinlock_t ide_lock;
-extern struct semaphore ide_cfg_sem;
+extern struct mutex ide_cfg_mtx;
/*
* Structure locking:
*
- * ide_cfg_sem and ide_lock together protect changes to
+ * ide_cfg_mtx and ide_lock together protect changes to
* ide_hwif_t->{next,hwgroup}
* ide_drive_t->next
*
diff --git a/include/linux/input.h b/include/linux/input.h
index d8521c72f69f..18c98b543030 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -981,15 +981,15 @@ struct input_dev {
struct mutex mutex; /* serializes open and close operations */
unsigned int users;
- struct class_device cdev;
+ struct device dev;
union { /* temporarily so while we switching to struct device */
- struct device *parent;
- } dev;
+ struct device *dev;
+ } cdev;
struct list_head h_list;
struct list_head node;
};
-#define to_input_dev(d) container_of(d, struct input_dev, cdev)
+#define to_input_dev(d) container_of(d, struct input_dev, dev)
/*
* Verify that we are in sync with input_device_id mod_devicetable.h #defines
@@ -1096,22 +1096,22 @@ struct input_handle {
struct list_head h_node;
};
-#define to_dev(n) container_of(n,struct input_dev,node)
-#define to_handler(n) container_of(n,struct input_handler,node)
-#define to_handle(n) container_of(n,struct input_handle,d_node)
-#define to_handle_h(n) container_of(n,struct input_handle,h_node)
+#define to_dev(n) container_of(n, struct input_dev, node)
+#define to_handler(n) container_of(n, struct input_handler, node)
+#define to_handle(n) container_of(n, struct input_handle, d_node)
+#define to_handle_h(n) container_of(n, struct input_handle, h_node)
struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev);
static inline struct input_dev *input_get_device(struct input_dev *dev)
{
- return to_input_dev(class_device_get(&dev->cdev));
+ return to_input_dev(get_device(&dev->dev));
}
static inline void input_put_device(struct input_dev *dev)
{
- class_device_put(&dev->cdev);
+ put_device(&dev->dev);
}
static inline void *input_get_drvdata(struct input_dev *dev)
diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h
index 8e2042b9d471..2eaa142cd061 100644
--- a/include/linux/ioprio.h
+++ b/include/linux/ioprio.h
@@ -47,8 +47,10 @@ enum {
#define IOPRIO_NORM (4)
static inline int task_ioprio(struct task_struct *task)
{
- WARN_ON(!ioprio_valid(task->ioprio));
- return IOPRIO_PRIO_DATA(task->ioprio);
+ if (ioprio_valid(task->ioprio))
+ return IOPRIO_PRIO_DATA(task->ioprio);
+
+ return IOPRIO_NORM;
}
static inline int task_nice_ioprio(struct task_struct *task)
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index c6d4ab86b83c..b021b3a2b65a 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -13,10 +13,6 @@
#ifndef __ASM_MV643XX_H
#define __ASM_MV643XX_H
-#ifdef __mips__
-#include <asm/addrspace.h>
-#include <asm/marvell.h>
-#endif
#include <asm/types.h>
/****************************************/
diff --git a/include/linux/pda_power.h b/include/linux/pda_power.h
new file mode 100644
index 000000000000..1375f15797e7
--- /dev/null
+++ b/include/linux/pda_power.h
@@ -0,0 +1,31 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PDA_POWER_H__
+#define __PDA_POWER_H__
+
+#define PDA_POWER_CHARGE_AC (1 << 0)
+#define PDA_POWER_CHARGE_USB (1 << 1)
+
+struct pda_power_pdata {
+ int (*is_ac_online)(void);
+ int (*is_usb_online)(void);
+ void (*set_charge)(int flags);
+
+ char **supplied_to;
+ size_t num_supplicants;
+
+ unsigned int wait_for_status; /* msecs, default is 500 */
+ unsigned int wait_for_charger; /* msecs, default is 500 */
+};
+
+#endif /* __PDA_POWER_H__ */
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index c8884f971228..8e4120285f72 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -9,13 +9,39 @@
#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
+/**
+ * struct pipe_buffer - a linux kernel pipe buffer
+ * @page: the page containing the data for the pipe buffer
+ * @offset: offset of data inside the @page
+ * @len: length of data inside the @page
+ * @ops: operations associated with this buffer. See @pipe_buf_operations.
+ * @flags: pipe buffer flags. See above.
+ * @private: private data owned by the ops.
+ **/
struct pipe_buffer {
struct page *page;
unsigned int offset, len;
const struct pipe_buf_operations *ops;
unsigned int flags;
+ unsigned long private;
};
+/**
+ * struct pipe_inode_info - a linux kernel pipe
+ * @wait: reader/writer wait point in case of empty/full pipe
+ * @nrbufs: the number of non-empty pipe buffers in this pipe
+ * @curbuf: the current pipe buffer entry
+ * @tmp_page: cached released page
+ * @readers: number of current readers of this pipe
+ * @writers: number of current writers of this pipe
+ * @waiting_writers: number of writers blocked waiting for room
+ * @r_counter: reader counter
+ * @w_counter: writer counter
+ * @fasync_readers: reader side fasync
+ * @fasync_writers: writer side fasync
+ * @inode: inode this pipe is attached to
+ * @bufs: the circular array of pipe buffers
+ **/
struct pipe_inode_info {
wait_queue_head_t wait;
unsigned int nrbufs, curbuf;
@@ -34,22 +60,73 @@ struct pipe_inode_info {
/*
* Note on the nesting of these functions:
*
- * ->pin()
+ * ->confirm()
* ->steal()
* ...
* ->map()
* ...
* ->unmap()
*
- * That is, ->map() must be called on a pinned buffer, same goes for ->steal().
+ * That is, ->map() must be called on a confirmed buffer,
+ * same goes for ->steal(). See below for the meaning of each
+ * operation. Also see kerneldoc in fs/pipe.c for the pipe
+ * and generic variants of these hooks.
*/
struct pipe_buf_operations {
+ /*
+ * This is set to 1, if the generic pipe read/write may coalesce
+ * data into an existing buffer. If this is set to 0, a new pipe
+ * page segment is always used for new data.
+ */
int can_merge;
+
+ /*
+ * ->map() returns a virtual address mapping of the pipe buffer.
+ * The last integer flag reflects whether this should be an atomic
+ * mapping or not. The atomic map is faster, however you can't take
+ * page faults before calling ->unmap() again. So if you need to eg
+ * access user data through copy_to/from_user(), then you must get
+ * a non-atomic map. ->map() uses the KM_USER0 atomic slot for
+ * atomic maps, so you can't map more than one pipe_buffer at once
+ * and you have to be careful if mapping another page as source
+ * or destination for a copy (IOW, it has to use something else
+ * than KM_USER0).
+ */
void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int);
+
+ /*
+ * Undoes ->map(), finishes the virtual mapping of the pipe buffer.
+ */
void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *, void *);
- int (*pin)(struct pipe_inode_info *, struct pipe_buffer *);
+
+ /*
+ * ->confirm() verifies that the data in the pipe buffer is there
+ * and that the contents are good. If the pages in the pipe belong
+ * to a file system, we may need to wait for IO completion in this
+ * hook. Returns 0 for good, or a negative error value in case of
+ * error.
+ */
+ int (*confirm)(struct pipe_inode_info *, struct pipe_buffer *);
+
+ /*
+ * When the contents of this pipe buffer has been completely
+ * consumed by a reader, ->release() is called.
+ */
void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
+
+ /*
+ * Attempt to take ownership of the pipe buffer and its contents.
+ * ->steal() returns 0 for success, in which case the contents
+ * of the pipe (the buf->page) is locked and now completely owned
+ * by the caller. The page may then be transferred to a different
+ * mapping, the most often used case is insertion into different
+ * file address space cache.
+ */
int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
+
+ /*
+ * Get a reference to the pipe buffer.
+ */
void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
};
@@ -68,39 +145,7 @@ void __free_pipe_info(struct pipe_inode_info *);
void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int);
void generic_pipe_buf_unmap(struct pipe_inode_info *, struct pipe_buffer *, void *);
void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
-int generic_pipe_buf_pin(struct pipe_inode_info *, struct pipe_buffer *);
+int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
-/*
- * splice is tied to pipes as a transport (at least for now), so we'll just
- * add the splice flags here.
- */
-#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */
-#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
- /* we may still block on the fd we splice */
- /* from/to, of course */
-#define SPLICE_F_MORE (0x04) /* expect more data */
-#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */
-
-/*
- * Passed to the actors
- */
-struct splice_desc {
- unsigned int len, total_len; /* current and remaining length */
- unsigned int flags; /* splice flags */
- struct file *file; /* file to read/write */
- loff_t pos; /* file position */
-};
-
-typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
- struct splice_desc *);
-
-extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
- loff_t *, size_t, unsigned int,
- splice_actor *);
-
-extern ssize_t __splice_from_pipe(struct pipe_inode_info *, struct file *,
- loff_t *, size_t, unsigned int,
- splice_actor *);
-
#endif
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
new file mode 100644
index 000000000000..606c0957997f
--- /dev/null
+++ b/include/linux/power_supply.h
@@ -0,0 +1,180 @@
+/*
+ * Universal power supply monitor class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#ifndef __LINUX_POWER_SUPPLY_H__
+#define __LINUX_POWER_SUPPLY_H__
+
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+
+/*
+ * All voltages, currents, charges, energies, time and temperatures in uV,
+ * µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ * stated. It's driver's job to convert its raw values to units in which
+ * this class operates.
+ */
+
+/*
+ * For systems where the charger determines the maximum battery capacity
+ * the min and max fields should be used to present these values to user
+ * space. Unused/unknown fields will not appear in sysfs.
+ */
+
+enum {
+ POWER_SUPPLY_STATUS_UNKNOWN = 0,
+ POWER_SUPPLY_STATUS_CHARGING,
+ POWER_SUPPLY_STATUS_DISCHARGING,
+ POWER_SUPPLY_STATUS_NOT_CHARGING,
+ POWER_SUPPLY_STATUS_FULL,
+};
+
+enum {
+ POWER_SUPPLY_HEALTH_UNKNOWN = 0,
+ POWER_SUPPLY_HEALTH_GOOD,
+ POWER_SUPPLY_HEALTH_OVERHEAT,
+ POWER_SUPPLY_HEALTH_DEAD,
+ POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+ POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+};
+
+enum {
+ POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
+ POWER_SUPPLY_TECHNOLOGY_NiMH,
+ POWER_SUPPLY_TECHNOLOGY_LION,
+ POWER_SUPPLY_TECHNOLOGY_LIPO,
+ POWER_SUPPLY_TECHNOLOGY_LiFe,
+ POWER_SUPPLY_TECHNOLOGY_NiCd,
+};
+
+enum {
+ POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
+ POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
+ POWER_SUPPLY_CAPACITY_LEVEL_LOW,
+ POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
+ POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
+ POWER_SUPPLY_CAPACITY_LEVEL_FULL,
+};
+
+enum power_supply_property {
+ /* Properties of type `int' */
+ POWER_SUPPLY_PROP_STATUS = 0,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_AVG,
+ POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_ENERGY_EMPTY,
+ POWER_SUPPLY_PROP_ENERGY_NOW,
+ POWER_SUPPLY_PROP_ENERGY_AVG,
+ POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+ /* Properties of type `const char *' */
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+enum power_supply_type {
+ POWER_SUPPLY_TYPE_BATTERY = 0,
+ POWER_SUPPLY_TYPE_UPS,
+ POWER_SUPPLY_TYPE_MAINS,
+ POWER_SUPPLY_TYPE_USB,
+};
+
+union power_supply_propval {
+ int intval;
+ const char *strval;
+};
+
+struct power_supply {
+ const char *name;
+ enum power_supply_type type;
+ enum power_supply_property *properties;
+ size_t num_properties;
+
+ char **supplied_to;
+ size_t num_supplicants;
+
+ int (*get_property)(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val);
+ void (*external_power_changed)(struct power_supply *psy);
+
+ /* For APM emulation, think legacy userspace. */
+ int use_for_apm;
+
+ /* private */
+ struct device *dev;
+ struct work_struct changed_work;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+ struct led_trigger *charging_full_trig;
+ char *charging_full_trig_name;
+ struct led_trigger *charging_trig;
+ char *charging_trig_name;
+ struct led_trigger *full_trig;
+ char *full_trig_name;
+ struct led_trigger *online_trig;
+ char *online_trig_name;
+#endif
+};
+
+/*
+ * This is recommended structure to specify static power supply parameters.
+ * Generic one, parametrizable for different power supplies. Power supply
+ * class itself does not use it, but that's what implementing most platform
+ * drivers, should try reuse for consistency.
+ */
+
+struct power_supply_info {
+ const char *name;
+ int technology;
+ int voltage_max_design;
+ int voltage_min_design;
+ int charge_full_design;
+ int charge_empty_design;
+ int energy_full_design;
+ int energy_empty_design;
+ int use_for_apm;
+};
+
+extern void power_supply_changed(struct power_supply *psy);
+extern int power_supply_am_i_supplied(struct power_supply *psy);
+
+extern int power_supply_register(struct device *parent,
+ struct power_supply *psy);
+extern void power_supply_unregister(struct power_supply *psy);
+
+/* For APM emulation, think legacy userspace. */
+extern struct class *power_supply_class;
+
+#endif /* __LINUX_POWER_SUPPLY_H__ */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 693f0e6c54d4..cfb680585ab8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -34,6 +34,8 @@
#define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3
+/* SCHED_ISO: reserved but not implemented yet */
+#define SCHED_IDLE 5
#ifdef __KERNEL__
@@ -130,6 +132,26 @@ extern unsigned long nr_active(void);
extern unsigned long nr_iowait(void);
extern unsigned long weighted_cpuload(const int cpu);
+struct seq_file;
+struct cfs_rq;
+#ifdef CONFIG_SCHED_DEBUG
+extern void proc_sched_show_task(struct task_struct *p, struct seq_file *m);
+extern void proc_sched_set_task(struct task_struct *p);
+extern void
+print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now);
+#else
+static inline void
+proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+{
+}
+static inline void proc_sched_set_task(struct task_struct *p)
+{
+}
+static inline void
+print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now)
+{
+}
+#endif
/*
* Task state bitmask. NOTE! These bits are also
@@ -193,6 +215,7 @@ struct task_struct;
extern void sched_init(void);
extern void sched_init_smp(void);
extern void init_idle(struct task_struct *idle, int cpu);
+extern void init_idle_bootup_task(struct task_struct *idle);
extern cpumask_t nohz_cpu_mask;
#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)
@@ -479,7 +502,7 @@ struct signal_struct {
* from jiffies_to_ns(utime + stime) if sched_clock uses something
* other than jiffies.)
*/
- unsigned long long sched_time;
+ unsigned long long sum_sched_runtime;
/*
* We don't bother to synchronize most readers of this at all,
@@ -521,31 +544,6 @@ struct signal_struct {
#define SIGNAL_STOP_CONTINUED 0x00000004 /* SIGCONT since WCONTINUED reap */
#define SIGNAL_GROUP_EXIT 0x00000008 /* group exit in progress */
-
-/*
- * Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
- * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
- * values are inverted: lower p->prio value means higher priority.
- *
- * The MAX_USER_RT_PRIO value allows the actual maximum
- * RT priority to be separate from the value exported to
- * user-space. This allows kernel threads to set their
- * priority to a value higher than any user task. Note:
- * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
- */
-
-#define MAX_USER_RT_PRIO 100
-#define MAX_RT_PRIO MAX_USER_RT_PRIO
-
-#define MAX_PRIO (MAX_RT_PRIO + 40)
-
-#define rt_prio(prio) unlikely((prio) < MAX_RT_PRIO)
-#define rt_task(p) rt_prio((p)->prio)
-#define batch_task(p) (unlikely((p)->policy == SCHED_BATCH))
-#define is_rt_policy(p) ((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
-#define has_rt_policy(p) unlikely(is_rt_policy((p)->policy))
-
/*
* Some day this will be a full-fledged user tracking system..
*/
@@ -583,13 +581,13 @@ struct reclaim_state;
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
struct sched_info {
/* cumulative counters */
- unsigned long cpu_time, /* time spent on the cpu */
- run_delay, /* time spent waiting on a runqueue */
- pcnt; /* # of timeslices run on this cpu */
+ unsigned long pcnt; /* # of times run on this cpu */
+ unsigned long long cpu_time, /* time spent on the cpu */
+ run_delay; /* time spent waiting on a runqueue */
/* timestamps */
- unsigned long last_arrival, /* when we last ran on a cpu */
- last_queued; /* when we were last queued to run */
+ unsigned long long last_arrival,/* when we last ran on a cpu */
+ last_queued; /* when we were last queued to run */
};
#endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */
@@ -639,18 +637,24 @@ static inline int sched_info_on(void)
#endif
}
-enum idle_type
-{
- SCHED_IDLE,
- NOT_IDLE,
- NEWLY_IDLE,
- MAX_IDLE_TYPES
+enum cpu_idle_type {
+ CPU_IDLE,
+ CPU_NOT_IDLE,
+ CPU_NEWLY_IDLE,
+ CPU_MAX_IDLE_TYPES
};
/*
* sched-domains (multiprocessor balancing) declarations:
*/
-#define SCHED_LOAD_SCALE 128UL /* increase resolution of load */
+
+/*
+ * Increase resolution of nice-level calculations:
+ */
+#define SCHED_LOAD_SHIFT 10
+#define SCHED_LOAD_SCALE (1L << SCHED_LOAD_SHIFT)
+
+#define SCHED_LOAD_SCALE_FUZZ (SCHED_LOAD_SCALE >> 5)
#ifdef CONFIG_SMP
#define SD_LOAD_BALANCE 1 /* Do load balancing on this domain. */
@@ -719,14 +723,14 @@ struct sched_domain {
#ifdef CONFIG_SCHEDSTATS
/* load_balance() stats */
- unsigned long lb_cnt[MAX_IDLE_TYPES];
- unsigned long lb_failed[MAX_IDLE_TYPES];
- unsigned long lb_balanced[MAX_IDLE_TYPES];
- unsigned long lb_imbalance[MAX_IDLE_TYPES];
- unsigned long lb_gained[MAX_IDLE_TYPES];
- unsigned long lb_hot_gained[MAX_IDLE_TYPES];
- unsigned long lb_nobusyg[MAX_IDLE_TYPES];
- unsigned long lb_nobusyq[MAX_IDLE_TYPES];
+ unsigned long lb_cnt[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_failed[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_balanced[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_imbalance[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_gained[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_hot_gained[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_nobusyg[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_nobusyq[CPU_MAX_IDLE_TYPES];
/* Active load balancing */
unsigned long alb_cnt;
@@ -753,12 +757,6 @@ struct sched_domain {
extern int partition_sched_domains(cpumask_t *partition1,
cpumask_t *partition2);
-/*
- * Maximum cache size the migration-costs auto-tuning code will
- * search from:
- */
-extern unsigned int max_cache_size;
-
#endif /* CONFIG_SMP */
@@ -809,14 +807,86 @@ struct mempolicy;
struct pipe_inode_info;
struct uts_namespace;
-enum sleep_type {
- SLEEP_NORMAL,
- SLEEP_NONINTERACTIVE,
- SLEEP_INTERACTIVE,
- SLEEP_INTERRUPTED,
+struct rq;
+struct sched_domain;
+
+struct sched_class {
+ struct sched_class *next;
+
+ void (*enqueue_task) (struct rq *rq, struct task_struct *p,
+ int wakeup, u64 now);
+ void (*dequeue_task) (struct rq *rq, struct task_struct *p,
+ int sleep, u64 now);
+ void (*yield_task) (struct rq *rq, struct task_struct *p);
+
+ void (*check_preempt_curr) (struct rq *rq, struct task_struct *p);
+
+ struct task_struct * (*pick_next_task) (struct rq *rq, u64 now);
+ void (*put_prev_task) (struct rq *rq, struct task_struct *p, u64 now);
+
+ int (*load_balance) (struct rq *this_rq, int this_cpu,
+ struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *total_load_moved);
+
+ void (*set_curr_task) (struct rq *rq);
+ void (*task_tick) (struct rq *rq, struct task_struct *p);
+ void (*task_new) (struct rq *rq, struct task_struct *p);
};
-struct prio_array;
+struct load_weight {
+ unsigned long weight, inv_weight;
+};
+
+/*
+ * CFS stats for a schedulable entity (task, task-group etc)
+ *
+ * Current field usage histogram:
+ *
+ * 4 se->block_start
+ * 4 se->run_node
+ * 4 se->sleep_start
+ * 4 se->sleep_start_fair
+ * 6 se->load.weight
+ * 7 se->delta_fair
+ * 15 se->wait_runtime
+ */
+struct sched_entity {
+ long wait_runtime;
+ unsigned long delta_fair_run;
+ unsigned long delta_fair_sleep;
+ unsigned long delta_exec;
+ s64 fair_key;
+ struct load_weight load; /* for load-balancing */
+ struct rb_node run_node;
+ unsigned int on_rq;
+
+ u64 wait_start_fair;
+ u64 wait_start;
+ u64 exec_start;
+ u64 sleep_start;
+ u64 sleep_start_fair;
+ u64 block_start;
+ u64 sleep_max;
+ u64 block_max;
+ u64 exec_max;
+ u64 wait_max;
+ u64 last_ran;
+
+ u64 sum_exec_runtime;
+ s64 sum_wait_runtime;
+ s64 sum_sleep_runtime;
+ unsigned long wait_runtime_overruns;
+ unsigned long wait_runtime_underruns;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ struct sched_entity *parent;
+ /* rq on which this entity is (to be) queued: */
+ struct cfs_rq *cfs_rq;
+ /* rq "owned" by this entity/group: */
+ struct cfs_rq *my_q;
+#endif
+};
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
@@ -832,23 +902,20 @@ struct task_struct {
int oncpu;
#endif
#endif
- int load_weight; /* for niceness load balancing purposes */
+
int prio, static_prio, normal_prio;
struct list_head run_list;
- struct prio_array *array;
+ struct sched_class *sched_class;
+ struct sched_entity se;
unsigned short ioprio;
#ifdef CONFIG_BLK_DEV_IO_TRACE
unsigned int btrace_seq;
#endif
- unsigned long sleep_avg;
- unsigned long long timestamp, last_ran;
- unsigned long long sched_time; /* sched_clock time spent running */
- enum sleep_type sleep_type;
unsigned int policy;
cpumask_t cpus_allowed;
- unsigned int time_slice, first_time_slice;
+ unsigned int time_slice;
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
struct sched_info sched_info;
@@ -1078,6 +1145,37 @@ struct task_struct {
#endif
};
+/*
+ * Priority of a process goes from 0..MAX_PRIO-1, valid RT
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
+ * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
+ * values are inverted: lower p->prio value means higher priority.
+ *
+ * The MAX_USER_RT_PRIO value allows the actual maximum
+ * RT priority to be separate from the value exported to
+ * user-space. This allows kernel threads to set their
+ * priority to a value higher than any user task. Note:
+ * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
+ */
+
+#define MAX_USER_RT_PRIO 100
+#define MAX_RT_PRIO MAX_USER_RT_PRIO
+
+#define MAX_PRIO (MAX_RT_PRIO + 40)
+#define DEFAULT_PRIO (MAX_RT_PRIO + 20)
+
+static inline int rt_prio(int prio)
+{
+ if (unlikely(prio < MAX_RT_PRIO))
+ return 1;
+ return 0;
+}
+
+static inline int rt_task(struct task_struct *p)
+{
+ return rt_prio(p->prio);
+}
+
static inline pid_t process_group(struct task_struct *tsk)
{
return tsk->signal->pgrp;
@@ -1223,7 +1321,7 @@ static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
extern unsigned long long sched_clock(void);
extern unsigned long long
-current_sched_time(const struct task_struct *current_task);
+task_sched_runtime(struct task_struct *task);
/* sched_exec is called by processes performing an exec */
#ifdef CONFIG_SMP
@@ -1232,6 +1330,8 @@ extern void sched_exec(void);
#define sched_exec() {}
#endif
+extern void sched_clock_unstable_event(void);
+
#ifdef CONFIG_HOTPLUG_CPU
extern void idle_task_exit(void);
#else
@@ -1240,6 +1340,14 @@ static inline void idle_task_exit(void) {}
extern void sched_idle_next(void);
+extern unsigned int sysctl_sched_granularity;
+extern unsigned int sysctl_sched_wakeup_granularity;
+extern unsigned int sysctl_sched_batch_wakeup_granularity;
+extern unsigned int sysctl_sched_stat_granularity;
+extern unsigned int sysctl_sched_runtime_limit;
+extern unsigned int sysctl_sched_child_runs_first;
+extern unsigned int sysctl_sched_features;
+
#ifdef CONFIG_RT_MUTEXES
extern int rt_mutex_getprio(struct task_struct *p);
extern void rt_mutex_setprio(struct task_struct *p, int prio);
@@ -1317,8 +1425,8 @@ extern void FASTCALL(wake_up_new_task(struct task_struct * tsk,
#else
static inline void kick_process(struct task_struct *tsk) { }
#endif
-extern void FASTCALL(sched_fork(struct task_struct * p, int clone_flags));
-extern void FASTCALL(sched_exit(struct task_struct * p));
+extern void sched_fork(struct task_struct *p, int clone_flags);
+extern void sched_dead(struct task_struct *p);
extern int in_group_p(gid_t);
extern int in_egroup_p(gid_t);
@@ -1406,7 +1514,7 @@ extern struct mm_struct * mm_alloc(void);
extern void FASTCALL(__mmdrop(struct mm_struct *));
static inline void mmdrop(struct mm_struct * mm)
{
- if (atomic_dec_and_test(&mm->mm_count))
+ if (unlikely(atomic_dec_and_test(&mm->mm_count)))
__mmdrop(mm);
}
@@ -1638,10 +1746,7 @@ static inline unsigned int task_cpu(const struct task_struct *p)
return task_thread_info(p)->cpu;
}
-static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
-{
- task_thread_info(p)->cpu = cpu;
-}
+extern void set_task_cpu(struct task_struct *p, unsigned int cpu);
#else
diff --git a/include/linux/splice.h b/include/linux/splice.h
new file mode 100644
index 000000000000..33e447f98a54
--- /dev/null
+++ b/include/linux/splice.h
@@ -0,0 +1,73 @@
+/*
+ * Function declerations and data structures related to the splice
+ * implementation.
+ *
+ * Copyright (C) 2007 Jens Axboe <jens.axboe@oracle.com>
+ *
+ */
+#ifndef SPLICE_H
+#define SPLICE_H
+
+#include <linux/pipe_fs_i.h>
+
+/*
+ * splice is tied to pipes as a transport (at least for now), so we'll just
+ * add the splice flags here.
+ */
+#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */
+#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
+ /* we may still block on the fd we splice */
+ /* from/to, of course */
+#define SPLICE_F_MORE (0x04) /* expect more data */
+#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */
+
+/*
+ * Passed to the actors
+ */
+struct splice_desc {
+ unsigned int len, total_len; /* current and remaining length */
+ unsigned int flags; /* splice flags */
+ /*
+ * actor() private data
+ */
+ union {
+ void __user *userptr; /* memory to write to */
+ struct file *file; /* file to read/write */
+ void *data; /* cookie */
+ } u;
+ loff_t pos; /* file position */
+};
+
+struct partial_page {
+ unsigned int offset;
+ unsigned int len;
+ unsigned long private;
+};
+
+/*
+ * Passed to splice_to_pipe
+ */
+struct splice_pipe_desc {
+ struct page **pages; /* page map */
+ struct partial_page *partial; /* pages[] may not be contig */
+ int nr_pages; /* number of pages in map */
+ unsigned int flags; /* splice flags */
+ const struct pipe_buf_operations *ops;/* ops associated with output pipe */
+};
+
+typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
+ struct splice_desc *);
+typedef int (splice_direct_actor)(struct pipe_inode_info *,
+ struct splice_desc *);
+
+extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
+ loff_t *, size_t, unsigned int,
+ splice_actor *);
+extern ssize_t __splice_from_pipe(struct pipe_inode_info *,
+ struct splice_desc *, splice_actor *);
+extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ struct splice_pipe_desc *);
+extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+ splice_direct_actor *);
+
+#endif
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 4a7ae8ab6eb8..129d50f2225c 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -253,7 +253,7 @@ struct svc_rqst {
* determine what device number
* to report (real or virtual)
*/
- int rq_sendfile_ok; /* turned off in gss privacy
+ int rq_splice_ok; /* turned off in gss privacy
* to prevent encrypting page
* cache pages */
wait_queue_head_t rq_wait; /* synchronization */
diff --git a/include/linux/topology.h b/include/linux/topology.h
index a9d1f049cc15..da6c39b2d051 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -98,7 +98,7 @@
.cache_nice_tries = 0, \
.busy_idx = 0, \
.idle_idx = 0, \
- .newidle_idx = 1, \
+ .newidle_idx = 0, \
.wake_idx = 0, \
.forkexec_idx = 0, \
.flags = SD_LOAD_BALANCE \
@@ -128,14 +128,15 @@
.imbalance_pct = 125, \
.cache_nice_tries = 1, \
.busy_idx = 2, \
- .idle_idx = 1, \
- .newidle_idx = 2, \
+ .idle_idx = 0, \
+ .newidle_idx = 0, \
.wake_idx = 1, \
.forkexec_idx = 1, \
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_NEWIDLE \
| SD_BALANCE_EXEC \
| SD_WAKE_AFFINE \
+ | SD_WAKE_IDLE \
| SD_SHARE_PKG_RESOURCES\
| BALANCE_FOR_MC_POWER, \
.last_balance = jiffies, \
@@ -158,14 +159,15 @@
.imbalance_pct = 125, \
.cache_nice_tries = 1, \
.busy_idx = 2, \
- .idle_idx = 1, \
- .newidle_idx = 2, \
+ .idle_idx = 0, \
+ .newidle_idx = 0, \
.wake_idx = 1, \
.forkexec_idx = 1, \
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_NEWIDLE \
| SD_BALANCE_EXEC \
| SD_WAKE_AFFINE \
+ | SD_WAKE_IDLE \
| BALANCE_FOR_PKG_POWER,\
.last_balance = jiffies, \
.balance_interval = 1, \
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 94bd38a6d947..56aa2ee21f1b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -729,6 +729,22 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
.bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
/**
+ * USB_DEVICE_INTERFACE_PROTOCOL - macro used to describe a usb
+ * device with a specific interface protocol
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific interface protocol of devices.
+ */
+#define USB_DEVICE_INTERFACE_PROTOCOL(vend,prod,pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+ .idVendor = (vend), \
+ .idProduct = (prod), \
+ .bInterfaceProtocol = (pr)
+
+/**
* USB_DEVICE_INFO - macro used to describe a class of usb devices
* @cl: bDeviceClass value
* @sc: bDeviceSubClass value
diff --git a/include/linux/wait.h b/include/linux/wait.h
index e820d00e1383..0e686280450b 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -366,15 +366,15 @@ static inline void remove_wait_queue_locked(wait_queue_head_t *q,
/*
* These are the old interfaces to sleep waiting for an event.
- * They are racy. DO NOT use them, use the wait_event* interfaces above.
- * We plan to remove these interfaces during 2.7.
+ * They are racy. DO NOT use them, use the wait_event* interfaces above.
+ * We plan to remove these interfaces.
*/
-extern void FASTCALL(sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
- signed long timeout));
-extern void FASTCALL(interruptible_sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t *q,
- signed long timeout));
+extern void sleep_on(wait_queue_head_t *q);
+extern long sleep_on_timeout(wait_queue_head_t *q,
+ signed long timeout);
+extern void interruptible_sleep_on(wait_queue_head_t *q);
+extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,
+ signed long timeout);
/*
* Waitqueues which are removed from the waitqueue_head at wakeup time
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index eae7e2e84497..ad6e278ba7f2 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -126,4 +126,6 @@
#define MANFID_POSSIO 0x030c
#define PRODID_POSSIO_GCC 0x0003
+#define MANFID_NEC 0x0010
+
#endif /* _LINUX_CISCODE_H */
diff --git a/init/Kconfig b/init/Kconfig
index a9e99f8328ff..d9d878a3bb46 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -686,6 +686,4 @@ config STOP_MACHINE
Need stop_machine() primitive.
endmenu
-menu "Block layer"
source "block/Kconfig"
-endmenu
diff --git a/init/main.c b/init/main.c
index eb8bdbae4fc7..0eb1c7463fe4 100644
--- a/init/main.c
+++ b/init/main.c
@@ -436,15 +436,16 @@ static void noinline __init_refok rest_init(void)
/*
* The boot idle thread must execute schedule()
- * at least one to get things moving:
+ * at least once to get things moving:
*/
+ init_idle_bootup_task(current);
preempt_enable_no_resched();
schedule();
preempt_disable();
/* Call into cpu_idle with preempt disabled */
cpu_idle();
-}
+}
/* Check for early params. */
static int __init do_early_param(char *param, char *val)
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index c0148ae992c4..81e697829633 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -99,9 +99,10 @@ void __delayacct_blkio_end(void)
int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
{
s64 tmp;
- struct timespec ts;
- unsigned long t1,t2,t3;
+ unsigned long t1;
+ unsigned long long t2, t3;
unsigned long flags;
+ struct timespec ts;
/* Though tsk->delays accessed later, early exit avoids
* unnecessary returning of other data
@@ -124,11 +125,10 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
d->cpu_count += t1;
- jiffies_to_timespec(t2, &ts);
- tmp = (s64)d->cpu_delay_total + timespec_to_ns(&ts);
+ tmp = (s64)d->cpu_delay_total + t2;
d->cpu_delay_total = (tmp < (s64)d->cpu_delay_total) ? 0 : tmp;
- tmp = (s64)d->cpu_run_virtual_total + (s64)jiffies_to_usecs(t3) * 1000;
+ tmp = (s64)d->cpu_run_virtual_total + t3;
d->cpu_run_virtual_total =
(tmp < (s64)d->cpu_run_virtual_total) ? 0 : tmp;
diff --git a/kernel/exit.c b/kernel/exit.c
index 5c8ecbaa19a5..ca6a11b73023 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -122,9 +122,9 @@ static void __exit_signal(struct task_struct *tsk)
sig->maj_flt += tsk->maj_flt;
sig->nvcsw += tsk->nvcsw;
sig->nivcsw += tsk->nivcsw;
- sig->sched_time += tsk->sched_time;
sig->inblock += task_io_get_inblock(tsk);
sig->oublock += task_io_get_oublock(tsk);
+ sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
sig = NULL; /* Marker for below. */
}
@@ -182,7 +182,6 @@ repeat:
zap_leader = (leader->exit_signal == -1);
}
- sched_exit(p);
write_unlock_irq(&tasklist_lock);
proc_flush_task(p);
release_thread(p);
@@ -291,7 +290,7 @@ static void reparent_to_kthreadd(void)
/* Set the exit signal to SIGCHLD so we signal init on exit */
current->exit_signal = SIGCHLD;
- if (!has_rt_policy(current) && (task_nice(current) < 0))
+ if (task_nice(current) < 0)
set_user_nice(current, 0);
/* cpus_allowed? */
/* rt_priority? */
diff --git a/kernel/fork.c b/kernel/fork.c
index 73ad5cda1bcd..da3a155bba0d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -877,7 +877,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
- sig->sched_time = 0;
+ sig->sum_sched_runtime = 0;
INIT_LIST_HEAD(&sig->cpu_timers[0]);
INIT_LIST_HEAD(&sig->cpu_timers[1]);
INIT_LIST_HEAD(&sig->cpu_timers[2]);
@@ -1040,7 +1040,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->utime = cputime_zero;
p->stime = cputime_zero;
- p->sched_time = 0;
+
#ifdef CONFIG_TASK_XACCT
p->rchar = 0; /* I/O counter: bytes read */
p->wchar = 0; /* I/O counter: bytes written */
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 1de710e18373..b53c8fcd9d82 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -161,7 +161,7 @@ static inline cputime_t virt_ticks(struct task_struct *p)
}
static inline unsigned long long sched_ns(struct task_struct *p)
{
- return (p == current) ? current_sched_time(p) : p->sched_time;
+ return task_sched_runtime(p);
}
int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
@@ -246,10 +246,10 @@ static int cpu_clock_sample_group_locked(unsigned int clock_idx,
} while (t != p);
break;
case CPUCLOCK_SCHED:
- cpu->sched = p->signal->sched_time;
+ cpu->sched = p->signal->sum_sched_runtime;
/* Add in each other live thread. */
while ((t = next_thread(t)) != p) {
- cpu->sched += t->sched_time;
+ cpu->sched += t->se.sum_exec_runtime;
}
cpu->sched += sched_ns(p);
break;
@@ -422,7 +422,7 @@ int posix_cpu_timer_del(struct k_itimer *timer)
*/
static void cleanup_timers(struct list_head *head,
cputime_t utime, cputime_t stime,
- unsigned long long sched_time)
+ unsigned long long sum_exec_runtime)
{
struct cpu_timer_list *timer, *next;
cputime_t ptime = cputime_add(utime, stime);
@@ -451,10 +451,10 @@ static void cleanup_timers(struct list_head *head,
++head;
list_for_each_entry_safe(timer, next, head, entry) {
list_del_init(&timer->entry);
- if (timer->expires.sched < sched_time) {
+ if (timer->expires.sched < sum_exec_runtime) {
timer->expires.sched = 0;
} else {
- timer->expires.sched -= sched_time;
+ timer->expires.sched -= sum_exec_runtime;
}
}
}
@@ -467,7 +467,7 @@ static void cleanup_timers(struct list_head *head,
void posix_cpu_timers_exit(struct task_struct *tsk)
{
cleanup_timers(tsk->cpu_timers,
- tsk->utime, tsk->stime, tsk->sched_time);
+ tsk->utime, tsk->stime, tsk->se.sum_exec_runtime);
}
void posix_cpu_timers_exit_group(struct task_struct *tsk)
@@ -475,7 +475,7 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
cleanup_timers(tsk->signal->cpu_timers,
cputime_add(tsk->utime, tsk->signal->utime),
cputime_add(tsk->stime, tsk->signal->stime),
- tsk->sched_time + tsk->signal->sched_time);
+ tsk->se.sum_exec_runtime + tsk->signal->sum_sched_runtime);
}
@@ -536,7 +536,7 @@ static void process_timer_rebalance(struct task_struct *p,
nsleft = max_t(unsigned long long, nsleft, 1);
do {
if (likely(!(t->flags & PF_EXITING))) {
- ns = t->sched_time + nsleft;
+ ns = t->se.sum_exec_runtime + nsleft;
if (t->it_sched_expires == 0 ||
t->it_sched_expires > ns) {
t->it_sched_expires = ns;
@@ -1004,7 +1004,7 @@ static void check_thread_timers(struct task_struct *tsk,
struct cpu_timer_list *t = list_first_entry(timers,
struct cpu_timer_list,
entry);
- if (!--maxfire || tsk->sched_time < t->expires.sched) {
+ if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) {
tsk->it_sched_expires = t->expires.sched;
break;
}
@@ -1024,7 +1024,7 @@ static void check_process_timers(struct task_struct *tsk,
int maxfire;
struct signal_struct *const sig = tsk->signal;
cputime_t utime, stime, ptime, virt_expires, prof_expires;
- unsigned long long sched_time, sched_expires;
+ unsigned long long sum_sched_runtime, sched_expires;
struct task_struct *t;
struct list_head *timers = sig->cpu_timers;
@@ -1044,12 +1044,12 @@ static void check_process_timers(struct task_struct *tsk,
*/
utime = sig->utime;
stime = sig->stime;
- sched_time = sig->sched_time;
+ sum_sched_runtime = sig->sum_sched_runtime;
t = tsk;
do {
utime = cputime_add(utime, t->utime);
stime = cputime_add(stime, t->stime);
- sched_time += t->sched_time;
+ sum_sched_runtime += t->se.sum_exec_runtime;
t = next_thread(t);
} while (t != tsk);
ptime = cputime_add(utime, stime);
@@ -1090,7 +1090,7 @@ static void check_process_timers(struct task_struct *tsk,
struct cpu_timer_list *t = list_first_entry(timers,
struct cpu_timer_list,
entry);
- if (!--maxfire || sched_time < t->expires.sched) {
+ if (!--maxfire || sum_sched_runtime < t->expires.sched) {
sched_expires = t->expires.sched;
break;
}
@@ -1182,7 +1182,7 @@ static void check_process_timers(struct task_struct *tsk,
virt_left = cputime_sub(virt_expires, utime);
virt_left = cputime_div_non_zero(virt_left, nthreads);
if (sched_expires) {
- sched_left = sched_expires - sched_time;
+ sched_left = sched_expires - sum_sched_runtime;
do_div(sched_left, nthreads);
sched_left = max_t(unsigned long long, sched_left, 1);
} else {
@@ -1208,7 +1208,7 @@ static void check_process_timers(struct task_struct *tsk,
t->it_virt_expires = ticks;
}
- sched = t->sched_time + sched_left;
+ sched = t->se.sum_exec_runtime + sched_left;
if (sched_expires && (t->it_sched_expires == 0 ||
t->it_sched_expires > sched)) {
t->it_sched_expires = sched;
@@ -1300,7 +1300,7 @@ void run_posix_cpu_timers(struct task_struct *tsk)
if (UNEXPIRED(prof) && UNEXPIRED(virt) &&
(tsk->it_sched_expires == 0 ||
- tsk->sched_time < tsk->it_sched_expires))
+ tsk->se.sum_exec_runtime < tsk->it_sched_expires))
return;
#undef UNEXPIRED
diff --git a/kernel/relay.c b/kernel/relay.c
index 95db8c79fe8f..3b299fb3855c 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -21,6 +21,7 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/cpu.h>
+#include <linux/splice.h>
/* list of open channels, for cpu hotplug */
static DEFINE_MUTEX(relay_channels_mutex);
@@ -121,6 +122,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)
buf->page_array[i] = alloc_page(GFP_KERNEL);
if (unlikely(!buf->page_array[i]))
goto depopulate;
+ set_page_private(buf->page_array[i], (unsigned long)buf);
}
mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL);
if (!mem)
@@ -970,43 +972,6 @@ static int subbuf_read_actor(size_t read_start,
return ret;
}
-/*
- * subbuf_send_actor - send up to one subbuf's worth of data
- */
-static int subbuf_send_actor(size_t read_start,
- struct rchan_buf *buf,
- size_t avail,
- read_descriptor_t *desc,
- read_actor_t actor)
-{
- unsigned long pidx, poff;
- unsigned int subbuf_pages;
- int ret = 0;
-
- subbuf_pages = buf->chan->alloc_size >> PAGE_SHIFT;
- pidx = (read_start / PAGE_SIZE) % subbuf_pages;
- poff = read_start & ~PAGE_MASK;
- while (avail) {
- struct page *p = buf->page_array[pidx];
- unsigned int len;
-
- len = PAGE_SIZE - poff;
- if (len > avail)
- len = avail;
-
- len = actor(desc, p, poff, len);
- if (desc->error)
- break;
-
- avail -= len;
- ret += len;
- poff = 0;
- pidx = (pidx + 1) % subbuf_pages;
- }
-
- return ret;
-}
-
typedef int (*subbuf_actor_t) (size_t read_start,
struct rchan_buf *buf,
size_t avail,
@@ -1067,19 +1032,159 @@ static ssize_t relay_file_read(struct file *filp,
NULL, &desc);
}
-static ssize_t relay_file_sendfile(struct file *filp,
- loff_t *ppos,
- size_t count,
- read_actor_t actor,
- void *target)
+static void relay_consume_bytes(struct rchan_buf *rbuf, int bytes_consumed)
{
- read_descriptor_t desc;
- desc.written = 0;
- desc.count = count;
- desc.arg.data = target;
- desc.error = 0;
- return relay_file_read_subbufs(filp, ppos, subbuf_send_actor,
- actor, &desc);
+ rbuf->bytes_consumed += bytes_consumed;
+
+ if (rbuf->bytes_consumed >= rbuf->chan->subbuf_size) {
+ relay_subbufs_consumed(rbuf->chan, rbuf->cpu, 1);
+ rbuf->bytes_consumed %= rbuf->chan->subbuf_size;
+ }
+}
+
+static void relay_pipe_buf_release(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ struct rchan_buf *rbuf;
+
+ rbuf = (struct rchan_buf *)page_private(buf->page);
+ relay_consume_bytes(rbuf, buf->private);
+}
+
+static struct pipe_buf_operations relay_pipe_buf_ops = {
+ .can_merge = 0,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .confirm = generic_pipe_buf_confirm,
+ .release = relay_pipe_buf_release,
+ .steal = generic_pipe_buf_steal,
+ .get = generic_pipe_buf_get,
+};
+
+/**
+ * subbuf_splice_actor - splice up to one subbuf's worth of data
+ */
+static int subbuf_splice_actor(struct file *in,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags,
+ int *nonpad_ret)
+{
+ unsigned int pidx, poff, total_len, subbuf_pages, ret;
+ struct rchan_buf *rbuf = in->private_data;
+ unsigned int subbuf_size = rbuf->chan->subbuf_size;
+ size_t read_start = ((size_t)*ppos) % rbuf->chan->alloc_size;
+ size_t read_subbuf = read_start / subbuf_size;
+ size_t padding = rbuf->padding[read_subbuf];
+ size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding;
+ struct page *pages[PIPE_BUFFERS];
+ struct partial_page partial[PIPE_BUFFERS];
+ struct splice_pipe_desc spd = {
+ .pages = pages,
+ .nr_pages = 0,
+ .partial = partial,
+ .flags = flags,
+ .ops = &relay_pipe_buf_ops,
+ };
+
+ if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
+ return 0;
+
+ /*
+ * Adjust read len, if longer than what is available
+ */
+ if (len > (subbuf_size - read_start % subbuf_size))
+ len = subbuf_size - read_start % subbuf_size;
+
+ subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT;
+ pidx = (read_start / PAGE_SIZE) % subbuf_pages;
+ poff = read_start & ~PAGE_MASK;
+
+ for (total_len = 0; spd.nr_pages < subbuf_pages; spd.nr_pages++) {
+ unsigned int this_len, this_end, private;
+ unsigned int cur_pos = read_start + total_len;
+
+ if (!len)
+ break;
+
+ this_len = min_t(unsigned long, len, PAGE_SIZE - poff);
+ private = this_len;
+
+ spd.pages[spd.nr_pages] = rbuf->page_array[pidx];
+ spd.partial[spd.nr_pages].offset = poff;
+
+ this_end = cur_pos + this_len;
+ if (this_end >= nonpad_end) {
+ this_len = nonpad_end - cur_pos;
+ private = this_len + padding;
+ }
+ spd.partial[spd.nr_pages].len = this_len;
+ spd.partial[spd.nr_pages].private = private;
+
+ len -= this_len;
+ total_len += this_len;
+ poff = 0;
+ pidx = (pidx + 1) % subbuf_pages;
+
+ if (this_end >= nonpad_end) {
+ spd.nr_pages++;
+ break;
+ }
+ }
+
+ if (!spd.nr_pages)
+ return 0;
+
+ ret = *nonpad_ret = splice_to_pipe(pipe, &spd);
+ if (ret < 0 || ret < total_len)
+ return ret;
+
+ if (read_start + ret == nonpad_end)
+ ret += padding;
+
+ return ret;
+}
+
+static ssize_t relay_file_splice_read(struct file *in,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags)
+{
+ ssize_t spliced;
+ int ret;
+ int nonpad_ret = 0;
+
+ ret = 0;
+ spliced = 0;
+
+ while (len) {
+ ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret);
+ if (ret < 0)
+ break;
+ else if (!ret) {
+ if (spliced)
+ break;
+ if (flags & SPLICE_F_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ }
+
+ *ppos += ret;
+ if (ret > len)
+ len = 0;
+ else
+ len -= ret;
+ spliced += nonpad_ret;
+ nonpad_ret = 0;
+ }
+
+ if (spliced)
+ return spliced;
+
+ return ret;
}
const struct file_operations relay_file_operations = {
@@ -1089,7 +1194,7 @@ const struct file_operations relay_file_operations = {
.read = relay_file_read,
.llseek = no_llseek,
.release = relay_file_release,
- .sendfile = relay_file_sendfile,
+ .splice_read = relay_file_splice_read,
};
EXPORT_SYMBOL_GPL(relay_file_operations);
diff --git a/kernel/sched.c b/kernel/sched.c
index 50e1a3122699..9fbced64bfee 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -16,13 +16,19 @@
* by Davide Libenzi, preemptible kernel bits by Robert Love.
* 2003-09-03 Interactivity tuning by Con Kolivas.
* 2004-04-02 Scheduler domains code by Nick Piggin
+ * 2007-04-15 Work begun on replacing all interactivity tuning with a
+ * fair scheduling design by Con Kolivas.
+ * 2007-05-05 Load balancing (smp-nice) and other improvements
+ * by Peter Williams
+ * 2007-05-06 Interactivity improvements to CFS by Mike Galbraith
+ * 2007-07-01 Group scheduling enhancements by Srivatsa Vaddagiri
*/
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/nmi.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/highmem.h>
#include <linux/smp_lock.h>
#include <asm/mmu_context.h>
@@ -53,9 +59,9 @@
#include <linux/kprobes.h>
#include <linux/delayacct.h>
#include <linux/reciprocal_div.h>
+#include <linux/unistd.h>
#include <asm/tlb.h>
-#include <asm/unistd.h>
/*
* Scheduler clock - returns current time in nanosec units.
@@ -91,6 +97,9 @@ unsigned long long __attribute__((weak)) sched_clock(void)
#define NS_TO_JIFFIES(TIME) ((TIME) / (1000000000 / HZ))
#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ))
+#define NICE_0_LOAD SCHED_LOAD_SCALE
+#define NICE_0_SHIFT SCHED_LOAD_SHIFT
+
/*
* These are the 'tuning knobs' of the scheduler:
*
@@ -100,87 +109,6 @@ unsigned long long __attribute__((weak)) sched_clock(void)
*/
#define MIN_TIMESLICE max(5 * HZ / 1000, 1)
#define DEF_TIMESLICE (100 * HZ / 1000)
-#define ON_RUNQUEUE_WEIGHT 30
-#define CHILD_PENALTY 95
-#define PARENT_PENALTY 100
-#define EXIT_WEIGHT 3
-#define PRIO_BONUS_RATIO 25
-#define MAX_BONUS (MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
-#define INTERACTIVE_DELTA 2
-#define MAX_SLEEP_AVG (DEF_TIMESLICE * MAX_BONUS)
-#define STARVATION_LIMIT (MAX_SLEEP_AVG)
-#define NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(MAX_SLEEP_AVG))
-
-/*
- * If a task is 'interactive' then we reinsert it in the active
- * array after it has expired its current timeslice. (it will not
- * continue to run immediately, it will still roundrobin with
- * other interactive tasks.)
- *
- * This part scales the interactivity limit depending on niceness.
- *
- * We scale it linearly, offset by the INTERACTIVE_DELTA delta.
- * Here are a few examples of different nice levels:
- *
- * TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0]
- * TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0]
- * TASK_INTERACTIVE( 0): [1,1,1,1,0,0,0,0,0,0,0]
- * TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0]
- * TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0]
- *
- * (the X axis represents the possible -5 ... 0 ... +5 dynamic
- * priority range a task can explore, a value of '1' means the
- * task is rated interactive.)
- *
- * Ie. nice +19 tasks can never get 'interactive' enough to be
- * reinserted into the active array. And only heavily CPU-hog nice -20
- * tasks will be expired. Default nice 0 tasks are somewhere between,
- * it takes some effort for them to get interactive, but it's not
- * too hard.
- */
-
-#define CURRENT_BONUS(p) \
- (NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
- MAX_SLEEP_AVG)
-
-#define GRANULARITY (10 * HZ / 1000 ? : 1)
-
-#ifdef CONFIG_SMP
-#define TIMESLICE_GRANULARITY(p) (GRANULARITY * \
- (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \
- num_online_cpus())
-#else
-#define TIMESLICE_GRANULARITY(p) (GRANULARITY * \
- (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)))
-#endif
-
-#define SCALE(v1,v1_max,v2_max) \
- (v1) * (v2_max) / (v1_max)
-
-#define DELTA(p) \
- (SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
- INTERACTIVE_DELTA)
-
-#define TASK_INTERACTIVE(p) \
- ((p)->prio <= (p)->static_prio - DELTA(p))
-
-#define INTERACTIVE_SLEEP(p) \
- (JIFFIES_TO_NS(MAX_SLEEP_AVG * \
- (MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1))
-
-#define TASK_PREEMPTS_CURR(p, rq) \
- ((p)->prio < (rq)->curr->prio)
-
-#define SCALE_PRIO(x, prio) \
- max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
-
-static unsigned int static_prio_timeslice(int static_prio)
-{
- if (static_prio < NICE_TO_PRIO(0))
- return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
- else
- return SCALE_PRIO(DEF_TIMESLICE, static_prio);
-}
#ifdef CONFIG_SMP
/*
@@ -203,28 +131,87 @@ static inline void sg_inc_cpu_power(struct sched_group *sg, u32 val)
}
#endif
+#define SCALE_PRIO(x, prio) \
+ max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
+
/*
- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
+ * static_prio_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
* to time slice values: [800ms ... 100ms ... 5ms]
- *
- * The higher a thread's priority, the bigger timeslices
- * it gets during one round of execution. But even the lowest
- * priority thread gets MIN_TIMESLICE worth of execution time.
*/
+static unsigned int static_prio_timeslice(int static_prio)
+{
+ if (static_prio == NICE_TO_PRIO(19))
+ return 1;
+
+ if (static_prio < NICE_TO_PRIO(0))
+ return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
+ else
+ return SCALE_PRIO(DEF_TIMESLICE, static_prio);
+}
+
+static inline int rt_policy(int policy)
+{
+ if (unlikely(policy == SCHED_FIFO) || unlikely(policy == SCHED_RR))
+ return 1;
+ return 0;
+}
-static inline unsigned int task_timeslice(struct task_struct *p)
+static inline int task_has_rt_policy(struct task_struct *p)
{
- return static_prio_timeslice(p->static_prio);
+ return rt_policy(p->policy);
}
/*
- * These are the runqueue data structures:
+ * This is the priority-queue data structure of the RT scheduling class:
*/
+struct rt_prio_array {
+ DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */
+ struct list_head queue[MAX_RT_PRIO];
+};
+
+struct load_stat {
+ struct load_weight load;
+ u64 load_update_start, load_update_last;
+ unsigned long delta_fair, delta_exec, delta_stat;
+};
+
+/* CFS-related fields in a runqueue */
+struct cfs_rq {
+ struct load_weight load;
+ unsigned long nr_running;
+
+ s64 fair_clock;
+ u64 exec_clock;
+ s64 wait_runtime;
+ u64 sleeper_bonus;
+ unsigned long wait_runtime_overruns, wait_runtime_underruns;
+
+ struct rb_root tasks_timeline;
+ struct rb_node *rb_leftmost;
+ struct rb_node *rb_load_balance_curr;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ /* 'curr' points to currently running entity on this cfs_rq.
+ * It is set to NULL otherwise (i.e when none are currently running).
+ */
+ struct sched_entity *curr;
+ struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */
-struct prio_array {
- unsigned int nr_active;
- DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
- struct list_head queue[MAX_PRIO];
+ /* leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
+ * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
+ * (like users, containers etc.)
+ *
+ * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
+ * list is used during load balance.
+ */
+ struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */
+#endif
+};
+
+/* Real-Time classes' related field in a runqueue: */
+struct rt_rq {
+ struct rt_prio_array active;
+ int rt_load_balance_idx;
+ struct list_head *rt_load_balance_head, *rt_load_balance_curr;
};
/*
@@ -235,22 +222,28 @@ struct prio_array {
* acquire operations must be ordered by ascending &runqueue.
*/
struct rq {
- spinlock_t lock;
+ spinlock_t lock; /* runqueue lock */
/*
* nr_running and cpu_load should be in the same cacheline because
* remote CPUs use both these fields when doing load calculation.
*/
unsigned long nr_running;
- unsigned long raw_weighted_load;
-#ifdef CONFIG_SMP
- unsigned long cpu_load[3];
+ #define CPU_LOAD_IDX_MAX 5
+ unsigned long cpu_load[CPU_LOAD_IDX_MAX];
unsigned char idle_at_tick;
#ifdef CONFIG_NO_HZ
unsigned char in_nohz_recently;
#endif
+ struct load_stat ls; /* capture load from *all* tasks on this cpu */
+ unsigned long nr_load_updates;
+ u64 nr_switches;
+
+ struct cfs_rq cfs;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ struct list_head leaf_cfs_rq_list; /* list of leaf cfs_rq on this cpu */
#endif
- unsigned long long nr_switches;
+ struct rt_rq rt;
/*
* This is part of a global counter where only the total sum
@@ -260,14 +253,18 @@ struct rq {
*/
unsigned long nr_uninterruptible;
- unsigned long expired_timestamp;
- /* Cached timestamp set by update_cpu_clock() */
- unsigned long long most_recent_timestamp;
struct task_struct *curr, *idle;
unsigned long next_balance;
struct mm_struct *prev_mm;
- struct prio_array *active, *expired, arrays[2];
- int best_expired_prio;
+
+ u64 clock, prev_clock_raw;
+ s64 clock_max_delta;
+
+ unsigned int clock_warps, clock_overflows;
+ unsigned int clock_unstable_events;
+
+ struct sched_class *load_balance_class;
+
atomic_t nr_iowait;
#ifdef CONFIG_SMP
@@ -307,6 +304,11 @@ struct rq {
static DEFINE_PER_CPU(struct rq, runqueues) ____cacheline_aligned_in_smp;
static DEFINE_MUTEX(sched_hotcpu_mutex);
+static inline void check_preempt_curr(struct rq *rq, struct task_struct *p)
+{
+ rq->curr->sched_class->check_preempt_curr(rq, p);
+}
+
static inline int cpu_of(struct rq *rq)
{
#ifdef CONFIG_SMP
@@ -317,6 +319,52 @@ static inline int cpu_of(struct rq *rq)
}
/*
+ * Per-runqueue clock, as finegrained as the platform can give us:
+ */
+static unsigned long long __rq_clock(struct rq *rq)
+{
+ u64 prev_raw = rq->prev_clock_raw;
+ u64 now = sched_clock();
+ s64 delta = now - prev_raw;
+ u64 clock = rq->clock;
+
+ /*
+ * Protect against sched_clock() occasionally going backwards:
+ */
+ if (unlikely(delta < 0)) {
+ clock++;
+ rq->clock_warps++;
+ } else {
+ /*
+ * Catch too large forward jumps too:
+ */
+ if (unlikely(delta > 2*TICK_NSEC)) {
+ clock++;
+ rq->clock_overflows++;
+ } else {
+ if (unlikely(delta > rq->clock_max_delta))
+ rq->clock_max_delta = delta;
+ clock += delta;
+ }
+ }
+
+ rq->prev_clock_raw = now;
+ rq->clock = clock;
+
+ return clock;
+}
+
+static inline unsigned long long rq_clock(struct rq *rq)
+{
+ int this_cpu = smp_processor_id();
+
+ if (this_cpu == cpu_of(rq))
+ return __rq_clock(rq);
+
+ return rq->clock;
+}
+
+/*
* The domain tree (rq->sd) is protected by RCU's quiescent state transition.
* See detach_destroy_domains: synchronize_sched for details.
*
@@ -331,6 +379,18 @@ static inline int cpu_of(struct rq *rq)
#define task_rq(p) cpu_rq(task_cpu(p))
#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/* Change a task's ->cfs_rq if it moves across CPUs */
+static inline void set_task_cfs_rq(struct task_struct *p)
+{
+ p->se.cfs_rq = &task_rq(p)->cfs;
+}
+#else
+static inline void set_task_cfs_rq(struct task_struct *p)
+{
+}
+#endif
+
#ifndef prepare_arch_switch
# define prepare_arch_switch(next) do { } while (0)
#endif
@@ -460,134 +520,6 @@ static inline void task_rq_unlock(struct rq *rq, unsigned long *flags)
spin_unlock_irqrestore(&rq->lock, *flags);
}
-#ifdef CONFIG_SCHEDSTATS
-/*
- * bump this up when changing the output format or the meaning of an existing
- * format, so that tools can adapt (or abort)
- */
-#define SCHEDSTAT_VERSION 14
-
-static int show_schedstat(struct seq_file *seq, void *v)
-{
- int cpu;
-
- seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
- seq_printf(seq, "timestamp %lu\n", jiffies);
- for_each_online_cpu(cpu) {
- struct rq *rq = cpu_rq(cpu);
-#ifdef CONFIG_SMP
- struct sched_domain *sd;
- int dcnt = 0;
-#endif
-
- /* runqueue-specific stats */
- seq_printf(seq,
- "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
- cpu, rq->yld_both_empty,
- rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
- rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
- rq->ttwu_cnt, rq->ttwu_local,
- rq->rq_sched_info.cpu_time,
- rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
-
- seq_printf(seq, "\n");
-
-#ifdef CONFIG_SMP
- /* domain-specific stats */
- preempt_disable();
- for_each_domain(cpu, sd) {
- enum idle_type itype;
- char mask_str[NR_CPUS];
-
- cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
- seq_printf(seq, "domain%d %s", dcnt++, mask_str);
- for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES;
- itype++) {
- seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
- "%lu",
- sd->lb_cnt[itype],
- sd->lb_balanced[itype],
- sd->lb_failed[itype],
- sd->lb_imbalance[itype],
- sd->lb_gained[itype],
- sd->lb_hot_gained[itype],
- sd->lb_nobusyq[itype],
- sd->lb_nobusyg[itype]);
- }
- seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
- " %lu %lu %lu\n",
- sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
- sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
- sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
- sd->ttwu_wake_remote, sd->ttwu_move_affine,
- sd->ttwu_move_balance);
- }
- preempt_enable();
-#endif
- }
- return 0;
-}
-
-static int schedstat_open(struct inode *inode, struct file *file)
-{
- unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
- char *buf = kmalloc(size, GFP_KERNEL);
- struct seq_file *m;
- int res;
-
- if (!buf)
- return -ENOMEM;
- res = single_open(file, show_schedstat, NULL);
- if (!res) {
- m = file->private_data;
- m->buf = buf;
- m->size = size;
- } else
- kfree(buf);
- return res;
-}
-
-const struct file_operations proc_schedstat_operations = {
- .open = schedstat_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/*
- * Expects runqueue lock to be held for atomicity of update
- */
-static inline void
-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
-{
- if (rq) {
- rq->rq_sched_info.run_delay += delta_jiffies;
- rq->rq_sched_info.pcnt++;
- }
-}
-
-/*
- * Expects runqueue lock to be held for atomicity of update
- */
-static inline void
-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
-{
- if (rq)
- rq->rq_sched_info.cpu_time += delta_jiffies;
-}
-# define schedstat_inc(rq, field) do { (rq)->field++; } while (0)
-# define schedstat_add(rq, field, amt) do { (rq)->field += (amt); } while (0)
-#else /* !CONFIG_SCHEDSTATS */
-static inline void
-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
-{}
-static inline void
-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
-{}
-# define schedstat_inc(rq, field) do { } while (0)
-# define schedstat_add(rq, field, amt) do { } while (0)
-#endif
-
/*
* this_rq_lock - lock this runqueue and disable interrupts.
*/
@@ -603,177 +535,172 @@ static inline struct rq *this_rq_lock(void)
return rq;
}
-#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
/*
- * Called when a process is dequeued from the active array and given
- * the cpu. We should note that with the exception of interactive
- * tasks, the expired queue will become the active queue after the active
- * queue is empty, without explicitly dequeuing and requeuing tasks in the
- * expired queue. (Interactive tasks may be requeued directly to the
- * active queue, thus delaying tasks in the expired queue from running;
- * see scheduler_tick()).
- *
- * This function is only called from sched_info_arrive(), rather than
- * dequeue_task(). Even though a task may be queued and dequeued multiple
- * times as it is shuffled about, we're really interested in knowing how
- * long it was from the *first* time it was queued to the time that it
- * finally hit a cpu.
+ * CPU frequency is/was unstable - start new by setting prev_clock_raw:
*/
-static inline void sched_info_dequeued(struct task_struct *t)
+void sched_clock_unstable_event(void)
{
- t->sched_info.last_queued = 0;
+ unsigned long flags;
+ struct rq *rq;
+
+ rq = task_rq_lock(current, &flags);
+ rq->prev_clock_raw = sched_clock();
+ rq->clock_unstable_events++;
+ task_rq_unlock(rq, &flags);
}
/*
- * Called when a task finally hits the cpu. We can now calculate how
- * long it was waiting to run. We also note when it began so that we
- * can keep stats on how long its timeslice is.
+ * resched_task - mark a task 'to be rescheduled now'.
+ *
+ * On UP this means the setting of the need_resched flag, on SMP it
+ * might also involve a cross-CPU call to trigger the scheduler on
+ * the target CPU.
*/
-static void sched_info_arrive(struct task_struct *t)
+#ifdef CONFIG_SMP
+
+#ifndef tsk_is_polling
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+#endif
+
+static void resched_task(struct task_struct *p)
{
- unsigned long now = jiffies, delta_jiffies = 0;
+ int cpu;
+
+ assert_spin_locked(&task_rq(p)->lock);
+
+ if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED)))
+ return;
- if (t->sched_info.last_queued)
- delta_jiffies = now - t->sched_info.last_queued;
- sched_info_dequeued(t);
- t->sched_info.run_delay += delta_jiffies;
- t->sched_info.last_arrival = now;
- t->sched_info.pcnt++;
+ set_tsk_thread_flag(p, TIF_NEED_RESCHED);
+
+ cpu = task_cpu(p);
+ if (cpu == smp_processor_id())
+ return;
- rq_sched_info_arrive(task_rq(t), delta_jiffies);
+ /* NEED_RESCHED must be visible before we test polling */
+ smp_mb();
+ if (!tsk_is_polling(p))
+ smp_send_reschedule(cpu);
}
-/*
- * Called when a process is queued into either the active or expired
- * array. The time is noted and later used to determine how long we
- * had to wait for us to reach the cpu. Since the expired queue will
- * become the active queue after active queue is empty, without dequeuing
- * and requeuing any tasks, we are interested in queuing to either. It
- * is unusual but not impossible for tasks to be dequeued and immediately
- * requeued in the same or another array: this can happen in sched_yield(),
- * set_user_nice(), and even load_balance() as it moves tasks from runqueue
- * to runqueue.
- *
- * This function is only called from enqueue_task(), but also only updates
- * the timestamp if it is already not set. It's assumed that
- * sched_info_dequeued() will clear that stamp when appropriate.
- */
-static inline void sched_info_queued(struct task_struct *t)
+static void resched_cpu(int cpu)
{
- if (unlikely(sched_info_on()))
- if (!t->sched_info.last_queued)
- t->sched_info.last_queued = jiffies;
+ struct rq *rq = cpu_rq(cpu);
+ unsigned long flags;
+
+ if (!spin_trylock_irqsave(&rq->lock, flags))
+ return;
+ resched_task(cpu_curr(cpu));
+ spin_unlock_irqrestore(&rq->lock, flags);
}
+#else
+static inline void resched_task(struct task_struct *p)
+{
+ assert_spin_locked(&task_rq(p)->lock);
+ set_tsk_need_resched(p);
+}
+#endif
-/*
- * Called when a process ceases being the active-running process, either
- * voluntarily or involuntarily. Now we can calculate how long we ran.
- */
-static inline void sched_info_depart(struct task_struct *t)
+static u64 div64_likely32(u64 divident, unsigned long divisor)
{
- unsigned long delta_jiffies = jiffies - t->sched_info.last_arrival;
+#if BITS_PER_LONG == 32
+ if (likely(divident <= 0xffffffffULL))
+ return (u32)divident / divisor;
+ do_div(divident, divisor);
- t->sched_info.cpu_time += delta_jiffies;
- rq_sched_info_depart(task_rq(t), delta_jiffies);
+ return divident;
+#else
+ return divident / divisor;
+#endif
}
-/*
- * Called when tasks are switched involuntarily due, typically, to expiring
- * their time slice. (This may also be called when switching to or from
- * the idle task.) We are only called when prev != next.
- */
-static inline void
-__sched_info_switch(struct task_struct *prev, struct task_struct *next)
+#if BITS_PER_LONG == 32
+# define WMULT_CONST (~0UL)
+#else
+# define WMULT_CONST (1UL << 32)
+#endif
+
+#define WMULT_SHIFT 32
+
+static inline unsigned long
+calc_delta_mine(unsigned long delta_exec, unsigned long weight,
+ struct load_weight *lw)
{
- struct rq *rq = task_rq(prev);
+ u64 tmp;
+ if (unlikely(!lw->inv_weight))
+ lw->inv_weight = WMULT_CONST / lw->weight;
+
+ tmp = (u64)delta_exec * weight;
/*
- * prev now departs the cpu. It's not interesting to record
- * stats about how efficient we were at scheduling the idle
- * process, however.
+ * Check whether we'd overflow the 64-bit multiplication:
*/
- if (prev != rq->idle)
- sched_info_depart(prev);
+ if (unlikely(tmp > WMULT_CONST)) {
+ tmp = ((tmp >> WMULT_SHIFT/2) * lw->inv_weight)
+ >> (WMULT_SHIFT/2);
+ } else {
+ tmp = (tmp * lw->inv_weight) >> WMULT_SHIFT;
+ }
- if (next != rq->idle)
- sched_info_arrive(next);
-}
-static inline void
-sched_info_switch(struct task_struct *prev, struct task_struct *next)
-{
- if (unlikely(sched_info_on()))
- __sched_info_switch(prev, next);
+ return (unsigned long)min(tmp, (u64)sysctl_sched_runtime_limit);
}
-#else
-#define sched_info_queued(t) do { } while (0)
-#define sched_info_switch(t, next) do { } while (0)
-#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
-/*
- * Adding/removing a task to/from a priority array:
- */
-static void dequeue_task(struct task_struct *p, struct prio_array *array)
+static inline unsigned long
+calc_delta_fair(unsigned long delta_exec, struct load_weight *lw)
{
- array->nr_active--;
- list_del(&p->run_list);
- if (list_empty(array->queue + p->prio))
- __clear_bit(p->prio, array->bitmap);
+ return calc_delta_mine(delta_exec, NICE_0_LOAD, lw);
}
-static void enqueue_task(struct task_struct *p, struct prio_array *array)
+static void update_load_add(struct load_weight *lw, unsigned long inc)
{
- sched_info_queued(p);
- list_add_tail(&p->run_list, array->queue + p->prio);
- __set_bit(p->prio, array->bitmap);
- array->nr_active++;
- p->array = array;
+ lw->weight += inc;
+ lw->inv_weight = 0;
}
-/*
- * Put task to the end of the run list without the overhead of dequeue
- * followed by enqueue.
- */
-static void requeue_task(struct task_struct *p, struct prio_array *array)
+static void update_load_sub(struct load_weight *lw, unsigned long dec)
{
- list_move_tail(&p->run_list, array->queue + p->prio);
+ lw->weight -= dec;
+ lw->inv_weight = 0;
}
-static inline void
-enqueue_task_head(struct task_struct *p, struct prio_array *array)
+static void __update_curr_load(struct rq *rq, struct load_stat *ls)
{
- list_add(&p->run_list, array->queue + p->prio);
- __set_bit(p->prio, array->bitmap);
- array->nr_active++;
- p->array = array;
+ if (rq->curr != rq->idle && ls->load.weight) {
+ ls->delta_exec += ls->delta_stat;
+ ls->delta_fair += calc_delta_fair(ls->delta_stat, &ls->load);
+ ls->delta_stat = 0;
+ }
}
/*
- * __normal_prio - return the priority that is based on the static
- * priority but is modified by bonuses/penalties.
+ * Update delta_exec, delta_fair fields for rq.
*
- * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
- * into the -5 ... 0 ... +5 bonus/penalty range.
+ * delta_fair clock advances at a rate inversely proportional to
+ * total load (rq->ls.load.weight) on the runqueue, while
+ * delta_exec advances at the same rate as wall-clock (provided
+ * cpu is not idle).
*
- * We use 25% of the full 0...39 priority range so that:
+ * delta_exec / delta_fair is a measure of the (smoothened) load on this
+ * runqueue over any given interval. This (smoothened) load is used
+ * during load balance.
*
- * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
- * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
- *
- * Both properties are important to certain workloads.
+ * This function is called /before/ updating rq->ls.load
+ * and when switching tasks.
*/
-
-static inline int __normal_prio(struct task_struct *p)
+static void update_curr_load(struct rq *rq, u64 now)
{
- int bonus, prio;
-
- bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
+ struct load_stat *ls = &rq->ls;
+ u64 start;
- prio = p->static_prio - bonus;
- if (prio < MAX_RT_PRIO)
- prio = MAX_RT_PRIO;
- if (prio > MAX_PRIO-1)
- prio = MAX_PRIO-1;
- return prio;
+ start = ls->load_update_start;
+ ls->load_update_start = now;
+ ls->delta_stat += now - start;
+ /*
+ * Stagger updates to ls->delta_fair. Very frequent updates
+ * can be expensive.
+ */
+ if (ls->delta_stat >= sysctl_sched_stat_granularity)
+ __update_curr_load(rq, ls);
}
/*
@@ -791,53 +718,146 @@ static inline int __normal_prio(struct task_struct *p)
* this code will need modification
*/
#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
-#define LOAD_WEIGHT(lp) \
+#define load_weight(lp) \
(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
#define PRIO_TO_LOAD_WEIGHT(prio) \
- LOAD_WEIGHT(static_prio_timeslice(prio))
+ load_weight(static_prio_timeslice(prio))
#define RTPRIO_TO_LOAD_WEIGHT(rp) \
- (PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))
+ (PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + load_weight(rp))
-static void set_load_weight(struct task_struct *p)
-{
- if (has_rt_policy(p)) {
-#ifdef CONFIG_SMP
- if (p == task_rq(p)->migration_thread)
- /*
- * The migration thread does the actual balancing.
- * Giving its load any weight will skew balancing
- * adversely.
- */
- p->load_weight = 0;
- else
-#endif
- p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
- } else
- p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
-}
+#define WEIGHT_IDLEPRIO 2
+#define WMULT_IDLEPRIO (1 << 31)
+
+/*
+ * Nice levels are multiplicative, with a gentle 10% change for every
+ * nice level changed. I.e. when a CPU-bound task goes from nice 0 to
+ * nice 1, it will get ~10% less CPU time than another CPU-bound task
+ * that remained on nice 0.
+ *
+ * The "10% effect" is relative and cumulative: from _any_ nice level,
+ * if you go up 1 level, it's -10% CPU usage, if you go down 1 level
+ * it's +10% CPU usage.
+ */
+static const int prio_to_weight[40] = {
+/* -20 */ 88818, 71054, 56843, 45475, 36380, 29104, 23283, 18626, 14901, 11921,
+/* -10 */ 9537, 7629, 6103, 4883, 3906, 3125, 2500, 2000, 1600, 1280,
+/* 0 */ NICE_0_LOAD /* 1024 */,
+/* 1 */ 819, 655, 524, 419, 336, 268, 215, 172, 137,
+/* 10 */ 110, 87, 70, 56, 45, 36, 29, 23, 18, 15,
+};
+
+static const u32 prio_to_wmult[40] = {
+ 48356, 60446, 75558, 94446, 118058, 147573,
+ 184467, 230589, 288233, 360285, 450347,
+ 562979, 703746, 879575, 1099582, 1374389,
+ 717986, 2147483, 2684354, 3355443, 4194304,
+ 244160, 6557201, 8196502, 10250518, 12782640,
+ 16025997, 19976592, 24970740, 31350126, 39045157,
+ 49367440, 61356675, 76695844, 95443717, 119304647,
+ 148102320, 186737708, 238609294, 286331153,
+};
static inline void
-inc_raw_weighted_load(struct rq *rq, const struct task_struct *p)
+inc_load(struct rq *rq, const struct task_struct *p, u64 now)
{
- rq->raw_weighted_load += p->load_weight;
+ update_curr_load(rq, now);
+ update_load_add(&rq->ls.load, p->se.load.weight);
}
static inline void
-dec_raw_weighted_load(struct rq *rq, const struct task_struct *p)
+dec_load(struct rq *rq, const struct task_struct *p, u64 now)
{
- rq->raw_weighted_load -= p->load_weight;
+ update_curr_load(rq, now);
+ update_load_sub(&rq->ls.load, p->se.load.weight);
}
-static inline void inc_nr_running(struct task_struct *p, struct rq *rq)
+static inline void inc_nr_running(struct task_struct *p, struct rq *rq, u64 now)
{
rq->nr_running++;
- inc_raw_weighted_load(rq, p);
+ inc_load(rq, p, now);
}
-static inline void dec_nr_running(struct task_struct *p, struct rq *rq)
+static inline void dec_nr_running(struct task_struct *p, struct rq *rq, u64 now)
{
rq->nr_running--;
- dec_raw_weighted_load(rq, p);
+ dec_load(rq, p, now);
+}
+
+static void activate_task(struct rq *rq, struct task_struct *p, int wakeup);
+
+/*
+ * runqueue iterator, to support SMP load-balancing between different
+ * scheduling classes, without having to expose their internal data
+ * structures to the load-balancing proper:
+ */
+struct rq_iterator {
+ void *arg;
+ struct task_struct *(*start)(void *);
+ struct task_struct *(*next)(void *);
+};
+
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *load_moved,
+ int this_best_prio, int best_prio, int best_prio_seen,
+ struct rq_iterator *iterator);
+
+#include "sched_stats.h"
+#include "sched_rt.c"
+#include "sched_fair.c"
+#include "sched_idletask.c"
+#ifdef CONFIG_SCHED_DEBUG
+# include "sched_debug.c"
+#endif
+
+#define sched_class_highest (&rt_sched_class)
+
+static void set_load_weight(struct task_struct *p)
+{
+ task_rq(p)->cfs.wait_runtime -= p->se.wait_runtime;
+ p->se.wait_runtime = 0;
+
+ if (task_has_rt_policy(p)) {
+ p->se.load.weight = prio_to_weight[0] * 2;
+ p->se.load.inv_weight = prio_to_wmult[0] >> 1;
+ return;
+ }
+
+ /*
+ * SCHED_IDLE tasks get minimal weight:
+ */
+ if (p->policy == SCHED_IDLE) {
+ p->se.load.weight = WEIGHT_IDLEPRIO;
+ p->se.load.inv_weight = WMULT_IDLEPRIO;
+ return;
+ }
+
+ p->se.load.weight = prio_to_weight[p->static_prio - MAX_RT_PRIO];
+ p->se.load.inv_weight = prio_to_wmult[p->static_prio - MAX_RT_PRIO];
+}
+
+static void
+enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+ sched_info_queued(p);
+ p->sched_class->enqueue_task(rq, p, wakeup, now);
+ p->se.on_rq = 1;
+}
+
+static void
+dequeue_task(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+ p->sched_class->dequeue_task(rq, p, sleep, now);
+ p->se.on_rq = 0;
+}
+
+/*
+ * __normal_prio - return the priority that is based on the static prio
+ */
+static inline int __normal_prio(struct task_struct *p)
+{
+ return p->static_prio;
}
/*
@@ -851,7 +871,7 @@ static inline int normal_prio(struct task_struct *p)
{
int prio;
- if (has_rt_policy(p))
+ if (task_has_rt_policy(p))
prio = MAX_RT_PRIO-1 - p->rt_priority;
else
prio = __normal_prio(p);
@@ -879,222 +899,47 @@ static int effective_prio(struct task_struct *p)
}
/*
- * __activate_task - move a task to the runqueue.
- */
-static void __activate_task(struct task_struct *p, struct rq *rq)
-{
- struct prio_array *target = rq->active;
-
- if (batch_task(p))
- target = rq->expired;
- enqueue_task(p, target);
- inc_nr_running(p, rq);
-}
-
-/*
- * __activate_idle_task - move idle task to the _front_ of runqueue.
- */
-static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
-{
- enqueue_task_head(p, rq->active);
- inc_nr_running(p, rq);
-}
-
-/*
- * Recalculate p->normal_prio and p->prio after having slept,
- * updating the sleep-average too:
+ * activate_task - move a task to the runqueue.
*/
-static int recalc_task_prio(struct task_struct *p, unsigned long long now)
+static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
{
- /* Caller must always ensure 'now >= p->timestamp' */
- unsigned long sleep_time = now - p->timestamp;
-
- if (batch_task(p))
- sleep_time = 0;
-
- if (likely(sleep_time > 0)) {
- /*
- * This ceiling is set to the lowest priority that would allow
- * a task to be reinserted into the active array on timeslice
- * completion.
- */
- unsigned long ceiling = INTERACTIVE_SLEEP(p);
-
- if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
- /*
- * Prevents user tasks from achieving best priority
- * with one single large enough sleep.
- */
- p->sleep_avg = ceiling;
- /*
- * Using INTERACTIVE_SLEEP() as a ceiling places a
- * nice(0) task 1ms sleep away from promotion, and
- * gives it 700ms to round-robin with no chance of
- * being demoted. This is more than generous, so
- * mark this sleep as non-interactive to prevent the
- * on-runqueue bonus logic from intervening should
- * this task not receive cpu immediately.
- */
- p->sleep_type = SLEEP_NONINTERACTIVE;
- } else {
- /*
- * Tasks waking from uninterruptible sleep are
- * limited in their sleep_avg rise as they
- * are likely to be waiting on I/O
- */
- if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
- if (p->sleep_avg >= ceiling)
- sleep_time = 0;
- else if (p->sleep_avg + sleep_time >=
- ceiling) {
- p->sleep_avg = ceiling;
- sleep_time = 0;
- }
- }
+ u64 now = rq_clock(rq);
- /*
- * This code gives a bonus to interactive tasks.
- *
- * The boost works by updating the 'average sleep time'
- * value here, based on ->timestamp. The more time a
- * task spends sleeping, the higher the average gets -
- * and the higher the priority boost gets as well.
- */
- p->sleep_avg += sleep_time;
-
- }
- if (p->sleep_avg > NS_MAX_SLEEP_AVG)
- p->sleep_avg = NS_MAX_SLEEP_AVG;
- }
+ if (p->state == TASK_UNINTERRUPTIBLE)
+ rq->nr_uninterruptible--;
- return effective_prio(p);
+ enqueue_task(rq, p, wakeup, now);
+ inc_nr_running(p, rq, now);
}
/*
- * activate_task - move a task to the runqueue and do priority recalculation
- *
- * Update all the scheduling statistics stuff. (sleep average
- * calculation, priority modifiers, etc.)
+ * activate_idle_task - move idle task to the _front_ of runqueue.
*/
-static void activate_task(struct task_struct *p, struct rq *rq, int local)
+static inline void activate_idle_task(struct task_struct *p, struct rq *rq)
{
- unsigned long long now;
+ u64 now = rq_clock(rq);
- if (rt_task(p))
- goto out;
-
- now = sched_clock();
-#ifdef CONFIG_SMP
- if (!local) {
- /* Compensate for drifting sched_clock */
- struct rq *this_rq = this_rq();
- now = (now - this_rq->most_recent_timestamp)
- + rq->most_recent_timestamp;
- }
-#endif
-
- /*
- * Sleep time is in units of nanosecs, so shift by 20 to get a
- * milliseconds-range estimation of the amount of time that the task
- * spent sleeping:
- */
- if (unlikely(prof_on == SLEEP_PROFILING)) {
- if (p->state == TASK_UNINTERRUPTIBLE)
- profile_hits(SLEEP_PROFILING, (void *)get_wchan(p),
- (now - p->timestamp) >> 20);
- }
-
- p->prio = recalc_task_prio(p, now);
+ if (p->state == TASK_UNINTERRUPTIBLE)
+ rq->nr_uninterruptible--;
- /*
- * This checks to make sure it's not an uninterruptible task
- * that is now waking up.
- */
- if (p->sleep_type == SLEEP_NORMAL) {
- /*
- * Tasks which were woken up by interrupts (ie. hw events)
- * are most likely of interactive nature. So we give them
- * the credit of extending their sleep time to the period
- * of time they spend on the runqueue, waiting for execution
- * on a CPU, first time around:
- */
- if (in_interrupt())
- p->sleep_type = SLEEP_INTERRUPTED;
- else {
- /*
- * Normal first-time wakeups get a credit too for
- * on-runqueue time, but it will be weighted down:
- */
- p->sleep_type = SLEEP_INTERACTIVE;
- }
- }
- p->timestamp = now;
-out:
- __activate_task(p, rq);
+ enqueue_task(rq, p, 0, now);
+ inc_nr_running(p, rq, now);
}
/*
* deactivate_task - remove a task from the runqueue.
*/
-static void deactivate_task(struct task_struct *p, struct rq *rq)
-{
- dec_nr_running(p, rq);
- dequeue_task(p, p->array);
- p->array = NULL;
-}
-
-/*
- * resched_task - mark a task 'to be rescheduled now'.
- *
- * On UP this means the setting of the need_resched flag, on SMP it
- * might also involve a cross-CPU call to trigger the scheduler on
- * the target CPU.
- */
-#ifdef CONFIG_SMP
-
-#ifndef tsk_is_polling
-#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
-#endif
-
-static void resched_task(struct task_struct *p)
+static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)
{
- int cpu;
+ u64 now = rq_clock(rq);
- assert_spin_locked(&task_rq(p)->lock);
+ if (p->state == TASK_UNINTERRUPTIBLE)
+ rq->nr_uninterruptible++;
- if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED)))
- return;
-
- set_tsk_thread_flag(p, TIF_NEED_RESCHED);
-
- cpu = task_cpu(p);
- if (cpu == smp_processor_id())
- return;
-
- /* NEED_RESCHED must be visible before we test polling */
- smp_mb();
- if (!tsk_is_polling(p))
- smp_send_reschedule(cpu);
+ dequeue_task(rq, p, sleep, now);
+ dec_nr_running(p, rq, now);
}
-static void resched_cpu(int cpu)
-{
- struct rq *rq = cpu_rq(cpu);
- unsigned long flags;
-
- if (!spin_trylock_irqsave(&rq->lock, flags))
- return;
- resched_task(cpu_curr(cpu));
- spin_unlock_irqrestore(&rq->lock, flags);
-}
-#else
-static inline void resched_task(struct task_struct *p)
-{
- assert_spin_locked(&task_rq(p)->lock);
- set_tsk_need_resched(p);
-}
-#endif
-
/**
* task_curr - is this task currently executing on a CPU?
* @p: the task in question.
@@ -1107,10 +952,42 @@ inline int task_curr(const struct task_struct *p)
/* Used instead of source_load when we know the type == 0 */
unsigned long weighted_cpuload(const int cpu)
{
- return cpu_rq(cpu)->raw_weighted_load;
+ return cpu_rq(cpu)->ls.load.weight;
+}
+
+static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
+{
+#ifdef CONFIG_SMP
+ task_thread_info(p)->cpu = cpu;
+ set_task_cfs_rq(p);
+#endif
}
#ifdef CONFIG_SMP
+
+void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
+{
+ int old_cpu = task_cpu(p);
+ struct rq *old_rq = cpu_rq(old_cpu), *new_rq = cpu_rq(new_cpu);
+ u64 clock_offset, fair_clock_offset;
+
+ clock_offset = old_rq->clock - new_rq->clock;
+ fair_clock_offset = old_rq->cfs.fair_clock -
+ new_rq->cfs.fair_clock;
+ if (p->se.wait_start)
+ p->se.wait_start -= clock_offset;
+ if (p->se.wait_start_fair)
+ p->se.wait_start_fair -= fair_clock_offset;
+ if (p->se.sleep_start)
+ p->se.sleep_start -= clock_offset;
+ if (p->se.block_start)
+ p->se.block_start -= clock_offset;
+ if (p->se.sleep_start_fair)
+ p->se.sleep_start_fair -= fair_clock_offset;
+
+ __set_task_cpu(p, new_cpu);
+}
+
struct migration_req {
struct list_head list;
@@ -1133,7 +1010,7 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
* If the task is not on a runqueue (and not running), then
* it is sufficient to simply update the task's cpu field.
*/
- if (!p->array && !task_running(rq, p)) {
+ if (!p->se.on_rq && !task_running(rq, p)) {
set_task_cpu(p, dest_cpu);
return 0;
}
@@ -1158,9 +1035,8 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
void wait_task_inactive(struct task_struct *p)
{
unsigned long flags;
+ int running, on_rq;
struct rq *rq;
- struct prio_array *array;
- int running;
repeat:
/*
@@ -1192,7 +1068,7 @@ repeat:
*/
rq = task_rq_lock(p, &flags);
running = task_running(rq, p);
- array = p->array;
+ on_rq = p->se.on_rq;
task_rq_unlock(rq, &flags);
/*
@@ -1215,7 +1091,7 @@ repeat:
* running right now), it's preempted, and we should
* yield - it could be a while.
*/
- if (unlikely(array)) {
+ if (unlikely(on_rq)) {
yield();
goto repeat;
}
@@ -1261,11 +1137,12 @@ void kick_process(struct task_struct *p)
static inline unsigned long source_load(int cpu, int type)
{
struct rq *rq = cpu_rq(cpu);
+ unsigned long total = weighted_cpuload(cpu);
if (type == 0)
- return rq->raw_weighted_load;
+ return total;
- return min(rq->cpu_load[type-1], rq->raw_weighted_load);
+ return min(rq->cpu_load[type-1], total);
}
/*
@@ -1275,11 +1152,12 @@ static inline unsigned long source_load(int cpu, int type)
static inline unsigned long target_load(int cpu, int type)
{
struct rq *rq = cpu_rq(cpu);
+ unsigned long total = weighted_cpuload(cpu);
if (type == 0)
- return rq->raw_weighted_load;
+ return total;
- return max(rq->cpu_load[type-1], rq->raw_weighted_load);
+ return max(rq->cpu_load[type-1], total);
}
/*
@@ -1288,9 +1166,10 @@ static inline unsigned long target_load(int cpu, int type)
static inline unsigned long cpu_avg_load_per_task(int cpu)
{
struct rq *rq = cpu_rq(cpu);
+ unsigned long total = weighted_cpuload(cpu);
unsigned long n = rq->nr_running;
- return n ? rq->raw_weighted_load / n : SCHED_LOAD_SCALE;
+ return n ? total / n : SCHED_LOAD_SCALE;
}
/*
@@ -1392,9 +1271,9 @@ static int sched_balance_self(int cpu, int flag)
struct sched_domain *tmp, *sd = NULL;
for_each_domain(cpu, tmp) {
- /*
- * If power savings logic is enabled for a domain, stop there.
- */
+ /*
+ * If power savings logic is enabled for a domain, stop there.
+ */
if (tmp->flags & SD_POWERSAVINGS_BALANCE)
break;
if (tmp->flags & flag)
@@ -1477,9 +1356,9 @@ static int wake_idle(int cpu, struct task_struct *p)
if (idle_cpu(i))
return i;
}
- }
- else
+ } else {
break;
+ }
}
return cpu;
}
@@ -1521,7 +1400,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
if (!(old_state & state))
goto out;
- if (p->array)
+ if (p->se.on_rq)
goto out_running;
cpu = task_cpu(p);
@@ -1576,11 +1455,11 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
* of the current CPU:
*/
if (sync)
- tl -= current->load_weight;
+ tl -= current->se.load.weight;
if ((tl <= load &&
tl + target_load(cpu, idx) <= tl_per_task) ||
- 100*(tl + p->load_weight) <= imbalance*load) {
+ 100*(tl + p->se.load.weight) <= imbalance*load) {
/*
* This domain has SD_WAKE_AFFINE and
* p is cache cold in this domain, and
@@ -1614,7 +1493,7 @@ out_set_cpu:
old_state = p->state;
if (!(old_state & state))
goto out;
- if (p->array)
+ if (p->se.on_rq)
goto out_running;
this_cpu = smp_processor_id();
@@ -1623,25 +1502,7 @@ out_set_cpu:
out_activate:
#endif /* CONFIG_SMP */
- if (old_state == TASK_UNINTERRUPTIBLE) {
- rq->nr_uninterruptible--;
- /*
- * Tasks on involuntary sleep don't earn
- * sleep_avg beyond just interactive state.
- */
- p->sleep_type = SLEEP_NONINTERACTIVE;
- } else
-
- /*
- * Tasks that have marked their sleep as noninteractive get
- * woken up with their sleep average not weighted in an
- * interactive way.
- */
- if (old_state & TASK_NONINTERACTIVE)
- p->sleep_type = SLEEP_NONINTERACTIVE;
-
-
- activate_task(p, rq, cpu == this_cpu);
+ activate_task(rq, p, 1);
/*
* Sync wakeups (i.e. those types of wakeups where the waker
* has indicated that it will leave the CPU in short order)
@@ -1650,10 +1511,8 @@ out_activate:
* the waker guarantees that the freshly woken up task is going
* to be considered on this CPU.)
*/
- if (!sync || cpu != this_cpu) {
- if (TASK_PREEMPTS_CURR(p, rq))
- resched_task(rq->curr);
- }
+ if (!sync || cpu != this_cpu)
+ check_preempt_curr(rq, p);
success = 1;
out_running:
@@ -1676,19 +1535,36 @@ int fastcall wake_up_state(struct task_struct *p, unsigned int state)
return try_to_wake_up(p, state, 0);
}
-static void task_running_tick(struct rq *rq, struct task_struct *p);
/*
* Perform scheduler related setup for a newly forked process p.
* p is forked by current.
- */
-void fastcall sched_fork(struct task_struct *p, int clone_flags)
-{
- int cpu = get_cpu();
+ *
+ * __sched_fork() is basic setup used by init_idle() too:
+ */
+static void __sched_fork(struct task_struct *p)
+{
+ p->se.wait_start_fair = 0;
+ p->se.wait_start = 0;
+ p->se.exec_start = 0;
+ p->se.sum_exec_runtime = 0;
+ p->se.delta_exec = 0;
+ p->se.delta_fair_run = 0;
+ p->se.delta_fair_sleep = 0;
+ p->se.wait_runtime = 0;
+ p->se.sum_wait_runtime = 0;
+ p->se.sum_sleep_runtime = 0;
+ p->se.sleep_start = 0;
+ p->se.sleep_start_fair = 0;
+ p->se.block_start = 0;
+ p->se.sleep_max = 0;
+ p->se.block_max = 0;
+ p->se.exec_max = 0;
+ p->se.wait_max = 0;
+ p->se.wait_runtime_overruns = 0;
+ p->se.wait_runtime_underruns = 0;
-#ifdef CONFIG_SMP
- cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
-#endif
- set_task_cpu(p, cpu);
+ INIT_LIST_HEAD(&p->run_list);
+ p->se.on_rq = 0;
/*
* We mark the process as running here, but have not actually
@@ -1697,16 +1573,29 @@ void fastcall sched_fork(struct task_struct *p, int clone_flags)
* event cannot wake it up and insert it on the runqueue either.
*/
p->state = TASK_RUNNING;
+}
+
+/*
+ * fork()/clone()-time setup:
+ */
+void sched_fork(struct task_struct *p, int clone_flags)
+{
+ int cpu = get_cpu();
+
+ __sched_fork(p);
+
+#ifdef CONFIG_SMP
+ cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
+#endif
+ __set_task_cpu(p, cpu);
/*
* Make sure we do not leak PI boosting priority to the child:
*/
p->prio = current->normal_prio;
- INIT_LIST_HEAD(&p->run_list);
- p->array = NULL;
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
- if (unlikely(sched_info_on()))
+ if (likely(sched_info_on()))
memset(&p->sched_info, 0, sizeof(p->sched_info));
#endif
#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
@@ -1716,34 +1605,16 @@ void fastcall sched_fork(struct task_struct *p, int clone_flags)
/* Want to start with kernel preemption disabled. */
task_thread_info(p)->preempt_count = 1;
#endif
- /*
- * Share the timeslice between parent and child, thus the
- * total amount of pending timeslices in the system doesn't change,
- * resulting in more scheduling fairness.
- */
- local_irq_disable();
- p->time_slice = (current->time_slice + 1) >> 1;
- /*
- * The remainder of the first timeslice might be recovered by
- * the parent if the child exits early enough.
- */
- p->first_time_slice = 1;
- current->time_slice >>= 1;
- p->timestamp = sched_clock();
- if (unlikely(!current->time_slice)) {
- /*
- * This case is rare, it happens when the parent has only
- * a single jiffy left from its timeslice. Taking the
- * runqueue lock is not a problem.
- */
- current->time_slice = 1;
- task_running_tick(cpu_rq(cpu), current);
- }
- local_irq_enable();
put_cpu();
}
/*
+ * After fork, child runs first. (default) If set to 0 then
+ * parent will (try to) run first.
+ */
+unsigned int __read_mostly sysctl_sched_child_runs_first = 1;
+
+/*
* wake_up_new_task - wake up a newly created task for the first time.
*
* This function will do some initial scheduler statistics housekeeping
@@ -1752,107 +1623,27 @@ void fastcall sched_fork(struct task_struct *p, int clone_flags)
*/
void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
{
- struct rq *rq, *this_rq;
unsigned long flags;
- int this_cpu, cpu;
+ struct rq *rq;
+ int this_cpu;
rq = task_rq_lock(p, &flags);
BUG_ON(p->state != TASK_RUNNING);
- this_cpu = smp_processor_id();
- cpu = task_cpu(p);
-
- /*
- * We decrease the sleep average of forking parents
- * and children as well, to keep max-interactive tasks
- * from forking tasks that are max-interactive. The parent
- * (current) is done further down, under its lock.
- */
- p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
- CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
+ this_cpu = smp_processor_id(); /* parent's CPU */
p->prio = effective_prio(p);
- if (likely(cpu == this_cpu)) {
- if (!(clone_flags & CLONE_VM)) {
- /*
- * The VM isn't cloned, so we're in a good position to
- * do child-runs-first in anticipation of an exec. This
- * usually avoids a lot of COW overhead.
- */
- if (unlikely(!current->array))
- __activate_task(p, rq);
- else {
- p->prio = current->prio;
- p->normal_prio = current->normal_prio;
- list_add_tail(&p->run_list, &current->run_list);
- p->array = current->array;
- p->array->nr_active++;
- inc_nr_running(p, rq);
- }
- set_need_resched();
- } else
- /* Run child last */
- __activate_task(p, rq);
- /*
- * We skip the following code due to cpu == this_cpu
- *
- * task_rq_unlock(rq, &flags);
- * this_rq = task_rq_lock(current, &flags);
- */
- this_rq = rq;
+ if (!sysctl_sched_child_runs_first || (clone_flags & CLONE_VM) ||
+ task_cpu(p) != this_cpu || !current->se.on_rq) {
+ activate_task(rq, p, 0);
} else {
- this_rq = cpu_rq(this_cpu);
-
/*
- * Not the local CPU - must adjust timestamp. This should
- * get optimised away in the !CONFIG_SMP case.
+ * Let the scheduling class do new task startup
+ * management (if any):
*/
- p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
- + rq->most_recent_timestamp;
- __activate_task(p, rq);
- if (TASK_PREEMPTS_CURR(p, rq))
- resched_task(rq->curr);
-
- /*
- * Parent and child are on different CPUs, now get the
- * parent runqueue to update the parent's ->sleep_avg:
- */
- task_rq_unlock(rq, &flags);
- this_rq = task_rq_lock(current, &flags);
- }
- current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
- PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
- task_rq_unlock(this_rq, &flags);
-}
-
-/*
- * Potentially available exiting-child timeslices are
- * retrieved here - this way the parent does not get
- * penalized for creating too many threads.
- *
- * (this cannot be used to 'generate' timeslices
- * artificially, because any timeslice recovered here
- * was given away by the parent in the first place.)
- */
-void fastcall sched_exit(struct task_struct *p)
-{
- unsigned long flags;
- struct rq *rq;
-
- /*
- * If the child was a (relative-) CPU hog then decrease
- * the sleep_avg of the parent as well.
- */
- rq = task_rq_lock(p->parent, &flags);
- if (p->first_time_slice && task_cpu(p) == task_cpu(p->parent)) {
- p->parent->time_slice += p->time_slice;
- if (unlikely(p->parent->time_slice > task_timeslice(p)))
- p->parent->time_slice = task_timeslice(p);
+ p->sched_class->task_new(rq, p);
}
- if (p->sleep_avg < p->parent->sleep_avg)
- p->parent->sleep_avg = p->parent->sleep_avg /
- (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
- (EXIT_WEIGHT + 1);
+ check_preempt_curr(rq, p);
task_rq_unlock(rq, &flags);
}
@@ -1917,7 +1708,7 @@ static inline void finish_task_switch(struct rq *rq, struct task_struct *prev)
/*
* Remove function-return probe instances associated with this
* task and put them back on the free list.
- */
+ */
kprobe_flush_task(prev);
put_task_struct(prev);
}
@@ -1945,13 +1736,15 @@ asmlinkage void schedule_tail(struct task_struct *prev)
* context_switch - switch to the new MM and the new
* thread's register state.
*/
-static inline struct task_struct *
+static inline void
context_switch(struct rq *rq, struct task_struct *prev,
struct task_struct *next)
{
- struct mm_struct *mm = next->mm;
- struct mm_struct *oldmm = prev->active_mm;
+ struct mm_struct *mm, *oldmm;
+ prepare_task_switch(rq, next);
+ mm = next->mm;
+ oldmm = prev->active_mm;
/*
* For paravirt, this is coupled with an exit in switch_to to
* combine the page table reload and the switch backend into
@@ -1959,16 +1752,15 @@ context_switch(struct rq *rq, struct task_struct *prev,
*/
arch_enter_lazy_cpu_mode();
- if (!mm) {
+ if (unlikely(!mm)) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);
- if (!prev->mm) {
+ if (unlikely(!prev->mm)) {
prev->active_mm = NULL;
- WARN_ON(rq->prev_mm);
rq->prev_mm = oldmm;
}
/*
@@ -1984,7 +1776,13 @@ context_switch(struct rq *rq, struct task_struct *prev,
/* Here we just switch the register state and the stack. */
switch_to(prev, next, prev);
- return prev;
+ barrier();
+ /*
+ * this_rq must be evaluated again because prev may have moved
+ * CPUs since it called schedule(), thus the 'rq' on its stack
+ * frame will be invalid.
+ */
+ finish_task_switch(this_rq(), prev);
}
/*
@@ -2057,17 +1855,65 @@ unsigned long nr_active(void)
return running + uninterruptible;
}
-#ifdef CONFIG_SMP
-
/*
- * Is this task likely cache-hot:
+ * Update rq->cpu_load[] statistics. This function is usually called every
+ * scheduler tick (TICK_NSEC).
*/
-static inline int
-task_hot(struct task_struct *p, unsigned long long now, struct sched_domain *sd)
+static void update_cpu_load(struct rq *this_rq)
{
- return (long long)(now - p->last_ran) < (long long)sd->cache_hot_time;
+ u64 fair_delta64, exec_delta64, idle_delta64, sample_interval64, tmp64;
+ unsigned long total_load = this_rq->ls.load.weight;
+ unsigned long this_load = total_load;
+ struct load_stat *ls = &this_rq->ls;
+ u64 now = __rq_clock(this_rq);
+ int i, scale;
+
+ this_rq->nr_load_updates++;
+ if (unlikely(!(sysctl_sched_features & SCHED_FEAT_PRECISE_CPU_LOAD)))
+ goto do_avg;
+
+ /* Update delta_fair/delta_exec fields first */
+ update_curr_load(this_rq, now);
+
+ fair_delta64 = ls->delta_fair + 1;
+ ls->delta_fair = 0;
+
+ exec_delta64 = ls->delta_exec + 1;
+ ls->delta_exec = 0;
+
+ sample_interval64 = now - ls->load_update_last;
+ ls->load_update_last = now;
+
+ if ((s64)sample_interval64 < (s64)TICK_NSEC)
+ sample_interval64 = TICK_NSEC;
+
+ if (exec_delta64 > sample_interval64)
+ exec_delta64 = sample_interval64;
+
+ idle_delta64 = sample_interval64 - exec_delta64;
+
+ tmp64 = div64_64(SCHED_LOAD_SCALE * exec_delta64, fair_delta64);
+ tmp64 = div64_64(tmp64 * exec_delta64, sample_interval64);
+
+ this_load = (unsigned long)tmp64;
+
+do_avg:
+
+ /* Update our load: */
+ for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
+ unsigned long old_load, new_load;
+
+ /* scale is effectively 1 << i now, and >> i divides by scale */
+
+ old_load = this_rq->cpu_load[i];
+ new_load = this_load;
+
+ this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
+ }
}
+#ifdef CONFIG_SMP
+
/*
* double_rq_lock - safely lock two runqueues
*
@@ -2184,23 +2030,17 @@ void sched_exec(void)
* pull_task - move a task from a remote runqueue to the local runqueue.
* Both runqueues must be locked.
*/
-static void pull_task(struct rq *src_rq, struct prio_array *src_array,
- struct task_struct *p, struct rq *this_rq,
- struct prio_array *this_array, int this_cpu)
+static void pull_task(struct rq *src_rq, struct task_struct *p,
+ struct rq *this_rq, int this_cpu)
{
- dequeue_task(p, src_array);
- dec_nr_running(p, src_rq);
+ deactivate_task(src_rq, p, 0);
set_task_cpu(p, this_cpu);
- inc_nr_running(p, this_rq);
- enqueue_task(p, this_array);
- p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
- + this_rq->most_recent_timestamp;
+ activate_task(this_rq, p, 0);
/*
* Note that idle threads have a prio of MAX_PRIO, for this test
* to be always true for them.
*/
- if (TASK_PREEMPTS_CURR(p, this_rq))
- resched_task(this_rq->curr);
+ check_preempt_curr(this_rq, p);
}
/*
@@ -2208,7 +2048,7 @@ static void pull_task(struct rq *src_rq, struct prio_array *src_array,
*/
static
int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
- struct sched_domain *sd, enum idle_type idle,
+ struct sched_domain *sd, enum cpu_idle_type idle,
int *all_pinned)
{
/*
@@ -2225,132 +2065,67 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
return 0;
/*
- * Aggressive migration if:
- * 1) task is cache cold, or
- * 2) too many balance attempts have failed.
+ * Aggressive migration if too many balance attempts have failed:
*/
-
- if (sd->nr_balance_failed > sd->cache_nice_tries) {
-#ifdef CONFIG_SCHEDSTATS
- if (task_hot(p, rq->most_recent_timestamp, sd))
- schedstat_inc(sd, lb_hot_gained[idle]);
-#endif
+ if (sd->nr_balance_failed > sd->cache_nice_tries)
return 1;
- }
- if (task_hot(p, rq->most_recent_timestamp, sd))
- return 0;
return 1;
}
-#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio)
-
-/*
- * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
- * load from busiest to this_rq, as part of a balancing operation within
- * "domain". Returns the number of tasks moved.
- *
- * Called with both runqueues locked.
- */
-static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
unsigned long max_nr_move, unsigned long max_load_move,
- struct sched_domain *sd, enum idle_type idle,
- int *all_pinned)
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *load_moved,
+ int this_best_prio, int best_prio, int best_prio_seen,
+ struct rq_iterator *iterator)
{
- int idx, pulled = 0, pinned = 0, this_best_prio, best_prio,
- best_prio_seen, skip_for_load;
- struct prio_array *array, *dst_array;
- struct list_head *head, *curr;
- struct task_struct *tmp;
- long rem_load_move;
+ int pulled = 0, pinned = 0, skip_for_load;
+ struct task_struct *p;
+ long rem_load_move = max_load_move;
if (max_nr_move == 0 || max_load_move == 0)
goto out;
- rem_load_move = max_load_move;
pinned = 1;
- this_best_prio = rq_best_prio(this_rq);
- best_prio = rq_best_prio(busiest);
- /*
- * Enable handling of the case where there is more than one task
- * with the best priority. If the current running task is one
- * of those with prio==best_prio we know it won't be moved
- * and therefore it's safe to override the skip (based on load) of
- * any task we find with that prio.
- */
- best_prio_seen = best_prio == busiest->curr->prio;
/*
- * We first consider expired tasks. Those will likely not be
- * executed in the near future, and they are most likely to
- * be cache-cold, thus switching CPUs has the least effect
- * on them.
+ * Start the load-balancing iterator:
*/
- if (busiest->expired->nr_active) {
- array = busiest->expired;
- dst_array = this_rq->expired;
- } else {
- array = busiest->active;
- dst_array = this_rq->active;
- }
-
-new_array:
- /* Start searching at priority 0: */
- idx = 0;
-skip_bitmap:
- if (!idx)
- idx = sched_find_first_bit(array->bitmap);
- else
- idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
- if (idx >= MAX_PRIO) {
- if (array == busiest->expired && busiest->active->nr_active) {
- array = busiest->active;
- dst_array = this_rq->active;
- goto new_array;
- }
+ p = iterator->start(iterator->arg);
+next:
+ if (!p)
goto out;
- }
-
- head = array->queue + idx;
- curr = head->prev;
-skip_queue:
- tmp = list_entry(curr, struct task_struct, run_list);
-
- curr = curr->prev;
-
/*
* To help distribute high priority tasks accross CPUs we don't
* skip a task if it will be the highest priority task (i.e. smallest
* prio value) on its new queue regardless of its load weight
*/
- skip_for_load = tmp->load_weight > rem_load_move;
- if (skip_for_load && idx < this_best_prio)
- skip_for_load = !best_prio_seen && idx == best_prio;
+ skip_for_load = (p->se.load.weight >> 1) > rem_load_move +
+ SCHED_LOAD_SCALE_FUZZ;
+ if (skip_for_load && p->prio < this_best_prio)
+ skip_for_load = !best_prio_seen && p->prio == best_prio;
if (skip_for_load ||
- !can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
+ !can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned)) {
- best_prio_seen |= idx == best_prio;
- if (curr != head)
- goto skip_queue;
- idx++;
- goto skip_bitmap;
+ best_prio_seen |= p->prio == best_prio;
+ p = iterator->next(iterator->arg);
+ goto next;
}
- pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
+ pull_task(busiest, p, this_rq, this_cpu);
pulled++;
- rem_load_move -= tmp->load_weight;
+ rem_load_move -= p->se.load.weight;
/*
* We only want to steal up to the prescribed number of tasks
* and the prescribed amount of weighted load.
*/
if (pulled < max_nr_move && rem_load_move > 0) {
- if (idx < this_best_prio)
- this_best_prio = idx;
- if (curr != head)
- goto skip_queue;
- idx++;
- goto skip_bitmap;
+ if (p->prio < this_best_prio)
+ this_best_prio = p->prio;
+ p = iterator->next(iterator->arg);
+ goto next;
}
out:
/*
@@ -2362,18 +2137,48 @@ out:
if (all_pinned)
*all_pinned = pinned;
+ *load_moved = max_load_move - rem_load_move;
return pulled;
}
/*
+ * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
+ * load from busiest to this_rq, as part of a balancing operation within
+ * "domain". Returns the number of tasks moved.
+ *
+ * Called with both runqueues locked.
+ */
+static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned)
+{
+ struct sched_class *class = sched_class_highest;
+ unsigned long load_moved, total_nr_moved = 0, nr_moved;
+ long rem_load_move = max_load_move;
+
+ do {
+ nr_moved = class->load_balance(this_rq, this_cpu, busiest,
+ max_nr_move, (unsigned long)rem_load_move,
+ sd, idle, all_pinned, &load_moved);
+ total_nr_moved += nr_moved;
+ max_nr_move -= nr_moved;
+ rem_load_move -= load_moved;
+ class = class->next;
+ } while (class && max_nr_move && rem_load_move > 0);
+
+ return total_nr_moved;
+}
+
+/*
* find_busiest_group finds and returns the busiest CPU group within the
* domain. It calculates and returns the amount of weighted load which
* should be moved to restore balance via the imbalance parameter.
*/
static struct sched_group *
find_busiest_group(struct sched_domain *sd, int this_cpu,
- unsigned long *imbalance, enum idle_type idle, int *sd_idle,
- cpumask_t *cpus, int *balance)
+ unsigned long *imbalance, enum cpu_idle_type idle,
+ int *sd_idle, cpumask_t *cpus, int *balance)
{
struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
unsigned long max_load, avg_load, total_load, this_load, total_pwr;
@@ -2391,9 +2196,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
max_load = this_load = total_load = total_pwr = 0;
busiest_load_per_task = busiest_nr_running = 0;
this_load_per_task = this_nr_running = 0;
- if (idle == NOT_IDLE)
+ if (idle == CPU_NOT_IDLE)
load_idx = sd->busy_idx;
- else if (idle == NEWLY_IDLE)
+ else if (idle == CPU_NEWLY_IDLE)
load_idx = sd->newidle_idx;
else
load_idx = sd->idle_idx;
@@ -2437,7 +2242,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
avg_load += load;
sum_nr_running += rq->nr_running;
- sum_weighted_load += rq->raw_weighted_load;
+ sum_weighted_load += weighted_cpuload(i);
}
/*
@@ -2477,8 +2282,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
* Busy processors will not participate in power savings
* balance.
*/
- if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
- goto group_next;
+ if (idle == CPU_NOT_IDLE ||
+ !(sd->flags & SD_POWERSAVINGS_BALANCE))
+ goto group_next;
/*
* If the local group is idle or completely loaded
@@ -2488,42 +2294,42 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
!this_nr_running))
power_savings_balance = 0;
- /*
+ /*
* If a group is already running at full capacity or idle,
* don't include that group in power savings calculations
- */
- if (!power_savings_balance || sum_nr_running >= group_capacity
+ */
+ if (!power_savings_balance || sum_nr_running >= group_capacity
|| !sum_nr_running)
- goto group_next;
+ goto group_next;
- /*
+ /*
* Calculate the group which has the least non-idle load.
- * This is the group from where we need to pick up the load
- * for saving power
- */
- if ((sum_nr_running < min_nr_running) ||
- (sum_nr_running == min_nr_running &&
+ * This is the group from where we need to pick up the load
+ * for saving power
+ */
+ if ((sum_nr_running < min_nr_running) ||
+ (sum_nr_running == min_nr_running &&
first_cpu(group->cpumask) <
first_cpu(group_min->cpumask))) {
- group_min = group;
- min_nr_running = sum_nr_running;
+ group_min = group;
+ min_nr_running = sum_nr_running;
min_load_per_task = sum_weighted_load /
sum_nr_running;
- }
+ }
- /*
+ /*
* Calculate the group which is almost near its
- * capacity but still has some space to pick up some load
- * from other group and save more power
- */
- if (sum_nr_running <= group_capacity - 1) {
- if (sum_nr_running > leader_nr_running ||
- (sum_nr_running == leader_nr_running &&
- first_cpu(group->cpumask) >
- first_cpu(group_leader->cpumask))) {
- group_leader = group;
- leader_nr_running = sum_nr_running;
- }
+ * capacity but still has some space to pick up some load
+ * from other group and save more power
+ */
+ if (sum_nr_running <= group_capacity - 1) {
+ if (sum_nr_running > leader_nr_running ||
+ (sum_nr_running == leader_nr_running &&
+ first_cpu(group->cpumask) >
+ first_cpu(group_leader->cpumask))) {
+ group_leader = group;
+ leader_nr_running = sum_nr_running;
+ }
}
group_next:
#endif
@@ -2578,7 +2384,7 @@ group_next:
* a think about bumping its value to force at least one task to be
* moved
*/
- if (*imbalance < busiest_load_per_task) {
+ if (*imbalance + SCHED_LOAD_SCALE_FUZZ < busiest_load_per_task/2) {
unsigned long tmp, pwr_now, pwr_move;
unsigned int imbn;
@@ -2592,7 +2398,8 @@ small_imbalance:
} else
this_load_per_task = SCHED_LOAD_SCALE;
- if (max_load - this_load >= busiest_load_per_task * imbn) {
+ if (max_load - this_load + SCHED_LOAD_SCALE_FUZZ >=
+ busiest_load_per_task * imbn) {
*imbalance = busiest_load_per_task;
return busiest;
}
@@ -2639,7 +2446,7 @@ small_imbalance:
out_balanced:
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
- if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
+ if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
goto ret;
if (this == group_leader && group_leader != group_min) {
@@ -2656,7 +2463,7 @@ ret:
* find_busiest_queue - find the busiest runqueue among the cpus in group.
*/
static struct rq *
-find_busiest_queue(struct sched_group *group, enum idle_type idle,
+find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
unsigned long imbalance, cpumask_t *cpus)
{
struct rq *busiest = NULL, *rq;
@@ -2664,17 +2471,19 @@ find_busiest_queue(struct sched_group *group, enum idle_type idle,
int i;
for_each_cpu_mask(i, group->cpumask) {
+ unsigned long wl;
if (!cpu_isset(i, *cpus))
continue;
rq = cpu_rq(i);
+ wl = weighted_cpuload(i);
- if (rq->nr_running == 1 && rq->raw_weighted_load > imbalance)
+ if (rq->nr_running == 1 && wl > imbalance)
continue;
- if (rq->raw_weighted_load > max_load) {
- max_load = rq->raw_weighted_load;
+ if (wl > max_load) {
+ max_load = wl;
busiest = rq;
}
}
@@ -2698,7 +2507,7 @@ static inline unsigned long minus_1_or_zero(unsigned long n)
* tasks if there is an imbalance.
*/
static int load_balance(int this_cpu, struct rq *this_rq,
- struct sched_domain *sd, enum idle_type idle,
+ struct sched_domain *sd, enum cpu_idle_type idle,
int *balance)
{
int nr_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
@@ -2711,10 +2520,10 @@ static int load_balance(int this_cpu, struct rq *this_rq,
/*
* When power savings policy is enabled for the parent domain, idle
* sibling can pick up load irrespective of busy siblings. In this case,
- * let the state of idle sibling percolate up as IDLE, instead of
- * portraying it as NOT_IDLE.
+ * let the state of idle sibling percolate up as CPU_IDLE, instead of
+ * portraying it as CPU_NOT_IDLE.
*/
- if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
+ if (idle != CPU_NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
!test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
sd_idle = 1;
@@ -2848,7 +2657,7 @@ out_one_pinned:
* Check this_cpu to ensure it is balanced within domain. Attempt to move
* tasks if there is an imbalance.
*
- * Called from schedule when this_rq is about to become idle (NEWLY_IDLE).
+ * Called from schedule when this_rq is about to become idle (CPU_NEWLY_IDLE).
* this_rq is locked.
*/
static int
@@ -2865,31 +2674,31 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
* When power savings policy is enabled for the parent domain, idle
* sibling can pick up load irrespective of busy siblings. In this case,
* let the state of idle sibling percolate up as IDLE, instead of
- * portraying it as NOT_IDLE.
+ * portraying it as CPU_NOT_IDLE.
*/
if (sd->flags & SD_SHARE_CPUPOWER &&
!test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
sd_idle = 1;
- schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_cnt[CPU_NEWLY_IDLE]);
redo:
- group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE,
+ group = find_busiest_group(sd, this_cpu, &imbalance, CPU_NEWLY_IDLE,
&sd_idle, &cpus, NULL);
if (!group) {
- schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_nobusyg[CPU_NEWLY_IDLE]);
goto out_balanced;
}
- busiest = find_busiest_queue(group, NEWLY_IDLE, imbalance,
+ busiest = find_busiest_queue(group, CPU_NEWLY_IDLE, imbalance,
&cpus);
if (!busiest) {
- schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_nobusyq[CPU_NEWLY_IDLE]);
goto out_balanced;
}
BUG_ON(busiest == this_rq);
- schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
+ schedstat_add(sd, lb_imbalance[CPU_NEWLY_IDLE], imbalance);
nr_moved = 0;
if (busiest->nr_running > 1) {
@@ -2897,7 +2706,7 @@ redo:
double_lock_balance(this_rq, busiest);
nr_moved = move_tasks(this_rq, this_cpu, busiest,
minus_1_or_zero(busiest->nr_running),
- imbalance, sd, NEWLY_IDLE, NULL);
+ imbalance, sd, CPU_NEWLY_IDLE, NULL);
spin_unlock(&busiest->lock);
if (!nr_moved) {
@@ -2908,7 +2717,7 @@ redo:
}
if (!nr_moved) {
- schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_failed[CPU_NEWLY_IDLE]);
if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
!test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
return -1;
@@ -2918,7 +2727,7 @@ redo:
return nr_moved;
out_balanced:
- schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_balanced[CPU_NEWLY_IDLE]);
if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
!test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
return -1;
@@ -2934,8 +2743,8 @@ out_balanced:
static void idle_balance(int this_cpu, struct rq *this_rq)
{
struct sched_domain *sd;
- int pulled_task = 0;
- unsigned long next_balance = jiffies + 60 * HZ;
+ int pulled_task = -1;
+ unsigned long next_balance = jiffies + HZ;
for_each_domain(this_cpu, sd) {
unsigned long interval;
@@ -2954,12 +2763,13 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
if (pulled_task)
break;
}
- if (!pulled_task)
+ if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
/*
* We are going idle. next_balance may be set based on
* a busy processor. So reset next_balance.
*/
this_rq->next_balance = next_balance;
+ }
}
/*
@@ -3003,7 +2813,7 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu)
schedstat_inc(sd, alb_cnt);
if (move_tasks(target_rq, target_cpu, busiest_rq, 1,
- RTPRIO_TO_LOAD_WEIGHT(100), sd, SCHED_IDLE,
+ RTPRIO_TO_LOAD_WEIGHT(100), sd, CPU_IDLE,
NULL))
schedstat_inc(sd, alb_pushed);
else
@@ -3012,32 +2822,6 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu)
spin_unlock(&target_rq->lock);
}
-static void update_load(struct rq *this_rq)
-{
- unsigned long this_load;
- unsigned int i, scale;
-
- this_load = this_rq->raw_weighted_load;
-
- /* Update our load: */
- for (i = 0, scale = 1; i < 3; i++, scale += scale) {
- unsigned long old_load, new_load;
-
- /* scale is effectively 1 << i now, and >> i divides by scale */
-
- old_load = this_rq->cpu_load[i];
- new_load = this_load;
- /*
- * Round up the averaging division if load is increasing. This
- * prevents us from getting stuck on 9 if the load is 10, for
- * example.
- */
- if (new_load > old_load)
- new_load += scale-1;
- this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
- }
-}
-
#ifdef CONFIG_NO_HZ
static struct {
atomic_t load_balancer;
@@ -3120,7 +2904,7 @@ static DEFINE_SPINLOCK(balancing);
*
* Balancing parameters are set up in arch_init_sched_domains.
*/
-static inline void rebalance_domains(int cpu, enum idle_type idle)
+static inline void rebalance_domains(int cpu, enum cpu_idle_type idle)
{
int balance = 1;
struct rq *rq = cpu_rq(cpu);
@@ -3134,13 +2918,16 @@ static inline void rebalance_domains(int cpu, enum idle_type idle)
continue;
interval = sd->balance_interval;
- if (idle != SCHED_IDLE)
+ if (idle != CPU_IDLE)
interval *= sd->busy_factor;
/* scale ms to jiffies */
interval = msecs_to_jiffies(interval);
if (unlikely(!interval))
interval = 1;
+ if (interval > HZ*NR_CPUS/10)
+ interval = HZ*NR_CPUS/10;
+
if (sd->flags & SD_SERIALIZE) {
if (!spin_trylock(&balancing))
@@ -3154,7 +2941,7 @@ static inline void rebalance_domains(int cpu, enum idle_type idle)
* longer idle, or one of our SMT siblings is
* not idle.
*/
- idle = NOT_IDLE;
+ idle = CPU_NOT_IDLE;
}
sd->last_balance = jiffies;
}
@@ -3182,11 +2969,12 @@ out:
*/
static void run_rebalance_domains(struct softirq_action *h)
{
- int local_cpu = smp_processor_id();
- struct rq *local_rq = cpu_rq(local_cpu);
- enum idle_type idle = local_rq->idle_at_tick ? SCHED_IDLE : NOT_IDLE;
+ int this_cpu = smp_processor_id();
+ struct rq *this_rq = cpu_rq(this_cpu);
+ enum cpu_idle_type idle = this_rq->idle_at_tick ?
+ CPU_IDLE : CPU_NOT_IDLE;
- rebalance_domains(local_cpu, idle);
+ rebalance_domains(this_cpu, idle);
#ifdef CONFIG_NO_HZ
/*
@@ -3194,13 +2982,13 @@ static void run_rebalance_domains(struct softirq_action *h)
* balancing on behalf of the other idle cpus whose ticks are
* stopped.
*/
- if (local_rq->idle_at_tick &&
- atomic_read(&nohz.load_balancer) == local_cpu) {
+ if (this_rq->idle_at_tick &&
+ atomic_read(&nohz.load_balancer) == this_cpu) {
cpumask_t cpus = nohz.cpu_mask;
struct rq *rq;
int balance_cpu;
- cpu_clear(local_cpu, cpus);
+ cpu_clear(this_cpu, cpus);
for_each_cpu_mask(balance_cpu, cpus) {
/*
* If this cpu gets work to do, stop the load balancing
@@ -3213,8 +3001,8 @@ static void run_rebalance_domains(struct softirq_action *h)
rebalance_domains(balance_cpu, SCHED_IDLE);
rq = cpu_rq(balance_cpu);
- if (time_after(local_rq->next_balance, rq->next_balance))
- local_rq->next_balance = rq->next_balance;
+ if (time_after(this_rq->next_balance, rq->next_balance))
+ this_rq->next_balance = rq->next_balance;
}
}
#endif
@@ -3227,9 +3015,8 @@ static void run_rebalance_domains(struct softirq_action *h)
* idle load balancing owner or decide to stop the periodic load balancing,
* if the whole system is idle.
*/
-static inline void trigger_load_balance(int cpu)
+static inline void trigger_load_balance(struct rq *rq, int cpu)
{
- struct rq *rq = cpu_rq(cpu);
#ifdef CONFIG_NO_HZ
/*
* If we were in the nohz mode recently and busy at the current
@@ -3281,13 +3068,29 @@ static inline void trigger_load_balance(int cpu)
if (time_after_eq(jiffies, rq->next_balance))
raise_softirq(SCHED_SOFTIRQ);
}
-#else
+
+#else /* CONFIG_SMP */
+
/*
* on UP we do not need to balance between CPUs:
*/
static inline void idle_balance(int cpu, struct rq *rq)
{
}
+
+/* Avoid "used but not defined" warning on UP */
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *load_moved,
+ int this_best_prio, int best_prio, int best_prio_seen,
+ struct rq_iterator *iterator)
+{
+ *load_moved = 0;
+
+ return 0;
+}
+
#endif
DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -3295,54 +3098,28 @@ DEFINE_PER_CPU(struct kernel_stat, kstat);
EXPORT_PER_CPU_SYMBOL(kstat);
/*
- * This is called on clock ticks and on context switches.
- * Bank in p->sched_time the ns elapsed since the last tick or switch.
- */
-static inline void
-update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
-{
- p->sched_time += now - p->last_ran;
- p->last_ran = rq->most_recent_timestamp = now;
-}
-
-/*
- * Return current->sched_time plus any more ns on the sched_clock
- * that have not yet been banked.
+ * Return p->sum_exec_runtime plus any more ns on the sched_clock
+ * that have not yet been banked in case the task is currently running.
*/
-unsigned long long current_sched_time(const struct task_struct *p)
+unsigned long long task_sched_runtime(struct task_struct *p)
{
- unsigned long long ns;
unsigned long flags;
+ u64 ns, delta_exec;
+ struct rq *rq;
- local_irq_save(flags);
- ns = p->sched_time + sched_clock() - p->last_ran;
- local_irq_restore(flags);
+ rq = task_rq_lock(p, &flags);
+ ns = p->se.sum_exec_runtime;
+ if (rq->curr == p) {
+ delta_exec = rq_clock(rq) - p->se.exec_start;
+ if ((s64)delta_exec > 0)
+ ns += delta_exec;
+ }
+ task_rq_unlock(rq, &flags);
return ns;
}
/*
- * We place interactive tasks back into the active array, if possible.
- *
- * To guarantee that this does not starve expired tasks we ignore the
- * interactivity of a task if the first expired task had to wait more
- * than a 'reasonable' amount of time. This deadline timeout is
- * load-dependent, as the frequency of array switched decreases with
- * increasing number of running tasks. We also ignore the interactivity
- * if a better static_prio task has expired:
- */
-static inline int expired_starving(struct rq *rq)
-{
- if (rq->curr->static_prio > rq->best_expired_prio)
- return 1;
- if (!STARVATION_LIMIT || !rq->expired_timestamp)
- return 0;
- if (jiffies - rq->expired_timestamp > STARVATION_LIMIT * rq->nr_running)
- return 1;
- return 0;
-}
-
-/*
* Account user cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @hardirq_offset: the offset to subtract from hardirq_count()
@@ -3415,81 +3192,6 @@ void account_steal_time(struct task_struct *p, cputime_t steal)
cpustat->steal = cputime64_add(cpustat->steal, tmp);
}
-static void task_running_tick(struct rq *rq, struct task_struct *p)
-{
- if (p->array != rq->active) {
- /* Task has expired but was not scheduled yet */
- set_tsk_need_resched(p);
- return;
- }
- spin_lock(&rq->lock);
- /*
- * The task was running during this tick - update the
- * time slice counter. Note: we do not update a thread's
- * priority until it either goes to sleep or uses up its
- * timeslice. This makes it possible for interactive tasks
- * to use up their timeslices at their highest priority levels.
- */
- if (rt_task(p)) {
- /*
- * RR tasks need a special form of timeslice management.
- * FIFO tasks have no timeslices.
- */
- if ((p->policy == SCHED_RR) && !--p->time_slice) {
- p->time_slice = task_timeslice(p);
- p->first_time_slice = 0;
- set_tsk_need_resched(p);
-
- /* put it at the end of the queue: */
- requeue_task(p, rq->active);
- }
- goto out_unlock;
- }
- if (!--p->time_slice) {
- dequeue_task(p, rq->active);
- set_tsk_need_resched(p);
- p->prio = effective_prio(p);
- p->time_slice = task_timeslice(p);
- p->first_time_slice = 0;
-
- if (!rq->expired_timestamp)
- rq->expired_timestamp = jiffies;
- if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
- enqueue_task(p, rq->expired);
- if (p->static_prio < rq->best_expired_prio)
- rq->best_expired_prio = p->static_prio;
- } else
- enqueue_task(p, rq->active);
- } else {
- /*
- * Prevent a too long timeslice allowing a task to monopolize
- * the CPU. We do this by splitting up the timeslice into
- * smaller pieces.
- *
- * Note: this does not mean the task's timeslices expire or
- * get lost in any way, they just might be preempted by
- * another task of equal priority. (one with higher
- * priority would have preempted this task already.) We
- * requeue this task to the end of the list on this priority
- * level, which is in essence a round-robin of tasks with
- * equal priority.
- *
- * This only applies to tasks in the interactive
- * delta range with at least TIMESLICE_GRANULARITY to requeue.
- */
- if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
- p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
- (p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
- (p->array == rq->active)) {
-
- requeue_task(p, rq->active);
- set_tsk_need_resched(p);
- }
- }
-out_unlock:
- spin_unlock(&rq->lock);
-}
-
/*
* This function gets called by the timer code, with HZ frequency.
* We call it with interrupts disabled.
@@ -3499,20 +3201,19 @@ out_unlock:
*/
void scheduler_tick(void)
{
- unsigned long long now = sched_clock();
- struct task_struct *p = current;
int cpu = smp_processor_id();
- int idle_at_tick = idle_cpu(cpu);
struct rq *rq = cpu_rq(cpu);
+ struct task_struct *curr = rq->curr;
- update_cpu_clock(p, rq, now);
+ spin_lock(&rq->lock);
+ if (curr != rq->idle) /* FIXME: needed? */
+ curr->sched_class->task_tick(rq, curr);
+ update_cpu_load(rq);
+ spin_unlock(&rq->lock);
- if (!idle_at_tick)
- task_running_tick(rq, p);
#ifdef CONFIG_SMP
- update_load(rq);
- rq->idle_at_tick = idle_at_tick;
- trigger_load_balance(cpu);
+ rq->idle_at_tick = idle_cpu(cpu);
+ trigger_load_balance(rq, cpu);
#endif
}
@@ -3554,170 +3255,129 @@ EXPORT_SYMBOL(sub_preempt_count);
#endif
-static inline int interactive_sleep(enum sleep_type sleep_type)
+/*
+ * Print scheduling while atomic bug:
+ */
+static noinline void __schedule_bug(struct task_struct *prev)
{
- return (sleep_type == SLEEP_INTERACTIVE ||
- sleep_type == SLEEP_INTERRUPTED);
+ printk(KERN_ERR "BUG: scheduling while atomic: %s/0x%08x/%d\n",
+ prev->comm, preempt_count(), prev->pid);
+ debug_show_held_locks(prev);
+ if (irqs_disabled())
+ print_irqtrace_events(prev);
+ dump_stack();
}
/*
- * schedule() is the main scheduler function.
+ * Various schedule()-time debugging checks and statistics:
*/
-asmlinkage void __sched schedule(void)
+static inline void schedule_debug(struct task_struct *prev)
{
- struct task_struct *prev, *next;
- struct prio_array *array;
- struct list_head *queue;
- unsigned long long now;
- unsigned long run_time;
- int cpu, idx, new_prio;
- long *switch_count;
- struct rq *rq;
-
/*
* Test if we are atomic. Since do_exit() needs to call into
* schedule() atomically, we ignore that path for now.
* Otherwise, whine if we are scheduling when we should not be.
*/
- if (unlikely(in_atomic() && !current->exit_state)) {
- printk(KERN_ERR "BUG: scheduling while atomic: "
- "%s/0x%08x/%d\n",
- current->comm, preempt_count(), current->pid);
- debug_show_held_locks(current);
- if (irqs_disabled())
- print_irqtrace_events(current);
- dump_stack();
- }
- profile_hit(SCHED_PROFILING, __builtin_return_address(0));
+ if (unlikely(in_atomic_preempt_off()) && unlikely(!prev->exit_state))
+ __schedule_bug(prev);
-need_resched:
- preempt_disable();
- prev = current;
- release_kernel_lock(prev);
-need_resched_nonpreemptible:
- rq = this_rq();
+ profile_hit(SCHED_PROFILING, __builtin_return_address(0));
- /*
- * The idle thread is not allowed to schedule!
- * Remove this check after it has been exercised a bit.
- */
- if (unlikely(prev == rq->idle) && prev->state != TASK_RUNNING) {
- printk(KERN_ERR "bad: scheduling from the idle thread!\n");
- dump_stack();
- }
+ schedstat_inc(this_rq(), sched_cnt);
+}
- schedstat_inc(rq, sched_cnt);
- now = sched_clock();
- if (likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) {
- run_time = now - prev->timestamp;
- if (unlikely((long long)(now - prev->timestamp) < 0))
- run_time = 0;
- } else
- run_time = NS_MAX_SLEEP_AVG;
+/*
+ * Pick up the highest-prio task:
+ */
+static inline struct task_struct *
+pick_next_task(struct rq *rq, struct task_struct *prev, u64 now)
+{
+ struct sched_class *class;
+ struct task_struct *p;
/*
- * Tasks charged proportionately less run_time at high sleep_avg to
- * delay them losing their interactive status
+ * Optimization: we know that if all tasks are in
+ * the fair class we can call that function directly:
*/
- run_time /= (CURRENT_BONUS(prev) ? : 1);
-
- spin_lock_irq(&rq->lock);
-
- switch_count = &prev->nivcsw;
- if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
- switch_count = &prev->nvcsw;
- if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
- unlikely(signal_pending(prev))))
- prev->state = TASK_RUNNING;
- else {
- if (prev->state == TASK_UNINTERRUPTIBLE)
- rq->nr_uninterruptible++;
- deactivate_task(prev, rq);
- }
- }
-
- cpu = smp_processor_id();
- if (unlikely(!rq->nr_running)) {
- idle_balance(cpu, rq);
- if (!rq->nr_running) {
- next = rq->idle;
- rq->expired_timestamp = 0;
- goto switch_tasks;
- }
+ if (likely(rq->nr_running == rq->cfs.nr_running)) {
+ p = fair_sched_class.pick_next_task(rq, now);
+ if (likely(p))
+ return p;
}
- array = rq->active;
- if (unlikely(!array->nr_active)) {
+ class = sched_class_highest;
+ for ( ; ; ) {
+ p = class->pick_next_task(rq, now);
+ if (p)
+ return p;
/*
- * Switch the active and expired arrays.
+ * Will never be NULL as the idle class always
+ * returns a non-NULL p:
*/
- schedstat_inc(rq, sched_switch);
- rq->active = rq->expired;
- rq->expired = array;
- array = rq->active;
- rq->expired_timestamp = 0;
- rq->best_expired_prio = MAX_PRIO;
+ class = class->next;
}
+}
+
+/*
+ * schedule() is the main scheduler function.
+ */
+asmlinkage void __sched schedule(void)
+{
+ struct task_struct *prev, *next;
+ long *switch_count;
+ struct rq *rq;
+ u64 now;
+ int cpu;
- idx = sched_find_first_bit(array->bitmap);
- queue = array->queue + idx;
- next = list_entry(queue->next, struct task_struct, run_list);
+need_resched:
+ preempt_disable();
+ cpu = smp_processor_id();
+ rq = cpu_rq(cpu);
+ rcu_qsctr_inc(cpu);
+ prev = rq->curr;
+ switch_count = &prev->nivcsw;
- if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
- unsigned long long delta = now - next->timestamp;
- if (unlikely((long long)(now - next->timestamp) < 0))
- delta = 0;
+ release_kernel_lock(prev);
+need_resched_nonpreemptible:
- if (next->sleep_type == SLEEP_INTERACTIVE)
- delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
+ schedule_debug(prev);
- array = next->array;
- new_prio = recalc_task_prio(next, next->timestamp + delta);
+ spin_lock_irq(&rq->lock);
+ clear_tsk_need_resched(prev);
- if (unlikely(next->prio != new_prio)) {
- dequeue_task(next, array);
- next->prio = new_prio;
- enqueue_task(next, array);
+ if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
+ if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
+ unlikely(signal_pending(prev)))) {
+ prev->state = TASK_RUNNING;
+ } else {
+ deactivate_task(rq, prev, 1);
}
+ switch_count = &prev->nvcsw;
}
- next->sleep_type = SLEEP_NORMAL;
-switch_tasks:
- if (next == rq->idle)
- schedstat_inc(rq, sched_goidle);
- prefetch(next);
- prefetch_stack(next);
- clear_tsk_need_resched(prev);
- rcu_qsctr_inc(task_cpu(prev));
- update_cpu_clock(prev, rq, now);
+ if (unlikely(!rq->nr_running))
+ idle_balance(cpu, rq);
- prev->sleep_avg -= run_time;
- if ((long)prev->sleep_avg <= 0)
- prev->sleep_avg = 0;
- prev->timestamp = prev->last_ran = now;
+ now = __rq_clock(rq);
+ prev->sched_class->put_prev_task(rq, prev, now);
+ next = pick_next_task(rq, prev, now);
sched_info_switch(prev, next);
+
if (likely(prev != next)) {
- next->timestamp = next->last_ran = now;
rq->nr_switches++;
rq->curr = next;
++*switch_count;
- prepare_task_switch(rq, next);
- prev = context_switch(rq, prev, next);
- barrier();
- /*
- * this_rq must be evaluated again because prev may have moved
- * CPUs since it called schedule(), thus the 'rq' on its stack
- * frame will be invalid.
- */
- finish_task_switch(this_rq(), prev);
+ context_switch(rq, prev, next); /* unlocks the rq */
} else
spin_unlock_irq(&rq->lock);
- prev = current;
- if (unlikely(reacquire_kernel_lock(prev) < 0))
+ if (unlikely(reacquire_kernel_lock(current) < 0)) {
+ cpu = smp_processor_id();
+ rq = cpu_rq(cpu);
goto need_resched_nonpreemptible;
+ }
preempt_enable_no_resched();
if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
goto need_resched;
@@ -4045,74 +3705,85 @@ out:
}
EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
-
-#define SLEEP_ON_VAR \
- unsigned long flags; \
- wait_queue_t wait; \
- init_waitqueue_entry(&wait, current);
-
-#define SLEEP_ON_HEAD \
- spin_lock_irqsave(&q->lock,flags); \
- __add_wait_queue(q, &wait); \
+static inline void
+sleep_on_head(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags)
+{
+ spin_lock_irqsave(&q->lock, *flags);
+ __add_wait_queue(q, wait);
spin_unlock(&q->lock);
+}
-#define SLEEP_ON_TAIL \
- spin_lock_irq(&q->lock); \
- __remove_wait_queue(q, &wait); \
- spin_unlock_irqrestore(&q->lock, flags);
+static inline void
+sleep_on_tail(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags)
+{
+ spin_lock_irq(&q->lock);
+ __remove_wait_queue(q, wait);
+ spin_unlock_irqrestore(&q->lock, *flags);
+}
-void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
+void __sched interruptible_sleep_on(wait_queue_head_t *q)
{
- SLEEP_ON_VAR
+ unsigned long flags;
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
current->state = TASK_INTERRUPTIBLE;
- SLEEP_ON_HEAD
+ sleep_on_head(q, &wait, &flags);
schedule();
- SLEEP_ON_TAIL
+ sleep_on_tail(q, &wait, &flags);
}
EXPORT_SYMBOL(interruptible_sleep_on);
-long fastcall __sched
+long __sched
interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
{
- SLEEP_ON_VAR
+ unsigned long flags;
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
current->state = TASK_INTERRUPTIBLE;
- SLEEP_ON_HEAD
+ sleep_on_head(q, &wait, &flags);
timeout = schedule_timeout(timeout);
- SLEEP_ON_TAIL
+ sleep_on_tail(q, &wait, &flags);
return timeout;
}
EXPORT_SYMBOL(interruptible_sleep_on_timeout);
-void fastcall __sched sleep_on(wait_queue_head_t *q)
+void __sched sleep_on(wait_queue_head_t *q)
{
- SLEEP_ON_VAR
+ unsigned long flags;
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
current->state = TASK_UNINTERRUPTIBLE;
- SLEEP_ON_HEAD
+ sleep_on_head(q, &wait, &flags);
schedule();
- SLEEP_ON_TAIL
+ sleep_on_tail(q, &wait, &flags);
}
EXPORT_SYMBOL(sleep_on);
-long fastcall __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
{
- SLEEP_ON_VAR
+ unsigned long flags;
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
current->state = TASK_UNINTERRUPTIBLE;
- SLEEP_ON_HEAD
+ sleep_on_head(q, &wait, &flags);
timeout = schedule_timeout(timeout);
- SLEEP_ON_TAIL
+ sleep_on_tail(q, &wait, &flags);
return timeout;
}
-
EXPORT_SYMBOL(sleep_on_timeout);
#ifdef CONFIG_RT_MUTEXES
@@ -4129,29 +3800,30 @@ EXPORT_SYMBOL(sleep_on_timeout);
*/
void rt_mutex_setprio(struct task_struct *p, int prio)
{
- struct prio_array *array;
unsigned long flags;
+ int oldprio, on_rq;
struct rq *rq;
- int oldprio;
+ u64 now;
BUG_ON(prio < 0 || prio > MAX_PRIO);
rq = task_rq_lock(p, &flags);
+ now = rq_clock(rq);
oldprio = p->prio;
- array = p->array;
- if (array)
- dequeue_task(p, array);
+ on_rq = p->se.on_rq;
+ if (on_rq)
+ dequeue_task(rq, p, 0, now);
+
+ if (rt_prio(prio))
+ p->sched_class = &rt_sched_class;
+ else
+ p->sched_class = &fair_sched_class;
+
p->prio = prio;
- if (array) {
- /*
- * If changing to an RT priority then queue it
- * in the active array!
- */
- if (rt_task(p))
- array = rq->active;
- enqueue_task(p, array);
+ if (on_rq) {
+ enqueue_task(rq, p, 0, now);
/*
* Reschedule if we are currently running on this runqueue and
* our priority decreased, or if we are not currently running on
@@ -4160,8 +3832,9 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
if (task_running(rq, p)) {
if (p->prio > oldprio)
resched_task(rq->curr);
- } else if (TASK_PREEMPTS_CURR(p, rq))
- resched_task(rq->curr);
+ } else {
+ check_preempt_curr(rq, p);
+ }
}
task_rq_unlock(rq, &flags);
}
@@ -4170,10 +3843,10 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
void set_user_nice(struct task_struct *p, long nice)
{
- struct prio_array *array;
- int old_prio, delta;
+ int old_prio, delta, on_rq;
unsigned long flags;
struct rq *rq;
+ u64 now;
if (TASK_NICE(p) == nice || nice < -20 || nice > 19)
return;
@@ -4182,20 +3855,21 @@ void set_user_nice(struct task_struct *p, long nice)
* the task might be in the middle of scheduling on another CPU.
*/
rq = task_rq_lock(p, &flags);
+ now = rq_clock(rq);
/*
* The RT priorities are set via sched_setscheduler(), but we still
* allow the 'normal' nice value to be set - but as expected
* it wont have any effect on scheduling until the task is
- * not SCHED_NORMAL/SCHED_BATCH:
+ * SCHED_FIFO/SCHED_RR:
*/
- if (has_rt_policy(p)) {
+ if (task_has_rt_policy(p)) {
p->static_prio = NICE_TO_PRIO(nice);
goto out_unlock;
}
- array = p->array;
- if (array) {
- dequeue_task(p, array);
- dec_raw_weighted_load(rq, p);
+ on_rq = p->se.on_rq;
+ if (on_rq) {
+ dequeue_task(rq, p, 0, now);
+ dec_load(rq, p, now);
}
p->static_prio = NICE_TO_PRIO(nice);
@@ -4204,9 +3878,9 @@ void set_user_nice(struct task_struct *p, long nice)
p->prio = effective_prio(p);
delta = p->prio - old_prio;
- if (array) {
- enqueue_task(p, array);
- inc_raw_weighted_load(rq, p);
+ if (on_rq) {
+ enqueue_task(rq, p, 0, now);
+ inc_load(rq, p, now);
/*
* If the task increased its priority or is running and
* lowered its priority, then reschedule its CPU:
@@ -4326,20 +4000,28 @@ static inline struct task_struct *find_process_by_pid(pid_t pid)
}
/* Actually do priority change: must hold rq lock. */
-static void __setscheduler(struct task_struct *p, int policy, int prio)
+static void
+__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
{
- BUG_ON(p->array);
+ BUG_ON(p->se.on_rq);
p->policy = policy;
+ switch (p->policy) {
+ case SCHED_NORMAL:
+ case SCHED_BATCH:
+ case SCHED_IDLE:
+ p->sched_class = &fair_sched_class;
+ break;
+ case SCHED_FIFO:
+ case SCHED_RR:
+ p->sched_class = &rt_sched_class;
+ break;
+ }
+
p->rt_priority = prio;
p->normal_prio = normal_prio(p);
/* we are holding p->pi_lock already */
p->prio = rt_mutex_getprio(p);
- /*
- * SCHED_BATCH tasks are treated as perpetual CPU hogs:
- */
- if (policy == SCHED_BATCH)
- p->sleep_avg = 0;
set_load_weight(p);
}
@@ -4354,8 +4036,7 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
int sched_setscheduler(struct task_struct *p, int policy,
struct sched_param *param)
{
- int retval, oldprio, oldpolicy = -1;
- struct prio_array *array;
+ int retval, oldprio, oldpolicy = -1, on_rq;
unsigned long flags;
struct rq *rq;
@@ -4366,27 +4047,27 @@ recheck:
if (policy < 0)
policy = oldpolicy = p->policy;
else if (policy != SCHED_FIFO && policy != SCHED_RR &&
- policy != SCHED_NORMAL && policy != SCHED_BATCH)
+ policy != SCHED_NORMAL && policy != SCHED_BATCH &&
+ policy != SCHED_IDLE)
return -EINVAL;
/*
* Valid priorities for SCHED_FIFO and SCHED_RR are
- * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and
- * SCHED_BATCH is 0.
+ * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL,
+ * SCHED_BATCH and SCHED_IDLE is 0.
*/
if (param->sched_priority < 0 ||
(p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
(!p->mm && param->sched_priority > MAX_RT_PRIO-1))
return -EINVAL;
- if (is_rt_policy(policy) != (param->sched_priority != 0))
+ if (rt_policy(policy) != (param->sched_priority != 0))
return -EINVAL;
/*
* Allow unprivileged RT tasks to decrease priority:
*/
if (!capable(CAP_SYS_NICE)) {
- if (is_rt_policy(policy)) {
+ if (rt_policy(policy)) {
unsigned long rlim_rtprio;
- unsigned long flags;
if (!lock_task_sighand(p, &flags))
return -ESRCH;
@@ -4402,6 +4083,12 @@ recheck:
param->sched_priority > rlim_rtprio)
return -EPERM;
}
+ /*
+ * Like positive nice levels, dont allow tasks to
+ * move out of SCHED_IDLE either:
+ */
+ if (p->policy == SCHED_IDLE && policy != SCHED_IDLE)
+ return -EPERM;
/* can't change other user's priorities */
if ((current->euid != p->euid) &&
@@ -4429,13 +4116,13 @@ recheck:
spin_unlock_irqrestore(&p->pi_lock, flags);
goto recheck;
}
- array = p->array;
- if (array)
- deactivate_task(p, rq);
+ on_rq = p->se.on_rq;
+ if (on_rq)
+ deactivate_task(rq, p, 0);
oldprio = p->prio;
- __setscheduler(p, policy, param->sched_priority);
- if (array) {
- __activate_task(p, rq);
+ __setscheduler(rq, p, policy, param->sched_priority);
+ if (on_rq) {
+ activate_task(rq, p, 0);
/*
* Reschedule if we are currently running on this runqueue and
* our priority decreased, or if we are not currently running on
@@ -4444,8 +4131,9 @@ recheck:
if (task_running(rq, p)) {
if (p->prio > oldprio)
resched_task(rq->curr);
- } else if (TASK_PREEMPTS_CURR(p, rq))
- resched_task(rq->curr);
+ } else {
+ check_preempt_curr(rq, p);
+ }
}
__task_rq_unlock(rq);
spin_unlock_irqrestore(&p->pi_lock, flags);
@@ -4717,41 +4405,18 @@ asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
/**
* sys_sched_yield - yield the current processor to other threads.
*
- * This function yields the current CPU by moving the calling thread
- * to the expired array. If there are no other threads running on this
- * CPU then this function will return.
+ * This function yields the current CPU to other tasks. If there are no
+ * other threads running on this CPU then this function will return.
*/
asmlinkage long sys_sched_yield(void)
{
struct rq *rq = this_rq_lock();
- struct prio_array *array = current->array, *target = rq->expired;
schedstat_inc(rq, yld_cnt);
- /*
- * We implement yielding by moving the task into the expired
- * queue.
- *
- * (special rule: RT tasks will just roundrobin in the active
- * array.)
- */
- if (rt_task(current))
- target = rq->active;
-
- if (array->nr_active == 1) {
+ if (unlikely(rq->nr_running == 1))
schedstat_inc(rq, yld_act_empty);
- if (!rq->expired->nr_active)
- schedstat_inc(rq, yld_both_empty);
- } else if (!rq->expired->nr_active)
- schedstat_inc(rq, yld_exp_empty);
-
- if (array != target) {
- dequeue_task(current, array);
- enqueue_task(current, target);
- } else
- /*
- * requeue_task is cheaper so perform that if possible.
- */
- requeue_task(current, array);
+ else
+ current->sched_class->yield_task(rq, current);
/*
* Since we are going to call schedule() anyway, there's
@@ -4902,6 +4567,7 @@ asmlinkage long sys_sched_get_priority_max(int policy)
break;
case SCHED_NORMAL:
case SCHED_BATCH:
+ case SCHED_IDLE:
ret = 0;
break;
}
@@ -4926,6 +4592,7 @@ asmlinkage long sys_sched_get_priority_min(int policy)
break;
case SCHED_NORMAL:
case SCHED_BATCH:
+ case SCHED_IDLE:
ret = 0;
}
return ret;
@@ -4960,7 +4627,7 @@ long sys_sched_rr_get_interval(pid_t pid, struct timespec __user *interval)
goto out_unlock;
jiffies_to_timespec(p->policy == SCHED_FIFO ?
- 0 : task_timeslice(p), &t);
+ 0 : static_prio_timeslice(p->static_prio), &t);
read_unlock(&tasklist_lock);
retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
out_nounlock:
@@ -5035,6 +4702,9 @@ void show_state_filter(unsigned long state_filter)
touch_all_softlockup_watchdogs();
+#ifdef CONFIG_SCHED_DEBUG
+ sysrq_sched_debug_show();
+#endif
read_unlock(&tasklist_lock);
/*
* Only show locks if all tasks are dumped:
@@ -5043,6 +4713,11 @@ void show_state_filter(unsigned long state_filter)
debug_show_all_locks();
}
+void __cpuinit init_idle_bootup_task(struct task_struct *idle)
+{
+ idle->sched_class = &idle_sched_class;
+}
+
/**
* init_idle - set up an idle thread for a given CPU
* @idle: task in question
@@ -5056,13 +4731,12 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
struct rq *rq = cpu_rq(cpu);
unsigned long flags;
- idle->timestamp = sched_clock();
- idle->sleep_avg = 0;
- idle->array = NULL;
+ __sched_fork(idle);
+ idle->se.exec_start = sched_clock();
+
idle->prio = idle->normal_prio = MAX_PRIO;
- idle->state = TASK_RUNNING;
idle->cpus_allowed = cpumask_of_cpu(cpu);
- set_task_cpu(idle, cpu);
+ __set_task_cpu(idle, cpu);
spin_lock_irqsave(&rq->lock, flags);
rq->curr = rq->idle = idle;
@@ -5077,6 +4751,10 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
#else
task_thread_info(idle)->preempt_count = 0;
#endif
+ /*
+ * The idle tasks have their own, simple scheduling class:
+ */
+ idle->sched_class = &idle_sched_class;
}
/*
@@ -5088,6 +4766,28 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
*/
cpumask_t nohz_cpu_mask = CPU_MASK_NONE;
+/*
+ * Increase the granularity value when there are more CPUs,
+ * because with more CPUs the 'effective latency' as visible
+ * to users decreases. But the relationship is not linear,
+ * so pick a second-best guess by going with the log2 of the
+ * number of CPUs.
+ *
+ * This idea comes from the SD scheduler of Con Kolivas:
+ */
+static inline void sched_init_granularity(void)
+{
+ unsigned int factor = 1 + ilog2(num_online_cpus());
+ const unsigned long gran_limit = 10000000;
+
+ sysctl_sched_granularity *= factor;
+ if (sysctl_sched_granularity > gran_limit)
+ sysctl_sched_granularity = gran_limit;
+
+ sysctl_sched_runtime_limit = sysctl_sched_granularity * 4;
+ sysctl_sched_wakeup_granularity = sysctl_sched_granularity / 2;
+}
+
#ifdef CONFIG_SMP
/*
* This is how migration works:
@@ -5161,7 +4861,7 @@ EXPORT_SYMBOL_GPL(set_cpus_allowed);
static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
{
struct rq *rq_dest, *rq_src;
- int ret = 0;
+ int ret = 0, on_rq;
if (unlikely(cpu_is_offline(dest_cpu)))
return ret;
@@ -5177,20 +4877,13 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
if (!cpu_isset(dest_cpu, p->cpus_allowed))
goto out;
+ on_rq = p->se.on_rq;
+ if (on_rq)
+ deactivate_task(rq_src, p, 0);
set_task_cpu(p, dest_cpu);
- if (p->array) {
- /*
- * Sync timestamp with rq_dest's before activating.
- * The same thing could be achieved by doing this step
- * afterwards, and pretending it was a local activate.
- * This way is cleaner and logically correct.
- */
- p->timestamp = p->timestamp - rq_src->most_recent_timestamp
- + rq_dest->most_recent_timestamp;
- deactivate_task(p, rq_src);
- __activate_task(p, rq_dest);
- if (TASK_PREEMPTS_CURR(p, rq_dest))
- resched_task(rq_dest->curr);
+ if (on_rq) {
+ activate_task(rq_dest, p, 0);
+ check_preempt_curr(rq_dest, p);
}
ret = 1;
out:
@@ -5342,7 +5035,8 @@ static void migrate_live_tasks(int src_cpu)
write_unlock_irq(&tasklist_lock);
}
-/* Schedules idle task to be the next runnable task on current CPU.
+/*
+ * Schedules idle task to be the next runnable task on current CPU.
* It does so by boosting its priority to highest possible and adding it to
* the _front_ of the runqueue. Used by CPU offline code.
*/
@@ -5362,10 +5056,10 @@ void sched_idle_next(void)
*/
spin_lock_irqsave(&rq->lock, flags);
- __setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
+ __setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
/* Add idle task to the _front_ of its priority queue: */
- __activate_idle_task(p, rq);
+ activate_idle_task(p, rq);
spin_unlock_irqrestore(&rq->lock, flags);
}
@@ -5415,16 +5109,15 @@ static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
static void migrate_dead_tasks(unsigned int dead_cpu)
{
struct rq *rq = cpu_rq(dead_cpu);
- unsigned int arr, i;
+ struct task_struct *next;
- for (arr = 0; arr < 2; arr++) {
- for (i = 0; i < MAX_PRIO; i++) {
- struct list_head *list = &rq->arrays[arr].queue[i];
-
- while (!list_empty(list))
- migrate_dead(dead_cpu, list_entry(list->next,
- struct task_struct, run_list));
- }
+ for ( ; ; ) {
+ if (!rq->nr_running)
+ break;
+ next = pick_next_task(rq, rq->curr, rq_clock(rq));
+ if (!next)
+ break;
+ migrate_dead(dead_cpu, next);
}
}
#endif /* CONFIG_HOTPLUG_CPU */
@@ -5448,14 +5141,14 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
- p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
+ p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);
if (IS_ERR(p))
return NOTIFY_BAD;
p->flags |= PF_NOFREEZE;
kthread_bind(p, cpu);
/* Must be high prio: stop_machine expects to yield to it. */
rq = task_rq_lock(p, &flags);
- __setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
+ __setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
task_rq_unlock(rq, &flags);
cpu_rq(cpu)->migration_thread = p;
break;
@@ -5486,9 +5179,10 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
rq->migration_thread = NULL;
/* Idle task back to normal (off runqueue, low prio) */
rq = task_rq_lock(rq->idle, &flags);
- deactivate_task(rq->idle, rq);
+ deactivate_task(rq, rq->idle, 0);
rq->idle->static_prio = MAX_PRIO;
- __setscheduler(rq->idle, SCHED_NORMAL, 0);
+ __setscheduler(rq, rq->idle, SCHED_NORMAL, 0);
+ rq->idle->sched_class = &idle_sched_class;
migrate_dead_tasks(cpu);
task_rq_unlock(rq, &flags);
migrate_nr_uninterruptible(rq);
@@ -5797,483 +5491,6 @@ init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
#define SD_NODES_PER_DOMAIN 16
-/*
- * Self-tuning task migration cost measurement between source and target CPUs.
- *
- * This is done by measuring the cost of manipulating buffers of varying
- * sizes. For a given buffer-size here are the steps that are taken:
- *
- * 1) the source CPU reads+dirties a shared buffer
- * 2) the target CPU reads+dirties the same shared buffer
- *
- * We measure how long they take, in the following 4 scenarios:
- *
- * - source: CPU1, target: CPU2 | cost1
- * - source: CPU2, target: CPU1 | cost2
- * - source: CPU1, target: CPU1 | cost3
- * - source: CPU2, target: CPU2 | cost4
- *
- * We then calculate the cost3+cost4-cost1-cost2 difference - this is
- * the cost of migration.
- *
- * We then start off from a small buffer-size and iterate up to larger
- * buffer sizes, in 5% steps - measuring each buffer-size separately, and
- * doing a maximum search for the cost. (The maximum cost for a migration
- * normally occurs when the working set size is around the effective cache
- * size.)
- */
-#define SEARCH_SCOPE 2
-#define MIN_CACHE_SIZE (64*1024U)
-#define DEFAULT_CACHE_SIZE (5*1024*1024U)
-#define ITERATIONS 1
-#define SIZE_THRESH 130
-#define COST_THRESH 130
-
-/*
- * The migration cost is a function of 'domain distance'. Domain
- * distance is the number of steps a CPU has to iterate down its
- * domain tree to share a domain with the other CPU. The farther
- * two CPUs are from each other, the larger the distance gets.
- *
- * Note that we use the distance only to cache measurement results,
- * the distance value is not used numerically otherwise. When two
- * CPUs have the same distance it is assumed that the migration
- * cost is the same. (this is a simplification but quite practical)
- */
-#define MAX_DOMAIN_DISTANCE 32
-
-static unsigned long long migration_cost[MAX_DOMAIN_DISTANCE] =
- { [ 0 ... MAX_DOMAIN_DISTANCE-1 ] =
-/*
- * Architectures may override the migration cost and thus avoid
- * boot-time calibration. Unit is nanoseconds. Mostly useful for
- * virtualized hardware:
- */
-#ifdef CONFIG_DEFAULT_MIGRATION_COST
- CONFIG_DEFAULT_MIGRATION_COST
-#else
- -1LL
-#endif
-};
-
-/*
- * Allow override of migration cost - in units of microseconds.
- * E.g. migration_cost=1000,2000,3000 will set up a level-1 cost
- * of 1 msec, level-2 cost of 2 msecs and level3 cost of 3 msecs:
- */
-static int __init migration_cost_setup(char *str)
-{
- int ints[MAX_DOMAIN_DISTANCE+1], i;
-
- str = get_options(str, ARRAY_SIZE(ints), ints);
-
- printk("#ints: %d\n", ints[0]);
- for (i = 1; i <= ints[0]; i++) {
- migration_cost[i-1] = (unsigned long long)ints[i]*1000;
- printk("migration_cost[%d]: %Ld\n", i-1, migration_cost[i-1]);
- }
- return 1;
-}
-
-__setup ("migration_cost=", migration_cost_setup);
-
-/*
- * Global multiplier (divisor) for migration-cutoff values,
- * in percentiles. E.g. use a value of 150 to get 1.5 times
- * longer cache-hot cutoff times.
- *
- * (We scale it from 100 to 128 to long long handling easier.)
- */
-
-#define MIGRATION_FACTOR_SCALE 128
-
-static unsigned int migration_factor = MIGRATION_FACTOR_SCALE;
-
-static int __init setup_migration_factor(char *str)
-{
- get_option(&str, &migration_factor);
- migration_factor = migration_factor * MIGRATION_FACTOR_SCALE / 100;
- return 1;
-}
-
-__setup("migration_factor=", setup_migration_factor);
-
-/*
- * Estimated distance of two CPUs, measured via the number of domains
- * we have to pass for the two CPUs to be in the same span:
- */
-static unsigned long domain_distance(int cpu1, int cpu2)
-{
- unsigned long distance = 0;
- struct sched_domain *sd;
-
- for_each_domain(cpu1, sd) {
- WARN_ON(!cpu_isset(cpu1, sd->span));
- if (cpu_isset(cpu2, sd->span))
- return distance;
- distance++;
- }
- if (distance >= MAX_DOMAIN_DISTANCE) {
- WARN_ON(1);
- distance = MAX_DOMAIN_DISTANCE-1;
- }
-
- return distance;
-}
-
-static unsigned int migration_debug;
-
-static int __init setup_migration_debug(char *str)
-{
- get_option(&str, &migration_debug);
- return 1;
-}
-
-__setup("migration_debug=", setup_migration_debug);
-
-/*
- * Maximum cache-size that the scheduler should try to measure.
- * Architectures with larger caches should tune this up during
- * bootup. Gets used in the domain-setup code (i.e. during SMP
- * bootup).
- */
-unsigned int max_cache_size;
-
-static int __init setup_max_cache_size(char *str)
-{
- get_option(&str, &max_cache_size);
- return 1;
-}
-
-__setup("max_cache_size=", setup_max_cache_size);
-
-/*
- * Dirty a big buffer in a hard-to-predict (for the L2 cache) way. This
- * is the operation that is timed, so we try to generate unpredictable
- * cachemisses that still end up filling the L2 cache:
- */
-static void touch_cache(void *__cache, unsigned long __size)
-{
- unsigned long size = __size / sizeof(long);
- unsigned long chunk1 = size / 3;
- unsigned long chunk2 = 2 * size / 3;
- unsigned long *cache = __cache;
- int i;
-
- for (i = 0; i < size/6; i += 8) {
- switch (i % 6) {
- case 0: cache[i]++;
- case 1: cache[size-1-i]++;
- case 2: cache[chunk1-i]++;
- case 3: cache[chunk1+i]++;
- case 4: cache[chunk2-i]++;
- case 5: cache[chunk2+i]++;
- }
- }
-}
-
-/*
- * Measure the cache-cost of one task migration. Returns in units of nsec.
- */
-static unsigned long long
-measure_one(void *cache, unsigned long size, int source, int target)
-{
- cpumask_t mask, saved_mask;
- unsigned long long t0, t1, t2, t3, cost;
-
- saved_mask = current->cpus_allowed;
-
- /*
- * Flush source caches to RAM and invalidate them:
- */
- sched_cacheflush();
-
- /*
- * Migrate to the source CPU:
- */
- mask = cpumask_of_cpu(source);
- set_cpus_allowed(current, mask);
- WARN_ON(smp_processor_id() != source);
-
- /*
- * Dirty the working set:
- */
- t0 = sched_clock();
- touch_cache(cache, size);
- t1 = sched_clock();
-
- /*
- * Migrate to the target CPU, dirty the L2 cache and access
- * the shared buffer. (which represents the working set
- * of a migrated task.)
- */
- mask = cpumask_of_cpu(target);
- set_cpus_allowed(current, mask);
- WARN_ON(smp_processor_id() != target);
-
- t2 = sched_clock();
- touch_cache(cache, size);
- t3 = sched_clock();
-
- cost = t1-t0 + t3-t2;
-
- if (migration_debug >= 2)
- printk("[%d->%d]: %8Ld %8Ld %8Ld => %10Ld.\n",
- source, target, t1-t0, t1-t0, t3-t2, cost);
- /*
- * Flush target caches to RAM and invalidate them:
- */
- sched_cacheflush();
-
- set_cpus_allowed(current, saved_mask);
-
- return cost;
-}
-
-/*
- * Measure a series of task migrations and return the average
- * result. Since this code runs early during bootup the system
- * is 'undisturbed' and the average latency makes sense.
- *
- * The algorithm in essence auto-detects the relevant cache-size,
- * so it will properly detect different cachesizes for different
- * cache-hierarchies, depending on how the CPUs are connected.
- *
- * Architectures can prime the upper limit of the search range via
- * max_cache_size, otherwise the search range defaults to 20MB...64K.
- */
-static unsigned long long
-measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
-{
- unsigned long long cost1, cost2;
- int i;
-
- /*
- * Measure the migration cost of 'size' bytes, over an
- * average of 10 runs:
- *
- * (We perturb the cache size by a small (0..4k)
- * value to compensate size/alignment related artifacts.
- * We also subtract the cost of the operation done on
- * the same CPU.)
- */
- cost1 = 0;
-
- /*
- * dry run, to make sure we start off cache-cold on cpu1,
- * and to get any vmalloc pagefaults in advance:
- */
- measure_one(cache, size, cpu1, cpu2);
- for (i = 0; i < ITERATIONS; i++)
- cost1 += measure_one(cache, size - i * 1024, cpu1, cpu2);
-
- measure_one(cache, size, cpu2, cpu1);
- for (i = 0; i < ITERATIONS; i++)
- cost1 += measure_one(cache, size - i * 1024, cpu2, cpu1);
-
- /*
- * (We measure the non-migrating [cached] cost on both
- * cpu1 and cpu2, to handle CPUs with different speeds)
- */
- cost2 = 0;
-
- measure_one(cache, size, cpu1, cpu1);
- for (i = 0; i < ITERATIONS; i++)
- cost2 += measure_one(cache, size - i * 1024, cpu1, cpu1);
-
- measure_one(cache, size, cpu2, cpu2);
- for (i = 0; i < ITERATIONS; i++)
- cost2 += measure_one(cache, size - i * 1024, cpu2, cpu2);
-
- /*
- * Get the per-iteration migration cost:
- */
- do_div(cost1, 2 * ITERATIONS);
- do_div(cost2, 2 * ITERATIONS);
-
- return cost1 - cost2;
-}
-
-static unsigned long long measure_migration_cost(int cpu1, int cpu2)
-{
- unsigned long long max_cost = 0, fluct = 0, avg_fluct = 0;
- unsigned int max_size, size, size_found = 0;
- long long cost = 0, prev_cost;
- void *cache;
-
- /*
- * Search from max_cache_size*5 down to 64K - the real relevant
- * cachesize has to lie somewhere inbetween.
- */
- if (max_cache_size) {
- max_size = max(max_cache_size * SEARCH_SCOPE, MIN_CACHE_SIZE);
- size = max(max_cache_size / SEARCH_SCOPE, MIN_CACHE_SIZE);
- } else {
- /*
- * Since we have no estimation about the relevant
- * search range
- */
- max_size = DEFAULT_CACHE_SIZE * SEARCH_SCOPE;
- size = MIN_CACHE_SIZE;
- }
-
- if (!cpu_online(cpu1) || !cpu_online(cpu2)) {
- printk("cpu %d and %d not both online!\n", cpu1, cpu2);
- return 0;
- }
-
- /*
- * Allocate the working set:
- */
- cache = vmalloc(max_size);
- if (!cache) {
- printk("could not vmalloc %d bytes for cache!\n", 2 * max_size);
- return 1000000; /* return 1 msec on very small boxen */
- }
-
- while (size <= max_size) {
- prev_cost = cost;
- cost = measure_cost(cpu1, cpu2, cache, size);
-
- /*
- * Update the max:
- */
- if (cost > 0) {
- if (max_cost < cost) {
- max_cost = cost;
- size_found = size;
- }
- }
- /*
- * Calculate average fluctuation, we use this to prevent
- * noise from triggering an early break out of the loop:
- */
- fluct = abs(cost - prev_cost);
- avg_fluct = (avg_fluct + fluct)/2;
-
- if (migration_debug)
- printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): "
- "(%8Ld %8Ld)\n",
- cpu1, cpu2, size,
- (long)cost / 1000000,
- ((long)cost / 100000) % 10,
- (long)max_cost / 1000000,
- ((long)max_cost / 100000) % 10,
- domain_distance(cpu1, cpu2),
- cost, avg_fluct);
-
- /*
- * If we iterated at least 20% past the previous maximum,
- * and the cost has dropped by more than 20% already,
- * (taking fluctuations into account) then we assume to
- * have found the maximum and break out of the loop early:
- */
- if (size_found && (size*100 > size_found*SIZE_THRESH))
- if (cost+avg_fluct <= 0 ||
- max_cost*100 > (cost+avg_fluct)*COST_THRESH) {
-
- if (migration_debug)
- printk("-> found max.\n");
- break;
- }
- /*
- * Increase the cachesize in 10% steps:
- */
- size = size * 10 / 9;
- }
-
- if (migration_debug)
- printk("[%d][%d] working set size found: %d, cost: %Ld\n",
- cpu1, cpu2, size_found, max_cost);
-
- vfree(cache);
-
- /*
- * A task is considered 'cache cold' if at least 2 times
- * the worst-case cost of migration has passed.
- *
- * (this limit is only listened to if the load-balancing
- * situation is 'nice' - if there is a large imbalance we
- * ignore it for the sake of CPU utilization and
- * processing fairness.)
- */
- return 2 * max_cost * migration_factor / MIGRATION_FACTOR_SCALE;
-}
-
-static void calibrate_migration_costs(const cpumask_t *cpu_map)
-{
- int cpu1 = -1, cpu2 = -1, cpu, orig_cpu = raw_smp_processor_id();
- unsigned long j0, j1, distance, max_distance = 0;
- struct sched_domain *sd;
-
- j0 = jiffies;
-
- /*
- * First pass - calculate the cacheflush times:
- */
- for_each_cpu_mask(cpu1, *cpu_map) {
- for_each_cpu_mask(cpu2, *cpu_map) {
- if (cpu1 == cpu2)
- continue;
- distance = domain_distance(cpu1, cpu2);
- max_distance = max(max_distance, distance);
- /*
- * No result cached yet?
- */
- if (migration_cost[distance] == -1LL)
- migration_cost[distance] =
- measure_migration_cost(cpu1, cpu2);
- }
- }
- /*
- * Second pass - update the sched domain hierarchy with
- * the new cache-hot-time estimations:
- */
- for_each_cpu_mask(cpu, *cpu_map) {
- distance = 0;
- for_each_domain(cpu, sd) {
- sd->cache_hot_time = migration_cost[distance];
- distance++;
- }
- }
- /*
- * Print the matrix:
- */
- if (migration_debug)
- printk("migration: max_cache_size: %d, cpu: %d MHz:\n",
- max_cache_size,
-#ifdef CONFIG_X86
- cpu_khz/1000
-#else
- -1
-#endif
- );
- if (system_state == SYSTEM_BOOTING && num_online_cpus() > 1) {
- printk("migration_cost=");
- for (distance = 0; distance <= max_distance; distance++) {
- if (distance)
- printk(",");
- printk("%ld", (long)migration_cost[distance] / 1000);
- }
- printk("\n");
- }
- j1 = jiffies;
- if (migration_debug)
- printk("migration: %ld seconds\n", (j1-j0) / HZ);
-
- /*
- * Move back to the original CPU. NUMA-Q gets confused
- * if we migrate to another quad during bootup.
- */
- if (raw_smp_processor_id() != orig_cpu) {
- cpumask_t mask = cpumask_of_cpu(orig_cpu),
- saved_mask = current->cpus_allowed;
-
- set_cpus_allowed(current, mask);
- set_cpus_allowed(current, saved_mask);
- }
-}
-
#ifdef CONFIG_NUMA
/**
@@ -6574,7 +5791,6 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
static int build_sched_domains(const cpumask_t *cpu_map)
{
int i;
- struct sched_domain *sd;
#ifdef CONFIG_NUMA
struct sched_group **sched_group_nodes = NULL;
int sd_allnodes = 0;
@@ -6582,7 +5798,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
/*
* Allocate the per-node list of sched groups
*/
- sched_group_nodes = kzalloc(sizeof(struct sched_group*)*MAX_NUMNODES,
+ sched_group_nodes = kzalloc(sizeof(struct sched_group *)*MAX_NUMNODES,
GFP_KERNEL);
if (!sched_group_nodes) {
printk(KERN_WARNING "Can not alloc sched group node list\n");
@@ -6601,8 +5817,8 @@ static int build_sched_domains(const cpumask_t *cpu_map)
cpus_and(nodemask, nodemask, *cpu_map);
#ifdef CONFIG_NUMA
- if (cpus_weight(*cpu_map)
- > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
+ if (cpus_weight(*cpu_map) >
+ SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
sd = &per_cpu(allnodes_domains, i);
*sd = SD_ALLNODES_INIT;
sd->span = *cpu_map;
@@ -6661,7 +5877,8 @@ static int build_sched_domains(const cpumask_t *cpu_map)
if (i != first_cpu(this_sibling_map))
continue;
- init_sched_build_groups(this_sibling_map, cpu_map, &cpu_to_cpu_group);
+ init_sched_build_groups(this_sibling_map, cpu_map,
+ &cpu_to_cpu_group);
}
#endif
@@ -6672,11 +5889,11 @@ static int build_sched_domains(const cpumask_t *cpu_map)
cpus_and(this_core_map, this_core_map, *cpu_map);
if (i != first_cpu(this_core_map))
continue;
- init_sched_build_groups(this_core_map, cpu_map, &cpu_to_core_group);
+ init_sched_build_groups(this_core_map, cpu_map,
+ &cpu_to_core_group);
}
#endif
-
/* Set up physical groups */
for (i = 0; i < MAX_NUMNODES; i++) {
cpumask_t nodemask = node_to_cpumask(i);
@@ -6691,7 +5908,8 @@ static int build_sched_domains(const cpumask_t *cpu_map)
#ifdef CONFIG_NUMA
/* Set up node groups */
if (sd_allnodes)
- init_sched_build_groups(*cpu_map, cpu_map, &cpu_to_allnodes_group);
+ init_sched_build_groups(*cpu_map, cpu_map,
+ &cpu_to_allnodes_group);
for (i = 0; i < MAX_NUMNODES; i++) {
/* Set up node groups */
@@ -6719,6 +5937,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
sched_group_nodes[i] = sg;
for_each_cpu_mask(j, nodemask) {
struct sched_domain *sd;
+
sd = &per_cpu(node_domains, j);
sd->groups = sg;
}
@@ -6763,19 +5982,22 @@ static int build_sched_domains(const cpumask_t *cpu_map)
/* Calculate CPU power for physical packages and nodes */
#ifdef CONFIG_SCHED_SMT
for_each_cpu_mask(i, *cpu_map) {
- sd = &per_cpu(cpu_domains, i);
+ struct sched_domain *sd = &per_cpu(cpu_domains, i);
+
init_sched_groups_power(i, sd);
}
#endif
#ifdef CONFIG_SCHED_MC
for_each_cpu_mask(i, *cpu_map) {
- sd = &per_cpu(core_domains, i);
+ struct sched_domain *sd = &per_cpu(core_domains, i);
+
init_sched_groups_power(i, sd);
}
#endif
for_each_cpu_mask(i, *cpu_map) {
- sd = &per_cpu(phys_domains, i);
+ struct sched_domain *sd = &per_cpu(phys_domains, i);
+
init_sched_groups_power(i, sd);
}
@@ -6803,10 +6025,6 @@ static int build_sched_domains(const cpumask_t *cpu_map)
#endif
cpu_attach_domain(sd, i);
}
- /*
- * Tune cache-hot values:
- */
- calibrate_migration_costs(cpu_map);
return 0;
@@ -7013,10 +6231,12 @@ void __init sched_init_smp(void)
/* Move init over to a non-isolated CPU */
if (set_cpus_allowed(current, non_isolated_cpus) < 0)
BUG();
+ sched_init_granularity();
}
#else
void __init sched_init_smp(void)
{
+ sched_init_granularity();
}
#endif /* CONFIG_SMP */
@@ -7030,28 +6250,51 @@ int in_sched_functions(unsigned long addr)
&& addr < (unsigned long)__sched_text_end);
}
+static inline void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
+{
+ cfs_rq->tasks_timeline = RB_ROOT;
+ cfs_rq->fair_clock = 1;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ cfs_rq->rq = rq;
+#endif
+}
+
void __init sched_init(void)
{
- int i, j, k;
+ u64 now = sched_clock();
int highest_cpu = 0;
+ int i, j;
+
+ /*
+ * Link up the scheduling class hierarchy:
+ */
+ rt_sched_class.next = &fair_sched_class;
+ fair_sched_class.next = &idle_sched_class;
+ idle_sched_class.next = NULL;
for_each_possible_cpu(i) {
- struct prio_array *array;
+ struct rt_prio_array *array;
struct rq *rq;
rq = cpu_rq(i);
spin_lock_init(&rq->lock);
lockdep_set_class(&rq->lock, &rq->rq_lock_key);
rq->nr_running = 0;
- rq->active = rq->arrays;
- rq->expired = rq->arrays + 1;
- rq->best_expired_prio = MAX_PRIO;
+ rq->clock = 1;
+ init_cfs_rq(&rq->cfs, rq);
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+ list_add(&rq->cfs.leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
+#endif
+ rq->ls.load_update_last = now;
+ rq->ls.load_update_start = now;
+ for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
+ rq->cpu_load[j] = 0;
#ifdef CONFIG_SMP
rq->sd = NULL;
- for (j = 1; j < 3; j++)
- rq->cpu_load[j] = 0;
rq->active_balance = 0;
+ rq->next_balance = jiffies;
rq->push_cpu = 0;
rq->cpu = i;
rq->migration_thread = NULL;
@@ -7059,16 +6302,14 @@ void __init sched_init(void)
#endif
atomic_set(&rq->nr_iowait, 0);
- for (j = 0; j < 2; j++) {
- array = rq->arrays + j;
- for (k = 0; k < MAX_PRIO; k++) {
- INIT_LIST_HEAD(array->queue + k);
- __clear_bit(k, array->bitmap);
- }
- // delimiter for bitsearch
- __set_bit(MAX_PRIO, array->bitmap);
+ array = &rq->rt.active;
+ for (j = 0; j < MAX_RT_PRIO; j++) {
+ INIT_LIST_HEAD(array->queue + j);
+ __clear_bit(j, array->bitmap);
}
highest_cpu = i;
+ /* delimiter for bitsearch: */
+ __set_bit(MAX_RT_PRIO, array->bitmap);
}
set_load_weight(&init_task);
@@ -7095,6 +6336,10 @@ void __init sched_init(void)
* when this runqueue becomes "idle".
*/
init_idle(current, smp_processor_id());
+ /*
+ * During early bootup we pretend to be a normal task:
+ */
+ current->sched_class = &fair_sched_class;
}
#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
@@ -7125,29 +6370,55 @@ EXPORT_SYMBOL(__might_sleep);
#ifdef CONFIG_MAGIC_SYSRQ
void normalize_rt_tasks(void)
{
- struct prio_array *array;
struct task_struct *g, *p;
unsigned long flags;
struct rq *rq;
+ int on_rq;
read_lock_irq(&tasklist_lock);
-
do_each_thread(g, p) {
- if (!rt_task(p))
+ p->se.fair_key = 0;
+ p->se.wait_runtime = 0;
+ p->se.wait_start_fair = 0;
+ p->se.wait_start = 0;
+ p->se.exec_start = 0;
+ p->se.sleep_start = 0;
+ p->se.sleep_start_fair = 0;
+ p->se.block_start = 0;
+ task_rq(p)->cfs.fair_clock = 0;
+ task_rq(p)->clock = 0;
+
+ if (!rt_task(p)) {
+ /*
+ * Renice negative nice level userspace
+ * tasks back to 0:
+ */
+ if (TASK_NICE(p) < 0 && p->mm)
+ set_user_nice(p, 0);
continue;
+ }
spin_lock_irqsave(&p->pi_lock, flags);
rq = __task_rq_lock(p);
+#ifdef CONFIG_SMP
+ /*
+ * Do not touch the migration thread:
+ */
+ if (p == rq->migration_thread)
+ goto out_unlock;
+#endif
- array = p->array;
- if (array)
- deactivate_task(p, task_rq(p));
- __setscheduler(p, SCHED_NORMAL, 0);
- if (array) {
- __activate_task(p, task_rq(p));
+ on_rq = p->se.on_rq;
+ if (on_rq)
+ deactivate_task(task_rq(p), p, 0);
+ __setscheduler(rq, p, SCHED_NORMAL, 0);
+ if (on_rq) {
+ activate_task(task_rq(p), p, 0);
resched_task(rq->curr);
}
-
+#ifdef CONFIG_SMP
+ out_unlock:
+#endif
__task_rq_unlock(rq);
spin_unlock_irqrestore(&p->pi_lock, flags);
} while_each_thread(g, p);
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
new file mode 100644
index 000000000000..1baf87cceb7c
--- /dev/null
+++ b/kernel/sched_debug.c
@@ -0,0 +1,275 @@
+/*
+ * kernel/time/sched_debug.c
+ *
+ * Print the CFS rbtree
+ *
+ * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/utsname.h>
+
+/*
+ * This allows printing both to /proc/sched_debug and
+ * to the console
+ */
+#define SEQ_printf(m, x...) \
+ do { \
+ if (m) \
+ seq_printf(m, x); \
+ else \
+ printk(x); \
+ } while (0)
+
+static void
+print_task(struct seq_file *m, struct rq *rq, struct task_struct *p, u64 now)
+{
+ if (rq->curr == p)
+ SEQ_printf(m, "R");
+ else
+ SEQ_printf(m, " ");
+
+ SEQ_printf(m, "%15s %5d %15Ld %13Ld %13Ld %9Ld %5d "
+ "%15Ld %15Ld %15Ld %15Ld %15Ld\n",
+ p->comm, p->pid,
+ (long long)p->se.fair_key,
+ (long long)(p->se.fair_key - rq->cfs.fair_clock),
+ (long long)p->se.wait_runtime,
+ (long long)(p->nvcsw + p->nivcsw),
+ p->prio,
+ (long long)p->se.sum_exec_runtime,
+ (long long)p->se.sum_wait_runtime,
+ (long long)p->se.sum_sleep_runtime,
+ (long long)p->se.wait_runtime_overruns,
+ (long long)p->se.wait_runtime_underruns);
+}
+
+static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu, u64 now)
+{
+ struct task_struct *g, *p;
+
+ SEQ_printf(m,
+ "\nrunnable tasks:\n"
+ " task PID tree-key delta waiting"
+ " switches prio"
+ " sum-exec sum-wait sum-sleep"
+ " wait-overrun wait-underrun\n"
+ "------------------------------------------------------------------"
+ "----------------"
+ "------------------------------------------------"
+ "--------------------------------\n");
+
+ read_lock_irq(&tasklist_lock);
+
+ do_each_thread(g, p) {
+ if (!p->se.on_rq || task_cpu(p) != rq_cpu)
+ continue;
+
+ print_task(m, rq, p, now);
+ } while_each_thread(g, p);
+
+ read_unlock_irq(&tasklist_lock);
+}
+
+static void
+print_cfs_rq_runtime_sum(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
+{
+ s64 wait_runtime_rq_sum = 0;
+ struct task_struct *p;
+ struct rb_node *curr;
+ unsigned long flags;
+ struct rq *rq = &per_cpu(runqueues, cpu);
+
+ spin_lock_irqsave(&rq->lock, flags);
+ curr = first_fair(cfs_rq);
+ while (curr) {
+ p = rb_entry(curr, struct task_struct, se.run_node);
+ wait_runtime_rq_sum += p->se.wait_runtime;
+
+ curr = rb_next(curr);
+ }
+ spin_unlock_irqrestore(&rq->lock, flags);
+
+ SEQ_printf(m, " .%-30s: %Ld\n", "wait_runtime_rq_sum",
+ (long long)wait_runtime_rq_sum);
+}
+
+void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now)
+{
+ SEQ_printf(m, "\ncfs_rq %p\n", cfs_rq);
+
+#define P(x) \
+ SEQ_printf(m, " .%-30s: %Ld\n", #x, (long long)(cfs_rq->x))
+
+ P(fair_clock);
+ P(exec_clock);
+ P(wait_runtime);
+ P(wait_runtime_overruns);
+ P(wait_runtime_underruns);
+ P(sleeper_bonus);
+#undef P
+
+ print_cfs_rq_runtime_sum(m, cpu, cfs_rq);
+}
+
+static void print_cpu(struct seq_file *m, int cpu, u64 now)
+{
+ struct rq *rq = &per_cpu(runqueues, cpu);
+
+#ifdef CONFIG_X86
+ {
+ unsigned int freq = cpu_khz ? : 1;
+
+ SEQ_printf(m, "\ncpu#%d, %u.%03u MHz\n",
+ cpu, freq / 1000, (freq % 1000));
+ }
+#else
+ SEQ_printf(m, "\ncpu#%d\n", cpu);
+#endif
+
+#define P(x) \
+ SEQ_printf(m, " .%-30s: %Ld\n", #x, (long long)(rq->x))
+
+ P(nr_running);
+ SEQ_printf(m, " .%-30s: %lu\n", "load",
+ rq->ls.load.weight);
+ P(ls.delta_fair);
+ P(ls.delta_exec);
+ P(nr_switches);
+ P(nr_load_updates);
+ P(nr_uninterruptible);
+ SEQ_printf(m, " .%-30s: %lu\n", "jiffies", jiffies);
+ P(next_balance);
+ P(curr->pid);
+ P(clock);
+ P(prev_clock_raw);
+ P(clock_warps);
+ P(clock_overflows);
+ P(clock_unstable_events);
+ P(clock_max_delta);
+ P(cpu_load[0]);
+ P(cpu_load[1]);
+ P(cpu_load[2]);
+ P(cpu_load[3]);
+ P(cpu_load[4]);
+#undef P
+
+ print_cfs_stats(m, cpu, now);
+
+ print_rq(m, rq, cpu, now);
+}
+
+static int sched_debug_show(struct seq_file *m, void *v)
+{
+ u64 now = ktime_to_ns(ktime_get());
+ int cpu;
+
+ SEQ_printf(m, "Sched Debug Version: v0.04, cfs-v20, %s %.*s\n",
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+
+ SEQ_printf(m, "now at %Lu nsecs\n", (unsigned long long)now);
+
+ for_each_online_cpu(cpu)
+ print_cpu(m, cpu, now);
+
+ SEQ_printf(m, "\n");
+
+ return 0;
+}
+
+void sysrq_sched_debug_show(void)
+{
+ sched_debug_show(NULL, NULL);
+}
+
+static int sched_debug_open(struct inode *inode, struct file *filp)
+{
+ return single_open(filp, sched_debug_show, NULL);
+}
+
+static struct file_operations sched_debug_fops = {
+ .open = sched_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init init_sched_debug_procfs(void)
+{
+ struct proc_dir_entry *pe;
+
+ pe = create_proc_entry("sched_debug", 0644, NULL);
+ if (!pe)
+ return -ENOMEM;
+
+ pe->proc_fops = &sched_debug_fops;
+
+ return 0;
+}
+
+__initcall(init_sched_debug_procfs);
+
+void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+{
+ unsigned long flags;
+ int num_threads = 1;
+
+ rcu_read_lock();
+ if (lock_task_sighand(p, &flags)) {
+ num_threads = atomic_read(&p->signal->count);
+ unlock_task_sighand(p, &flags);
+ }
+ rcu_read_unlock();
+
+ SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid, num_threads);
+ SEQ_printf(m, "----------------------------------------------\n");
+#define P(F) \
+ SEQ_printf(m, "%-25s:%20Ld\n", #F, (long long)p->F)
+
+ P(se.wait_start);
+ P(se.wait_start_fair);
+ P(se.exec_start);
+ P(se.sleep_start);
+ P(se.sleep_start_fair);
+ P(se.block_start);
+ P(se.sleep_max);
+ P(se.block_max);
+ P(se.exec_max);
+ P(se.wait_max);
+ P(se.wait_runtime);
+ P(se.wait_runtime_overruns);
+ P(se.wait_runtime_underruns);
+ P(se.sum_wait_runtime);
+ P(se.sum_exec_runtime);
+ SEQ_printf(m, "%-25s:%20Ld\n",
+ "nr_switches", (long long)(p->nvcsw + p->nivcsw));
+ P(se.load.weight);
+ P(policy);
+ P(prio);
+#undef P
+
+ {
+ u64 t0, t1;
+
+ t0 = sched_clock();
+ t1 = sched_clock();
+ SEQ_printf(m, "%-25s:%20Ld\n",
+ "clock-delta", (long long)(t1-t0));
+ }
+}
+
+void proc_sched_set_task(struct task_struct *p)
+{
+ p->se.sleep_max = p->se.block_max = p->se.exec_max = p->se.wait_max = 0;
+ p->se.wait_runtime_overruns = p->se.wait_runtime_underruns = 0;
+ p->se.sum_exec_runtime = 0;
+}
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
new file mode 100644
index 000000000000..6971db0a7160
--- /dev/null
+++ b/kernel/sched_fair.c
@@ -0,0 +1,1131 @@
+/*
+ * Completely Fair Scheduling (CFS) Class (SCHED_NORMAL/SCHED_BATCH)
+ *
+ * Copyright (C) 2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * Interactivity improvements by Mike Galbraith
+ * (C) 2007 Mike Galbraith <efault@gmx.de>
+ *
+ * Various enhancements by Dmitry Adamushko.
+ * (C) 2007 Dmitry Adamushko <dmitry.adamushko@gmail.com>
+ *
+ * Group scheduling enhancements by Srivatsa Vaddagiri
+ * Copyright IBM Corporation, 2007
+ * Author: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
+ *
+ * Scaled math optimizations by Thomas Gleixner
+ * Copyright (C) 2007, Thomas Gleixner <tglx@linutronix.de>
+ */
+
+/*
+ * Preemption granularity:
+ * (default: 2 msec, units: nanoseconds)
+ *
+ * NOTE: this granularity value is not the same as the concept of
+ * 'timeslice length' - timeslices in CFS will typically be somewhat
+ * larger than this value. (to see the precise effective timeslice
+ * length of your workload, run vmstat and monitor the context-switches
+ * field)
+ *
+ * On SMP systems the value of this is multiplied by the log2 of the
+ * number of CPUs. (i.e. factor 2x on 2-way systems, 3x on 4-way
+ * systems, 4x on 8-way systems, 5x on 16-way systems, etc.)
+ */
+unsigned int sysctl_sched_granularity __read_mostly = 2000000000ULL/HZ;
+
+/*
+ * SCHED_BATCH wake-up granularity.
+ * (default: 10 msec, units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+unsigned int sysctl_sched_batch_wakeup_granularity __read_mostly =
+ 10000000000ULL/HZ;
+
+/*
+ * SCHED_OTHER wake-up granularity.
+ * (default: 1 msec, units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+unsigned int sysctl_sched_wakeup_granularity __read_mostly = 1000000000ULL/HZ;
+
+unsigned int sysctl_sched_stat_granularity __read_mostly;
+
+/*
+ * Initialized in sched_init_granularity():
+ */
+unsigned int sysctl_sched_runtime_limit __read_mostly;
+
+/*
+ * Debugging: various feature bits
+ */
+enum {
+ SCHED_FEAT_FAIR_SLEEPERS = 1,
+ SCHED_FEAT_SLEEPER_AVG = 2,
+ SCHED_FEAT_SLEEPER_LOAD_AVG = 4,
+ SCHED_FEAT_PRECISE_CPU_LOAD = 8,
+ SCHED_FEAT_START_DEBIT = 16,
+ SCHED_FEAT_SKIP_INITIAL = 32,
+};
+
+unsigned int sysctl_sched_features __read_mostly =
+ SCHED_FEAT_FAIR_SLEEPERS *1 |
+ SCHED_FEAT_SLEEPER_AVG *1 |
+ SCHED_FEAT_SLEEPER_LOAD_AVG *1 |
+ SCHED_FEAT_PRECISE_CPU_LOAD *1 |
+ SCHED_FEAT_START_DEBIT *1 |
+ SCHED_FEAT_SKIP_INITIAL *0;
+
+extern struct sched_class fair_sched_class;
+
+/**************************************************************
+ * CFS operations on generic schedulable entities:
+ */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+/* cpu runqueue to which this cfs_rq is attached */
+static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+{
+ return cfs_rq->rq;
+}
+
+/* currently running entity (if any) on this cfs_rq */
+static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq)
+{
+ return cfs_rq->curr;
+}
+
+/* An entity is a task if it doesn't "own" a runqueue */
+#define entity_is_task(se) (!se->my_q)
+
+static inline void
+set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ cfs_rq->curr = se;
+}
+
+#else /* CONFIG_FAIR_GROUP_SCHED */
+
+static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+{
+ return container_of(cfs_rq, struct rq, cfs);
+}
+
+static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq)
+{
+ struct rq *rq = rq_of(cfs_rq);
+
+ if (unlikely(rq->curr->sched_class != &fair_sched_class))
+ return NULL;
+
+ return &rq->curr->se;
+}
+
+#define entity_is_task(se) 1
+
+static inline void
+set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se) { }
+
+#endif /* CONFIG_FAIR_GROUP_SCHED */
+
+static inline struct task_struct *task_of(struct sched_entity *se)
+{
+ return container_of(se, struct task_struct, se);
+}
+
+
+/**************************************************************
+ * Scheduling class tree data structure manipulation methods:
+ */
+
+/*
+ * Enqueue an entity into the rb-tree:
+ */
+static inline void
+__enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
+ struct rb_node *parent = NULL;
+ struct sched_entity *entry;
+ s64 key = se->fair_key;
+ int leftmost = 1;
+
+ /*
+ * Find the right place in the rbtree:
+ */
+ while (*link) {
+ parent = *link;
+ entry = rb_entry(parent, struct sched_entity, run_node);
+ /*
+ * We dont care about collisions. Nodes with
+ * the same key stay together.
+ */
+ if (key - entry->fair_key < 0) {
+ link = &parent->rb_left;
+ } else {
+ link = &parent->rb_right;
+ leftmost = 0;
+ }
+ }
+
+ /*
+ * Maintain a cache of leftmost tree entries (it is frequently
+ * used):
+ */
+ if (leftmost)
+ cfs_rq->rb_leftmost = &se->run_node;
+
+ rb_link_node(&se->run_node, parent, link);
+ rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline);
+ update_load_add(&cfs_rq->load, se->load.weight);
+ cfs_rq->nr_running++;
+ se->on_rq = 1;
+}
+
+static inline void
+__dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ if (cfs_rq->rb_leftmost == &se->run_node)
+ cfs_rq->rb_leftmost = rb_next(&se->run_node);
+ rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
+ update_load_sub(&cfs_rq->load, se->load.weight);
+ cfs_rq->nr_running--;
+ se->on_rq = 0;
+}
+
+static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq)
+{
+ return cfs_rq->rb_leftmost;
+}
+
+static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq)
+{
+ return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node);
+}
+
+/**************************************************************
+ * Scheduling class statistics methods:
+ */
+
+/*
+ * We rescale the rescheduling granularity of tasks according to their
+ * nice level, but only linearly, not exponentially:
+ */
+static long
+niced_granularity(struct sched_entity *curr, unsigned long granularity)
+{
+ u64 tmp;
+
+ /*
+ * Negative nice levels get the same granularity as nice-0:
+ */
+ if (likely(curr->load.weight >= NICE_0_LOAD))
+ return granularity;
+ /*
+ * Positive nice level tasks get linearly finer
+ * granularity:
+ */
+ tmp = curr->load.weight * (u64)granularity;
+
+ /*
+ * It will always fit into 'long':
+ */
+ return (long) (tmp >> NICE_0_SHIFT);
+}
+
+static inline void
+limit_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ long limit = sysctl_sched_runtime_limit;
+
+ /*
+ * Niced tasks have the same history dynamic range as
+ * non-niced tasks:
+ */
+ if (unlikely(se->wait_runtime > limit)) {
+ se->wait_runtime = limit;
+ schedstat_inc(se, wait_runtime_overruns);
+ schedstat_inc(cfs_rq, wait_runtime_overruns);
+ }
+ if (unlikely(se->wait_runtime < -limit)) {
+ se->wait_runtime = -limit;
+ schedstat_inc(se, wait_runtime_underruns);
+ schedstat_inc(cfs_rq, wait_runtime_underruns);
+ }
+}
+
+static inline void
+__add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta)
+{
+ se->wait_runtime += delta;
+ schedstat_add(se, sum_wait_runtime, delta);
+ limit_wait_runtime(cfs_rq, se);
+}
+
+static void
+add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta)
+{
+ schedstat_add(cfs_rq, wait_runtime, -se->wait_runtime);
+ __add_wait_runtime(cfs_rq, se, delta);
+ schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
+}
+
+/*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+ */
+static inline void
+__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr, u64 now)
+{
+ unsigned long delta, delta_exec, delta_fair;
+ long delta_mine;
+ struct load_weight *lw = &cfs_rq->load;
+ unsigned long load = lw->weight;
+
+ if (unlikely(!load))
+ return;
+
+ delta_exec = curr->delta_exec;
+#ifdef CONFIG_SCHEDSTATS
+ if (unlikely(delta_exec > curr->exec_max))
+ curr->exec_max = delta_exec;
+#endif
+
+ curr->sum_exec_runtime += delta_exec;
+ cfs_rq->exec_clock += delta_exec;
+
+ delta_fair = calc_delta_fair(delta_exec, lw);
+ delta_mine = calc_delta_mine(delta_exec, curr->load.weight, lw);
+
+ if (cfs_rq->sleeper_bonus > sysctl_sched_stat_granularity) {
+ delta = calc_delta_mine(cfs_rq->sleeper_bonus,
+ curr->load.weight, lw);
+ if (unlikely(delta > cfs_rq->sleeper_bonus))
+ delta = cfs_rq->sleeper_bonus;
+
+ cfs_rq->sleeper_bonus -= delta;
+ delta_mine -= delta;
+ }
+
+ cfs_rq->fair_clock += delta_fair;
+ /*
+ * We executed delta_exec amount of time on the CPU,
+ * but we were only entitled to delta_mine amount of
+ * time during that period (if nr_running == 1 then
+ * the two values are equal)
+ * [Note: delta_mine - delta_exec is negative]:
+ */
+ add_wait_runtime(cfs_rq, curr, delta_mine - delta_exec);
+}
+
+static void update_curr(struct cfs_rq *cfs_rq, u64 now)
+{
+ struct sched_entity *curr = cfs_rq_curr(cfs_rq);
+ unsigned long delta_exec;
+
+ if (unlikely(!curr))
+ return;
+
+ /*
+ * Get the amount of time the current task was running
+ * since the last time we changed load (this cannot
+ * overflow on 32 bits):
+ */
+ delta_exec = (unsigned long)(now - curr->exec_start);
+
+ curr->delta_exec += delta_exec;
+
+ if (unlikely(curr->delta_exec > sysctl_sched_stat_granularity)) {
+ __update_curr(cfs_rq, curr, now);
+ curr->delta_exec = 0;
+ }
+ curr->exec_start = now;
+}
+
+static inline void
+update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ se->wait_start_fair = cfs_rq->fair_clock;
+ se->wait_start = now;
+}
+
+/*
+ * We calculate fair deltas here, so protect against the random effects
+ * of a multiplication overflow by capping it to the runtime limit:
+ */
+#if BITS_PER_LONG == 32
+static inline unsigned long
+calc_weighted(unsigned long delta, unsigned long weight, int shift)
+{
+ u64 tmp = (u64)delta * weight >> shift;
+
+ if (unlikely(tmp > sysctl_sched_runtime_limit*2))
+ return sysctl_sched_runtime_limit*2;
+ return tmp;
+}
+#else
+static inline unsigned long
+calc_weighted(unsigned long delta, unsigned long weight, int shift)
+{
+ return delta * weight >> shift;
+}
+#endif
+
+/*
+ * Task is being enqueued - update stats:
+ */
+static void
+update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ s64 key;
+
+ /*
+ * Are we enqueueing a waiting task? (for current tasks
+ * a dequeue/enqueue event is a NOP)
+ */
+ if (se != cfs_rq_curr(cfs_rq))
+ update_stats_wait_start(cfs_rq, se, now);
+ /*
+ * Update the key:
+ */
+ key = cfs_rq->fair_clock;
+
+ /*
+ * Optimize the common nice 0 case:
+ */
+ if (likely(se->load.weight == NICE_0_LOAD)) {
+ key -= se->wait_runtime;
+ } else {
+ u64 tmp;
+
+ if (se->wait_runtime < 0) {
+ tmp = -se->wait_runtime;
+ key += (tmp * se->load.inv_weight) >>
+ (WMULT_SHIFT - NICE_0_SHIFT);
+ } else {
+ tmp = se->wait_runtime;
+ key -= (tmp * se->load.weight) >> NICE_0_SHIFT;
+ }
+ }
+
+ se->fair_key = key;
+}
+
+/*
+ * Note: must be called with a freshly updated rq->fair_clock.
+ */
+static inline void
+__update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ unsigned long delta_fair = se->delta_fair_run;
+
+#ifdef CONFIG_SCHEDSTATS
+ {
+ s64 delta_wait = now - se->wait_start;
+ if (unlikely(delta_wait > se->wait_max))
+ se->wait_max = delta_wait;
+ }
+#endif
+
+ if (unlikely(se->load.weight != NICE_0_LOAD))
+ delta_fair = calc_weighted(delta_fair, se->load.weight,
+ NICE_0_SHIFT);
+
+ add_wait_runtime(cfs_rq, se, delta_fair);
+}
+
+static void
+update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ unsigned long delta_fair;
+
+ delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit),
+ (u64)(cfs_rq->fair_clock - se->wait_start_fair));
+
+ se->delta_fair_run += delta_fair;
+ if (unlikely(abs(se->delta_fair_run) >=
+ sysctl_sched_stat_granularity)) {
+ __update_stats_wait_end(cfs_rq, se, now);
+ se->delta_fair_run = 0;
+ }
+
+ se->wait_start_fair = 0;
+ se->wait_start = 0;
+}
+
+static inline void
+update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ update_curr(cfs_rq, now);
+ /*
+ * Mark the end of the wait period if dequeueing a
+ * waiting task:
+ */
+ if (se != cfs_rq_curr(cfs_rq))
+ update_stats_wait_end(cfs_rq, se, now);
+}
+
+/*
+ * We are picking a new current task - update its stats:
+ */
+static inline void
+update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ /*
+ * We are starting a new run period:
+ */
+ se->exec_start = now;
+}
+
+/*
+ * We are descheduling a task - update its stats:
+ */
+static inline void
+update_stats_curr_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ se->exec_start = 0;
+}
+
+/**************************************************
+ * Scheduling class queueing methods:
+ */
+
+static void
+__enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ unsigned long load = cfs_rq->load.weight, delta_fair;
+ long prev_runtime;
+
+ if (sysctl_sched_features & SCHED_FEAT_SLEEPER_LOAD_AVG)
+ load = rq_of(cfs_rq)->cpu_load[2];
+
+ delta_fair = se->delta_fair_sleep;
+
+ /*
+ * Fix up delta_fair with the effect of us running
+ * during the whole sleep period:
+ */
+ if (sysctl_sched_features & SCHED_FEAT_SLEEPER_AVG)
+ delta_fair = div64_likely32((u64)delta_fair * load,
+ load + se->load.weight);
+
+ if (unlikely(se->load.weight != NICE_0_LOAD))
+ delta_fair = calc_weighted(delta_fair, se->load.weight,
+ NICE_0_SHIFT);
+
+ prev_runtime = se->wait_runtime;
+ __add_wait_runtime(cfs_rq, se, delta_fair);
+ delta_fair = se->wait_runtime - prev_runtime;
+
+ /*
+ * Track the amount of bonus we've given to sleepers:
+ */
+ cfs_rq->sleeper_bonus += delta_fair;
+
+ schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
+}
+
+static void
+enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ struct task_struct *tsk = task_of(se);
+ unsigned long delta_fair;
+
+ if ((entity_is_task(se) && tsk->policy == SCHED_BATCH) ||
+ !(sysctl_sched_features & SCHED_FEAT_FAIR_SLEEPERS))
+ return;
+
+ delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit),
+ (u64)(cfs_rq->fair_clock - se->sleep_start_fair));
+
+ se->delta_fair_sleep += delta_fair;
+ if (unlikely(abs(se->delta_fair_sleep) >=
+ sysctl_sched_stat_granularity)) {
+ __enqueue_sleeper(cfs_rq, se, now);
+ se->delta_fair_sleep = 0;
+ }
+
+ se->sleep_start_fair = 0;
+
+#ifdef CONFIG_SCHEDSTATS
+ if (se->sleep_start) {
+ u64 delta = now - se->sleep_start;
+
+ if ((s64)delta < 0)
+ delta = 0;
+
+ if (unlikely(delta > se->sleep_max))
+ se->sleep_max = delta;
+
+ se->sleep_start = 0;
+ se->sum_sleep_runtime += delta;
+ }
+ if (se->block_start) {
+ u64 delta = now - se->block_start;
+
+ if ((s64)delta < 0)
+ delta = 0;
+
+ if (unlikely(delta > se->block_max))
+ se->block_max = delta;
+
+ se->block_start = 0;
+ se->sum_sleep_runtime += delta;
+ }
+#endif
+}
+
+static void
+enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+ int wakeup, u64 now)
+{
+ /*
+ * Update the fair clock.
+ */
+ update_curr(cfs_rq, now);
+
+ if (wakeup)
+ enqueue_sleeper(cfs_rq, se, now);
+
+ update_stats_enqueue(cfs_rq, se, now);
+ __enqueue_entity(cfs_rq, se);
+}
+
+static void
+dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+ int sleep, u64 now)
+{
+ update_stats_dequeue(cfs_rq, se, now);
+ if (sleep) {
+ se->sleep_start_fair = cfs_rq->fair_clock;
+#ifdef CONFIG_SCHEDSTATS
+ if (entity_is_task(se)) {
+ struct task_struct *tsk = task_of(se);
+
+ if (tsk->state & TASK_INTERRUPTIBLE)
+ se->sleep_start = now;
+ if (tsk->state & TASK_UNINTERRUPTIBLE)
+ se->block_start = now;
+ }
+ cfs_rq->wait_runtime -= se->wait_runtime;
+#endif
+ }
+ __dequeue_entity(cfs_rq, se);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void
+__check_preempt_curr_fair(struct cfs_rq *cfs_rq, struct sched_entity *se,
+ struct sched_entity *curr, unsigned long granularity)
+{
+ s64 __delta = curr->fair_key - se->fair_key;
+
+ /*
+ * Take scheduling granularity into account - do not
+ * preempt the current task unless the best task has
+ * a larger than sched_granularity fairness advantage:
+ */
+ if (__delta > niced_granularity(curr, granularity))
+ resched_task(rq_of(cfs_rq)->curr);
+}
+
+static inline void
+set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ /*
+ * Any task has to be enqueued before it get to execute on
+ * a CPU. So account for the time it spent waiting on the
+ * runqueue. (note, here we rely on pick_next_task() having
+ * done a put_prev_task_fair() shortly before this, which
+ * updated rq->fair_clock - used by update_stats_wait_end())
+ */
+ update_stats_wait_end(cfs_rq, se, now);
+ update_stats_curr_start(cfs_rq, se, now);
+ set_cfs_rq_curr(cfs_rq, se);
+}
+
+static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq, u64 now)
+{
+ struct sched_entity *se = __pick_next_entity(cfs_rq);
+
+ set_next_entity(cfs_rq, se, now);
+
+ return se;
+}
+
+static void
+put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev, u64 now)
+{
+ /*
+ * If still on the runqueue then deactivate_task()
+ * was not called and update_curr() has to be done:
+ */
+ if (prev->on_rq)
+ update_curr(cfs_rq, now);
+
+ update_stats_curr_end(cfs_rq, prev, now);
+
+ if (prev->on_rq)
+ update_stats_wait_start(cfs_rq, prev, now);
+ set_cfs_rq_curr(cfs_rq, NULL);
+}
+
+static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
+{
+ struct rq *rq = rq_of(cfs_rq);
+ struct sched_entity *next;
+ u64 now = __rq_clock(rq);
+
+ /*
+ * Dequeue and enqueue the task to update its
+ * position within the tree:
+ */
+ dequeue_entity(cfs_rq, curr, 0, now);
+ enqueue_entity(cfs_rq, curr, 0, now);
+
+ /*
+ * Reschedule if another task tops the current one.
+ */
+ next = __pick_next_entity(cfs_rq);
+ if (next == curr)
+ return;
+
+ __check_preempt_curr_fair(cfs_rq, next, curr, sysctl_sched_granularity);
+}
+
+/**************************************************
+ * CFS operations on tasks:
+ */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+/* Walk up scheduling entities hierarchy */
+#define for_each_sched_entity(se) \
+ for (; se; se = se->parent)
+
+static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+{
+ return p->se.cfs_rq;
+}
+
+/* runqueue on which this entity is (to be) queued */
+static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+{
+ return se->cfs_rq;
+}
+
+/* runqueue "owned" by this group */
+static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+{
+ return grp->my_q;
+}
+
+/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
+ * another cpu ('this_cpu')
+ */
+static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+{
+ /* A later patch will take group into account */
+ return &cpu_rq(this_cpu)->cfs;
+}
+
+/* Iterate thr' all leaf cfs_rq's on a runqueue */
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+ list_for_each_entry(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
+
+/* Do the two (enqueued) tasks belong to the same group ? */
+static inline int is_same_group(struct task_struct *curr, struct task_struct *p)
+{
+ if (curr->se.cfs_rq == p->se.cfs_rq)
+ return 1;
+
+ return 0;
+}
+
+#else /* CONFIG_FAIR_GROUP_SCHED */
+
+#define for_each_sched_entity(se) \
+ for (; se; se = NULL)
+
+static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+{
+ return &task_rq(p)->cfs;
+}
+
+static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+{
+ struct task_struct *p = task_of(se);
+ struct rq *rq = task_rq(p);
+
+ return &rq->cfs;
+}
+
+/* runqueue "owned" by this group */
+static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+{
+ return NULL;
+}
+
+static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+{
+ return &cpu_rq(this_cpu)->cfs;
+}
+
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+ for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
+
+static inline int is_same_group(struct task_struct *curr, struct task_struct *p)
+{
+ return 1;
+}
+
+#endif /* CONFIG_FAIR_GROUP_SCHED */
+
+/*
+ * The enqueue_task method is called before nr_running is
+ * increased. Here we update the fair scheduling stats and
+ * then put the task into the rbtree:
+ */
+static void
+enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+ struct cfs_rq *cfs_rq;
+ struct sched_entity *se = &p->se;
+
+ for_each_sched_entity(se) {
+ if (se->on_rq)
+ break;
+ cfs_rq = cfs_rq_of(se);
+ enqueue_entity(cfs_rq, se, wakeup, now);
+ }
+}
+
+/*
+ * The dequeue_task method is called before nr_running is
+ * decreased. We remove the task from the rbtree and
+ * update the fair scheduling stats:
+ */
+static void
+dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+ struct cfs_rq *cfs_rq;
+ struct sched_entity *se = &p->se;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+ dequeue_entity(cfs_rq, se, sleep, now);
+ /* Don't dequeue parent if it has other entities besides us */
+ if (cfs_rq->load.weight)
+ break;
+ }
+}
+
+/*
+ * sched_yield() support is very simple - we dequeue and enqueue
+ */
+static void yield_task_fair(struct rq *rq, struct task_struct *p)
+{
+ struct cfs_rq *cfs_rq = task_cfs_rq(p);
+ u64 now = __rq_clock(rq);
+
+ /*
+ * Dequeue and enqueue the task to update its
+ * position within the tree:
+ */
+ dequeue_entity(cfs_rq, &p->se, 0, now);
+ enqueue_entity(cfs_rq, &p->se, 0, now);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void check_preempt_curr_fair(struct rq *rq, struct task_struct *p)
+{
+ struct task_struct *curr = rq->curr;
+ struct cfs_rq *cfs_rq = task_cfs_rq(curr);
+ unsigned long gran;
+
+ if (unlikely(rt_prio(p->prio))) {
+ update_curr(cfs_rq, rq_clock(rq));
+ resched_task(curr);
+ return;
+ }
+
+ gran = sysctl_sched_wakeup_granularity;
+ /*
+ * Batch tasks prefer throughput over latency:
+ */
+ if (unlikely(p->policy == SCHED_BATCH))
+ gran = sysctl_sched_batch_wakeup_granularity;
+
+ if (is_same_group(curr, p))
+ __check_preempt_curr_fair(cfs_rq, &p->se, &curr->se, gran);
+}
+
+static struct task_struct *pick_next_task_fair(struct rq *rq, u64 now)
+{
+ struct cfs_rq *cfs_rq = &rq->cfs;
+ struct sched_entity *se;
+
+ if (unlikely(!cfs_rq->nr_running))
+ return NULL;
+
+ do {
+ se = pick_next_entity(cfs_rq, now);
+ cfs_rq = group_cfs_rq(se);
+ } while (cfs_rq);
+
+ return task_of(se);
+}
+
+/*
+ * Account for a descheduled task:
+ */
+static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, u64 now)
+{
+ struct sched_entity *se = &prev->se;
+ struct cfs_rq *cfs_rq;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+ put_prev_entity(cfs_rq, se, now);
+ }
+}
+
+/**************************************************
+ * Fair scheduling class load-balancing methods:
+ */
+
+/*
+ * Load-balancing iterator. Note: while the runqueue stays locked
+ * during the whole iteration, the current task might be
+ * dequeued so the iterator has to be dequeue-safe. Here we
+ * achieve that by always pre-iterating before returning
+ * the current task:
+ */
+static inline struct task_struct *
+__load_balance_iterator(struct cfs_rq *cfs_rq, struct rb_node *curr)
+{
+ struct task_struct *p;
+
+ if (!curr)
+ return NULL;
+
+ p = rb_entry(curr, struct task_struct, se.run_node);
+ cfs_rq->rb_load_balance_curr = rb_next(curr);
+
+ return p;
+}
+
+static struct task_struct *load_balance_start_fair(void *arg)
+{
+ struct cfs_rq *cfs_rq = arg;
+
+ return __load_balance_iterator(cfs_rq, first_fair(cfs_rq));
+}
+
+static struct task_struct *load_balance_next_fair(void *arg)
+{
+ struct cfs_rq *cfs_rq = arg;
+
+ return __load_balance_iterator(cfs_rq, cfs_rq->rb_load_balance_curr);
+}
+
+static int cfs_rq_best_prio(struct cfs_rq *cfs_rq)
+{
+ struct sched_entity *curr;
+ struct task_struct *p;
+
+ if (!cfs_rq->nr_running)
+ return MAX_PRIO;
+
+ curr = __pick_next_entity(cfs_rq);
+ p = task_of(curr);
+
+ return p->prio;
+}
+
+static int
+load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *total_load_moved)
+{
+ struct cfs_rq *busy_cfs_rq;
+ unsigned long load_moved, total_nr_moved = 0, nr_moved;
+ long rem_load_move = max_load_move;
+ struct rq_iterator cfs_rq_iterator;
+
+ cfs_rq_iterator.start = load_balance_start_fair;
+ cfs_rq_iterator.next = load_balance_next_fair;
+
+ for_each_leaf_cfs_rq(busiest, busy_cfs_rq) {
+ struct cfs_rq *this_cfs_rq;
+ long imbalance;
+ unsigned long maxload;
+ int this_best_prio, best_prio, best_prio_seen = 0;
+
+ this_cfs_rq = cpu_cfs_rq(busy_cfs_rq, this_cpu);
+
+ imbalance = busy_cfs_rq->load.weight -
+ this_cfs_rq->load.weight;
+ /* Don't pull if this_cfs_rq has more load than busy_cfs_rq */
+ if (imbalance <= 0)
+ continue;
+
+ /* Don't pull more than imbalance/2 */
+ imbalance /= 2;
+ maxload = min(rem_load_move, imbalance);
+
+ this_best_prio = cfs_rq_best_prio(this_cfs_rq);
+ best_prio = cfs_rq_best_prio(busy_cfs_rq);
+
+ /*
+ * Enable handling of the case where there is more than one task
+ * with the best priority. If the current running task is one
+ * of those with prio==best_prio we know it won't be moved
+ * and therefore it's safe to override the skip (based on load)
+ * of any task we find with that prio.
+ */
+ if (cfs_rq_curr(busy_cfs_rq) == &busiest->curr->se)
+ best_prio_seen = 1;
+
+ /* pass busy_cfs_rq argument into
+ * load_balance_[start|next]_fair iterators
+ */
+ cfs_rq_iterator.arg = busy_cfs_rq;
+ nr_moved = balance_tasks(this_rq, this_cpu, busiest,
+ max_nr_move, maxload, sd, idle, all_pinned,
+ &load_moved, this_best_prio, best_prio,
+ best_prio_seen, &cfs_rq_iterator);
+
+ total_nr_moved += nr_moved;
+ max_nr_move -= nr_moved;
+ rem_load_move -= load_moved;
+
+ if (max_nr_move <= 0 || rem_load_move <= 0)
+ break;
+ }
+
+ *total_load_moved = max_load_move - rem_load_move;
+
+ return total_nr_moved;
+}
+
+/*
+ * scheduler tick hitting a task of our scheduling class:
+ */
+static void task_tick_fair(struct rq *rq, struct task_struct *curr)
+{
+ struct cfs_rq *cfs_rq;
+ struct sched_entity *se = &curr->se;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+ entity_tick(cfs_rq, se);
+ }
+}
+
+/*
+ * Share the fairness runtime between parent and child, thus the
+ * total amount of pressure for CPU stays equal - new tasks
+ * get a chance to run but frequent forkers are not allowed to
+ * monopolize the CPU. Note: the parent runqueue is locked,
+ * the child is not running yet.
+ */
+static void task_new_fair(struct rq *rq, struct task_struct *p)
+{
+ struct cfs_rq *cfs_rq = task_cfs_rq(p);
+ struct sched_entity *se = &p->se;
+ u64 now = rq_clock(rq);
+
+ sched_info_queued(p);
+
+ update_stats_enqueue(cfs_rq, se, now);
+ /*
+ * Child runs first: we let it run before the parent
+ * until it reschedules once. We set up the key so that
+ * it will preempt the parent:
+ */
+ p->se.fair_key = current->se.fair_key -
+ niced_granularity(&rq->curr->se, sysctl_sched_granularity) - 1;
+ /*
+ * The first wait is dominated by the child-runs-first logic,
+ * so do not credit it with that waiting time yet:
+ */
+ if (sysctl_sched_features & SCHED_FEAT_SKIP_INITIAL)
+ p->se.wait_start_fair = 0;
+
+ /*
+ * The statistical average of wait_runtime is about
+ * -granularity/2, so initialize the task with that:
+ */
+ if (sysctl_sched_features & SCHED_FEAT_START_DEBIT)
+ p->se.wait_runtime = -(sysctl_sched_granularity / 2);
+
+ __enqueue_entity(cfs_rq, se);
+ inc_nr_running(p, rq, now);
+}
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/* Account for a task changing its policy or group.
+ *
+ * This routine is mostly called to set cfs_rq->curr field when a task
+ * migrates between groups/classes.
+ */
+static void set_curr_task_fair(struct rq *rq)
+{
+ struct task_struct *curr = rq->curr;
+ struct sched_entity *se = &curr->se;
+ u64 now = rq_clock(rq);
+ struct cfs_rq *cfs_rq;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+ set_next_entity(cfs_rq, se, now);
+ }
+}
+#else
+static void set_curr_task_fair(struct rq *rq)
+{
+}
+#endif
+
+/*
+ * All the scheduling class methods:
+ */
+struct sched_class fair_sched_class __read_mostly = {
+ .enqueue_task = enqueue_task_fair,
+ .dequeue_task = dequeue_task_fair,
+ .yield_task = yield_task_fair,
+
+ .check_preempt_curr = check_preempt_curr_fair,
+
+ .pick_next_task = pick_next_task_fair,
+ .put_prev_task = put_prev_task_fair,
+
+ .load_balance = load_balance_fair,
+
+ .set_curr_task = set_curr_task_fair,
+ .task_tick = task_tick_fair,
+ .task_new = task_new_fair,
+};
+
+#ifdef CONFIG_SCHED_DEBUG
+void print_cfs_stats(struct seq_file *m, int cpu, u64 now)
+{
+ struct rq *rq = cpu_rq(cpu);
+ struct cfs_rq *cfs_rq;
+
+ for_each_leaf_cfs_rq(rq, cfs_rq)
+ print_cfs_rq(m, cpu, cfs_rq, now);
+}
+#endif
diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c
new file mode 100644
index 000000000000..41841e741c4a
--- /dev/null
+++ b/kernel/sched_idletask.c
@@ -0,0 +1,71 @@
+/*
+ * idle-task scheduling class.
+ *
+ * (NOTE: these are not related to SCHED_IDLE tasks which are
+ * handled in sched_fair.c)
+ */
+
+/*
+ * Idle tasks are unconditionally rescheduled:
+ */
+static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p)
+{
+ resched_task(rq->idle);
+}
+
+static struct task_struct *pick_next_task_idle(struct rq *rq, u64 now)
+{
+ schedstat_inc(rq, sched_goidle);
+
+ return rq->idle;
+}
+
+/*
+ * It is not legal to sleep in the idle task - print a warning
+ * message if some code attempts to do it:
+ */
+static void
+dequeue_task_idle(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+ spin_unlock_irq(&rq->lock);
+ printk(KERN_ERR "bad: scheduling from the idle thread!\n");
+ dump_stack();
+ spin_lock_irq(&rq->lock);
+}
+
+static void put_prev_task_idle(struct rq *rq, struct task_struct *prev, u64 now)
+{
+}
+
+static int
+load_balance_idle(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *total_load_moved)
+{
+ return 0;
+}
+
+static void task_tick_idle(struct rq *rq, struct task_struct *curr)
+{
+}
+
+/*
+ * Simple, special scheduling class for the per-CPU idle tasks:
+ */
+static struct sched_class idle_sched_class __read_mostly = {
+ /* no enqueue/yield_task for idle tasks */
+
+ /* dequeue is not valid, we print a debug message there: */
+ .dequeue_task = dequeue_task_idle,
+
+ .check_preempt_curr = check_preempt_curr_idle,
+
+ .pick_next_task = pick_next_task_idle,
+ .put_prev_task = put_prev_task_idle,
+
+ .load_balance = load_balance_idle,
+
+ .task_tick = task_tick_idle,
+ /* no .task_new for idle tasks */
+};
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
new file mode 100644
index 000000000000..1192a2741b99
--- /dev/null
+++ b/kernel/sched_rt.c
@@ -0,0 +1,255 @@
+/*
+ * Real-Time Scheduling Class (mapped to the SCHED_FIFO and SCHED_RR
+ * policies)
+ */
+
+/*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+ */
+static inline void update_curr_rt(struct rq *rq, u64 now)
+{
+ struct task_struct *curr = rq->curr;
+ u64 delta_exec;
+
+ if (!task_has_rt_policy(curr))
+ return;
+
+ delta_exec = now - curr->se.exec_start;
+ if (unlikely((s64)delta_exec < 0))
+ delta_exec = 0;
+ if (unlikely(delta_exec > curr->se.exec_max))
+ curr->se.exec_max = delta_exec;
+
+ curr->se.sum_exec_runtime += delta_exec;
+ curr->se.exec_start = now;
+}
+
+static void
+enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+ struct rt_prio_array *array = &rq->rt.active;
+
+ list_add_tail(&p->run_list, array->queue + p->prio);
+ __set_bit(p->prio, array->bitmap);
+}
+
+/*
+ * Adding/removing a task to/from a priority array:
+ */
+static void
+dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+ struct rt_prio_array *array = &rq->rt.active;
+
+ update_curr_rt(rq, now);
+
+ list_del(&p->run_list);
+ if (list_empty(array->queue + p->prio))
+ __clear_bit(p->prio, array->bitmap);
+}
+
+/*
+ * Put task to the end of the run list without the overhead of dequeue
+ * followed by enqueue.
+ */
+static void requeue_task_rt(struct rq *rq, struct task_struct *p)
+{
+ struct rt_prio_array *array = &rq->rt.active;
+
+ list_move_tail(&p->run_list, array->queue + p->prio);
+}
+
+static void
+yield_task_rt(struct rq *rq, struct task_struct *p)
+{
+ requeue_task_rt(rq, p);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p)
+{
+ if (p->prio < rq->curr->prio)
+ resched_task(rq->curr);
+}
+
+static struct task_struct *pick_next_task_rt(struct rq *rq, u64 now)
+{
+ struct rt_prio_array *array = &rq->rt.active;
+ struct task_struct *next;
+ struct list_head *queue;
+ int idx;
+
+ idx = sched_find_first_bit(array->bitmap);
+ if (idx >= MAX_RT_PRIO)
+ return NULL;
+
+ queue = array->queue + idx;
+ next = list_entry(queue->next, struct task_struct, run_list);
+
+ next->se.exec_start = now;
+
+ return next;
+}
+
+static void put_prev_task_rt(struct rq *rq, struct task_struct *p, u64 now)
+{
+ update_curr_rt(rq, now);
+ p->se.exec_start = 0;
+}
+
+/*
+ * Load-balancing iterator. Note: while the runqueue stays locked
+ * during the whole iteration, the current task might be
+ * dequeued so the iterator has to be dequeue-safe. Here we
+ * achieve that by always pre-iterating before returning
+ * the current task:
+ */
+static struct task_struct *load_balance_start_rt(void *arg)
+{
+ struct rq *rq = arg;
+ struct rt_prio_array *array = &rq->rt.active;
+ struct list_head *head, *curr;
+ struct task_struct *p;
+ int idx;
+
+ idx = sched_find_first_bit(array->bitmap);
+ if (idx >= MAX_RT_PRIO)
+ return NULL;
+
+ head = array->queue + idx;
+ curr = head->prev;
+
+ p = list_entry(curr, struct task_struct, run_list);
+
+ curr = curr->prev;
+
+ rq->rt.rt_load_balance_idx = idx;
+ rq->rt.rt_load_balance_head = head;
+ rq->rt.rt_load_balance_curr = curr;
+
+ return p;
+}
+
+static struct task_struct *load_balance_next_rt(void *arg)
+{
+ struct rq *rq = arg;
+ struct rt_prio_array *array = &rq->rt.active;
+ struct list_head *head, *curr;
+ struct task_struct *p;
+ int idx;
+
+ idx = rq->rt.rt_load_balance_idx;
+ head = rq->rt.rt_load_balance_head;
+ curr = rq->rt.rt_load_balance_curr;
+
+ /*
+ * If we arrived back to the head again then
+ * iterate to the next queue (if any):
+ */
+ if (unlikely(head == curr)) {
+ int next_idx = find_next_bit(array->bitmap, MAX_RT_PRIO, idx+1);
+
+ if (next_idx >= MAX_RT_PRIO)
+ return NULL;
+
+ idx = next_idx;
+ head = array->queue + idx;
+ curr = head->prev;
+
+ rq->rt.rt_load_balance_idx = idx;
+ rq->rt.rt_load_balance_head = head;
+ }
+
+ p = list_entry(curr, struct task_struct, run_list);
+
+ curr = curr->prev;
+
+ rq->rt.rt_load_balance_curr = curr;
+
+ return p;
+}
+
+static int
+load_balance_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *load_moved)
+{
+ int this_best_prio, best_prio, best_prio_seen = 0;
+ int nr_moved;
+ struct rq_iterator rt_rq_iterator;
+
+ best_prio = sched_find_first_bit(busiest->rt.active.bitmap);
+ this_best_prio = sched_find_first_bit(this_rq->rt.active.bitmap);
+
+ /*
+ * Enable handling of the case where there is more than one task
+ * with the best priority. If the current running task is one
+ * of those with prio==best_prio we know it won't be moved
+ * and therefore it's safe to override the skip (based on load)
+ * of any task we find with that prio.
+ */
+ if (busiest->curr->prio == best_prio)
+ best_prio_seen = 1;
+
+ rt_rq_iterator.start = load_balance_start_rt;
+ rt_rq_iterator.next = load_balance_next_rt;
+ /* pass 'busiest' rq argument into
+ * load_balance_[start|next]_rt iterators
+ */
+ rt_rq_iterator.arg = busiest;
+
+ nr_moved = balance_tasks(this_rq, this_cpu, busiest, max_nr_move,
+ max_load_move, sd, idle, all_pinned, load_moved,
+ this_best_prio, best_prio, best_prio_seen,
+ &rt_rq_iterator);
+
+ return nr_moved;
+}
+
+static void task_tick_rt(struct rq *rq, struct task_struct *p)
+{
+ /*
+ * RR tasks need a special form of timeslice management.
+ * FIFO tasks have no timeslices.
+ */
+ if (p->policy != SCHED_RR)
+ return;
+
+ if (--p->time_slice)
+ return;
+
+ p->time_slice = static_prio_timeslice(p->static_prio);
+ set_tsk_need_resched(p);
+
+ /* put it at the end of the queue: */
+ requeue_task_rt(rq, p);
+}
+
+/*
+ * No parent/child timeslice management necessary for RT tasks,
+ * just activate them:
+ */
+static void task_new_rt(struct rq *rq, struct task_struct *p)
+{
+ activate_task(rq, p, 1);
+}
+
+static struct sched_class rt_sched_class __read_mostly = {
+ .enqueue_task = enqueue_task_rt,
+ .dequeue_task = dequeue_task_rt,
+ .yield_task = yield_task_rt,
+
+ .check_preempt_curr = check_preempt_curr_rt,
+
+ .pick_next_task = pick_next_task_rt,
+ .put_prev_task = put_prev_task_rt,
+
+ .load_balance = load_balance_rt,
+
+ .task_tick = task_tick_rt,
+ .task_new = task_new_rt,
+};
diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h
new file mode 100644
index 000000000000..c63c38f6fa6e
--- /dev/null
+++ b/kernel/sched_stats.h
@@ -0,0 +1,235 @@
+
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * bump this up when changing the output format or the meaning of an existing
+ * format, so that tools can adapt (or abort)
+ */
+#define SCHEDSTAT_VERSION 14
+
+static int show_schedstat(struct seq_file *seq, void *v)
+{
+ int cpu;
+
+ seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+ seq_printf(seq, "timestamp %lu\n", jiffies);
+ for_each_online_cpu(cpu) {
+ struct rq *rq = cpu_rq(cpu);
+#ifdef CONFIG_SMP
+ struct sched_domain *sd;
+ int dcnt = 0;
+#endif
+
+ /* runqueue-specific stats */
+ seq_printf(seq,
+ "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %llu %llu %lu",
+ cpu, rq->yld_both_empty,
+ rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
+ rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
+ rq->ttwu_cnt, rq->ttwu_local,
+ rq->rq_sched_info.cpu_time,
+ rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
+
+ seq_printf(seq, "\n");
+
+#ifdef CONFIG_SMP
+ /* domain-specific stats */
+ preempt_disable();
+ for_each_domain(cpu, sd) {
+ enum cpu_idle_type itype;
+ char mask_str[NR_CPUS];
+
+ cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
+ seq_printf(seq, "domain%d %s", dcnt++, mask_str);
+ for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
+ itype++) {
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
+ "%lu",
+ sd->lb_cnt[itype],
+ sd->lb_balanced[itype],
+ sd->lb_failed[itype],
+ sd->lb_imbalance[itype],
+ sd->lb_gained[itype],
+ sd->lb_hot_gained[itype],
+ sd->lb_nobusyq[itype],
+ sd->lb_nobusyg[itype]);
+ }
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+ " %lu %lu %lu\n",
+ sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
+ sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
+ sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
+ sd->ttwu_wake_remote, sd->ttwu_move_affine,
+ sd->ttwu_move_balance);
+ }
+ preempt_enable();
+#endif
+ }
+ return 0;
+}
+
+static int schedstat_open(struct inode *inode, struct file *file)
+{
+ unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
+ char *buf = kmalloc(size, GFP_KERNEL);
+ struct seq_file *m;
+ int res;
+
+ if (!buf)
+ return -ENOMEM;
+ res = single_open(file, show_schedstat, NULL);
+ if (!res) {
+ m = file->private_data;
+ m->buf = buf;
+ m->size = size;
+ } else
+ kfree(buf);
+ return res;
+}
+
+const struct file_operations proc_schedstat_operations = {
+ .open = schedstat_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
+ * Expects runqueue lock to be held for atomicity of update
+ */
+static inline void
+rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
+{
+ if (rq) {
+ rq->rq_sched_info.run_delay += delta;
+ rq->rq_sched_info.pcnt++;
+ }
+}
+
+/*
+ * Expects runqueue lock to be held for atomicity of update
+ */
+static inline void
+rq_sched_info_depart(struct rq *rq, unsigned long long delta)
+{
+ if (rq)
+ rq->rq_sched_info.cpu_time += delta;
+}
+# define schedstat_inc(rq, field) do { (rq)->field++; } while (0)
+# define schedstat_add(rq, field, amt) do { (rq)->field += (amt); } while (0)
+#else /* !CONFIG_SCHEDSTATS */
+static inline void
+rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
+{}
+static inline void
+rq_sched_info_depart(struct rq *rq, unsigned long long delta)
+{}
+# define schedstat_inc(rq, field) do { } while (0)
+# define schedstat_add(rq, field, amt) do { } while (0)
+#endif
+
+#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
+/*
+ * Called when a process is dequeued from the active array and given
+ * the cpu. We should note that with the exception of interactive
+ * tasks, the expired queue will become the active queue after the active
+ * queue is empty, without explicitly dequeuing and requeuing tasks in the
+ * expired queue. (Interactive tasks may be requeued directly to the
+ * active queue, thus delaying tasks in the expired queue from running;
+ * see scheduler_tick()).
+ *
+ * This function is only called from sched_info_arrive(), rather than
+ * dequeue_task(). Even though a task may be queued and dequeued multiple
+ * times as it is shuffled about, we're really interested in knowing how
+ * long it was from the *first* time it was queued to the time that it
+ * finally hit a cpu.
+ */
+static inline void sched_info_dequeued(struct task_struct *t)
+{
+ t->sched_info.last_queued = 0;
+}
+
+/*
+ * Called when a task finally hits the cpu. We can now calculate how
+ * long it was waiting to run. We also note when it began so that we
+ * can keep stats on how long its timeslice is.
+ */
+static void sched_info_arrive(struct task_struct *t)
+{
+ unsigned long long now = sched_clock(), delta = 0;
+
+ if (t->sched_info.last_queued)
+ delta = now - t->sched_info.last_queued;
+ sched_info_dequeued(t);
+ t->sched_info.run_delay += delta;
+ t->sched_info.last_arrival = now;
+ t->sched_info.pcnt++;
+
+ rq_sched_info_arrive(task_rq(t), delta);
+}
+
+/*
+ * Called when a process is queued into either the active or expired
+ * array. The time is noted and later used to determine how long we
+ * had to wait for us to reach the cpu. Since the expired queue will
+ * become the active queue after active queue is empty, without dequeuing
+ * and requeuing any tasks, we are interested in queuing to either. It
+ * is unusual but not impossible for tasks to be dequeued and immediately
+ * requeued in the same or another array: this can happen in sched_yield(),
+ * set_user_nice(), and even load_balance() as it moves tasks from runqueue
+ * to runqueue.
+ *
+ * This function is only called from enqueue_task(), but also only updates
+ * the timestamp if it is already not set. It's assumed that
+ * sched_info_dequeued() will clear that stamp when appropriate.
+ */
+static inline void sched_info_queued(struct task_struct *t)
+{
+ if (unlikely(sched_info_on()))
+ if (!t->sched_info.last_queued)
+ t->sched_info.last_queued = sched_clock();
+}
+
+/*
+ * Called when a process ceases being the active-running process, either
+ * voluntarily or involuntarily. Now we can calculate how long we ran.
+ */
+static inline void sched_info_depart(struct task_struct *t)
+{
+ unsigned long long delta = sched_clock() - t->sched_info.last_arrival;
+
+ t->sched_info.cpu_time += delta;
+ rq_sched_info_depart(task_rq(t), delta);
+}
+
+/*
+ * Called when tasks are switched involuntarily due, typically, to expiring
+ * their time slice. (This may also be called when switching to or from
+ * the idle task.) We are only called when prev != next.
+ */
+static inline void
+__sched_info_switch(struct task_struct *prev, struct task_struct *next)
+{
+ struct rq *rq = task_rq(prev);
+
+ /*
+ * prev now departs the cpu. It's not interesting to record
+ * stats about how efficient we were at scheduling the idle
+ * process, however.
+ */
+ if (prev != rq->idle)
+ sched_info_depart(prev);
+
+ if (next != rq->idle)
+ sched_info_arrive(next);
+}
+static inline void
+sched_info_switch(struct task_struct *prev, struct task_struct *next)
+{
+ if (unlikely(sched_info_on()))
+ __sched_info_switch(prev, next);
+}
+#else
+#define sched_info_queued(t) do { } while (0)
+#define sched_info_switch(t, next) do { } while (0)
+#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
+
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 0b9886a00e74..73217a9e2875 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -488,7 +488,6 @@ void __init softirq_init(void)
static int ksoftirqd(void * __bind_cpu)
{
- set_user_nice(current, 19);
current->flags |= PF_NOFREEZE;
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 30ee462ee79f..51f5dac42a00 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -206,7 +206,87 @@ static ctl_table root_table[] = {
{ .ctl_name = 0 }
};
+#ifdef CONFIG_SCHED_DEBUG
+static unsigned long min_sched_granularity_ns = 100000; /* 100 usecs */
+static unsigned long max_sched_granularity_ns = 1000000000; /* 1 second */
+static unsigned long min_wakeup_granularity_ns; /* 0 usecs */
+static unsigned long max_wakeup_granularity_ns = 1000000000; /* 1 second */
+#endif
+
static ctl_table kern_table[] = {
+#ifdef CONFIG_SCHED_DEBUG
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_granularity_ns",
+ .data = &sysctl_sched_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_sched_granularity_ns,
+ .extra2 = &max_sched_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_wakeup_granularity_ns",
+ .data = &sysctl_sched_wakeup_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_wakeup_granularity_ns,
+ .extra2 = &max_wakeup_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_batch_wakeup_granularity_ns",
+ .data = &sysctl_sched_batch_wakeup_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_wakeup_granularity_ns,
+ .extra2 = &max_wakeup_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_stat_granularity_ns",
+ .data = &sysctl_sched_stat_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_wakeup_granularity_ns,
+ .extra2 = &max_wakeup_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_runtime_limit_ns",
+ .data = &sysctl_sched_runtime_limit,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_sched_granularity_ns,
+ .extra2 = &max_sched_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_child_runs_first",
+ .data = &sysctl_sched_child_runs_first,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_features",
+ .data = &sysctl_sched_features,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+#endif
{
.ctl_name = KERN_PANIC,
.procname = "panic",
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index da95e10cfd70..fab32a286371 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -105,6 +105,15 @@ config DETECT_SOFTLOCKUP
can be detected via the NMI-watchdog, on platforms that
support it.)
+config SCHED_DEBUG
+ bool "Collect scheduler debugging info"
+ depends on DEBUG_KERNEL && PROC_FS
+ default y
+ help
+ If you say Y here, the /proc/sched_debug file will be provided
+ that can help debug the scheduler. The runtime overhead of this
+ option is minimal.
+
config SCHEDSTATS
bool "Collect scheduler statistics"
depends on DEBUG_KERNEL && PROC_FS
diff --git a/mm/filemap.c b/mm/filemap.c
index d1d9814f99dd..c6ebd9f912ab 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1245,26 +1245,6 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o
return written;
}
-ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
-{
- read_descriptor_t desc;
-
- if (!count)
- return 0;
-
- desc.written = 0;
- desc.count = count;
- desc.arg.data = target;
- desc.error = 0;
-
- do_generic_file_read(in_file, ppos, &desc, actor);
- if (desc.written)
- return desc.written;
- return desc.error;
-}
-EXPORT_SYMBOL(generic_file_sendfile);
-
static ssize_t
do_readahead(struct address_space *mapping, struct file *filp,
unsigned long index, unsigned long nr)
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index fa360e566d88..65ffc321f0c0 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -159,28 +159,6 @@ xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
}
EXPORT_SYMBOL_GPL(xip_file_read);
-ssize_t
-xip_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
-{
- read_descriptor_t desc;
-
- if (!count)
- return 0;
-
- desc.written = 0;
- desc.count = count;
- desc.arg.data = target;
- desc.error = 0;
-
- do_xip_mapping_read(in_file->f_mapping, &in_file->f_ra, in_file,
- ppos, &desc, actor);
- if (desc.written)
- return desc.written;
- return desc.error;
-}
-EXPORT_SYMBOL_GPL(xip_file_sendfile);
-
/*
* __xip_unmap is invoked from xip_unmap and
* xip_write
diff --git a/mm/shmem.c b/mm/shmem.c
index b6aae2b33393..0493e4d0bcaa 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1100,9 +1100,9 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
* Normally, filepage is NULL on entry, and either found
* uptodate immediately, or allocated and zeroed, or read
* in under swappage, which is then assigned to filepage.
- * But shmem_prepare_write passes in a locked filepage,
- * which may be found not uptodate by other callers too,
- * and may need to be copied from the swappage read in.
+ * But shmem_readpage and shmem_prepare_write pass in a locked
+ * filepage, which may be found not uptodate by other callers
+ * too, and may need to be copied from the swappage read in.
*/
repeat:
if (!filepage)
@@ -1485,9 +1485,18 @@ static const struct inode_operations shmem_symlink_inode_operations;
static const struct inode_operations shmem_symlink_inline_operations;
/*
- * Normally tmpfs makes no use of shmem_prepare_write, but it
- * lets a tmpfs file be used read-write below the loop driver.
+ * Normally tmpfs avoids the use of shmem_readpage and shmem_prepare_write;
+ * but providing them allows a tmpfs file to be used for splice, sendfile, and
+ * below the loop driver, in the generic fashion that many filesystems support.
*/
+static int shmem_readpage(struct file *file, struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL);
+ unlock_page(page);
+ return error;
+}
+
static int
shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
@@ -1711,25 +1720,6 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count
return desc.error;
}
-static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
-{
- read_descriptor_t desc;
-
- if (!count)
- return 0;
-
- desc.written = 0;
- desc.count = count;
- desc.arg.data = target;
- desc.error = 0;
-
- do_shmem_file_read(in_file, ppos, &desc, actor);
- if (desc.written)
- return desc.written;
- return desc.error;
-}
-
static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
@@ -2386,6 +2376,7 @@ static const struct address_space_operations shmem_aops = {
.writepage = shmem_writepage,
.set_page_dirty = __set_page_dirty_no_writeback,
#ifdef CONFIG_TMPFS
+ .readpage = shmem_readpage,
.prepare_write = shmem_prepare_write,
.commit_write = simple_commit_write,
#endif
@@ -2399,7 +2390,8 @@ static const struct file_operations shmem_file_operations = {
.read = shmem_file_read,
.write = shmem_file_write,
.fsync = simple_sync_file,
- .sendfile = shmem_file_sendfile,
+ .splice_read = generic_file_splice_read,
+ .splice_write = generic_file_splice_write,
#endif
};
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index c308756c2f9d..6398e6e67493 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -456,18 +456,13 @@ void
ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
struct ieee80211softmac_network *add_net)
{
- struct list_head *list_ptr;
- struct ieee80211softmac_network *softmac_net = NULL;
+ struct ieee80211softmac_network *softmac_net;
- list_for_each(list_ptr, &mac->network_list) {
- softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+ list_for_each_entry(softmac_net, &mac->network_list, list) {
if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
- break;
- else
- softmac_net = NULL;
+ return;
}
- if(softmac_net == NULL)
- list_add(&(add_net->list), &mac->network_list);
+ list_add(&(add_net->list), &mac->network_list);
}
/* Add a network to the list, with locking */
@@ -506,16 +501,13 @@ struct ieee80211softmac_network *
ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
u8 *bssid)
{
- struct list_head *list_ptr;
- struct ieee80211softmac_network *softmac_net = NULL;
- list_for_each(list_ptr, &mac->network_list) {
- softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+ struct ieee80211softmac_network *softmac_net;
+
+ list_for_each_entry(softmac_net, &mac->network_list, list) {
if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
- break;
- else
- softmac_net = NULL;
+ return softmac_net;
}
- return softmac_net;
+ return NULL;
}
/* Get a network from the list by BSSID with locking */
@@ -537,11 +529,9 @@ struct ieee80211softmac_network *
ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
struct ieee80211softmac_essid *essid)
{
- struct list_head *list_ptr;
- struct ieee80211softmac_network *softmac_net = NULL;
+ struct ieee80211softmac_network *softmac_net;
- list_for_each(list_ptr, &mac->network_list) {
- softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+ list_for_each_entry(softmac_net, &mac->network_list, list) {
if (softmac_net->essid.len == essid->len &&
!memcmp(softmac_net->essid.data, essid->data, essid->len))
return softmac_net;
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 099a983797da..c094583386fd 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -853,7 +853,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
u32 priv_len, maj_stat;
int pad, saved_len, remaining_len, offset;
- rqstp->rq_sendfile_ok = 0;
+ rqstp->rq_splice_ok = 0;
priv_len = svc_getnl(&buf->head[0]);
if (rqstp->rq_deferred) {
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e673ef993904..55ea6df069de 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -814,7 +814,7 @@ svc_process(struct svc_rqst *rqstp)
rqstp->rq_res.tail[0].iov_base = NULL;
rqstp->rq_res.tail[0].iov_len = 0;
/* Will be turned off only in gss privacy case: */
- rqstp->rq_sendfile_ok = 1;
+ rqstp->rq_splice_ok = 1;
/* tcp needs a space for the record length... */
if (rqstp->rq_prot == IPPROTO_TCP)
svc_putnl(resv, 0);
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index 5f38f670102c..a1aa89f2faf3 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -118,7 +118,7 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type,
default: return -1;
}
- chip = dev->private;
+ chip = input_get_drvdata(dev);
if (! chip || (beep = chip->beep) == NULL)
return -1;
@@ -239,8 +239,8 @@ int __init snd_pmac_attach_beep(struct snd_pmac *chip)
input_dev->evbit[0] = BIT(EV_SND);
input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
input_dev->event = snd_pmac_beep_event;
- input_dev->private = chip;
- input_dev->cdev.dev = &chip->pdev->dev;
+ input_dev->dev.parent = &chip->pdev->dev;
+ input_set_drvdata(input_dev, chip);
beep->dev = input_dev;
beep->buf = dmabuf;
@@ -251,8 +251,8 @@ int __init snd_pmac_attach_beep(struct snd_pmac *chip)
err = snd_ctl_add(chip->card, beep_ctl);
if (err < 0)
goto fail1;
-
- chip->beep = beep;
+
+ chip->beep = beep;
err = input_register_device(beep->dev);
if (err)